Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ HelenOS.config	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -89,5 +89,5 @@
 @ "tmpfs" TMPFS image
 @ "fat" FAT16 image
-@ "ext2fs" EXT2 image
+@ "ext4fs" ext4 image
 ! RDFMT (choice)
 
@@ -457,4 +457,7 @@
 ! [(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 Samsung S3C24XX on-chip UART
 ! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=arm32&MACHINE=gta02] CONFIG_S3C24XX_UART (y/n)
@@ -482,5 +485,5 @@
 
 % Serial line input module
-! [CONFIG_DSRLNIN=y|(PLATFORM=arm32&MACHINE=gta02)|(PLATFORM=ia64&MACHINE=i460GX&CONFIG_NS16550=y)|(PLATFORM=ia64&MACHINE=ski)|(PLATFORM=sparc64&PROCESSOR=sun4v)] CONFIG_SRLN (y)
+! [CONFIG_DSRLNIN=y|(PLATFORM=arm32&MACHINE=gta02)|(PLATFORM=arm32&MACHINE=integratorcp&CONFIG_ARM926_UART=y)|(PLATFORM=ia64&MACHINE=i460GX&CONFIG_NS16550=y)|(PLATFORM=ia64&MACHINE=ski)|(PLATFORM=sparc64&PROCESSOR=sun4v)] CONFIG_SRLN (y)
 
 % EGA support
@@ -579,7 +582,4 @@
 # USB settings
 
-% USB verbose messages
-! CONFIG_USB_VERBOSE (n/y)
-
 % Start virtual USB host controller
 ! CONFIG_RUN_VIRTUAL_USB_HC (n/y)
@@ -589,5 +589,5 @@
 @ "ganged" Root hub ports are all powered or all off.
 @ "per_port" Powered status of every root hub port is independent.
-! [PLATFORM=ia32|PLATFORM=amd64] OHCI_POWER_SWITCH (choice)
+! [PLATFORM=ia32|PLATFORM=amd64|PLATFORM=ppc32] OHCI_POWER_SWITCH (choice)
 
 % GRUB boot loader architecture
Index: Makefile
===================================================================
--- Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -45,5 +45,5 @@
 CONFIG_HEADER = config.h
 
-.PHONY: all precheck cscope autotool config_auto config_default config distclean clean check releasefile release
+.PHONY: all precheck cscope cscope_parts autotool config_auto config_default config distclean clean check releasefile release
 
 all: $(COMMON_MAKEFILE) $(COMMON_HEADER) $(CONFIG_MAKEFILE) $(CONFIG_HEADER)
@@ -58,4 +58,10 @@
 cscope:
 	find abi kernel boot uspace -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE).out
+
+cscope_parts:
+	find abi -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE)_abi.out
+	find kernel -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE)_kernel.out
+	find boot -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE)_boot.out
+	find uspace -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE)_uspace.out
 
 # Pre-integration build check
Index: abi/include/ddi/irq.h
===================================================================
--- abi/include/ddi/irq.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ abi/include/ddi/irq.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,44 +42,74 @@
 
 typedef enum {
-	/** Read 1 byte from the I/O space. */
+	/** Read 1 byte from the I/O space.
+	 *
+	 * *addr(8) -> scratch[dstarg]
+	 */
 	CMD_PIO_READ_8 = 1,
-	/** Read 2 bytes from the I/O space. */
+	
+	/** Read 2 bytes from the I/O space.
+	 *
+	 * *addr(16) -> scratch[dstarg]
+	 */
 	CMD_PIO_READ_16,
-	/** Read 4 bytes from the I/O space. */
+	
+	/** Read 4 bytes from the I/O space.
+	 *
+	 * *addr(32) -> scratch[dstarg]
+	 */
 	CMD_PIO_READ_32,
 	
-	/** Write 1 byte to the I/O space. */
+	/** Write 1 byte to the I/O space.
+	 *
+	 * value(8) -> *addr
+	 */
 	CMD_PIO_WRITE_8,
-	/** Write 2 bytes to the I/O space. */
+	
+	/** Write 2 bytes to the I/O space.
+	 *
+	 * value(16) -> *addr
+	 */
 	CMD_PIO_WRITE_16,
-	/** Write 4 bytes to the I/O space. */
+	
+	/** Write 4 bytes to the I/O space.
+	 *
+	 * value(32) -> *addr
+	 */
 	CMD_PIO_WRITE_32,
 	
-	/**
-	 * Write 1 byte from the source argument
-	 * to the I/O space.
+	/** Write 1 byte to the I/O space.
+	 *
+	 * scratch[srcarg](8) -> *addr
 	 */
 	CMD_PIO_WRITE_A_8,
-	/**
-	 * Write 2 bytes from the source argument
-	 * to the I/O space.
+	
+	/** Write 2 bytes to the I/O space.
+	 *
+	 * scratch[srcarg](16) -> *addr
 	 */
 	CMD_PIO_WRITE_A_16,
-	/**
-	 * Write 4 bytes from the source argument
-	 * to the I/O space.
+	
+	/** Write 4 bytes to the I/O space.
+	 *
+	 * scratch[srcarg](32) -> *addr
 	 */
 	CMD_PIO_WRITE_A_32,
 	
-	/**
-	 * Perform a bit masking on the source argument
-	 * and store the result into the destination argument.
+	/** Load value.
+	 *
+	 * value -> scratch[dstarg]
 	 */
-	CMD_BTEST,
+	CMD_LOAD,
 	
-	/**
-	 * Predicate the execution of the following
-	 * N commands by the boolean value of the source
-	 * argument.
+	/** Perform bitwise conjunction.
+	 *
+	 * scratch[srcarg] & value -> scratch[dstarg]
+	 */
+	CMD_AND,
+	
+	/** Predicate the execution of the following commands.
+	 *
+	 * if (scratch[srcarg] == 0)
+	 *  (skip the following 'value' commands)
 	 */
 	CMD_PREDICATE,
Index: abi/include/fb/visuals.h
===================================================================
--- abi/include/fb/visuals.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ abi/include/fb/visuals.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2006 Martin Decky
+ * Copyright (c) 2011 Petr Koupy
  * All rights reserved.
  *
@@ -46,7 +47,11 @@
 	VISUAL_BGR_0_8_8_8,
 	VISUAL_BGR_8_8_8_0,
+	VISUAL_ABGR_8_8_8_8,
+	VISUAL_BGRA_8_8_8_8,
 	VISUAL_RGB_8_8_8,
 	VISUAL_RGB_0_8_8_8,
-	VISUAL_RGB_8_8_8_0
+	VISUAL_RGB_8_8_8_0,
+	VISUAL_ARGB_8_8_8_8,
+	VISUAL_RGBA_8_8_8_8
 } visual_t;
 
Index: abi/include/ipc/ipc.h
===================================================================
--- abi/include/ipc/ipc.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ abi/include/ipc/ipc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -57,9 +57,6 @@
 #define IPC_CALL_FORWARDED  (1 << 2)
 
-/** Identify connect_me_to answer */
-#define IPC_CALL_CONN_ME_TO  (1 << 3)
-
 /** Interrupt notification */
-#define IPC_CALL_NOTIF  (1 << 4)
+#define IPC_CALL_NOTIF  (1 << 3)
 
 
Index: abi/include/mm/as.h
===================================================================
--- abi/include/mm/as.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ abi/include/mm/as.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,8 +37,9 @@
 
 /** Address space area flags. */
-#define AS_AREA_READ       1
-#define AS_AREA_WRITE      2
-#define AS_AREA_EXEC       4
-#define AS_AREA_CACHEABLE  8
+#define AS_AREA_READ       0x01
+#define AS_AREA_WRITE      0x02
+#define AS_AREA_EXEC       0x04
+#define AS_AREA_CACHEABLE  0x08
+#define AS_AREA_GUARD      0x10
 
 /** Address space area info exported to uspace. */
Index: abi/include/syscall.h
===================================================================
--- abi/include/syscall.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ abi/include/syscall.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -63,6 +63,4 @@
 	SYS_PAGE_FIND_MAPPING,
 	
-	SYS_IPC_CALL_SYNC_FAST,
-	SYS_IPC_CALL_SYNC_SLOW,
 	SYS_IPC_CALL_ASYNC_FAST,
 	SYS_IPC_CALL_ASYNC_SLOW,
Index: boot/Makefile
===================================================================
--- boot/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,6 +47,6 @@
 	$(MKFAT) 1048576 $(DIST_PATH) $@
 endif
-ifeq ($(RDFMT),ext2fs)
-	$(MKEXT2) 1048576 $(DIST_PATH) $@
+ifeq ($(RDFMT),ext4fs)
+	$(MKEXT4) 1048576 $(DIST_PATH) $@
 endif
 
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/Makefile.common	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -55,5 +55,5 @@
 MKTMPFS = $(TOOLS_PATH)/mktmpfs.py
 MKFAT = $(TOOLS_PATH)/mkfat.py
-MKEXT2 = $(TOOLS_PATH)/mkext2.py
+MKEXT4 = $(TOOLS_PATH)/mkext4.py
 MKUIMAGE = $(TOOLS_PATH)/mkuimage.py
 
@@ -74,5 +74,6 @@
 	$(USPACE_PATH)/srv/locsrv/locsrv \
 	$(USPACE_PATH)/srv/bd/rd/rd \
-	$(USPACE_PATH)/srv/vfs/vfs
+	$(USPACE_PATH)/srv/vfs/vfs \
+	$(USPACE_PATH)/srv/logger/logger
 
 ifeq ($(RDFMT),tmpfs)
@@ -84,13 +85,15 @@
 endif
 
-ifeq ($(RDFMT),ext2fs)
-	INIT_TASKS += $(USPACE_PATH)/srv/fs/ext2fs/ext2fs
+ifeq ($(RDFMT),ext4fs)
+	INIT_TASKS += $(USPACE_PATH)/srv/fs/ext4fs/ext4fs
 endif
 
 RD_SRVS_ESSENTIAL = \
-	$(USPACE_PATH)/srv/hid/fb/fb \
 	$(USPACE_PATH)/srv/hid/input/input \
+	$(USPACE_PATH)/srv/hid/output/output \
 	$(USPACE_PATH)/srv/hid/console/console \
-	$(USPACE_PATH)/srv/fs/locfs/locfs
+	$(USPACE_PATH)/srv/devman/devman \
+	$(USPACE_PATH)/srv/fs/locfs/locfs \
+	$(USPACE_PATH)/srv/hid/compositor/compositor
 
 RD_SRVS_NON_ESSENTIAL = \
@@ -98,4 +101,5 @@
 	$(USPACE_PATH)/srv/bd/part/guid_part/g_part \
 	$(USPACE_PATH)/srv/bd/part/mbr_part/mbr_part \
+	$(USPACE_PATH)/srv/bd/sata_bd/sata_bd \
 	$(USPACE_PATH)/srv/clipboard/clipboard \
 	$(USPACE_PATH)/srv/fs/tmpfs/tmpfs \
@@ -104,6 +108,9 @@
 	$(USPACE_PATH)/srv/fs/cdfs/cdfs \
 	$(USPACE_PATH)/srv/fs/exfat/exfat \
+	$(USPACE_PATH)/srv/fs/udf/udf \
 	$(USPACE_PATH)/srv/fs/ext2fs/ext2fs \
+	$(USPACE_PATH)/srv/fs/ext4fs/ext4fs \
 	$(USPACE_PATH)/srv/hid/remcons/remcons \
+	$(USPACE_PATH)/srv/hid/isdv4_tablet/isdv4_tablet \
 	$(USPACE_PATH)/srv/net/dnsres/dnsres \
 	$(USPACE_PATH)/srv/net/ethip/ethip \
@@ -112,10 +119,10 @@
 	$(USPACE_PATH)/srv/net/tcp/tcp \
 	$(USPACE_PATH)/srv/net/udp/udp \
-	$(USPACE_PATH)/srv/taskmon/taskmon \
-	$(USPACE_PATH)/srv/devman/devman
+	$(USPACE_PATH)/srv/taskmon/taskmon
 
 RD_DRVS = \
 	infrastructure/root \
 	infrastructure/rootvirt \
+	fb/kfb \
 	test/test1 \
 	test/test2 \
@@ -123,5 +130,6 @@
 	nic/ne2k \
 	nic/e1k \
-	nic/rtl8139
+	nic/rtl8139 \
+	block/ahci
 
 RD_DRV_CFG =
@@ -147,7 +155,10 @@
 	$(USPACE_PATH)/app/bdsh/bdsh \
 	$(USPACE_PATH)/app/getterm/getterm \
-	$(USPACE_PATH)/app/klog/klog
+	$(USPACE_PATH)/app/klog/klog \
+	$(USPACE_PATH)/app/vlaunch/vlaunch \
+	$(USPACE_PATH)/app/vterm/vterm
 
 RD_APPS_NON_ESSENTIAL = \
+	$(USPACE_PATH)/app/bithenge/bithenge \
 	$(USPACE_PATH)/app/blkdump/blkdump \
 	$(USPACE_PATH)/app/bnchmark/bnchmark \
@@ -162,8 +173,8 @@
 	$(USPACE_PATH)/app/killall/killall \
 	$(USPACE_PATH)/app/loc/loc \
+	$(USPACE_PATH)/app/logset/logset \
 	$(USPACE_PATH)/app/mkfat/mkfat \
 	$(USPACE_PATH)/app/mkexfat/mkexfat \
 	$(USPACE_PATH)/app/mkmfs/mkmfs \
-	$(USPACE_PATH)/app/lsusb/lsusb \
 	$(USPACE_PATH)/app/sbi/sbi \
 	$(USPACE_PATH)/app/sportdmp/sportdmp \
@@ -172,4 +183,5 @@
 	$(USPACE_PATH)/app/tester/tester \
 	$(USPACE_PATH)/app/testread/testread \
+	$(USPACE_PATH)/app/testwrit/testwrit \
 	$(USPACE_PATH)/app/tetris/tetris \
 	$(USPACE_PATH)/app/trace/trace \
@@ -186,5 +198,7 @@
 	$(USPACE_PATH)/app/vuhid/vuh \
 	$(USPACE_PATH)/app/mkbd/mkbd \
-	$(USPACE_PATH)/app/websrv/websrv
+	$(USPACE_PATH)/app/websrv/websrv \
+	$(USPACE_PATH)/app/date/date \
+	$(USPACE_PATH)/app/vdemo/vdemo
 
 ifeq ($(CONFIG_PCC),y)
Index: boot/arch/amd64/Makefile.inc
===================================================================
--- boot/arch/amd64/Makefile.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/arch/amd64/Makefile.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,4 +42,5 @@
 	char/ps2mouse \
 	char/xtkbd \
+	time/cmos-rtc \
 	bus/usb/ehci\
 	bus/usb/ohci \
Index: boot/arch/arm32/include/main.h
===================================================================
--- boot/arch/arm32/include/main.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/arch/arm32/include/main.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -52,8 +52,8 @@
 
 /** GXemul testarm serial console output register */
-#define TESTARM_SCONS_ADDR 	0x10000000
+#define TESTARM_SCONS_ADDR	0x10000000
 
 /** IntegratorCP serial console output register */
-#define ICP_SCONS_ADDR 		0x16000000
+#define ICP_SCONS_ADDR		0x16000000
 
 extern void bootstrap(void);
Index: boot/arch/ia64/Makefile.inc
===================================================================
--- boot/arch/ia64/Makefile.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/arch/ia64/Makefile.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -31,7 +31,17 @@
 BFD_ARCH = ia64
 
+#
+# FIXME:
+#
+# The -fno-selective-scheduling and -fno-selective-scheduling2 options
+# should be removed as soon as a bug in GCC concerning unchecked
+# speculative loads is fixed.
+#
+# See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53975 for reference.
+#
+
 BITS = 64
 ENDIANESS = LE
-EXTRA_CFLAGS = -fno-unwind-tables -mfixed-range=f32-f127 -mno-pic -mno-sdata
+EXTRA_CFLAGS = -fno-unwind-tables -mfixed-range=f32-f127 -mno-pic -mno-sdata -fno-selective-scheduling -fno-selective-scheduling2
 
 RD_SRVS_NON_ESSENTIAL +=
Index: boot/arch/mips32/Makefile.inc
===================================================================
--- boot/arch/mips32/Makefile.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/arch/mips32/Makefile.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -29,5 +29,5 @@
 BFD_ARCH = mips
 BITS = 32
-EXTRA_CFLAGS = -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=32
+EXTRA_CFLAGS = -msoft-float -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=32
 
 RD_SRVS_NON_ESSENTIAL += \
@@ -48,5 +48,4 @@
 	BFD_OUTPUT = binary
 	ENDIANESS = LE
-	EXTRA_GCC_CFLAGS = -mhard-float
 endif
 
Index: boot/arch/mips64/Makefile.inc
===================================================================
--- boot/arch/mips64/Makefile.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/arch/mips64/Makefile.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -29,5 +29,5 @@
 BFD_ARCH = mips:4000
 BITS = 64
-EXTRA_CFLAGS = -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=64
+EXTRA_CFLAGS = -msoft-float -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=64
 
 ifeq ($(MACHINE),msim)
@@ -35,5 +35,4 @@
 	BFD_OUTPUT = binary
 	ENDIANESS = LE
-	EXTRA_GCC_CFLAGS = -mhard-float
 endif
 
Index: boot/arch/ppc32/Makefile.inc
===================================================================
--- boot/arch/ppc32/Makefile.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/arch/ppc32/Makefile.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -43,5 +43,13 @@
 
 RD_DRVS += \
-	infrastructure/rootmac
+	infrastructure/rootmac \
+	bus/pci/pciintel \
+	bus/usb/ohci \
+	bus/usb/usbflbk \
+	bus/usb/usbhub \
+	bus/usb/usbhid \
+	bus/usb/usbmast \
+	bus/usb/usbmid \
+	bus/usb/vhc
 
 SOURCES = \
Index: boot/arch/ppc32/_link.ld.in
===================================================================
--- boot/arch/ppc32/_link.ld.in	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/arch/ppc32/_link.ld.in	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -2,5 +2,5 @@
 
 SECTIONS {
-	. = 0x01000000;
+	. = 0x02000000;
 	.text : {
 		*(BOOTSTRAP);
Index: boot/arch/ppc32/include/arch.h
===================================================================
--- boot/arch/ppc32/include/arch.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/arch/ppc32/include/arch.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,5 +35,5 @@
 #define BOOT_OFFSET  0x8000
 
-#define LOADER_ADDRESS  0x01000000
+#define LOADER_ADDRESS  0x02000000
 
 #ifndef __ASM__
Index: boot/arch/ppc32/src/main.c
===================================================================
--- boot/arch/ppc32/src/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/arch/ppc32/src/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -103,4 +103,10 @@
 	}
 	
+	if (top >= (size_t) loader_address_pa) {
+		printf("Inflated components overlap loader area.\n");
+		printf("The boot image is too large. Halting.\n");
+		halt();
+	}
+	
 	void *balloc_base;
 	void *balloc_base_pa;
Index: boot/generic/include/printf.h
===================================================================
--- boot/generic/include/printf.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/generic/include/printf.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,15 +35,5 @@
 #include <typedefs.h>
 #include <stdarg.h>
-
-#ifndef NVERIFY_PRINTF
-
-#define PRINTF_ATTRIBUTE(start, end) \
-	__attribute__((format(gnu_printf, start, end)))
-
-#else /* NVERIFY_PRINTF */
-
-#define PRINTF_ATTRIBUTE(start, end)
-
-#endif /* NVERIFY_PRINTF */
+#include <printf_verify.h>
 
 #define EOF  (-1)
Index: boot/generic/include/printf_verify.h
===================================================================
--- boot/generic/include/printf_verify.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ boot/generic/include/printf_verify.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+/** @file
+ */
+
+#ifndef BOOT_PRINTF_VERIFY_H_
+#define BOOT_PRINTF_VERIFY_H_
+
+#ifndef NVERIFY_PRINTF
+
+#define PRINTF_ATTRIBUTE(start, end) \
+	__attribute__((format(gnu_printf, start, end)))
+
+#else /* NVERIFY_PRINTF */
+
+#define PRINTF_ATTRIBUTE(start, end)
+
+#endif /* NVERIFY_PRINTF */
+
+#endif
+
+/** @}
+ */
Index: boot/generic/src/str.c
===================================================================
--- boot/generic/src/str.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ boot/generic/src/str.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -354,12 +354,17 @@
  *
  * Do a char-by-char comparison of two NULL-terminated strings.
- * The strings are considered equal iff they consist of the same
- * characters on the minimum of their lengths.
+ * The strings are considered equal iff their length is equal
+ * and both strings consist of the same sequence of characters.
+ *
+ * A string S1 is less than another string S2 if it has a character with
+ * lower value at the first character position where the strings differ.
+ * If the strings differ in length, the shorter one is treated as if
+ * padded by characters with a value of zero.
  *
  * @param s1 First string to compare.
  * @param s2 Second string to compare.
  *
- * @return 0 if the strings are equal, -1 if first is smaller,
- *         1 if second smaller.
+ * @return 0 if the strings are equal, -1 if the first is less than the second,
+ *         1 if the second is less than the first.
  *
  */
Index: contrib/arch/HelenOS.adl
===================================================================
--- contrib/arch/HelenOS.adl	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ contrib/arch/HelenOS.adl	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -1,3 +1,3 @@
-system architecture HelenOS version 0.4.1 {
+system architecture HelenOS version 0.5.0 {
 	/* SPARTAN kernel */
 	inst kernel kernel;
Index: contrib/arch/uspace/srv/fs/fat/fat.bp
===================================================================
--- contrib/arch/uspace/srv/fs/fat/fat.bp	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ contrib/arch/uspace/srv/fs/fat/fat.bp	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -7,5 +7,5 @@
 			?ipc_m_data_write /* mount options */ ;
 			tentative {
-				[/uspace/lib/libblock/fnc.block_init%rd]
+				[/uspace/lib/block/fnc.block_init%rd]
 			}
 		} +
Index: contrib/bazaar/bzreml/__init__.py
===================================================================
--- contrib/bazaar/bzreml/__init__.py	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ contrib/bazaar/bzreml/__init__.py	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -52,5 +52,5 @@
 
 from bzrlib import errors
-from bzrlib import revision
+from bzrlib import revision as _mod_revision
 from bzrlib import __version__ as bzrlib_version
 
@@ -102,10 +102,18 @@
 	return ""
 
+def iter_reverse_revision_history(repository, revision_id):
+	"""Iterate backwards through revision ids in the lefthand history"""
+	
+	graph = repository.get_graph()
+	stop_revisions = (None, _mod_revision.NULL_REVISION)
+	return graph.iter_lefthand_ancestry(revision_id, stop_revisions)
+
 def revision_sequence(branch, revision_old_id, revision_new_id):
 	"""Calculate a sequence of revisions"""
 	
-	for revision_ac_id in branch.repository.iter_reverse_revision_history(revision_new_id):
+	for revision_ac_id in iter_reverse_revision_history(branch.repository, revision_new_id):
 		if (revision_ac_id == revision_old_id):
 			break
+		
 		yield revision_ac_id
 
@@ -117,7 +125,9 @@
 		branch.repository.lock_read()
 		try:
-			body = StringIO()
+			revision_prev_id = revision_old_id
 			
-			for revision_ac_id in revision_sequence(branch, revision_old_id, revision_new_id):
+			for revision_ac_id in reversed(list(revision_sequence(branch, revision_old_id, revision_new_id))):
+				body = StringIO()
+				
 				revision_ac = branch.repository.get_revision(revision_ac_id)
 				revision_ac_no = branch.revision_id_to_revno(revision_ac_id)
@@ -139,5 +149,5 @@
 				body.write("\n")
 				
-				commit_message = ""
+				commit_message = None
 				body.write("Log:\n")
 				if (not revision_ac.message):
@@ -147,59 +157,60 @@
 					for line in log.split("\n"):
 						body.write("%s\n" % line)
-						if (commit_message == ""):
+						if (commit_message == None):
 							commit_message = line
 				
-				if (commit_message == ""):
+				if (commit_message == None):
 					commit_message = "(empty)"
 				
 				body.write("\n")
+				
+				tree_prev = branch.repository.revision_tree(revision_prev_id)
+				tree_ac = branch.repository.revision_tree(revision_ac_id)
+				
+				delta = tree_ac.changes_from(tree_prev)
+				
+				if (len(delta.added) > 0):
+					body.write("Added:\n")
+					for item in delta.added:
+						body.write("    %s\n" % item[0])
+				
+				if (len(delta.removed) > 0):
+					body.write("Removed:\n")
+					for item in delta.removed:
+						body.write("    %s\n" % item[0])
+				
+				if (len(delta.renamed) > 0):
+					body.write("Renamed:\n")
+					for item in delta.renamed:
+						body.write("    %s -> %s\n" % (item[0], item[1]))
+				
+				if (len(delta.kind_changed) > 0):
+					body.write("Changed:\n")
+					for item in delta.kind_changed:
+						body.write("    %s\n" % item[0])
+				
+				if (len(delta.modified) > 0):
+					body.write("Modified:\n")
+					for item in delta.modified:
+						body.write("    %s\n" % item[0])
+				
+				body.write("\n")
+				
+				tree_prev.lock_read()
+				try:
+					tree_ac.lock_read()
+					try:
+						diff = DiffTree.from_trees_options(tree_prev, tree_ac, body, "utf8", None, "", "", None)
+						diff.show_diff(None, None)
+					finally:
+						tree_ac.unlock()
+				finally:
+					tree_prev.unlock()
+				
+				subject = "r%d - %s" % (revision_ac_no, commit_message)
+				send_smtp("localhost", config_sender(config), config_to(config), subject, body.getvalue())
+				
+				revision_prev_id = revision_ac_id
 			
-			tree_old = branch.repository.revision_tree(revision_old_id)
-			tree_new = branch.repository.revision_tree(revision_new_id)
-			
-			revision_new_no = branch.revision_id_to_revno(revision_new_id)
-			delta = tree_new.changes_from(tree_old)
-			
-			if (len(delta.added) > 0):
-				body.write("Added:\n")
-				for item in delta.added:
-					body.write("    %s\n" % item[0])
-			
-			if (len(delta.removed) > 0):
-				body.write("Removed:\n")
-				for item in delta.removed:
-					body.write("    %s\n" % item[0])
-			
-			if (len(delta.renamed) > 0):
-				body.write("Renamed:\n")
-				for item in delta.renamed:
-					body.write("    %s -> %s\n" % (item[0], item[1]))
-			
-			if (len(delta.kind_changed) > 0):
-				body.write("Changed:\n")
-				for item in delta.kind_changed:
-					body.write("    %s\n" % item[0])
-			
-			if (len(delta.modified) > 0):
-				body.write("Modified:\n")
-				for item in delta.modified:
-					body.write("    %s\n" % item[0])
-			
-			body.write("\n")
-			
-			tree_old.lock_read()
-			try:
-				tree_new.lock_read()
-				try:
-					diff = DiffTree.from_trees_options(tree_old, tree_new, body, "utf8", None, "", "", None)
-					diff.show_diff(None, None)
-				finally:
-					tree_new.unlock()
-			finally:
-				tree_old.unlock()
-			
-			subject = "r%d - %s" % (revision_new_no, commit_message)
-			
-			send_smtp("localhost", config_sender(config), config_to(config), subject, body.getvalue())
 		finally:
 			branch.repository.unlock()
Index: contrib/bazaar/bzreml/setup.py
===================================================================
--- contrib/bazaar/bzreml/setup.py	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ contrib/bazaar/bzreml/setup.py	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -7,5 +7,5 @@
 	description = 'Commit email plugin for Bazaar',
 	keywords = 'plugin bzr email',
-	version = '1.2',
+	version = '1.3',
 	url = 'http://www.decky.cz/',
 	license = 'BSD',
@@ -13,5 +13,5 @@
 	author_email = 'martin@decky.cz',
 	long_description = """Hooks into Bazaar and sends commit notification emails.""",
-	package_dir = {'bzrlib.plugins.eml':'.'}, 
+	package_dir = {'bzrlib.plugins.eml':'.'},
 	packages = ['bzrlib.plugins.eml']
 )
Index: contrib/bazaar/mbprotect/__init__.py
===================================================================
--- contrib/bazaar/mbprotect/__init__.py	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ contrib/bazaar/mbprotect/__init__.py	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -44,4 +44,12 @@
 import bzrlib.branch
 from bzrlib.errors import TipChangeRejected
+from bzrlib import revision as _mod_revision
+
+def iter_reverse_revision_history(repository, revision_id):
+	"""Iterate backwards through revision ids in the lefthand history"""
+	
+	graph = repository.get_graph()
+	stop_revisions = (None, _mod_revision.NULL_REVISION)
+	return graph.iter_lefthand_ancestry(revision_id, stop_revisions)
 
 def pre_change_branch_tip(params):
@@ -54,5 +62,5 @@
 	# First permitted case is appending changesets to main branch.Look for
 	# old tip in new main branch.
-	for revision_id in repo.iter_reverse_revision_history(params.new_revid):
+	for revision_id in iter_reverse_revision_history(repo, params.new_revid):
 		if revision_id == params.old_revid:
 			return	# Found old tip
@@ -60,5 +68,5 @@
 	# Another permitted case is backing out changesets. Look for new tip
 	# in old branch.
-	for revision_id in repo.iter_reverse_revision_history(params.old_revid):
+	for revision_id in iter_reverse_revision_history(repo, params.old_revid):
 		if revision_id == params.new_revid:
 			return	# Found new tip
Index: contrib/conf/mips32-gx.sh
===================================================================
--- contrib/conf/mips32-gx.sh	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ contrib/conf/mips32-gx.sh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -8,3 +8,10 @@
 fi
 
-gxemul $@ -E oldtestmips -C R4000 -X image.boot -d d0:"$DISK_IMG"
+if [ "$1" == "-E" ] && [ -n "$2" ]; then
+	MACHINE="$2"
+	shift 2
+else
+	MACHINE="oldtestmips"
+fi
+
+gxemul $@ -E "$MACHINE" -C R4000 -X image.boot -d d0:"$DISK_IMG"
Index: contrib/conf/sparc64-qe
===================================================================
--- contrib/conf/sparc64-qe	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ contrib/conf/sparc64-qe	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+qemu-system-sparc64 $@ -M sun4u -boot d -cdrom image.iso
Index: defaults/amd64/Makefile.config
===================================================================
--- defaults/amd64/Makefile.config	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ defaults/amd64/Makefile.config	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -54,5 +54,5 @@
 
 # Default framebuffer mode
-CONFIG_BFB_MODE = 800x600
+CONFIG_BFB_MODE = 1024x768
 
 # Default framebuffer depth
Index: defaults/ia32/Makefile.config
===================================================================
--- defaults/ia32/Makefile.config	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ defaults/ia32/Makefile.config	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -60,5 +60,5 @@
 
 # Default framebuffer mode
-CONFIG_BFB_MODE = 800x600
+CONFIG_BFB_MODE = 1024x768
 
 # Default framebuffer depth
Index: defaults/mips32/Makefile.config
===================================================================
--- defaults/mips32/Makefile.config	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ defaults/mips32/Makefile.config	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,2 +47,4 @@
 CONFIG_MOUNT_DATA = n
 
+# Barebone build with essential binaries only 
+CONFIG_BAREBONE = y
Index: defaults/ppc32/Makefile.config
===================================================================
--- defaults/ppc32/Makefile.config	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ defaults/ppc32/Makefile.config	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -44,2 +44,5 @@
 CONFIG_MOUNT_DATA = n
 
+# OHCI root hub power switch, ganged is enough
+OHCI_POWER_SWITCH = ganged
+
Index: defaults/sparc64/ultra/Makefile.config
===================================================================
--- defaults/sparc64/ultra/Makefile.config	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ defaults/sparc64/ultra/Makefile.config	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -4,2 +4,5 @@
 # CPU type
 PROCESSOR = us
+
+# Barebone build with essential binaries only
+CONFIG_BAREBONE = y
Index: kernel/Makefile
===================================================================
--- kernel/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -196,4 +196,5 @@
 	generic/src/console/chardev.c \
 	generic/src/console/console.c \
+	generic/src/console/prompt.c \
 	generic/src/cpu/cpu.c \
 	generic/src/ddi/ddi.c \
@@ -256,4 +257,15 @@
 	generic/src/ipc/ipc.c \
 	generic/src/ipc/sysipc.c \
+	generic/src/ipc/sysipc_ops.c \
+	generic/src/ipc/ops/clnestab.c \
+	generic/src/ipc/ops/conctmeto.c \
+	generic/src/ipc/ops/concttome.c \
+	generic/src/ipc/ops/connclone.c \
+	generic/src/ipc/ops/dataread.c \
+	generic/src/ipc/ops/datawrite.c \
+	generic/src/ipc/ops/debug.c \
+	generic/src/ipc/ops/sharein.c \
+	generic/src/ipc/ops/shareout.c \
+	generic/src/ipc/ops/stchngath.c \
 	generic/src/ipc/ipcrsc.c \
 	generic/src/ipc/irq.c \
Index: kernel/arch/abs32le/include/mm/page.h
===================================================================
--- kernel/arch/abs32le/include/mm/page.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/abs32le/include/mm/page.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -105,4 +105,12 @@
 	set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
 
+/* Set PTE present bit accessors for each level. */
+#define SET_PTL1_PRESENT_ARCH(ptl0, i)	\
+	set_pt_present((pte_t *) (ptl0), (size_t) (i))
+#define SET_PTL2_PRESENT_ARCH(ptl1, i)
+#define SET_PTL3_PRESENT_ARCH(ptl2, i)
+#define SET_FRAME_PRESENT_ARCH(ptl3, i) \
+	set_pt_present((pte_t *) (ptl3), (size_t) (i))
+
 /* Macros for querying the last level entries. */
 #define PTE_VALID_ARCH(p) \
@@ -173,4 +181,13 @@
 }
 
+NO_TRACE static inline void set_pt_present(pte_t *pt, size_t i)
+    WRITES(ARRAY_RANGE(pt, PTL0_ENTRIES_ARCH))
+    REQUIRES_ARRAY_MUTABLE(pt, PTL0_ENTRIES_ARCH)
+{
+	pte_t *p = &pt[i];
+
+	p->present = 1;
+}
+
 extern void page_arch_init(void);
 extern void page_fault(unsigned int, istate_t *);
Index: kernel/arch/amd64/Makefile.inc
===================================================================
--- kernel/arch/amd64/Makefile.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/amd64/Makefile.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,24 +33,5 @@
 
 FPU_NO_CFLAGS = -mno-sse -mno-sse2
-
-#
-# FIXME:
-#
-# The -fno-optimize-sibling-calls should be removed as soon as a bug
-# in GCC concerning the "large" memory model and tail call optimization
-# is fixed.
-#
-# When GCC generates a code for tail call, instead of generating ..
-#
-#   jmp *fnc
-#
-# it generates an assembly code with an illegal immediate prefix:
-#
-#   jmp *$fnc
-#
-# See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48385 for reference.
-#
-
-CMN1 = -m64 -mcmodel=large -mno-red-zone -fno-unwind-tables -fno-omit-frame-pointer -fno-optimize-sibling-calls
+CMN1 = -m64 -mcmodel=large -mno-red-zone -fno-unwind-tables -fno-omit-frame-pointer
 GCC_CFLAGS += $(CMN1)
 ICC_CFLAGS += $(CMN1)
Index: kernel/arch/amd64/include/mm/page.h
===================================================================
--- kernel/arch/amd64/include/mm/page.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/amd64/include/mm/page.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -119,4 +119,14 @@
 	set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
 
+/* Set PTE present bit accessors for each level. */
+#define SET_PTL1_PRESENT_ARCH(ptl0, i) \
+	set_pt_present((pte_t *) (ptl0), (size_t) (i))
+#define SET_PTL2_PRESENT_ARCH(ptl1, i) \
+	set_pt_present((pte_t *) (ptl1), (size_t) (i))
+#define SET_PTL3_PRESENT_ARCH(ptl2, i) \
+	set_pt_present((pte_t *) (ptl2), (size_t) (i))
+#define SET_FRAME_PRESENT_ARCH(ptl3, i) \
+	set_pt_present((pte_t *) (ptl3), (size_t) (i))
+
 /* Macros for querying the last-level PTE entries. */
 #define PTE_VALID_ARCH(p) \
@@ -215,4 +225,11 @@
 }
 
+NO_TRACE static inline void set_pt_present(pte_t *pt, size_t i)
+{
+	pte_t *p = &pt[i];
+
+	p->present = 1;
+}
+
 extern void page_arch_init(void);
 extern void page_fault(unsigned int, istate_t *);
Index: kernel/arch/amd64/src/asm.S
===================================================================
--- kernel/arch/amd64/src/asm.S	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/amd64/src/asm.S	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -362,5 +362,13 @@
 	 */
 	call syscall_handler
-	
+
+	/*
+	 * Test if the saved return address is canonical and not-kernel.
+	 * We do this by looking at the 16 most significant bits
+	 * of the saved return address (two bytes at offset 6).
+	 */
+	testw $0xffff, ISTATE_OFFSET_RIP+6(%rsp)
+	jnz bad_rip 
+
 	cli
 	
@@ -388,4 +396,14 @@
 	sysretq
 
+bad_rip:
+	movq %rsp, %rdi
+	movabs $bad_rip_msg, %rsi
+	xorb %al, %al
+	callq fault_from_uspace
+	/* not reached */
+	
+bad_rip_msg:
+	.asciz "Invalid instruction pointer."
+
 /** Print Unicode character to EGA display.
  *
Index: kernel/arch/amd64/src/boot/multiboot.S
===================================================================
--- kernel/arch/amd64/src/boot/multiboot.S	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/amd64/src/boot/multiboot.S	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -76,4 +76,5 @@
 
 multiboot_image_start:
+	cli
 	cld
 	
@@ -81,6 +82,10 @@
 	movl $START_STACK, %esp
 	
-	/* Initialize Global Descriptor Table register */
+	/*
+	 * Initialize Global Descriptor Table and
+	 * Interrupt Descriptor Table registers
+	 */
 	lgdtl bootstrap_gdtr
+	lidtl bootstrap_idtr
 	
 	/* Kernel data + stack */
@@ -645,4 +650,9 @@
 .section K_DATA_START, "aw", @progbits
 
+.global bootstrap_idtr
+bootstrap_idtr:
+	.word 0
+	.long 0
+
 .global bootstrap_gdtr
 bootstrap_gdtr:
Index: kernel/arch/amd64/src/boot/multiboot2.S
===================================================================
--- kernel/arch/amd64/src/boot/multiboot2.S	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/amd64/src/boot/multiboot2.S	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -116,4 +116,5 @@
 
 multiboot2_image_start:
+	cli
 	cld
 	
@@ -121,6 +122,10 @@
 	movl $START_STACK, %esp
 	
-	/* Initialize Global Descriptor Table register */
+	/*
+	 * Initialize Global Descriptor Table and
+	 * Interrupt Descriptor Table registers
+	 */
 	lgdtl bootstrap_gdtr
+	lidtl bootstrap_idtr
 	
 	/* Kernel data + stack */
Index: kernel/arch/amd64/src/boot/vesa_ret.inc
===================================================================
--- kernel/arch/amd64/src/boot/vesa_ret.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/amd64/src/boot/vesa_ret.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -1,4 +1,5 @@
 .code32
 vesa_init_protected:
+	cli
 	cld
 	
Index: kernel/arch/amd64/src/mm/page.c
===================================================================
--- kernel/arch/amd64/src/mm/page.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/amd64/src/mm/page.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -57,5 +57,5 @@
 	uintptr_t cur;
 	unsigned int identity_flags =
-	    PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL | PAGE_WRITE;
+	    PAGE_GLOBAL | PAGE_CACHEABLE | PAGE_EXEC | PAGE_WRITE | PAGE_READ;
 		
 	page_mapping_operations = &pt_mapping_operations;
Index: kernel/arch/arm32/Makefile.inc
===================================================================
--- kernel/arch/arm32/Makefile.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/arm32/Makefile.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,5 +33,5 @@
 ATSIGN = %
 
-GCC_CFLAGS += -march=armv4
+GCC_CFLAGS += -march=armv4 -fno-omit-frame-pointer -mapcs-frame
 
 BITS = 32
Index: kernel/arch/arm32/include/istate.h
===================================================================
--- kernel/arch/arm32/include/istate.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/arm32/include/istate.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -49,4 +49,5 @@
 /** Struct representing CPU state saved when an exception occurs. */
 typedef struct istate {
+	uint32_t dummy;
 	uint32_t spsr;
 	uint32_t sp;
Index: kernel/arch/arm32/include/mm/page.h
===================================================================
--- kernel/arch/arm32/include/mm/page.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/arm32/include/mm/page.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,4 +40,5 @@
 #include <mm/mm.h>
 #include <arch/exception.h>
+#include <arch/barrier.h>
 #include <trace.h>
 
@@ -109,4 +110,12 @@
 #define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
 	set_pt_level1_flags((pte_t *) (ptl3), (size_t) (i), (x))
+
+/* Set PTE present bit accessors for each level. */
+#define SET_PTL1_PRESENT_ARCH(ptl0, i) \
+	set_pt_level0_present((pte_t *) (ptl0), (size_t) (i))
+#define SET_PTL2_PRESENT_ARCH(ptl1, i)
+#define SET_PTL3_PRESENT_ARCH(ptl2, i)
+#define SET_FRAME_PRESENT_ARCH(ptl3, i) \
+	set_pt_level1_present((pte_t *) (ptl3), (size_t) (i))
 
 /* Macros for querying the last-level PTE entries. */
@@ -267,4 +276,12 @@
 }
 
+NO_TRACE static inline void set_pt_level0_present(pte_t *pt, size_t i)
+{
+	pte_level0_t *p = &pt[i].l0;
+
+	p->should_be_zero = 0;
+	write_barrier();
+	p->descriptor_type = PTE_DESCRIPTOR_COARSE_TABLE;
+}
 
 /** Sets flags of level 1 page table entry.
@@ -283,11 +300,8 @@
 	pte_level1_t *p = &pt[i].l1;
 	
-	if (flags & PAGE_NOT_PRESENT) {
+	if (flags & PAGE_NOT_PRESENT)
 		p->descriptor_type = PTE_DESCRIPTOR_NOT_PRESENT;
-		p->access_permission_3 = 1;
-	} else {
+	else
 		p->descriptor_type = PTE_DESCRIPTOR_SMALL_PAGE;
-		p->access_permission_3 = p->access_permission_0;
-	}
 	
 	p->cacheable = p->bufferable = (flags & PAGE_CACHEABLE) != 0;
@@ -312,8 +326,13 @@
 }
 
-
+NO_TRACE static inline void set_pt_level1_present(pte_t *pt, size_t i)
+{
+	pte_level1_t *p = &pt[i].l1;
+
+	p->descriptor_type = PTE_DESCRIPTOR_SMALL_PAGE;
+}
+	
 extern void page_arch_init(void);
 
-
 #endif /* __ASM__ */
 
Index: kernel/arch/arm32/src/exc_handler.S
===================================================================
--- kernel/arch/arm32/src/exc_handler.S	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/arm32/src/exc_handler.S	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -130,7 +130,9 @@
 	stmfd r13!, {r2}
 2:
+	sub sp, sp, #4
 .endm
 
 .macro LOAD_REGS_FROM_STACK
+	add sp, sp, #4
 	ldmfd r13!, {r0}
 	msr spsr, r0
Index: kernel/arch/arm32/src/exception.c
===================================================================
--- kernel/arch/arm32/src/exception.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/arm32/src/exception.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -123,5 +123,5 @@
 	
 	asm volatile (
-		"mrc p15, 0, %[control_reg], c1, c1"
+		"mrc p15, 0, %[control_reg], c1, c0"
 		: [control_reg] "=r" (control_reg)
 	);
@@ -131,5 +131,5 @@
 	
 	asm volatile (
-		"mcr p15, 0, %[control_reg], c1, c1"
+		"mcr p15, 0, %[control_reg], c1, c0"
 		:: [control_reg] "r" (control_reg)
 	);
Index: kernel/arch/arm32/src/mach/integratorcp/integratorcp.c
===================================================================
--- kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,5 +38,7 @@
 #include <console/chardev.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>
@@ -53,7 +55,15 @@
 #include <print.h>
 
+
 #define SDRAM_SIZE	(sdram[((*(uint32_t *)(ICP_CMCR+ICP_SDRAMCR_OFFSET) & ICP_SDRAM_MASK) >> 2)])
-static icp_hw_map_t icp_hw_map;
-static irq_t icp_timer_irq;
+
+static struct {
+	icp_hw_map_t hw_map;
+	irq_t timer_irq;
+	arm926_uart_t uart;
+} icp;
+
+
+
 struct arm_machine_ops icp_machine_ops = {
 	icp_init,
@@ -70,5 +80,4 @@
 
 static bool hw_map_init_called = false;
-static bool vga_init = false;
 uint32_t sdram[8] = {
 	16777216,	/* 16mb */
@@ -89,12 +98,12 @@
 void icp_vga_init(void)
 {
-	*(uint32_t*)((char *)(icp_hw_map.cmcr)+0x14) = 0xA05F0000;
-	*(uint32_t*)((char *)(icp_hw_map.cmcr)+0x1C) = 0x12C11000;
-	*(uint32_t*)icp_hw_map.vga = 0x3F1F3F9C;
-	*(uint32_t*)((char *)(icp_hw_map.vga) + 0x4) = 0x080B61DF;
-	*(uint32_t*)((char *)(icp_hw_map.vga) + 0x8) = 0x067F3800;
-	*(uint32_t*)((char *)(icp_hw_map.vga) + 0x10) = ICP_FB;
-	*(uint32_t *)((char *)(icp_hw_map.vga) + 0x1C) = 0x182B;
-	*(uint32_t*)((char *)(icp_hw_map.cmcr)+0xC) = 0x33805000;
+	*(uint32_t*)((char *)(icp.hw_map.cmcr)+0x14) = 0xA05F0000;
+	*(uint32_t*)((char *)(icp.hw_map.cmcr)+0x1C) = 0x12C11000;
+	*(uint32_t*)icp.hw_map.vga = 0x3F1F3F9C;
+	*(uint32_t*)((char *)(icp.hw_map.vga) + 0x4) = 0x080B61DF;
+	*(uint32_t*)((char *)(icp.hw_map.vga) + 0x8) = 0x067F3800;
+	*(uint32_t*)((char *)(icp.hw_map.vga) + 0x10) = ICP_FB;
+	*(uint32_t *)((char *)(icp.hw_map.vga) + 0x1C) = 0x182B;
+	*(uint32_t*)((char *)(icp.hw_map.cmcr)+0xC) = 0x33805000;
 	
 }
@@ -103,5 +112,5 @@
 static inline uint32_t icp_irqc_get_sources(void)
 {
-	return *((uint32_t *) icp_hw_map.irqc);
+	return *((uint32_t *) icp.hw_map.irqc);
 }
 
@@ -113,5 +122,5 @@
 static inline void icp_irqc_mask(uint32_t irq)
 {
-	*((uint32_t *) icp_hw_map.irqc_mask) = (1 << irq);
+	*((uint32_t *) icp.hw_map.irqc_mask) = (1 << irq);
 }
 
@@ -123,33 +132,33 @@
 static inline void icp_irqc_unmask(uint32_t irq)
 {
-	*((uint32_t *) icp_hw_map.irqc_unmask) |= (1 << irq);
-}
-
-/** Initializes icp_hw_map. */
+	*((uint32_t *) icp.hw_map.irqc_unmask) |= (1 << irq);
+}
+
+/** Initializes icp.hw_map. */
 void icp_init(void)
 {
-	icp_hw_map.uart = km_map(ICP_UART, PAGE_SIZE,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
-	icp_hw_map.kbd_ctrl = km_map(ICP_KBD, PAGE_SIZE, PAGE_NOT_CACHEABLE);
-	icp_hw_map.kbd_stat = icp_hw_map.kbd_ctrl + ICP_KBD_STAT;
-	icp_hw_map.kbd_data = icp_hw_map.kbd_ctrl + ICP_KBD_DATA;
-	icp_hw_map.kbd_intstat = icp_hw_map.kbd_ctrl + ICP_KBD_INTR_STAT;
-	icp_hw_map.rtc = km_map(ICP_RTC, PAGE_SIZE,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
-	icp_hw_map.rtc1_load = icp_hw_map.rtc + ICP_RTC1_LOAD_OFFSET;
-	icp_hw_map.rtc1_read = icp_hw_map.rtc + ICP_RTC1_READ_OFFSET;
-	icp_hw_map.rtc1_ctl = icp_hw_map.rtc + ICP_RTC1_CTL_OFFSET;
-	icp_hw_map.rtc1_intrclr = icp_hw_map.rtc + ICP_RTC1_INTRCLR_OFFSET;
-	icp_hw_map.rtc1_bgload = icp_hw_map.rtc + ICP_RTC1_BGLOAD_OFFSET;
-	icp_hw_map.rtc1_intrstat = icp_hw_map.rtc + ICP_RTC1_INTRSTAT_OFFSET;
-
-	icp_hw_map.irqc = km_map(ICP_IRQC, PAGE_SIZE,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
-	icp_hw_map.irqc_mask = icp_hw_map.irqc + ICP_IRQC_MASK_OFFSET;
-	icp_hw_map.irqc_unmask = icp_hw_map.irqc + ICP_IRQC_UNMASK_OFFSET;
-	icp_hw_map.cmcr = km_map(ICP_CMCR, PAGE_SIZE,
-	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
-	icp_hw_map.sdramcr = icp_hw_map.cmcr + ICP_SDRAMCR_OFFSET;
-	icp_hw_map.vga = km_map(ICP_VGA, PAGE_SIZE,
+	icp.hw_map.uart = km_map(ICP_UART, PAGE_SIZE,
+	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	icp.hw_map.kbd_ctrl = km_map(ICP_KBD, PAGE_SIZE, PAGE_NOT_CACHEABLE);
+	icp.hw_map.kbd_stat = icp.hw_map.kbd_ctrl + ICP_KBD_STAT;
+	icp.hw_map.kbd_data = icp.hw_map.kbd_ctrl + ICP_KBD_DATA;
+	icp.hw_map.kbd_intstat = icp.hw_map.kbd_ctrl + ICP_KBD_INTR_STAT;
+	icp.hw_map.rtc = km_map(ICP_RTC, PAGE_SIZE,
+	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	icp.hw_map.rtc1_load = icp.hw_map.rtc + ICP_RTC1_LOAD_OFFSET;
+	icp.hw_map.rtc1_read = icp.hw_map.rtc + ICP_RTC1_READ_OFFSET;
+	icp.hw_map.rtc1_ctl = icp.hw_map.rtc + ICP_RTC1_CTL_OFFSET;
+	icp.hw_map.rtc1_intrclr = icp.hw_map.rtc + ICP_RTC1_INTRCLR_OFFSET;
+	icp.hw_map.rtc1_bgload = icp.hw_map.rtc + ICP_RTC1_BGLOAD_OFFSET;
+	icp.hw_map.rtc1_intrstat = icp.hw_map.rtc + ICP_RTC1_INTRSTAT_OFFSET;
+
+	icp.hw_map.irqc = km_map(ICP_IRQC, PAGE_SIZE,
+	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	icp.hw_map.irqc_mask = icp.hw_map.irqc + ICP_IRQC_MASK_OFFSET;
+	icp.hw_map.irqc_unmask = icp.hw_map.irqc + ICP_IRQC_UNMASK_OFFSET;
+	icp.hw_map.cmcr = km_map(ICP_CMCR, PAGE_SIZE,
+	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
+	icp.hw_map.sdramcr = icp.hw_map.cmcr + ICP_SDRAMCR_OFFSET;
+	icp.hw_map.vga = km_map(ICP_VGA, PAGE_SIZE,
 	    PAGE_WRITE | PAGE_NOT_CACHEABLE);
 
@@ -164,7 +173,7 @@
 {
 	icp_irqc_mask(ICP_TIMER_IRQ);
-	*((uint32_t*) icp_hw_map.rtc1_load) = frequency;
-	*((uint32_t*) icp_hw_map.rtc1_bgload) = frequency;
-	*((uint32_t*) icp_hw_map.rtc1_ctl) = ICP_RTC_CTL_VALUE;
+	*((uint32_t*) icp.hw_map.rtc1_load) = frequency;
+	*((uint32_t*) icp.hw_map.rtc1_bgload) = frequency;
+	*((uint32_t*) icp.hw_map.rtc1_ctl) = ICP_RTC_CTL_VALUE;
 	icp_irqc_unmask(ICP_TIMER_IRQ);
 }
@@ -172,6 +181,6 @@
 static irq_ownership_t icp_timer_claim(irq_t *irq)
 {
-	if (icp_hw_map.rtc1_intrstat) {
-		*((uint32_t*) icp_hw_map.rtc1_intrclr) = 1;
+	if (icp.hw_map.rtc1_intrstat) {
+		*((uint32_t*) icp.hw_map.rtc1_intrclr) = 1;
 		return IRQ_ACCEPT;
 	} else
@@ -200,11 +209,11 @@
 static void icp_timer_irq_init(void)
 {
-	irq_initialize(&icp_timer_irq);
-	icp_timer_irq.devno = device_assign_devno();
-	icp_timer_irq.inr = ICP_TIMER_IRQ;
-	icp_timer_irq.claim = icp_timer_claim;
-	icp_timer_irq.handler = icp_timer_irq_handler;
-
-	irq_register(&icp_timer_irq);
+	irq_initialize(&icp.timer_irq);
+	icp.timer_irq.devno = device_assign_devno();
+	icp.timer_irq.inr = ICP_TIMER_IRQ;
+	icp.timer_irq.claim = icp_timer_claim;
+	icp.timer_irq.handler = icp_timer_irq_handler;
+
+	irq_register(&icp.timer_irq);
 }
 
@@ -231,5 +240,5 @@
 
 	if (hw_map_init_called) {
-		*size = (sdram[((*(uint32_t *)icp_hw_map.sdramcr &
+		*size = (sdram[((*(uint32_t *)icp.hw_map.sdramcr &
 		    ICP_SDRAM_MASK) >> 2)]);
 	} else {
@@ -286,4 +295,5 @@
 {
 #ifdef CONFIG_FB
+	static bool vga_init = false;
 	if (!vga_init) {
 		icp_vga_init();
@@ -304,4 +314,9 @@
 		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)))
+		stdout_wire(&icp.uart.outdev);
+#endif
 }
 
@@ -310,7 +325,7 @@
 
 	pl050_t *pl050 = malloc(sizeof(pl050_t), FRAME_ATOMIC);
-	pl050->status = (ioport8_t *)icp_hw_map.kbd_stat;
-	pl050->data = (ioport8_t *)icp_hw_map.kbd_data;
-	pl050->ctrl = (ioport8_t *)icp_hw_map.kbd_ctrl;
+	pl050->status = (ioport8_t *)icp.hw_map.kbd_stat;
+	pl050->data = (ioport8_t *)icp.hw_map.kbd_data;
+	pl050->ctrl = (ioport8_t *)icp.hw_map.kbd_ctrl;
 		
 	pl050_instance_t *pl050_instance = pl050_init(pl050, ICP_KBD_IRQ);
@@ -335,4 +350,13 @@
 	    ICP_KBD);
 
+#ifdef CONFIG_ARM926_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);
+        }
+#endif
 }
 
Index: kernel/arch/arm32/src/mm/page_fault.c
===================================================================
--- kernel/arch/arm32/src/mm/page_fault.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/arm32/src/mm/page_fault.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -77,49 +77,4 @@
 }
 
-/** Decides whether the instruction is load/store or not.
- *
- * @param instr Instruction
- *
- * @return true when instruction is load/store, false otherwise
- *
- */
-static inline bool is_load_store_instruction(instruction_t instr)
-{
-	/* load store immediate offset */
-	if (instr.type == 0x2)
-		return true;
-	
-	/* load store register offset */
-	if ((instr.type == 0x3) && (instr.bit4 == 0))
-		return true;
-	
-	/* load store multiple */
-	if (instr.type == 0x4)
-		return true;
-	
-	/* oprocessor load/store */
-	if (instr.type == 0x6)
-		return true;
-	
-	return false;
-}
-
-/** Decides whether the instruction is swap or not.
- *
- * @param instr Instruction
- *
- * @return true when instruction is swap, false otherwise
- */
-static inline bool is_swap_instruction(instruction_t instr)
-{
-	/* swap, swapb instruction */
-	if ((instr.type == 0x0) &&
-	    ((instr.opcode == 0x8) || (instr.opcode == 0xa)) &&
-	    (instr.access == 0x0) && (instr.bits567 == 0x4) && (instr.bit4 == 1))
-		return true;
-	
-	return false;
-}
-
 /** Decides whether read or write into memory is requested.
  *
@@ -128,5 +83,5 @@
  *
  * @return Type of access into memory, PF_ACCESS_EXEC if no memory access is
- * 	   requested.
+ *	   requested.
  */
 static pf_access_t get_memory_access_type(uint32_t instr_addr,
@@ -146,23 +101,38 @@
 	}
 
-	/* load store instructions */
-	if (is_load_store_instruction(instr)) {
-		if (instr.access == 1) {
-			return PF_ACCESS_READ;
-		} else {
-			return PF_ACCESS_WRITE;
+	/* See ARM Architecture reference manual ARMv7-A and ARMV7-R edition
+	 * A5.3 (PDF p. 206) */
+	static const struct {
+		uint32_t mask;
+		uint32_t value;
+		pf_access_t access;
+	} ls_inst[] = {
+		/* Store word/byte */
+		{ 0x0e100000, 0x04000000, PF_ACCESS_WRITE }, /*STR(B) imm*/
+		{ 0x0e100010, 0x06000000, PF_ACCESS_WRITE }, /*STR(B) reg*/
+		/* Load word/byte */
+		{ 0x0e100000, 0x04100000, PF_ACCESS_READ }, /*LDR(B) imm*/
+		{ 0x0e100010, 0x06100000, PF_ACCESS_READ }, /*LDR(B) reg*/
+		/* Store half-word/dual  A5.2.8 */
+		{ 0x0e1000b0, 0x000000b0, PF_ACCESS_WRITE }, /*STRH imm reg*/
+		/* Load half-word/dual A5.2.8 */
+		{ 0x0e0000f0, 0x000000d0, PF_ACCESS_READ }, /*LDRH imm reg*/
+		{ 0x0e1000b0, 0x001000b0, PF_ACCESS_READ }, /*LDRH imm reg*/
+		/* Block data transfer, Store */
+		{ 0x0e100000, 0x08000000, PF_ACCESS_WRITE }, /* STM variants */
+		{ 0x0e100000, 0x08100000, PF_ACCESS_READ },  /* LDM variants */
+		/* Swap */
+		{ 0x0fb00000, 0x01000000, PF_ACCESS_WRITE },
+	};
+	const uint32_t inst = *(uint32_t*)instr_addr;
+	for (unsigned i = 0; i < sizeof(ls_inst) / sizeof(ls_inst[0]); ++i) {
+		if ((inst & ls_inst[i].mask) == ls_inst[i].value) {
+			return ls_inst[i].access;
 		}
-	}
-
-	/* swap, swpb instruction */
-	if (is_swap_instruction(instr)) {
-		return PF_ACCESS_WRITE;
 	}
 
 	panic("page_fault - instruction doesn't access memory "
 	    "(instr_code: %#0" PRIx32 ", badvaddr:%p).",
-	    instr_union.pc, (void *) badvaddr);
-
-	return PF_ACCESS_EXEC;
+	    inst, (void *) badvaddr);
 }
 
Index: kernel/arch/ia32/include/mm/page.h
===================================================================
--- kernel/arch/ia32/include/mm/page.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/ia32/include/mm/page.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -115,4 +115,12 @@
 	set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
 
+/* Set PTE present bit accessors for each level. */
+#define SET_PTL1_PRESENT_ARCH(ptl0, i) \
+	set_pt_present((pte_t *) (ptl0), (size_t) (i))
+#define SET_PTL2_PRESENT_ARCH(ptl1, i)
+#define SET_PTL3_PRESENT_ARCH(ptl2, i)
+#define SET_FRAME_PRESENT_ARCH(ptl3, i) \
+	set_pt_present((pte_t *) (ptl3), (size_t) (i))
+
 /* Macros for querying the last level entries. */
 #define PTE_VALID_ARCH(p) \
@@ -194,4 +202,11 @@
 }
 
+NO_TRACE static inline void set_pt_present(pte_t *pt, size_t i)
+{
+	pte_t *p = &pt[i];
+
+	p->present = 1;
+}
+
 extern void page_arch_init(void);
 extern void page_fault(unsigned int, istate_t *);
Index: kernel/arch/ia32/src/boot/multiboot.S
===================================================================
--- kernel/arch/ia32/src/boot/multiboot.S	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/ia32/src/boot/multiboot.S	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -73,4 +73,5 @@
 
 multiboot_image_start:
+	cli
 	cld
 	
@@ -78,6 +79,10 @@
 	movl $START_STACK, %esp
 	
-	/* Initialize Global Descriptor Table register */
+	/*
+	 * Initialize Global Descriptor Table and
+	 * Interrupt Descriptor Table registers
+	 */
 	lgdtl bootstrap_gdtr
+	lidtl bootstrap_idtr
 	
 	/* Kernel data + stack */
@@ -701,4 +706,9 @@
 page_directory:
 	.space 4096, 0
+
+.global bootstrap_idtr
+bootstrap_idtr:
+	.word 0
+	.long 0
 
 .global bootstrap_gdtr
Index: kernel/arch/ia32/src/boot/multiboot2.S
===================================================================
--- kernel/arch/ia32/src/boot/multiboot2.S	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/ia32/src/boot/multiboot2.S	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -114,4 +114,5 @@
 
 multiboot2_image_start:
+	cli
 	cld
 	
@@ -119,6 +120,10 @@
 	movl $START_STACK, %esp
 	
-	/* Initialize Global Descriptor Table register */
+	/*
+	 * Initialize Global Descriptor Table and
+	 * Interrupt Descriptor Table registers
+	 */
 	lgdtl bootstrap_gdtr
+	lidtl bootstrap_idtr
 	
 	/* Kernel data + stack */
Index: kernel/arch/ia32/src/boot/vesa_prot.inc
===================================================================
--- kernel/arch/ia32/src/boot/vesa_prot.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/ia32/src/boot/vesa_prot.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -88,4 +88,11 @@
 		/* Returned back to protected mode */
 		
+		/*
+		 * Initialize Global Descriptor Table and
+		 * Interrupt Descriptor Table registers
+		 */
+		lgdtl bootstrap_gdtr
+		lidtl bootstrap_idtr
+		
 		movzx %ax, %ecx
 		mov %ecx, KA2PA(bfb_scanline)
Index: kernel/arch/ia32/src/boot/vesa_real.inc
===================================================================
--- kernel/arch/ia32/src/boot/vesa_real.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/ia32/src/boot/vesa_real.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -30,5 +30,10 @@
 .code32
 vesa_init:
+	lidtl vesa_idtr
 	jmp $GDT_SELECTOR(VESA_INIT_DES), $vesa_init_real - vesa_init
+
+vesa_idtr:
+	.word 0x3ff
+	.long 0
 
 .code16
Index: kernel/arch/ia32/src/boot/vesa_ret.inc
===================================================================
--- kernel/arch/ia32/src/boot/vesa_ret.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/ia32/src/boot/vesa_ret.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -1,4 +1,5 @@
 .code32
 vesa_init_protected:
+	cli
 	cld
 	
Index: kernel/arch/ia32/src/mm/page.c
===================================================================
--- kernel/arch/ia32/src/mm/page.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/ia32/src/mm/page.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -71,8 +71,5 @@
 	for (cur = 0; cur < min(config.identity_size, config.physmem_end);
 	    cur += FRAME_SIZE) {
-		flags = PAGE_CACHEABLE | PAGE_WRITE;
-		if ((PA2KA(cur) >= config.base) &&
-		    (PA2KA(cur) < config.base + config.kernel_size))
-			flags |= PAGE_GLOBAL;
+		flags = PAGE_GLOBAL | PAGE_CACHEABLE | PAGE_WRITE | PAGE_READ;
 		page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
 	}
Index: kernel/arch/ia32/src/smp/apic.c
===================================================================
--- kernel/arch/ia32/src/smp/apic.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/ia32/src/smp/apic.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -259,4 +259,24 @@
 }
 
+#define DELIVS_PENDING_SILENT_RETRIES	4	
+
+static void l_apic_wait_for_delivery(void)
+{
+	icr_t icr;
+	unsigned retries = 0;
+
+	do {
+		if (retries++ > DELIVS_PENDING_SILENT_RETRIES) {
+			retries = 0;
+#ifdef CONFIG_DEBUG
+			printf("IPI is pending.\n");
+#endif
+			delay(20);
+		}
+		icr.lo = l_apic[ICRlo];
+	} while (icr.delivs == DELIVS_PENDING);
+	
+}
+
 /** Send all CPUs excluding CPU IPI vector.
  *
@@ -279,11 +299,6 @@
 	
 	l_apic[ICRlo] = icr.lo;
-	
-	icr.lo = l_apic[ICRlo];
-	if (icr.delivs == DELIVS_PENDING) {
-#ifdef CONFIG_DEBUG
-		printf("IPI is pending.\n");
-#endif
-	}
+
+	l_apic_wait_for_delivery();
 	
 	return apic_poll_errors();
@@ -327,11 +342,7 @@
 		return 0;
 	
+	l_apic_wait_for_delivery();
+
 	icr.lo = l_apic[ICRlo];
-	if (icr.delivs == DELIVS_PENDING) {
-#ifdef CONFIG_DEBUG
-		printf("IPI is pending.\n");
-#endif
-	}
-	
 	icr.delmod = DELMOD_INIT;
 	icr.destmod = DESTMOD_PHYS;
Index: kernel/arch/ia64/Makefile.inc
===================================================================
--- kernel/arch/ia64/Makefile.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/ia64/Makefile.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -30,5 +30,15 @@
 BFD_ARCH = ia64-elf64
 
-CMN1 = -mconstant-gp -fno-unwind-tables -mfixed-range=f32-f127
+#
+# FIXME:
+#
+# The -fno-selective-scheduling and -fno-selective-scheduling2 options
+# should be removed as soon as a bug in GCC concerning unchecked
+# speculative loads is fixed.
+#
+# See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53975 for reference.
+#
+
+CMN1 = -mconstant-gp -fno-unwind-tables -mfixed-range=f32-f127 -fno-selective-scheduling -fno-selective-scheduling2
 GCC_CFLAGS += $(CMN1)
 ICC_CFLAGS += $(CMN1)
Index: kernel/arch/ia64/src/drivers/ski.c
===================================================================
--- kernel/arch/ia64/src/drivers/ski.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/ia64/src/drivers/ski.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -150,6 +150,6 @@
 	
 	if (instance) {
-		instance->thread = thread_create(kskipoll, instance, TASK, 0,
-		    "kskipoll", true);
+		instance->thread = thread_create(kskipoll, instance, TASK,
+		    THREAD_FLAG_UNCOUNTED, "kskipoll");
 		
 		if (!instance->thread) {
Index: kernel/arch/mips32/Makefile.inc
===================================================================
--- kernel/arch/mips32/Makefile.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/mips32/Makefile.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -29,5 +29,5 @@
 BFD_ARCH = mips
 BFD = binary
-GCC_CFLAGS += -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=32
+GCC_CFLAGS += -msoft-float -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=32
 
 BITS = 32
@@ -48,5 +48,4 @@
 	BFD_NAME = elf32-tradlittlemips
 	ENDIANESS = LE
-	GCC_CFLAGS += -mhard-float
 endif
 
Index: kernel/arch/mips32/include/mm/page.h
===================================================================
--- kernel/arch/mips32/include/mm/page.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/mips32/include/mm/page.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -128,4 +128,12 @@
 	set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
 
+/* Set PTE present bit accessors for each level. */
+#define SET_PTL1_PRESENT_ARCH(ptl0, i) \
+	set_pt_present((pte_t *) (ptl0), (size_t) (i))
+#define SET_PTL2_PRESENT_ARCH(ptl1, i)
+#define SET_PTL3_PRESENT_ARCH(ptl2, i)
+#define SET_FRAME_PRESENT_ARCH(ptl3, i) \
+	set_pt_present((pte_t *) (ptl3), (size_t) (i))
+
 /* Last-level info macros. */
 #define PTE_VALID_ARCH(pte)			(*((uint32_t *) (pte)) != 0)
@@ -182,4 +190,12 @@
 }
 
+NO_TRACE static inline void set_pt_present(pte_t *pt, size_t i)
+{
+	pte_t *p = &pt[i];
+
+	p->p = 1;
+}
+	
+
 extern void page_arch_init(void);
 
Index: kernel/arch/mips64/Makefile.inc
===================================================================
--- kernel/arch/mips64/Makefile.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/mips64/Makefile.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -29,5 +29,5 @@
 BFD_ARCH = mips:4000
 BFD = binary
-GCC_CFLAGS += -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=64
+GCC_CFLAGS += -msoft-float -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=64
 AFLAGS = -64
 
@@ -40,5 +40,4 @@
 	BFD_NAME = elf64-tradlittlemips
 	ENDIANESS = LE
-	GCC_CFLAGS += -mhard-float
 endif
 
Index: kernel/arch/ppc32/include/mm/page.h
===================================================================
--- kernel/arch/ppc32/include/mm/page.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/ppc32/include/mm/page.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -128,4 +128,14 @@
 #define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
 	set_pt_flags((pte_t *) (ptl3), (size_t) (i), (x))
+
+/* Set PTE present accessors for each level. */
+#define SET_PTL1_PRESENT_ARCH(ptl0, i) \
+	set_pt_present((pte_t *) (ptl0), (size_t) (i))
+
+#define SET_PTL2_PRESENT_ARCH(ptl1, i)
+#define SET_PTL3_PRESENT_ARCH(ptl2, i)
+
+#define SET_FRAME_PRESENT_ARCH(ptl3, i) \
+	set_pt_present((pte_t *) (ptl3), (size_t) (i))
 
 /* Macros for querying the last-level PTEs. */
@@ -175,4 +185,11 @@
 }
 
+NO_TRACE static inline void set_pt_present(pte_t *pt, size_t i)
+{
+	pte_t *entry = &pt[i];
+
+	entry->present = 1;
+}
+
 extern void page_arch_init(void);
 
Index: kernel/arch/sparc64/src/drivers/niagara.c
===================================================================
--- kernel/arch/sparc64/src/drivers/niagara.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/sparc64/src/drivers/niagara.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -184,6 +184,6 @@
 	
 	instance = malloc(sizeof(niagara_instance_t), FRAME_ATOMIC);
-	instance->thread = thread_create(kniagarapoll, NULL, TASK, 0,
-	    "kniagarapoll", true);
+	instance->thread = thread_create(kniagarapoll, NULL, TASK,
+	    THREAD_FLAG_UNCOUNTED, "kniagarapoll");
 	
 	if (!instance->thread) {
Index: kernel/arch/sparc64/src/proc/sun4u/scheduler.c
===================================================================
--- kernel/arch/sparc64/src/proc/sun4u/scheduler.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/sparc64/src/proc/sun4u/scheduler.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -51,5 +51,5 @@
 void before_thread_runs_arch(void)
 {
-	if ((THREAD->flags & THREAD_FLAG_USPACE)) {
+	if (THREAD->uspace) {
 		/*
 		 * Write kernel stack address to %g6 of the alternate and
@@ -74,6 +74,6 @@
 void after_thread_ran_arch(void)
 {
-	if ((THREAD->flags & THREAD_FLAG_USPACE)) {
-		/* sample the state of the userspace window buffer */	
+	if (THREAD->uspace) {
+		/* sample the state of the userspace window buffer */
 		THREAD->arch.uspace_window_buffer = (uint8_t *) read_from_ag_g7();
 	}
Index: kernel/arch/sparc64/src/proc/sun4v/scheduler.c
===================================================================
--- kernel/arch/sparc64/src/proc/sun4v/scheduler.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/sparc64/src/proc/sun4v/scheduler.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -54,5 +54,5 @@
 void before_thread_runs_arch(void)
 {
-	if ((THREAD->flags & THREAD_FLAG_USPACE)) {
+	if (THREAD->uspace) {
 		uint64_t sp = (uintptr_t) THREAD->kstack + STACK_SIZE -
 		    (STACK_BIAS + ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT));
@@ -66,6 +66,6 @@
 void after_thread_ran_arch(void)
 {
-	if ((THREAD->flags & THREAD_FLAG_USPACE)) {
-		/* sample the state of the userspace window buffer */	
+	if (THREAD->uspace) {
+		/* sample the state of the userspace window buffer */
 		THREAD->arch.uspace_window_buffer =
 		    (uint8_t *) asi_u64_read(ASI_SCRATCHPAD, SCRATCHPAD_WBUF);
Index: kernel/arch/sparc64/src/proc/thread.c
===================================================================
--- kernel/arch/sparc64/src/proc/thread.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/sparc64/src/proc/thread.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -61,5 +61,5 @@
 void thread_create_arch(thread_t *t)
 {
-	if ((t->flags & THREAD_FLAG_USPACE) && (!t->arch.uspace_window_buffer))
+	if ((t->uspace) && (!t->arch.uspace_window_buffer))
 		{
 		/*
Index: kernel/arch/sparc64/src/smp/sun4u/ipi.c
===================================================================
--- kernel/arch/sparc64/src/smp/sun4u/ipi.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/arch/sparc64/src/smp/sun4u/ipi.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -124,5 +124,5 @@
 			(void) interrupts_disable();
 		}
-	} while (done);
+	} while (!done);
 	
 	preemption_enable();
Index: kernel/genarch/Makefile.inc
===================================================================
--- kernel/genarch/Makefile.inc	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/genarch/Makefile.inc	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -91,4 +91,9 @@
 endif
 
+ifeq ($(CONFIG_ARM926_UART),y)
+	GENARCH_SOURCES += \
+		genarch/src/drivers/arm926_uart/arm926_uart.c
+endif
+
 ifeq ($(CONFIG_S3C24XX_IRQC),y)
 	GENARCH_SOURCES += \
Index: kernel/genarch/include/drivers/arm926_uart/arm926_uart.h
===================================================================
--- kernel/genarch/include/drivers/arm926_uart/arm926_uart.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/genarch/include/drivers/arm926_uart/arm926_uart.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,169 @@
+/*
+ * 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/mm/page_pt.h
===================================================================
--- kernel/genarch/include/mm/page_pt.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/genarch/include/mm/page_pt.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -115,4 +115,13 @@
 
 /*
+ * These macros are provided to set the present bit within the page tables.
+ *
+ */
+#define SET_PTL1_PRESENT(ptl0, i)   SET_PTL1_PRESENT_ARCH(ptl0, i)
+#define SET_PTL2_PRESENT(ptl1, i)   SET_PTL2_PRESENT_ARCH(ptl1, i)
+#define SET_PTL3_PRESENT(ptl2, i)   SET_PTL3_PRESENT_ARCH(ptl2, i)
+#define SET_FRAME_PRESENT(ptl3, i)  SET_FRAME_PRESENT_ARCH(ptl3, i)
+
+/*
  * Macros for querying the last-level PTEs.
  *
Index: kernel/genarch/include/multiboot/multiboot.h
===================================================================
--- kernel/genarch/include/multiboot/multiboot.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/genarch/include/multiboot/multiboot.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -99,4 +99,5 @@
 
 extern void multiboot_extract_command(char *, size_t, const char *);
+extern void multiboot_extract_argument(char *, size_t, const char *);
 extern void multiboot_info_parse(uint32_t, const multiboot_info_t *);
 
Index: kernel/genarch/src/drivers/arm926_uart/arm926_uart.c
===================================================================
--- kernel/genarch/src/drivers/arm926_uart/arm926_uart.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/genarch/src/drivers/arm926_uart/arm926_uart.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,140 @@
+/*
+ * 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/kbrd/kbrd.c
===================================================================
--- kernel/genarch/src/kbrd/kbrd.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/genarch/src/kbrd/kbrd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -158,6 +158,6 @@
 	    = malloc(sizeof(kbrd_instance_t), FRAME_ATOMIC);
 	if (instance) {
-		instance->thread
-			= thread_create(kkbrd, (void *) instance, TASK, 0, "kkbrd", false);
+		instance->thread = thread_create(kkbrd, (void *) instance,
+		    TASK, THREAD_FLAG_NONE, "kkbrd");
 		
 		if (!instance->thread) {
Index: kernel/genarch/src/mm/as_ht.c
===================================================================
--- kernel/genarch/src/mm/as_ht.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/genarch/src/mm/as_ht.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -78,6 +78,6 @@
 		hash_table_create(&page_ht, PAGE_HT_ENTRIES, 2, &ht_operations);
 		mutex_initialize(&page_ht_lock, MUTEX_PASSIVE);
-		pte_cache = slab_cache_create("pte_cache", sizeof(pte_t), 0, NULL, NULL,
-		    SLAB_CACHE_MAGDEFERRED);
+		pte_cache = slab_cache_create("pte_t", sizeof(pte_t), 0,
+		    NULL, NULL, SLAB_CACHE_MAGDEFERRED);
 	}
 	
Index: kernel/genarch/src/mm/page_ht.c
===================================================================
--- kernel/genarch/src/mm/page_ht.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/genarch/src/mm/page_ht.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -45,4 +45,5 @@
 #include <typedefs.h>
 #include <arch/asm.h>
+#include <arch/barrier.h>
 #include <synch/spinlock.h>
 #include <arch.h>
@@ -207,4 +208,6 @@
 		pte->page = ALIGN_DOWN(page, PAGE_SIZE);
 		pte->frame = ALIGN_DOWN(frame, FRAME_SIZE);
+
+		write_barrier();
 		
 		hash_table_insert(&page_ht, key, &pte->link);
Index: kernel/genarch/src/mm/page_pt.c
===================================================================
--- kernel/genarch/src/mm/page_pt.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/genarch/src/mm/page_pt.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -43,4 +43,5 @@
 #include <arch/mm/page.h>
 #include <arch/mm/as.h>
+#include <arch/barrier.h>
 #include <typedefs.h>
 #include <arch/asm.h>
@@ -86,6 +87,8 @@
 		SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
 		SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page),
-		    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
+		    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
 		    PAGE_WRITE);
+		write_barrier();
+		SET_PTL1_PRESENT(ptl0, PTL0_INDEX(page));
 	}
 	
@@ -98,6 +101,8 @@
 		SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
 		SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page),
-		    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
+		    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
 		    PAGE_WRITE);
+		write_barrier();
+		SET_PTL2_PRESENT(ptl1, PTL1_INDEX(page));	
 	}
 	
@@ -110,6 +115,8 @@
 		SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
 		SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page),
-		    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
+		    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
 		    PAGE_WRITE);
+		write_barrier();
+		SET_PTL3_PRESENT(ptl2, PTL2_INDEX(page));
 	}
 	
@@ -117,5 +124,7 @@
 	
 	SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame);
-	SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags);
+	SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags | PAGE_NOT_PRESENT);
+	write_barrier();
+	SET_FRAME_PRESENT(ptl3, PTL3_INDEX(page));
 }
 
@@ -279,12 +288,22 @@
 	if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
 		return NULL;
+
+	read_barrier();
 	
 	pte_t *ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
 	if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
 		return NULL;
+
+#if (PTL1_ENTRIES != 0)
+	read_barrier();
+#endif
 	
 	pte_t *ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
 	if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
 		return NULL;
+
+#if (PTL2_ENTRIES != 0)
+	read_barrier();
+#endif
 	
 	pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
@@ -346,6 +365,6 @@
 		SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(addr), KA2PA(l1));
 		SET_PTL1_FLAGS(ptl0, PTL0_INDEX(addr),
-		    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
-		    PAGE_WRITE);
+		    PAGE_PRESENT | PAGE_USER | PAGE_CACHEABLE |
+		    PAGE_EXEC | PAGE_WRITE | PAGE_READ);
 	}
 }
Index: kernel/genarch/src/multiboot/multiboot.c
===================================================================
--- kernel/genarch/src/multiboot/multiboot.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/genarch/src/multiboot/multiboot.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -71,4 +71,33 @@
 }
 
+/** Extract arguments from the multiboot module command line.
+ *
+ * @param buf      Destination buffer (will be always NULL-terminated).
+ * @param size     Size of destination buffer (in bytes).
+ * @param cmd_line Input string (the command line).
+ *
+ */
+void multiboot_extract_argument(char *buf, size_t size, const char *cmd_line)
+{
+	/* Start after first space. */
+	const char *start = str_chr(cmd_line, ' ');
+	if (start == NULL) {
+		str_cpy(buf, size, "");
+		return;
+	}
+
+	const char *end = cmd_line + str_size(cmd_line);
+
+	/* Skip the space(s). */
+	while (start != end) {
+		if (start[0] == ' ')
+			start++;
+		else
+			break;
+	}
+
+	str_ncpy(buf, size, start, (size_t) (end - start));
+}
+
 static void multiboot_modules(uint32_t count, multiboot_module_t *mods)
 {
@@ -84,6 +113,10 @@
 			multiboot_extract_command(init.tasks[init.cnt].name,
 			    CONFIG_TASK_NAME_BUFLEN, MULTIBOOT_PTR(mods[i].string));
-		} else
+			multiboot_extract_argument(init.tasks[init.cnt].arguments,
+			    CONFIG_TASK_ARGUMENTS_BUFLEN, MULTIBOOT_PTR(mods[i].string));
+		} else {
 			init.tasks[init.cnt].name[0] = 0;
+			init.tasks[init.cnt].arguments[0] = 0;
+		}
 		
 		init.cnt++;
Index: kernel/genarch/src/multiboot/multiboot2.c
===================================================================
--- kernel/genarch/src/multiboot/multiboot2.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/genarch/src/multiboot/multiboot2.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -49,4 +49,6 @@
 		multiboot_extract_command(init.tasks[init.cnt].name,
 		    CONFIG_TASK_NAME_BUFLEN, module->string);
+		multiboot_extract_argument(init.tasks[init.cnt].arguments,
+		    CONFIG_TASK_ARGUMENTS_BUFLEN, module->string);
 		
 		init.cnt++;
Index: kernel/genarch/src/srln/srln.c
===================================================================
--- kernel/genarch/src/srln/srln.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/genarch/src/srln/srln.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -130,6 +130,6 @@
 	    = malloc(sizeof(srln_instance_t), FRAME_ATOMIC);
 	if (instance) {
-		instance->thread
-			= thread_create(ksrln, (void *) instance, TASK, 0, "ksrln", false);
+		instance->thread = thread_create(ksrln, (void *) instance,
+		    TASK, THREAD_FLAG_NONE, "ksrln");
 		
 		if (!instance->thread) {
Index: kernel/generic/include/config.h
===================================================================
--- kernel/generic/include/config.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/config.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,4 +47,11 @@
 #define CONFIG_INIT_TASKS        32
 #define CONFIG_TASK_NAME_BUFLEN  32
+#define CONFIG_TASK_ARGUMENTS_BUFLEN 64
+
+/**
+ * Maximum buffer size allowed for IPC_M_DATA_WRITE and IPC_M_DATA_READ
+ * requests.
+ */
+#define DATA_XFER_LIMIT  (64 * 1024)
 
 #ifndef __ASM__
@@ -56,4 +63,5 @@
 	size_t size;
 	char name[CONFIG_TASK_NAME_BUFLEN];
+	char arguments[CONFIG_TASK_ARGUMENTS_BUFLEN];
 } init_task_t;
 
Index: kernel/generic/include/console/prompt.h
===================================================================
--- kernel/generic/include/console/prompt.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/include/console/prompt.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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 genericconsole
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_CONSOLE_PROMPT_H_
+#define KERN_CONSOLE_PROMPT_H_
+
+#include <console/chardev.h>
+
+#define MAX_TAB_HINTS 37
+
+extern bool console_prompt_display_all_hints(indev_t *, size_t);
+extern bool console_prompt_more_hints(indev_t *, size_t *);
+
+#endif
+
+/** @}
+ */
Index: kernel/generic/include/debug.h
===================================================================
--- kernel/generic/include/debug.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/debug.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,5 +37,5 @@
 
 #include <panic.h>
-#include <symtab.h>
+#include <symtab_lookup.h>
 
 #define CALLER  ((uintptr_t) __builtin_return_address(0))
Index: kernel/generic/include/interrupt.h
===================================================================
--- kernel/generic/include/interrupt.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/interrupt.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,4 +38,5 @@
 #include <arch/interrupt.h>
 #include <print.h>
+#include <stdarg.h>
 #include <typedefs.h>
 #include <proc/task.h>
@@ -58,4 +59,6 @@
 extern exc_table_t exc_table[];
 
+extern void fault_from_uspace(istate_t *, const char *, ...)
+    PRINTF_ATTRIBUTE(2, 3);
 extern void fault_if_from_uspace(istate_t *, const char *, ...)
     PRINTF_ATTRIBUTE(2, 3);
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/ipc/ipc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -65,4 +65,5 @@
 	mutex_t lock;
 	link_t link;
+	struct task *caller;
 	struct answerbox *callee;
 	ipc_phone_state_t state;
@@ -72,11 +73,11 @@
 typedef struct answerbox {
 	IRQ_SPINLOCK_DECLARE(lock);
+
+	/** Answerbox is active until it enters cleanup. */
+	bool active;
 	
 	struct task *task;
 	
 	waitq_t wq;
-	
-	/** Linkage for the list of task's synchronous answerboxes. */
-	link_t sync_box_link;
 	
 	/** Phones connected to this answerbox. */
@@ -109,16 +110,43 @@
 
 typedef struct {
-	link_t link;
+	/**
+	 * Task link.
+	 * Valid only when the call is not forgotten.
+	 * Protected by the task's active_calls_lock.
+	 */
+	link_t ta_link;
+
+	atomic_t refcnt;
+
+	/** Answerbox link. */
+	link_t ab_link;
 	
 	unsigned int flags;
+
+	/** Protects the forget member. */
+	SPINLOCK_DECLARE(forget_lock);
+
+	/**
+	 * True if the caller 'forgot' this call and donated it to the callee.
+	 * Forgotten calls are discarded upon answering (the answer is not
+	 * delivered) and answered calls cannot be forgotten. Forgotten calls
+	 * also do not figure on the task's active call list.
+	 *
+	 * We keep this separate from the flags so that it is not necessary
+	 * to take a lock when accessing them.
+	 */
+	bool forget;
+
+	/** True if the call is in the active list. */
+	bool active;
 	
-	/** Identification of the caller. */
+	/**
+	 * Identification of the caller.
+	 * Valid only when the call is not forgotten.
+	 */
 	struct task *sender;
 	
-	/*
-	 * The caller box is different from sender->answerbox
-	 * for synchronous calls.
-	 */
-	answerbox_t *callerbox;
+	/** Phone which was used to send the call. */
+	phone_t *caller_phone;
 	
 	/** Private data to internal IPC. */
@@ -127,14 +155,10 @@
 	/** Data passed from/to userspace. */
 	ipc_data_t data;
-	
+
+	/** Method as it was sent in the request. */
+	sysarg_t request_method;
+
 	/** Buffer for IPC_M_DATA_WRITE and IPC_M_DATA_READ. */
 	uint8_t *buffer;
-	
-	/*
-	 * The forward operation can masquerade the caller phone. For those
-	 * cases, we must keep it aside so that the answer is processed
-	 * correctly.
-	 */
-	phone_t *caller_phone;
 } call_t;
 
@@ -145,13 +169,15 @@
 extern call_t *ipc_call_alloc(unsigned int);
 extern void ipc_call_free(call_t *);
+extern void ipc_call_hold(call_t *);
+extern void ipc_call_release(call_t *);
 
 extern int ipc_call(phone_t *, call_t *);
-extern int ipc_call_sync(phone_t *, call_t *);
 extern call_t *ipc_wait_for_call(answerbox_t *, uint32_t, unsigned int);
 extern int ipc_forward(call_t *, phone_t *, answerbox_t *, unsigned int);
 extern void ipc_answer(answerbox_t *, call_t *);
+extern void _ipc_answer_free_call(call_t *, bool);
 
-extern void ipc_phone_init(phone_t *);
-extern void ipc_phone_connect(phone_t *, answerbox_t *);
+extern void ipc_phone_init(phone_t *, struct task *);
+extern bool ipc_phone_connect(phone_t *, answerbox_t *);
 extern int ipc_phone_hangup(phone_t *);
 
@@ -161,5 +187,5 @@
 extern void ipc_backsend_err(phone_t *, call_t *, sysarg_t);
 extern void ipc_answerbox_slam_phones(answerbox_t *, bool);
-extern void ipc_cleanup_call_list(list_t *);
+extern void ipc_cleanup_call_list(answerbox_t *, list_t *);
 
 extern void ipc_print_task(task_id_t);
Index: kernel/generic/include/ipc/ipcrsc.h
===================================================================
--- kernel/generic/include/ipc/ipcrsc.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/ipc/ipcrsc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,6 +40,7 @@
 
 extern call_t *get_call(sysarg_t);
+extern int phone_get(sysarg_t, phone_t **);
 extern int phone_alloc(task_t *);
-extern void phone_connect(int, answerbox_t *);
+extern bool phone_connect(int, answerbox_t *);
 extern void phone_dealloc(int);
 
Index: kernel/generic/include/ipc/irq.h
===================================================================
--- kernel/generic/include/ipc/irq.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/ipc/irq.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,8 +37,8 @@
 
 /** Maximum number of IPC IRQ programmed I/O ranges. */
-#define IRQ_MAX_RANGE_COUNT	8
+#define IRQ_MAX_RANGE_COUNT  8
 
 /** Maximum length of IPC IRQ program. */
-#define IRQ_MAX_PROG_SIZE  20
+#define IRQ_MAX_PROG_SIZE  256
 
 #include <ipc/ipc.h>
Index: kernel/generic/include/ipc/sysipc.h
===================================================================
--- kernel/generic/include/ipc/sysipc.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/ipc/sysipc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,7 +40,4 @@
 #include <typedefs.h>
 
-extern sysarg_t sys_ipc_call_sync_fast(sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t, ipc_data_t *);
-extern sysarg_t sys_ipc_call_sync_slow(sysarg_t, ipc_data_t *, ipc_data_t *);
 extern sysarg_t sys_ipc_call_async_fast(sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t, sysarg_t);
Index: kernel/generic/include/ipc/sysipc_ops.h
===================================================================
--- kernel/generic/include/ipc/sysipc_ops.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/include/ipc/sysipc_ops.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,165 @@
+/*
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_SYSIPC_OPS_H_
+#define KERN_SYSIPC_OPS_H_
+
+#include <ipc/ipc.h>
+
+#define SYSIPC_OP(op, call, ...) \
+	({ \
+		int rc = EOK; \
+		\
+		sysipc_ops_t *ops; \
+		ops = sysipc_ops_get((call)->request_method); \
+		if (ops->op) \
+			rc = ops->op((call), ##__VA_ARGS__); \
+		rc; \
+	})
+
+/**
+ * This header declares the per-method IPC callbacks. Using these callbacks,
+ * each IPC method (but system methods in particular), can define actions that
+ * will be called at specific moments in the call life-cycle.
+ *
+ * Normally, the kernel will attempt to invoke the following callbacks in the
+ * following order on each call:
+ *
+ * request_preprocess()
+ * request_process()
+ * answer_preprocess()
+ * answer_process()
+ *
+ * This callback invocation sequence is a natural order of processing. Note,
+ * however, that due to various special circumstances, callbacks may be called
+ * also in a different than natural order of processing. This means that some
+ * callbacks may be skipped and some others may be called instead.
+ *
+ * The additional callbacks that may be called are as follows:
+ *
+ * request_forget()
+ * answer_cleanup()
+ *
+ * There are several notable scenarios in which some callbacks of the natural
+ * order of processing will be skipped.
+ *
+ * The request_process(), answer_preprocess() and answer_process() callbacks
+ * will be skipped if the call cannot be delivered to the callee. This may
+ * happen when e.g. the request_preprocess() callback fails or the connection
+ * to the callee is not functional. The next callback that will be invoked on
+ * the call is request_forget().
+ *
+ * The comments for each callback type describe the specifics of each callback
+ * such as the context in which it is invoked and various constraints.
+ */
+
+typedef struct {
+	/**
+	 * This callback is called from request_preprocess().
+	 * 
+	 * Context:		caller
+	 * Caller alive:	guaranteed
+	 * Races with:		N/A
+	 * Invoked on:		all calls
+	 */
+	int (* request_preprocess)(call_t *, phone_t *);
+
+	/**
+	 * This callback is called when the IPC cleanup code wins the race to
+	 * forget the call.
+	 *
+	 * Context:		caller
+	 * Caller alive:	guaranteed
+	 * Races with:		request_process(), answer_cleanup(),
+	 *			_ipc_answer_free_call()
+	 * Invoked on:		all forgotten calls
+	 */	
+	int (* request_forget)(call_t *);
+
+	/**
+	 * This callback is called from process_request().
+	 *
+	 * Context:		callee
+	 * Caller alive:	no guarantee
+	 * Races with:		request_forget()
+	 * Invoked on:		all calls delivered to the callee
+	 */	
+	int (* request_process)(call_t *, answerbox_t *);
+
+	/**
+	 * This callback is called when answer_preprocess() loses the race to
+	 * answer the call.
+	 *
+	 * Context:		callee
+	 * Caller alive:	no guarantee
+	 * Races with:		request_forget()
+	 * Invoked on:		all forgotten calls
+	 */
+	int (* answer_cleanup)(call_t *, ipc_data_t *);
+
+	/**
+	 * This callback is called when answer_preprocess() wins the race to
+	 * answer the call.
+	 *
+	 * Context:		callee
+	 * Caller alive:	guaranteed
+	 * Races with:		N/A
+	 * Invoked on:		all answered calls
+	 */
+	int (* answer_preprocess)(call_t *, ipc_data_t *);
+
+	/**
+	 * This callback is called from process_answer().
+	 *
+	 * Context:		caller
+	 * Caller alive:	guaranteed
+	 * Races with:		N/A
+	 * Invoked on:		all answered calls
+	 */
+	int (* answer_process)(call_t *);
+} sysipc_ops_t;
+
+extern sysipc_ops_t *sysipc_ops_get(sysarg_t);
+
+extern int null_request_preprocess(call_t *, phone_t *);
+extern int null_request_forget(call_t *);
+extern int null_request_process(call_t *, answerbox_t *);
+extern int null_answer_cleanup(call_t *, ipc_data_t *);
+extern int null_answer_preprocess(call_t *, ipc_data_t *);
+extern int null_answer_process(call_t *);
+
+#endif
+
+/** @}
+ */
Index: kernel/generic/include/ipc/sysipc_priv.h
===================================================================
--- kernel/generic/include/ipc/sysipc_priv.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/include/ipc/sysipc_priv.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,45 @@
+/*
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_SYSIPC_PRIV_H_
+#define KERN_SYSIPC_PRIV_H_
+
+#include <ipc/ipc.h>
+
+extern int answer_preprocess(call_t *, ipc_data_t *);
+
+#endif
+
+/** @}
+ */
Index: kernel/generic/include/lib/elf_load.h
===================================================================
--- kernel/generic/include/lib/elf_load.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/lib/elf_load.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,16 +42,15 @@
  * ELF error return codes
  */
-#define EE_OK			0	/* No error */
-#define EE_INVALID		1	/* Invalid ELF image */
-#define	EE_MEMORY		2	/* Cannot allocate address space */
-#define EE_INCOMPATIBLE		3	/* ELF image is not compatible with current architecture */
-#define EE_UNSUPPORTED		4	/* Non-supported ELF (e.g. dynamic ELFs) */
-#define EE_LOADER		5	/* The image is actually a program loader. */
-#define EE_IRRECOVERABLE	6
+#define EE_OK             0  /* No error */
+#define EE_INVALID        1  /* Invalid ELF image */
+#define EE_MEMORY         2  /* Cannot allocate address space */
+#define EE_INCOMPATIBLE   3  /* ELF image is not compatible with current architecture */
+#define EE_UNSUPPORTED    4  /* Non-supported ELF (e.g. dynamic ELFs) */
+#define EE_LOADER         5  /* The image is actually a program loader. */
+#define EE_IRRECOVERABLE  6  /* Irrecoverable error. */
 
 /**
  * This flags is passed when running the loader, otherwise elf_load()
  * would return with a EE_LOADER error code.
- *
  */
 #define ELD_F_NONE    0
Index: kernel/generic/include/macros.h
===================================================================
--- kernel/generic/include/macros.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/macros.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -52,8 +52,19 @@
     uint64_t sz2)
 {
-	uint64_t e1 = s1 + sz1;
-	uint64_t e2 = s2 + sz2;
-	
-	return ((s1 < e2) && (s2 < e1));
+	uint64_t e1 = s1 + sz1 - 1;
+	uint64_t e2 = s2 + sz2 - 1;
+
+	/* both sizes are non-zero */
+	if (sz1 && sz2)
+		return ((s1 <= e2) && (s2 <= e1));
+
+	/* one size is non-zero */
+	if (sz2)
+		return ((s1 >= s2) && (s1 <= e2));
+	if (sz1)
+		return ((s2 >= s1) && (s2 <= e1));
+
+	/* both are zero */
+	return (s1 == s2);
 }
 
@@ -119,4 +130,12 @@
 	    | ((((uint64_t) (up)) & UINT32_C(0xffffffff)) << 32))
 
+/* Test for sum overflow. */
+#define overflows(a, b) \
+	((a) + (b) < (a))
+
+/* Test for sum overflow into positive numbers. */
+#define overflows_into_positive(a, b)	\
+	(overflows((a), (b)) && ((a) + (b) > 0))
+
 /** Pseudorandom generator
  *
Index: kernel/generic/include/print.h
===================================================================
--- kernel/generic/include/print.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/print.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,15 +38,5 @@
 #include <typedefs.h>
 #include <stdarg.h>
-
-#ifndef NVERIFY_PRINTF
-
-#define PRINTF_ATTRIBUTE(start, end) \
-	__attribute__((format(gnu_printf, start, end)))
-
-#else /* NVERIFY_PRINTF */
-
-#define PRINTF_ATTRIBUTE(start, end)
-
-#endif /* NVERIFY_PRINTF */
+#include <printf/verify.h>
 
 #define EOF  (-1)
Index: kernel/generic/include/printf/verify.h
===================================================================
--- kernel/generic/include/printf/verify.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/include/printf/verify.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012 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 generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_PRINTF_VERIFY_H_
+#define KERN_PRINTF_VERIFY_H_
+
+#ifndef NVERIFY_PRINTF
+
+#define PRINTF_ATTRIBUTE(start, end) \
+	__attribute__((format(gnu_printf, start, end)))
+
+#else /* NVERIFY_PRINTF */
+
+#define PRINTF_ATTRIBUTE(start, end)
+
+#endif /* NVERIFY_PRINTF */
+
+#endif
+
+/** @}
+ */
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/proc/task.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -91,9 +91,24 @@
 	
 	/* IPC stuff */
-	answerbox_t answerbox;  /**< Communication endpoint */
+
+	/** Receiving communication endpoint */
+	answerbox_t answerbox;
+
+	/** Sending communication endpoints */
 	phone_t phones[IPC_MAX_PHONES];
-	stats_ipc_t ipc_info;   /**< IPC statistics */
-	list_t sync_boxes;      /**< List of synchronous answerboxes. */
+
+	/** Spinlock protecting the active_calls list. */
+	SPINLOCK_DECLARE(active_calls_lock);
+
+	/**
+	 * List of all calls sent by this task that have not yet been
+	 * answered.
+	 */
+	list_t active_calls;
+
 	event_t events[EVENT_TASK_END - EVENT_END];
+
+	/** IPC statistics */
+	stats_ipc_t ipc_info;
 	
 #ifdef CONFIG_UDEBUG
Index: kernel/generic/include/proc/thread.h
===================================================================
--- kernel/generic/include/proc/thread.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/proc/thread.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -54,21 +54,13 @@
 
 /* Thread flags */
-
-/** Thread cannot be migrated to another CPU.
- *
- * When using this flag, the caller must set cpu in the thread_t
- * structure manually before calling thread_ready (even on uniprocessor).
- *
- */
-#define THREAD_FLAG_WIRED  (1 << 0)
-
-/** Thread was migrated to another CPU and has not run yet. */
-#define THREAD_FLAG_STOLEN  (1 << 1)
-
-/** Thread executes in userspace. */
-#define THREAD_FLAG_USPACE  (1 << 2)
-
-/** Thread will be attached by the caller. */
-#define THREAD_FLAG_NOATTACH  (1 << 3)
+typedef enum {
+	THREAD_FLAG_NONE = 0,
+	/** Thread executes in user space. */
+	THREAD_FLAG_USPACE = (1 << 0),
+	/** Thread will be attached by the caller. */
+	THREAD_FLAG_NOATTACH = (1 << 1),
+	/** Thread accounting doesn't affect accumulated task accounting. */
+	THREAD_FLAG_UNCOUNTED = (1 << 2)
+} thread_flags_t;
 
 /** Thread structure. There is one per thread. */
@@ -147,5 +139,5 @@
 	
 	fpu_context_t *saved_fpu_context;
-	int fpu_context_exists;
+	bool fpu_context_exists;
 	
 	/*
@@ -154,18 +146,22 @@
 	 * thread. This disables migration.
 	 */
-	int fpu_context_engaged;
+	bool fpu_context_engaged;
 	
 	/* The thread will not be migrated if nomigrate is non-zero. */
-	int nomigrate;
-	
-	/** Thread's state. */
+	unsigned int nomigrate;
+	
+	/** Thread state. */
 	state_t state;
-	/** Thread's flags. */
-	unsigned int flags;
-	
-	/** Thread's CPU. */
+	
+	/** Thread CPU. */
 	cpu_t *cpu;
 	/** Containing task. */
 	task_t *task;
+	/** Thread is wired to CPU. */
+	bool wired;
+	/** Thread was migrated to another CPU and has not run yet. */
+	bool stolen;
+	/** Thread is executed in user space. */
+	bool uspace;
 	
 	/** Ticks before preemption. */
@@ -216,5 +212,6 @@
 extern void thread_init(void);
 extern thread_t *thread_create(void (*)(void *), void *, task_t *,
-    unsigned int, const char *, bool);
+    thread_flags_t, const char *);
+extern void thread_wire(thread_t *, cpu_t *);
 extern void thread_attach(thread_t *, task_t *);
 extern void thread_ready(thread_t *);
Index: kernel/generic/include/symtab.h
===================================================================
--- kernel/generic/include/symtab.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/include/symtab.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,27 +36,9 @@
 #define KERN_SYMTAB_H_
 
-#include <typedefs.h>
+#include <symtab_lookup.h>
+#include <console/chardev.h>
 
-#define MAX_SYMBOL_NAME  64
-
-struct symtab_entry {
-	uint64_t address_le;
-	char symbol_name[MAX_SYMBOL_NAME];
-};
-
-extern int symtab_name_lookup(uintptr_t, const char **, uintptr_t *);
-extern const char *symtab_fmt_name_lookup(uintptr_t);
-extern int symtab_addr_lookup(const char *, uintptr_t *);
 extern void symtab_print_search(const char *);
-extern int symtab_compl(char *, size_t);
-
-#ifdef CONFIG_SYMTAB
-
-/** Symtable linked together by build process
- *
- */
-extern struct symtab_entry symbol_table[];
-
-#endif /* CONFIG_SYMTAB */
+extern int symtab_compl(char *, size_t, indev_t *);
 
 #endif
Index: kernel/generic/include/symtab_lookup.h
===================================================================
--- kernel/generic/include/symtab_lookup.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/include/symtab_lookup.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005 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 generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_SYMTAB_LOOKUP_H_
+#define KERN_SYMTAB_LOOKUP_H_
+
+#include <typedefs.h>
+
+#define MAX_SYMBOL_NAME  64
+
+struct symtab_entry {
+	uint64_t address_le;
+	char symbol_name[MAX_SYMBOL_NAME];
+};
+
+extern int symtab_name_lookup(uintptr_t, const char **, uintptr_t *);
+extern const char *symtab_fmt_name_lookup(uintptr_t);
+extern int symtab_addr_lookup(const char *, uintptr_t *);
+
+#ifdef CONFIG_SYMTAB
+
+/** Symtable linked together by build process
+ *
+ */
+extern struct symtab_entry symbol_table[];
+
+#endif /* CONFIG_SYMTAB */
+
+#endif
+
+/** @}
+ */
Index: kernel/generic/src/adt/btree.c
===================================================================
--- kernel/generic/src/adt/btree.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/adt/btree.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -71,5 +71,5 @@
 void btree_init(void)
 {
-	btree_node_slab = slab_cache_create("btree_node_slab",
+	btree_node_slab = slab_cache_create("btree_node_t",
 	    sizeof(btree_node_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED);
 }
Index: kernel/generic/src/console/cmd.c
===================================================================
--- kernel/generic/src/console/cmd.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/console/cmd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -724,11 +724,7 @@
 		thread_t *thread;
 		if ((thread = thread_create((void (*)(void *)) cmd_call0,
-		    (void *) argv, TASK, THREAD_FLAG_WIRED, "call0", false))) {
-			irq_spinlock_lock(&thread->lock, true);
-			thread->cpu = &cpus[i];
-			irq_spinlock_unlock(&thread->lock, true);
-			
+		    (void *) argv, TASK, THREAD_FLAG_NONE, "call0"))) {
 			printf("cpu%u: ", i);
-			
+			thread_wire(thread, &cpus[i]);
 			thread_ready(thread);
 			thread_join(thread);
Index: kernel/generic/src/console/kconsole.c
===================================================================
--- kernel/generic/src/console/kconsole.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/console/kconsole.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -43,4 +43,5 @@
 #include <console/chardev.h>
 #include <console/cmd.h>
+#include <console/prompt.h>
 #include <print.h>
 #include <panic.h>
@@ -201,12 +202,23 @@
  *
  */
-NO_TRACE static int cmdtab_compl(char *input, size_t size)
+NO_TRACE static int cmdtab_compl(char *input, size_t size, indev_t *indev)
 {
 	const char *name = input;
 	
 	size_t found = 0;
+	
+	/*
+	 * Maximum Match Length: Length of longest matching common
+	 * substring in case more than one match is found.
+	 */
+	size_t max_match_len = size;
+	size_t max_match_len_tmp = size;
+	size_t input_len = str_length(input);
 	link_t *pos = NULL;
 	const char *hint;
 	char *output = malloc(MAX_CMDLINE, 0);
+	size_t hints_to_show = MAX_TAB_HINTS - 1;
+	size_t total_hints_shown = 0;
+	bool continue_showing_hints = true;
 	
 	output[0] = 0;
@@ -218,4 +230,14 @@
 		pos = pos->next;
 		found++;
+	}
+	
+	/*
+	 * If the number of possible completions is more than MAX_TAB_HINTS,
+	 * ask the user whether to display them or not.
+	 */
+	if (found > MAX_TAB_HINTS) {
+		printf("\n");
+		continue_showing_hints =
+		    console_prompt_display_all_hints(indev, found);
 	}
 	
@@ -225,7 +247,29 @@
 		while (cmdtab_search_one(name, &pos)) {
 			cmd_info_t *hlp = list_get_instance(pos, cmd_info_t, link);
-			printf("%s (%s)\n", hlp->name, hlp->description);
+			
+			if (continue_showing_hints) {
+				printf("%s (%s)\n", hlp->name, hlp->description);
+				--hints_to_show;
+				++total_hints_shown;
+				
+				if ((hints_to_show == 0) && (total_hints_shown != found)) {
+					/* Ask user to continue */
+					continue_showing_hints =
+					    console_prompt_more_hints(indev, &hints_to_show);
+				}
+			}
+			
 			pos = pos->next;
-		}
+			
+			for (max_match_len_tmp = 0;
+			    (output[max_match_len_tmp] ==
+			    hlp->name[input_len + max_match_len_tmp]) &&
+			    (max_match_len_tmp < max_match_len); ++max_match_len_tmp);
+			
+			max_match_len = max_match_len_tmp;
+		}
+		
+		/* Keep only the characters common in all completions */
+		output[max_match_len] = 0;
 	}
 	
@@ -280,6 +324,8 @@
 				continue;
 			
-			/* Find the beginning of the word
-			   and copy it to tmp */
+			/*
+			 * Find the beginning of the word
+			 * and copy it to tmp
+			 */
 			size_t beg;
 			for (beg = position - 1; (beg > 0) && (!isspace(current[beg]));
@@ -294,23 +340,17 @@
 			if (beg == 0) {
 				/* Command completion */
-				found = cmdtab_compl(tmp, STR_BOUNDS(MAX_CMDLINE));
+				found = cmdtab_compl(tmp, STR_BOUNDS(MAX_CMDLINE), indev);
 			} else {
 				/* Symbol completion */
-				found = symtab_compl(tmp, STR_BOUNDS(MAX_CMDLINE));
+				found = symtab_compl(tmp, STR_BOUNDS(MAX_CMDLINE), indev);
 			}
 			
 			if (found == 0)
 				continue;
-			
-			if (found > 1) {
-				/* No unique hint, list was printed */
-				printf("%s> ", prompt);
-				printf("%ls", current);
-				print_cc('\b', wstr_length(current) - position);
-				continue;
-			}
-			
-			/* We have a hint */
-			
+
+			/*
+			 * We have hints, possibly many. In case of more than one hint,
+			 * tmp will contain the common prefix.
+			 */
 			size_t off = 0;
 			size_t i = 0;
@@ -318,6 +358,18 @@
 				if (!wstr_linsert(current, ch, position + i, MAX_CMDLINE))
 					break;
+				
 				i++;
 			}
+			
+			if (found > 1) {
+				/* No unique hint, list was printed */
+				printf("%s> ", prompt);
+				printf("%ls", current);
+				position += str_length(tmp);
+				print_cc('\b', wstr_length(current) - position);
+				continue;
+			}
+			
+			/* We have a hint */
 			
 			printf("%ls", current + position);
@@ -540,5 +592,5 @@
 /** Parse command line.
  *
- * @param cmdline Command line as read from input device. 
+ * @param cmdline Command line as read from input device.
  * @param size    Size (in bytes) of the string.
  *
Index: kernel/generic/src/console/prompt.c
===================================================================
--- kernel/generic/src/console/prompt.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/src/console/prompt.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2012 Sandeep Kumar
+ * Copyright (c) 2012 Vojtech Horky
+ * 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 genericconsole
+ * @{
+ */
+
+/**
+ * @file
+ * @brief Kernel console special prompts.
+ */
+
+#include <console/prompt.h>
+
+/** Display the <i>display all possibilities</i> prompt and wait for answer.
+ *
+ * @param indev Where to read characters from.
+ * @param hints Number of hints that would be displayed.
+ *
+ * @return Whether to print all hints.
+ *
+ */
+bool console_prompt_display_all_hints(indev_t *indev, size_t hints)
+{
+	ASSERT(indev);
+	ASSERT(hints > 0);
+	
+	printf("Display all %zu possibilities? (y or n) ", hints);
+	
+	while (true) {
+		wchar_t answer = indev_pop_character(indev);
+		
+		if ((answer == 'y') || (answer == 'Y')) {
+			printf("y");
+			return true;
+		}
+		
+		if ((answer == 'n') || (answer == 'N')) {
+			printf("n");
+			return false;
+		}
+	}
+}
+
+/** Display the <i>--more--</i> prompt and wait for answer.
+ *
+ * When the function returns false, @p display_hints is set to zero.
+ *
+ * @param[in]  indev         Where to read characters from.
+ * @param[out] display_hints How many hints to display.
+ *
+ * @return Whether to display more hints.
+ *
+ */
+bool console_prompt_more_hints(indev_t *indev, size_t *display_hints)
+{
+	ASSERT(indev);
+	ASSERT(display_hints != NULL);
+	
+	printf("--More--");
+	while (true) {
+		wchar_t continue_showing_hints = indev_pop_character(indev);
+		/* Display a full page again? */
+		if ((continue_showing_hints == 'y') ||
+		    (continue_showing_hints == 'Y') ||
+		    (continue_showing_hints == ' ')) {
+			*display_hints = MAX_TAB_HINTS - 1;
+			break;
+		}
+		
+		/* Stop displaying hints? */
+		if ((continue_showing_hints == 'n') ||
+		    (continue_showing_hints == 'N') ||
+		    (continue_showing_hints == 'q') ||
+		    (continue_showing_hints == 'Q')) {
+			*display_hints = 0;
+			break;
+		}
+		
+		/* Show one more hint? */
+		if (continue_showing_hints == '\n') {
+			*display_hints = 1;
+			break;
+		}
+	}
+	
+	/* Delete the --More-- option */
+	printf("\r         \r");
+	
+	return *display_hints > 0;
+}
+
+/** @}
+ */
Index: kernel/generic/src/debug/symtab.c
===================================================================
--- kernel/generic/src/debug/symtab.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/debug/symtab.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -43,4 +43,5 @@
 #include <typedefs.h>
 #include <errno.h>
+#include <console/prompt.h>
 
 /** Get name of a symbol that seems most likely to correspond to address.
@@ -209,5 +210,5 @@
  *
  */
-int symtab_compl(char *input, size_t size)
+int symtab_compl(char *input, size_t size, indev_t *indev)
 {
 #ifdef CONFIG_SYMTAB
@@ -227,5 +228,22 @@
 	char output[MAX_SYMBOL_NAME];
 	
+	/*
+	 * Maximum Match Length: Length of longest matching common substring in
+	 * case more than one match is found.
+	 */
+	size_t max_match_len = size;
+	size_t max_match_len_tmp = size;
+	size_t input_len = str_length(input);
+	char *sym_name;
+	size_t hints_to_show = MAX_TAB_HINTS - 1;
+	size_t total_hints_shown = 0;
+	bool continue_showing_hints = true;
+	
 	output[0] = 0;
+	
+	while ((hint = symtab_search_one(name, &pos)))
+		pos++;
+	
+	pos = 0;
 	
 	while ((hint = symtab_search_one(name, &pos))) {
@@ -235,4 +253,14 @@
 		pos++;
 		found++;
+	}
+	
+	/*
+	 * If the number of possible completions is more than MAX_TAB_HINTS,
+	 * ask the user whether to display them or not.
+	 */
+	if (found > MAX_TAB_HINTS) {
+		printf("\n");
+		continue_showing_hints =
+		    console_prompt_display_all_hints(indev, found);
 	}
 	
@@ -241,7 +269,30 @@
 		pos = 0;
 		while (symtab_search_one(name, &pos)) {
-			printf("%s\n", symbol_table[pos].symbol_name);
+			sym_name = symbol_table[pos].symbol_name;
 			pos++;
+			
+			if (continue_showing_hints) {
+				/* We are still showing hints */
+				printf("%s\n", sym_name);
+				--hints_to_show;
+				++total_hints_shown;
+				
+				if ((hints_to_show == 0) && (total_hints_shown != found)) {
+					/* Ask the user to continue */
+					continue_showing_hints =
+					    console_prompt_more_hints(indev, &hints_to_show);
+				}
+			}
+			
+			for (max_match_len_tmp = 0;
+			    (output[max_match_len_tmp] ==
+			    sym_name[input_len + max_match_len_tmp]) &&
+			    (max_match_len_tmp < max_match_len); ++max_match_len_tmp);
+			
+			max_match_len = max_match_len_tmp;
 		}
+		
+		/* Keep only the characters common in all completions */
+		output[max_match_len] = 0;
 	}
 	
Index: kernel/generic/src/interrupt/interrupt.c
===================================================================
--- kernel/generic/src/interrupt/interrupt.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/interrupt/interrupt.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -50,4 +50,5 @@
 #include <panic.h>
 #include <print.h>
+#include <stdarg.h>
 #include <symtab.h>
 #include <proc/thread.h>
@@ -165,12 +166,6 @@
 }
 
-/** Terminate thread and task if exception came from userspace.
- *
- */
-NO_TRACE void fault_if_from_uspace(istate_t *istate, const char *fmt, ...)
-{
-	if (!istate_from_uspace(istate))
-		return;
-	
+static NO_TRACE void fault_from_uspace_core(istate_t *istate, const char *fmt, va_list args)
+{
 	printf("Task %s (%" PRIu64 ") killed due to an exception at "
 	    "program counter %p.\n", TASK->name, TASK->taskid,
@@ -181,12 +176,34 @@
 	
 	printf("Kill message: ");
+	vprintf(fmt, args);
+	printf("\n");
+	
+	task_kill_self(true);
+}
+
+/** Terminate thread and task after the exception came from userspace.
+ *
+ */
+NO_TRACE void fault_from_uspace(istate_t *istate, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	fault_from_uspace_core(istate, fmt, args);
+	va_end(args);
+}
+
+/** Terminate thread and task if exception came from userspace.
+ *
+ */
+NO_TRACE void fault_if_from_uspace(istate_t *istate, const char *fmt, ...)
+{
+	if (!istate_from_uspace(istate))
+		return;
 	
 	va_list args;
 	va_start(args, fmt);
-	vprintf(fmt, args);
+	fault_from_uspace_core(istate, fmt, args);
 	va_end(args);
-	printf("\n");
-	
-	task_kill_self(true);
 }
 
Index: kernel/generic/src/ipc/event.c
===================================================================
--- kernel/generic/src/ipc/event.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/ipc/event.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -163,9 +163,13 @@
 				call->data.task_id = TASK ? TASK->taskid : 0;
 				
-				irq_spinlock_lock(&event->answerbox->irq_lock, true);
-				list_append(&call->link, &event->answerbox->irq_notifs);
-				irq_spinlock_unlock(&event->answerbox->irq_lock, true);
-				
-				waitq_wakeup(&event->answerbox->wq, WAKEUP_FIRST);
+				irq_spinlock_lock(&event->answerbox->irq_lock,
+				    true);
+				list_append(&call->ab_link,
+				    &event->answerbox->irq_notifs);
+				irq_spinlock_unlock(&event->answerbox->irq_lock,
+				    true);
+				
+				waitq_wakeup(&event->answerbox->wq,
+				    WAKEUP_FIRST);
 				
 				if (mask)
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/ipc/ipc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -45,4 +45,6 @@
 #include <ipc/kbox.h>
 #include <ipc/event.h>
+#include <ipc/sysipc_ops.h>
+#include <ipc/sysipc_priv.h>
 #include <errno.h>
 #include <mm/slab.h>
@@ -71,7 +73,23 @@
 {
 	memsetb(call, sizeof(*call), 0);
-	call->callerbox = &TASK->answerbox;
-	call->sender = TASK;
+	spinlock_initialize(&call->forget_lock, "forget_lock");
+	call->active = false;
+	call->forget = false;
+	call->sender = NULL;
 	call->buffer = NULL;
+}
+
+void ipc_call_hold(call_t *call)
+{
+	atomic_inc(&call->refcnt);
+}
+
+void ipc_call_release(call_t *call)
+{
+	if (atomic_predec(&call->refcnt) == 0) {
+		if (call->buffer)
+			free(call->buffer);
+		slab_free(ipc_call_slab, call);
+	}
 }
 
@@ -84,5 +102,5 @@
  *
  * @return If flags permit it, return NULL, or initialized kernel
- *         call structure.
+ *         call structure with one reference.
  *
  */
@@ -90,6 +108,8 @@
 {
 	call_t *call = slab_alloc(ipc_call_slab, flags);
-	if (call)
+	if (call) {
 		_ipc_call_init(call);
+		ipc_call_hold(call);
+	}
 	
 	return call;
@@ -103,8 +123,5 @@
 void ipc_call_free(call_t *call)
 {
-	/* Check to see if we have data in the IPC_M_DATA_SEND buffer. */
-	if (call->buffer)
-		free(call->buffer);
-	slab_free(ipc_call_slab, call);
+	ipc_call_release(call);
 }
 
@@ -120,5 +137,4 @@
 	irq_spinlock_initialize(&box->irq_lock, "ipc.box.irqlock");
 	waitq_initialize(&box->wq);
-	link_initialize(&box->sync_box_link);
 	list_initialize(&box->connected_phones);
 	list_initialize(&box->calls);
@@ -134,18 +150,24 @@
  * @param phone Initialized phone structure.
  * @param box   Initialized answerbox structure.
- *
- */
-void ipc_phone_connect(phone_t *phone, answerbox_t *box)
-{
+ * @return      True if the phone was connected, false otherwise.
+ */
+bool ipc_phone_connect(phone_t *phone, answerbox_t *box)
+{
+	bool active;
+
 	mutex_lock(&phone->lock);
-	
-	phone->state = IPC_PHONE_CONNECTED;
-	phone->callee = box;
-	
 	irq_spinlock_lock(&box->lock, true);
-	list_append(&phone->link, &box->connected_phones);
+
+	active = box->active;
+	if (active) {
+		phone->state = IPC_PHONE_CONNECTED;
+		phone->callee = box;
+		list_append(&phone->link, &box->connected_phones);
+	}
+
 	irq_spinlock_unlock(&box->lock, true);
-	
 	mutex_unlock(&phone->lock);
+
+	return active;
 }
 
@@ -153,9 +175,11 @@
  *
  * @param phone Phone structure to be initialized.
- *
- */
-void ipc_phone_init(phone_t *phone)
+ * @param caller Owning task.
+ *
+ */
+void ipc_phone_init(phone_t *phone, task_t *caller)
 {
 	mutex_initialize(&phone->lock, MUTEX_PASSIVE);
+	phone->caller = caller;
 	phone->callee = NULL;
 	phone->state = IPC_PHONE_FREE;
@@ -163,47 +187,4 @@
 }
 
-/** Helper function to facilitate synchronous calls.
- *
- * @param phone   Destination kernel phone structure.
- * @param request Call structure with request.
- *
- * @return EOK on success or EINTR if the sleep was interrupted.
- *
- */
-int ipc_call_sync(phone_t *phone, call_t *request)
-{
-	answerbox_t *sync_box = slab_alloc(ipc_answerbox_slab, 0);
-	ipc_answerbox_init(sync_box, TASK);
-	
-	/*
-	 * Put the answerbox on the TASK's list of synchronous answerboxes so
-	 * that it can be cleaned up if the call is interrupted.
-	 */
-	irq_spinlock_lock(&TASK->lock, true);
-	list_append(&sync_box->sync_box_link, &TASK->sync_boxes);
-	irq_spinlock_unlock(&TASK->lock, true);
-	
-	/* We will receive data in a special box. */
-	request->callerbox = sync_box;
-	
-	ipc_call(phone, request);
-	if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT,
-	    SYNCH_FLAGS_INTERRUPTIBLE)) {
-		/* The answerbox and the call will be freed by ipc_cleanup(). */
-		return EINTR;
-	}
-	
-	/*
-	 * The answer arrived without interruption so we can remove the
-	 * answerbox from the TASK's list of synchronous answerboxes.
-	 */
-	irq_spinlock_lock(&TASK->lock, true);
-	list_remove(&sync_box->sync_box_link);
-	irq_spinlock_unlock(&TASK->lock, true);
-	
-	slab_free(ipc_answerbox_slab, sync_box);
-	return EOK;
-}
-
 /** Answer a message which was not dispatched and is not listed in any queue.
  *
@@ -212,23 +193,36 @@
  *
  */
-static void _ipc_answer_free_call(call_t *call, bool selflocked)
-{
-	answerbox_t *callerbox = call->callerbox;
-	bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox));
-	
+void _ipc_answer_free_call(call_t *call, bool selflocked)
+{
 	/* Count sent answer */
 	irq_spinlock_lock(&TASK->lock, true);
 	TASK->ipc_info.answer_sent++;
 	irq_spinlock_unlock(&TASK->lock, true);
+
+	spinlock_lock(&call->forget_lock);
+	if (call->forget) {
+		/* This is a forgotten call and call->sender is not valid. */
+		spinlock_unlock(&call->forget_lock);
+		ipc_call_free(call);
+		return;
+	} else {
+		/*
+		 * If the call is still active, i.e. it was answered
+		 * in a non-standard way, remove the call from the
+		 * sender's active call list.
+		 */
+		if (call->active) {
+			spinlock_lock(&call->sender->active_calls_lock);
+			list_remove(&call->ta_link);
+			spinlock_unlock(&call->sender->active_calls_lock);
+		}
+	}
+	spinlock_unlock(&call->forget_lock);
+
+	answerbox_t *callerbox = &call->sender->answerbox;
+	bool do_lock = ((!selflocked) || (callerbox != &TASK->answerbox));
 	
 	call->flags |= IPC_CALL_ANSWERED;
 	
-	if (call->flags & IPC_CALL_FORWARDED) {
-		if (call->caller_phone) {
-			/* Demasquerade the caller phone. */
-			call->data.phone = call->caller_phone;
-		}
-	}
-
 	call->data.task_id = TASK->taskid;
 	
@@ -236,5 +230,5 @@
 		irq_spinlock_lock(&callerbox->lock, true);
 	
-	list_append(&call->link, &callerbox->answers);
+	list_append(&call->ab_link, &callerbox->answers);
 	
 	if (do_lock)
@@ -254,9 +248,26 @@
 	/* Remove from active box */
 	irq_spinlock_lock(&box->lock, true);
-	list_remove(&call->link);
+	list_remove(&call->ab_link);
 	irq_spinlock_unlock(&box->lock, true);
 	
 	/* Send back answer */
 	_ipc_answer_free_call(call, false);
+}
+
+static void _ipc_call_actions_internal(phone_t *phone, call_t *call)
+{
+	task_t *caller = phone->caller;
+
+	atomic_inc(&phone->active_calls);
+	call->caller_phone = phone;
+	call->sender = caller;
+
+	call->active = true;
+	spinlock_lock(&caller->active_calls_lock);
+	list_append(&call->ta_link, &caller->active_calls);
+	spinlock_unlock(&caller->active_calls_lock);
+
+	call->data.phone = phone;
+	call->data.task_id = caller->taskid;
 }
 
@@ -273,6 +284,5 @@
 void ipc_backsend_err(phone_t *phone, call_t *call, sysarg_t err)
 {
-	call->data.phone = phone;
-	atomic_inc(&phone->active_calls);
+	_ipc_call_actions_internal(phone, call);
 	IPC_SET_RETVAL(call->data, err);
 	_ipc_answer_free_call(call, false);
@@ -288,17 +298,16 @@
 static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call)
 {
+	task_t *caller = phone->caller;
+
 	/* Count sent ipc call */
-	irq_spinlock_lock(&TASK->lock, true);
-	TASK->ipc_info.call_sent++;
-	irq_spinlock_unlock(&TASK->lock, true);
-	
-	if (!(call->flags & IPC_CALL_FORWARDED)) {
-		atomic_inc(&phone->active_calls);
-		call->data.phone = phone;
-		call->data.task_id = TASK->taskid;
-	}
+	irq_spinlock_lock(&caller->lock, true);
+	caller->ipc_info.call_sent++;
+	irq_spinlock_unlock(&caller->lock, true);
+	
+	if (!(call->flags & IPC_CALL_FORWARDED))
+		_ipc_call_actions_internal(phone, call);
 	
 	irq_spinlock_lock(&box->lock, true);
-	list_append(&call->link, &box->calls);
+	list_append(&call->ab_link, &box->calls);
 	irq_spinlock_unlock(&box->lock, true);
 	
@@ -320,8 +329,5 @@
 	if (phone->state != IPC_PHONE_CONNECTED) {
 		mutex_unlock(&phone->lock);
-		if (call->flags & IPC_CALL_FORWARDED) {
-			IPC_SET_RETVAL(call->data, EFORWARD);
-			_ipc_answer_free_call(call, false);
-		} else {
+		if (!(call->flags & IPC_CALL_FORWARDED)) {
 			if (phone->state == IPC_PHONE_HUNGUP)
 				ipc_backsend_err(phone, call, EHANGUP);
@@ -370,4 +376,5 @@
 		call_t *call = ipc_call_alloc(0);
 		IPC_SET_IMETHOD(call->data, IPC_M_PHONE_HUNGUP);
+		call->request_method = IPC_M_PHONE_HUNGUP;
 		call->flags |= IPC_CALL_DISCARD_ANSWER;
 		_ipc_call(phone, box, call);
@@ -401,10 +408,8 @@
 	TASK->ipc_info.forwarded++;
 	irq_spinlock_pass(&TASK->lock, &oldbox->lock);
-	list_remove(&call->link);
+	list_remove(&call->ab_link);
 	irq_spinlock_unlock(&oldbox->lock, true);
 	
 	if (mode & IPC_FF_ROUTE_FROM_ME) {
-		if (!call->caller_phone)
-			call->caller_phone = call->data.phone;
 		call->data.phone = newphone;
 		call->data.task_id = TASK->taskid;
@@ -451,6 +456,6 @@
 		
 		request = list_get_instance(list_first(&box->irq_notifs),
-		    call_t, link);
-		list_remove(&request->link);
+		    call_t, ab_link);
+		list_remove(&request->ab_link);
 		
 		irq_spinlock_unlock(&box->irq_lock, false);
@@ -461,7 +466,7 @@
 		/* Handle asynchronous answers */
 		request = list_get_instance(list_first(&box->answers),
-		    call_t, link);
-		list_remove(&request->link);
-		atomic_dec(&request->data.phone->active_calls);
+		    call_t, ab_link);
+		list_remove(&request->ab_link);
+		atomic_dec(&request->caller_phone->active_calls);
 	} else if (!list_empty(&box->calls)) {
 		/* Count received call */
@@ -470,9 +475,9 @@
 		/* Handle requests */
 		request = list_get_instance(list_first(&box->calls),
-		    call_t, link);
-		list_remove(&request->link);
+		    call_t, ab_link);
+		list_remove(&request->ab_link);
 		
 		/* Append request to dispatch queue */
-		list_append(&request->link, &box->dispatched_calls);
+		list_append(&request->ab_link, &box->dispatched_calls);
 	} else {
 		/* This can happen regularly after ipc_cleanup */
@@ -494,19 +499,29 @@
 /** Answer all calls from list with EHANGUP answer.
  *
+ * @param box Answerbox with the list.
  * @param lst Head of the list to be cleaned up.
- *
- */
-void ipc_cleanup_call_list(list_t *lst)
-{
+ */
+void ipc_cleanup_call_list(answerbox_t *box, list_t *lst)
+{
+	irq_spinlock_lock(&box->lock, true);
 	while (!list_empty(lst)) {
-		call_t *call = list_get_instance(list_first(lst), call_t, link);
-		if (call->buffer)
-			free(call->buffer);
-		
-		list_remove(&call->link);
-		
+		call_t *call = list_get_instance(list_first(lst), call_t,
+		    ab_link);
+		
+		list_remove(&call->ab_link);
+
+		irq_spinlock_unlock(&box->lock, true);
+
+		if (lst == &box->calls)
+			SYSIPC_OP(request_process, call, box);
+
+		ipc_data_t old = call->data;
 		IPC_SET_RETVAL(call->data, EHANGUP);
+		answer_preprocess(call, &old);
 		_ipc_answer_free_call(call, true);
-	}
+
+		irq_spinlock_lock(&box->lock, true);
+	}
+	irq_spinlock_unlock(&box->lock, true);
 }
 
@@ -546,5 +561,7 @@
 			mutex_unlock(&phone->lock);
 			irq_spinlock_unlock(&box->lock, true);
-			
+
+			// FIXME: phone can become deallocated at any time now
+
 			/*
 			 * Send one message to the answerbox for each
@@ -554,4 +571,5 @@
 			 */
 			IPC_SET_IMETHOD(call->data, IPC_M_PHONE_HUNGUP);
+			call->request_method = IPC_M_PHONE_HUNGUP;
 			call->flags |= IPC_CALL_DISCARD_ANSWER;
 			_ipc_call(phone, box, call);
@@ -574,4 +592,127 @@
 }
 
+static void ipc_forget_all_active_calls(void)
+{
+	call_t *call;
+
+restart:
+	spinlock_lock(&TASK->active_calls_lock);
+	if (list_empty(&TASK->active_calls)) {
+		/*
+		 * We are done, there are no more active calls.
+		 * Nota bene: there may still be answers waiting for pick up.
+		 */
+		spinlock_unlock(&TASK->active_calls_lock);	
+		return;	
+	}
+	
+	call = list_get_instance(list_first(&TASK->active_calls), call_t,
+	    ta_link);
+
+	if (!spinlock_trylock(&call->forget_lock)) {
+		/*
+		 * Avoid deadlock and let async_answer() or
+		 *  _ipc_answer_free_call() win the race to dequeue the first
+		 * call on the list.
+		 */
+		spinlock_unlock(&TASK->active_calls_lock);	
+		goto restart;
+	}
+
+	/*
+	 * Forget the call and donate it to the task which holds up the answer.
+	 */
+
+	call->forget = true;
+	call->sender = NULL;
+	list_remove(&call->ta_link);
+
+	/*
+	 * The call may be freed by _ipc_answer_free_call() before we are done
+	 * with it; to avoid working with a destroyed call_t structure, we
+	 * must hold a reference to it.
+	 */
+	ipc_call_hold(call);
+
+	spinlock_unlock(&call->forget_lock);
+	spinlock_unlock(&TASK->active_calls_lock);
+
+	atomic_dec(&call->caller_phone->active_calls);
+
+	SYSIPC_OP(request_forget, call);
+
+	ipc_call_release(call);
+
+	goto restart;
+}
+
+/** Wait for all answers to asynchronous calls to arrive. */
+static void ipc_wait_for_all_answered_calls(void)
+{
+	call_t *call;
+	size_t i;
+
+restart:
+	/*
+	 * Go through all phones, until they are all free.
+	 * Locking is needed as there may be connection handshakes in progress.
+	 */
+	for (i = 0; i < IPC_MAX_PHONES; i++) {
+		phone_t *phone = &TASK->phones[i];
+
+		mutex_lock(&phone->lock);	
+		if ((phone->state == IPC_PHONE_HUNGUP) &&
+		    (atomic_get(&phone->active_calls) == 0)) {
+			phone->state = IPC_PHONE_FREE;
+			phone->callee = NULL;
+		}
+
+		/*
+		 * We might have had some IPC_PHONE_CONNECTING phones at the
+		 * beginning of ipc_cleanup(). Depending on whether these were
+		 * forgotten or answered, they will eventually enter the
+		 * IPC_PHONE_FREE or IPC_PHONE_CONNECTED states, respectively.
+		 * In the latter case, the other side may slam the open phones
+		 * at any time, in which case we will get an IPC_PHONE_SLAMMED
+		 * phone.
+		 */
+		if ((phone->state == IPC_PHONE_CONNECTED) ||
+		    (phone->state == IPC_PHONE_SLAMMED)) {
+			mutex_unlock(&phone->lock);
+			ipc_phone_hangup(phone);
+			/*
+			 * Now there may be one extra active call, which needs
+			 * to be forgotten.
+			 */
+			ipc_forget_all_active_calls();
+			goto restart;
+		}
+
+		/*
+		 * If the hangup succeeded, it has sent a HANGUP message, the
+		 * IPC is now in HUNGUP state, we wait for the reply to come
+		 */
+		if (phone->state != IPC_PHONE_FREE) {
+			mutex_unlock(&phone->lock);
+			break;
+		}
+
+		mutex_unlock(&phone->lock);
+	}
+		
+	/* Got into cleanup */
+	if (i == IPC_MAX_PHONES)
+		return;
+		
+	call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,
+	    SYNCH_FLAGS_NONE);
+	ASSERT(call->flags & (IPC_CALL_ANSWERED | IPC_CALL_NOTIF));
+
+	SYSIPC_OP(answer_process, call);
+
+	ipc_call_free(call);
+	goto restart;
+}
+
 /** Clean up all IPC communication of the current task.
  *
@@ -582,7 +723,16 @@
 void ipc_cleanup(void)
 {
+	/*
+	 * Mark the answerbox as inactive.
+	 *
+	 * The main purpose for doing this is to prevent any pending callback
+	 * connections from getting established beyond this point.
+	 */
+	irq_spinlock_lock(&TASK->answerbox.lock, true);
+	TASK->answerbox.active = false;
+	irq_spinlock_unlock(&TASK->answerbox.lock, true);
+
 	/* Disconnect all our phones ('ipc_phone_hangup') */
-	size_t i;
-	for (i = 0; i < IPC_MAX_PHONES; i++)
+	for (size_t i = 0; i < IPC_MAX_PHONES; i++)
 		ipc_phone_hangup(&TASK->phones[i]);
 	
@@ -602,65 +752,10 @@
 	
 	/* Answer all messages in 'calls' and 'dispatched_calls' queues */
-	irq_spinlock_lock(&TASK->answerbox.lock, true);
-	ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls);
-	ipc_cleanup_call_list(&TASK->answerbox.calls);
-	irq_spinlock_unlock(&TASK->answerbox.lock, true);
-	
-	/* Wait for all answers to interrupted synchronous calls to arrive */
-	ipl_t ipl = interrupts_disable();
-	while (!list_empty(&TASK->sync_boxes)) {
-		answerbox_t *box = list_get_instance(
-		    list_first(&TASK->sync_boxes), answerbox_t, sync_box_link);
-		
-		list_remove(&box->sync_box_link);
-		call_t *call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,
-		    SYNCH_FLAGS_NONE);
-		ipc_call_free(call);
-		slab_free(ipc_answerbox_slab, box);
-	}
-	interrupts_restore(ipl);
-	
-	/* Wait for all answers to asynchronous calls to arrive */
-	while (true) {
-		/*
-		 * Go through all phones, until they are all FREE
-		 * Locking is not needed, no one else should modify
-		 * it when we are in cleanup
-		 */
-		for (i = 0; i < IPC_MAX_PHONES; i++) {
-			if (TASK->phones[i].state == IPC_PHONE_HUNGUP &&
-			    atomic_get(&TASK->phones[i].active_calls) == 0) {
-				TASK->phones[i].state = IPC_PHONE_FREE;
-				TASK->phones[i].callee = NULL;
-			}
-			
-			/*
-			 * Just for sure, we might have had some
-			 * IPC_PHONE_CONNECTING phones
-			 */
-			if (TASK->phones[i].state == IPC_PHONE_CONNECTED)
-				ipc_phone_hangup(&TASK->phones[i]);
-			
-			/*
-			 * If the hangup succeeded, it has sent a HANGUP
-			 * message, the IPC is now in HUNGUP state, we
-			 * wait for the reply to come
-			 */
-			
-			if (TASK->phones[i].state != IPC_PHONE_FREE)
-				break;
-		}
-		
-		/* Got into cleanup */
-		if (i == IPC_MAX_PHONES)
-			break;
-		
-		call_t *call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,
-		    SYNCH_FLAGS_NONE);
-		ASSERT((call->flags & IPC_CALL_ANSWERED) ||
-		    (call->flags & IPC_CALL_NOTIF));
-		
-		ipc_call_free(call);
-	}
+	ipc_cleanup_call_list(&TASK->answerbox, &TASK->answerbox.calls);
+	ipc_cleanup_call_list(&TASK->answerbox,
+	    &TASK->answerbox.dispatched_calls);
+
+	ipc_forget_all_active_calls();
+	ipc_wait_for_all_answered_calls();
 }
 
@@ -670,8 +765,42 @@
 void ipc_init(void)
 {
-	ipc_call_slab = slab_cache_create("ipc_call", sizeof(call_t), 0, NULL,
+	ipc_call_slab = slab_cache_create("call_t", sizeof(call_t), 0, NULL,
 	    NULL, 0);
-	ipc_answerbox_slab = slab_cache_create("ipc_answerbox",
+	ipc_answerbox_slab = slab_cache_create("answerbox_t",
 	    sizeof(answerbox_t), 0, NULL, NULL, 0);
+}
+
+
+static void ipc_print_call_list(list_t *list)
+{
+	list_foreach(*list, cur) {
+		call_t *call = list_get_instance(cur, call_t, ab_link);
+		
+#ifdef __32_BITS__
+		printf("%10p ", call);
+#endif
+		
+#ifdef __64_BITS__
+		printf("%18p ", call);
+#endif
+		
+		spinlock_lock(&call->forget_lock);
+
+		printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun
+		    " %-6" PRIun " %-6" PRIun " %-7x",
+		    IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data),
+		    IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
+		    IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
+		    call->flags);
+
+		if (call->forget) {
+			printf(" ? (call forgotten)\n");
+		} else {
+			printf(" %" PRIu64 " (%s)\n",
+			    call->sender->taskid, call->sender->name);
+		}
+
+		spinlock_unlock(&call->forget_lock);
+	}
 }
 
@@ -747,62 +876,9 @@
 	
 	printf(" --- incomming calls ---\n");
-	list_foreach(task->answerbox.calls, cur) {
-		call_t *call = list_get_instance(cur, call_t, link);
-		
-#ifdef __32_BITS__
-		printf("%10p ", call);
-#endif
-		
-#ifdef __64_BITS__
-		printf("%18p ", call);
-#endif
-		
-		printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun
-		    " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n",
-		    IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data),
-		    IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
-		    IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
-		    call->flags, call->sender->taskid, call->sender->name);
-	}
-	
+	ipc_print_call_list(&task->answerbox.calls);
 	printf(" --- dispatched calls ---\n");
-	list_foreach(task->answerbox.dispatched_calls, cur) {
-		call_t *call = list_get_instance(cur, call_t, link);
-		
-#ifdef __32_BITS__
-		printf("%10p ", call);
-#endif
-		
-#ifdef __64_BITS__
-		printf("%18p ", call);
-#endif
-		
-		printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun
-		    " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n",
-		    IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data),
-		    IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
-		    IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
-		    call->flags, call->sender->taskid, call->sender->name);
-	}
-	
+	ipc_print_call_list(&task->answerbox.dispatched_calls);
 	printf(" --- incoming answers ---\n");
-	list_foreach(task->answerbox.answers, cur) {
-		call_t *call = list_get_instance(cur, call_t, link);
-		
-#ifdef __32_BITS__
-		printf("%10p ", call);
-#endif
-		
-#ifdef __64_BITS__
-		printf("%18p ", call);
-#endif
-		
-		printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun
-		    " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n",
-		    IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data),
-		    IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
-		    IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
-		    call->flags, call->sender->taskid, call->sender->name);
-	}
+	ipc_print_call_list(&task->answerbox.answers);
 	
 	irq_spinlock_unlock(&task->answerbox.lock, false);
Index: kernel/generic/src/ipc/ipcrsc.c
===================================================================
--- kernel/generic/src/ipc/ipcrsc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/ipc/ipcrsc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -132,4 +132,5 @@
 #include <ipc/ipcrsc.h>
 #include <debug.h>
+#include <abi/errno.h>
 
 /** Find call_t * in call table according to callid.
@@ -151,5 +152,5 @@
 	
 	list_foreach(TASK->answerbox.dispatched_calls, lst) {
-		call_t *call = list_get_instance(lst, call_t, link);
+		call_t *call = list_get_instance(lst, call_t, ab_link);
 		if ((sysarg_t) call == callid) {
 			result = call;
@@ -162,4 +163,21 @@
 }
 
+/** Get phone from the current task by ID.
+ *
+ * @param phoneid Phone ID.
+ * @param phone   Place to store pointer to phone.
+ *
+ * @return EOK on success, EINVAL if ID is invalid.
+ *
+ */
+int phone_get(sysarg_t phoneid, phone_t **phone)
+{
+	if (phoneid >= IPC_MAX_PHONES)
+		return EINVAL;
+	
+	*phone = &TASK->phones[phoneid];
+	return EOK;
+}
+
 /** Allocate new phone slot in the specified task.
  *
@@ -176,10 +194,12 @@
 	size_t i;
 	for (i = 0; i < IPC_MAX_PHONES; i++) {
-		if ((task->phones[i].state == IPC_PHONE_HUNGUP) &&
-		    (atomic_get(&task->phones[i].active_calls) == 0))
-			task->phones[i].state = IPC_PHONE_FREE;
+		phone_t *phone = &task->phones[i];
+
+		if ((phone->state == IPC_PHONE_HUNGUP) &&
+		    (atomic_get(&phone->active_calls) == 0))
+			phone->state = IPC_PHONE_FREE;
 		
-		if (task->phones[i].state == IPC_PHONE_FREE) {
-			task->phones[i].state = IPC_PHONE_CONNECTING;
+		if (phone->state == IPC_PHONE_FREE) {
+			phone->state = IPC_PHONE_CONNECTING;
 			break;
 		}
@@ -223,4 +243,5 @@
  * @param phoneid Phone handle to be connected.
  * @param box     Answerbox to which to connect the phone handle.
+ * @return        True if the phone was connected, false otherwise.
  *
  * The procedure _enforces_ that the user first marks the phone
@@ -229,10 +250,10 @@
  *
  */
-void phone_connect(int phoneid, answerbox_t *box)
+bool phone_connect(int phoneid, answerbox_t *box)
 {
 	phone_t *phone = &TASK->phones[phoneid];
 	
 	ASSERT(phone->state == IPC_PHONE_CONNECTING);
-	ipc_phone_connect(phone, box);
+	return ipc_phone_connect(phone, box);
 }
 
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/ipc/irq.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -39,14 +39,14 @@
  * when interrupt is detected. The application may provide a simple 'top-half'
  * handler as part of its registration, which can perform simple operations
- * (read/write port/memory, add information to notification ipc message).
+ * (read/write port/memory, add information to notification IPC message).
  *
  * The structure of a notification message is as follows:
  * - IMETHOD: interface and method as registered by
  *            the SYS_IRQ_REGISTER syscall
- * - ARG1: payload modified by a 'top-half' handler
- * - ARG2: payload modified by a 'top-half' handler
- * - ARG3: payload modified by a 'top-half' handler
- * - ARG4: payload modified by a 'top-half' handler
- * - ARG5: payload modified by a 'top-half' handler
+ * - ARG1: payload modified by a 'top-half' handler (scratch[1])
+ * - ARG2: payload modified by a 'top-half' handler (scratch[2])
+ * - ARG3: payload modified by a 'top-half' handler (scratch[3])
+ * - ARG4: payload modified by a 'top-half' handler (scratch[4])
+ * - ARG5: payload modified by a 'top-half' handler (scratch[5])
  * - in_phone_hash: interrupt counter (may be needed to assure correct order
  *                  in multithreaded drivers)
@@ -87,7 +87,5 @@
 static void ranges_unmap(irq_pio_range_t *ranges, size_t rangecount)
 {
-	size_t i;
-
-	for (i = 0; i < rangecount; i++) {
+	for (size_t i = 0; i < rangecount; i++) {
 #ifdef IO_SPACE_BOUNDARY
 		if ((void *) ranges[i].base >= IO_SPACE_BOUNDARY)
@@ -100,14 +98,11 @@
     irq_cmd_t *cmds, size_t cmdcount)
 {
-	uintptr_t *pbase;
-	size_t i, j;
-
 	/* Copy the physical base addresses aside. */
-	pbase = malloc(rangecount * sizeof(uintptr_t), 0);
-	for (i = 0; i < rangecount; i++)
+	uintptr_t *pbase = malloc(rangecount * sizeof(uintptr_t), 0);
+	for (size_t i = 0; i < rangecount; i++)
 		pbase[i] = ranges[i].base;
-
+	
 	/* Map the PIO ranges into the kernel virtual address space. */
-	for (i = 0; i < rangecount; i++) {
+	for (size_t i = 0; i < rangecount; i++) {
 #ifdef IO_SPACE_BOUNDARY
 		if ((void *) ranges[i].base < IO_SPACE_BOUNDARY)
@@ -122,25 +117,25 @@
 		}
 	}
-
+	
 	/* Rewrite the pseudocode addresses from physical to kernel virtual. */
-	for (i = 0; i < cmdcount; i++) {
+	for (size_t i = 0; i < cmdcount; i++) {
 		uintptr_t addr;
 		size_t size;
-
+		
 		/* Process only commands that use an address. */
 		switch (cmds[i].cmd) {
 		case CMD_PIO_READ_8:
-        	case CMD_PIO_WRITE_8:
-        	case CMD_PIO_WRITE_A_8:
+		case CMD_PIO_WRITE_8:
+		case CMD_PIO_WRITE_A_8:
 			size = 1;
 			break;
-        	case CMD_PIO_READ_16:
-        	case CMD_PIO_WRITE_16:
-        	case CMD_PIO_WRITE_A_16:
+		case CMD_PIO_READ_16:
+		case CMD_PIO_WRITE_16:
+		case CMD_PIO_WRITE_A_16:
 			size = 2;
 			break;
-        	case CMD_PIO_READ_32:
-        	case CMD_PIO_WRITE_32:
-        	case CMD_PIO_WRITE_A_32:
+		case CMD_PIO_READ_32:
+		case CMD_PIO_WRITE_32:
+		case CMD_PIO_WRITE_A_32:
 			size = 4;
 			break;
@@ -149,21 +144,21 @@
 			continue;
 		}
-
+		
 		addr = (uintptr_t) cmds[i].addr;
 		
+		size_t j;
 		for (j = 0; j < rangecount; j++) {
-
 			/* Find the matching range. */
 			if (!iswithin(pbase[j], ranges[j].size, addr, size))
 				continue;
-
+			
 			/* Switch the command to a kernel virtual address. */
 			addr -= pbase[j];
 			addr += ranges[j].base;
-
+			
 			cmds[i].addr = (void *) addr;
 			break;
 		}
-
+		
 		if (j == rangecount) {
 			/*
@@ -176,6 +171,46 @@
 		}
 	}
-
+	
 	free(pbase);
+	return EOK;
+}
+
+/** Statically check the top-half pseudocode
+ *
+ * Check the top-half pseudocode for invalid or unsafe
+ * constructs.
+ *
+ */
+static int code_check(irq_cmd_t *cmds, size_t cmdcount)
+{
+	for (size_t i = 0; i < cmdcount; i++) {
+		/*
+		 * Check for accepted ranges.
+		 */
+		if (cmds[i].cmd >= CMD_LAST)
+			return EINVAL;
+		
+		if (cmds[i].srcarg >= IPC_CALL_LEN)
+			return EINVAL;
+		
+		if (cmds[i].dstarg >= IPC_CALL_LEN)
+			return EINVAL;
+		
+		switch (cmds[i].cmd) {
+		case CMD_PREDICATE:
+			/*
+			 * Check for control flow overflow.
+			 * Note that jumping just beyond the last
+			 * command is a correct behaviour.
+			 */
+			if (i + cmds[i].value > cmdcount)
+				return EINVAL;
+			
+			break;
+		default:
+			break;
+		}
+	}
+	
 	return EOK;
 }
@@ -207,5 +242,5 @@
 	irq_pio_range_t *ranges = NULL;
 	irq_cmd_t *cmds = NULL;
-
+	
 	irq_code_t *code = malloc(sizeof(*code), 0);
 	int rc = copy_from_uspace(code, ucode, sizeof(*code));
@@ -222,5 +257,5 @@
 	if (rc != EOK)
 		goto error;
-
+	
 	cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0);
 	rc = copy_from_uspace(cmds, code->cmds,
@@ -228,20 +263,26 @@
 	if (rc != EOK)
 		goto error;
-
+	
+	rc = code_check(cmds, code->cmdcount);
+	if (rc != EOK)
+		goto error;
+	
 	rc = ranges_map_and_apply(ranges, code->rangecount, cmds,
 	    code->cmdcount);
 	if (rc != EOK)
 		goto error;
-
+	
 	code->ranges = ranges;
 	code->cmds = cmds;
-
+	
 	return code;
-
+	
 error:
 	if (cmds)
 		free(cmds);
+	
 	if (ranges)
 		free(ranges);
+	
 	free(code);
 	return NULL;
@@ -250,11 +291,12 @@
 /** Register an answerbox as a receiving end for IRQ notifications.
  *
- * @param box		Receiving answerbox.
- * @param inr		IRQ number.
- * @param devno		Device number.
- * @param imethod	Interface and method to be associated with the
- *			notification.
- * @param ucode		Uspace pointer to top-half pseudocode.
- * @return		EOK on success or a negative error code.
+ * @param box     Receiving answerbox.
+ * @param inr     IRQ number.
+ * @param devno   Device number.
+ * @param imethod Interface and method to be associated with the
+ *                notification.
+ * @param ucode   Uspace pointer to top-half pseudocode.
+ *
+ * @return EOK on success or a negative error code.
  *
  */
@@ -266,5 +308,5 @@
 		(sysarg_t) devno
 	};
-
+	
 	if ((inr < 0) || (inr > last_inr))
 		return ELIMIT;
@@ -329,8 +371,10 @@
 /** Unregister task from IRQ notification.
  *
- * @param box		Answerbox associated with the notification.
- * @param inr		IRQ number.
- * @param devno		Device number.
- * @return		EOK on success or a negative error code.
+ * @param box   Answerbox associated with the notification.
+ * @param inr   IRQ number.
+ * @param devno Device number.
+ *
+ * @return EOK on success or a negative error code.
+ *
  */
 int ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno)
@@ -340,5 +384,5 @@
 		(sysarg_t) devno
 	};
-
+	
 	if ((inr < 0) || (inr > last_inr))
 		return ELIMIT;
@@ -436,5 +480,5 @@
 		/* Remove from the hash table. */
 		hash_table_remove(&irq_uspace_hash_table, key, 2);
-
+		
 		/*
 		 * Release both locks so that we can free the pseudo code.
@@ -442,5 +486,5 @@
 		irq_spinlock_unlock(&box->irq_lock, false);
 		irq_spinlock_unlock(&irq_uspace_hash_table_lock, true);
-
+		
 		code_free(irq->notif_cfg.code);
 		free(irq);
@@ -466,5 +510,5 @@
 {
 	irq_spinlock_lock(&irq->notif_cfg.answerbox->irq_lock, false);
-	list_append(&call->link, &irq->notif_cfg.answerbox->irq_notifs);
+	list_append(&call->ab_link, &irq->notif_cfg.answerbox->irq_notifs);
 	irq_spinlock_unlock(&irq->notif_cfg.answerbox->irq_lock, false);
 	
@@ -492,30 +536,19 @@
 	
 	for (size_t i = 0; i < code->cmdcount; i++) {
-		uint32_t dstval;
-		
 		uintptr_t srcarg = code->cmds[i].srcarg;
 		uintptr_t dstarg = code->cmds[i].dstarg;
 		
-		if (srcarg >= IPC_CALL_LEN)
-			break;
-		
-		if (dstarg >= IPC_CALL_LEN)
-			break;
-	
 		switch (code->cmds[i].cmd) {
 		case CMD_PIO_READ_8:
-			dstval = pio_read_8((ioport8_t *) code->cmds[i].addr);
-			if (dstarg)
-				scratch[dstarg] = dstval;
+			scratch[dstarg] =
+			    pio_read_8((ioport8_t *) code->cmds[i].addr);
 			break;
 		case CMD_PIO_READ_16:
-			dstval = pio_read_16((ioport16_t *) code->cmds[i].addr);
-			if (dstarg)
-				scratch[dstarg] = dstval;
+			scratch[dstarg] =
+			    pio_read_16((ioport16_t *) code->cmds[i].addr);
 			break;
 		case CMD_PIO_READ_32:
-			dstval = pio_read_32((ioport32_t *) code->cmds[i].addr);
-			if (dstarg)
-				scratch[dstarg] = dstval;
+			scratch[dstarg] =
+			    pio_read_32((ioport32_t *) code->cmds[i].addr);
 			break;
 		case CMD_PIO_WRITE_8:
@@ -532,32 +565,26 @@
 			break;
 		case CMD_PIO_WRITE_A_8:
-			if (srcarg) {
-				pio_write_8((ioport8_t *) code->cmds[i].addr,
-				    (uint8_t) scratch[srcarg]);
-			}
+			pio_write_8((ioport8_t *) code->cmds[i].addr,
+			    (uint8_t) scratch[srcarg]);
 			break;
 		case CMD_PIO_WRITE_A_16:
-			if (srcarg) {
-				pio_write_16((ioport16_t *) code->cmds[i].addr,
-				    (uint16_t) scratch[srcarg]);
-			}
+			pio_write_16((ioport16_t *) code->cmds[i].addr,
+			    (uint16_t) scratch[srcarg]);
 			break;
 		case CMD_PIO_WRITE_A_32:
-			if (srcarg) {
-				pio_write_32((ioport32_t *) code->cmds[i].addr,
-				    (uint32_t) scratch[srcarg]);
-			}
-			break;
-		case CMD_BTEST:
-			if ((srcarg) && (dstarg)) {
-				dstval = scratch[srcarg] & code->cmds[i].value;
-				scratch[dstarg] = dstval;
-			}
+			pio_write_32((ioport32_t *) code->cmds[i].addr,
+			    (uint32_t) scratch[srcarg]);
+			break;
+		case CMD_LOAD:
+			scratch[dstarg] = code->cmds[i].value;
+			break;
+		case CMD_AND:
+			scratch[dstarg] = scratch[srcarg] &
+			    code->cmds[i].value;
 			break;
 		case CMD_PREDICATE:
-			if ((srcarg) && (!scratch[srcarg])) {
+			if (scratch[srcarg] == 0)
 				i += code->cmds[i].value;
-				continue;
-			}
+			
 			break;
 		case CMD_ACCEPT:
@@ -582,5 +609,5 @@
 {
 	ASSERT(irq);
-
+	
 	ASSERT(interrupts_disabled());
 	ASSERT(irq_spinlock_locked(&irq->lock));
Index: kernel/generic/src/ipc/kbox.c
===================================================================
--- kernel/generic/src/ipc/kbox.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/ipc/kbox.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -48,4 +48,12 @@
 {
 	/*
+	 * Not really needed, just to be consistent with the meaning of
+	 * answerbox_t.active.
+	 */
+	irq_spinlock_lock(&TASK->kb.box.lock, true);
+	TASK->kb.box.active = false;
+	irq_spinlock_unlock(&TASK->kb.box.lock, true);
+
+	/*
 	 * Only hold kb.cleanup_lock while setting kb.finished -
 	 * this is enough.
@@ -88,8 +96,6 @@
 	
 	/* Answer all messages in 'calls' and 'dispatched_calls' queues. */
-	irq_spinlock_lock(&TASK->kb.box.lock, true);
-	ipc_cleanup_call_list(&TASK->kb.box.dispatched_calls);
-	ipc_cleanup_call_list(&TASK->kb.box.calls);
-	irq_spinlock_unlock(&TASK->kb.box.lock, true);
+	ipc_cleanup_call_list(&TASK->kb.box, &TASK->kb.box.calls);
+	ipc_cleanup_call_list(&TASK->kb.box, &TASK->kb.box.dispatched_calls);
 }
 
@@ -162,5 +168,5 @@
 	while (!done) {
 		call_t *call = ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT,
-			SYNCH_FLAGS_NONE);
+		    SYNCH_FLAGS_NONE);
 		
 		if (call == NULL)
@@ -236,5 +242,5 @@
 	
 	/* Connect the newly allocated phone to the kbox */
-	ipc_phone_connect(&TASK->phones[newphid], &task->kb.box);
+	(void) ipc_phone_connect(&TASK->phones[newphid], &task->kb.box);
 	
 	if (task->kb.thread != NULL) {
@@ -244,6 +250,6 @@
 	
 	/* Create a kbox thread */
-	thread_t *kb_thread = thread_create(kbox_thread_proc, NULL, task, 0,
-	    "kbox", false);
+	thread_t *kb_thread = thread_create(kbox_thread_proc, NULL, task,
+	    THREAD_FLAG_NONE, "kbox");
 	if (!kb_thread) {
 		mutex_unlock(&task->kb.cleanup_lock);
Index: kernel/generic/src/ipc/ops/clnestab.c
===================================================================
--- kernel/generic/src/ipc/ops/clnestab.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/src/ipc/ops/clnestab.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,88 @@
+/*
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/sysipc_ops.h>
+#include <ipc/ipc.h>
+#include <synch/mutex.h>
+#include <abi/errno.h>
+
+static int request_preprocess(call_t *call, phone_t *phone)
+{
+	IPC_SET_ARG5(call->data, (sysarg_t) phone);
+
+	return EOK;	
+}
+
+static int answer_cleanup(call_t *answer, ipc_data_t *olddata)
+{
+	phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
+
+	mutex_lock(&phone->lock);
+	if (phone->state == IPC_PHONE_CONNECTED) {
+		irq_spinlock_lock(&phone->callee->lock, true);
+		list_remove(&phone->link);
+		phone->state = IPC_PHONE_SLAMMED;
+		irq_spinlock_unlock(&phone->callee->lock, true);
+	}
+	mutex_unlock(&phone->lock);
+
+	return EOK;
+}
+
+static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
+{
+
+	if (IPC_GET_RETVAL(answer->data) != EOK) {
+		/*
+		 * The other party on the cloned phone rejected our request
+		 * for connection on the protocol level.  We need to break the
+		 * connection without sending IPC_M_HUNGUP back.
+		 */
+		answer_cleanup(answer, olddata);
+	}
+	
+	return EOK;
+}
+
+sysipc_ops_t ipc_m_clone_establish_ops = {
+	.request_preprocess = request_preprocess,
+	.request_forget = null_request_forget,
+	.request_process = null_request_process,
+	.answer_cleanup = answer_cleanup,
+	.answer_preprocess = answer_preprocess,
+	.answer_process = null_answer_process,
+};
+
+/** @}
+ */
Index: kernel/generic/src/ipc/ops/conctmeto.c
===================================================================
--- kernel/generic/src/ipc/ops/conctmeto.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/src/ipc/ops/conctmeto.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/sysipc_ops.h>
+#include <ipc/ipc.h>
+#include <ipc/ipcrsc.h>
+#include <abi/errno.h>
+#include <arch.h>
+
+static int request_preprocess(call_t *call, phone_t *phone)
+{
+	int newphid = phone_alloc(TASK);
+
+	if (newphid < 0)
+		return ELIMIT;
+		
+	/* Set arg5 for server */
+	IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]);
+	call->priv = newphid;
+
+	return EOK;
+}
+
+static int request_forget(call_t *call)
+{
+	phone_dealloc(call->priv);
+	return EOK;
+}
+
+static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
+{
+	phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
+
+	/* If the user accepted call, connect */
+	if (IPC_GET_RETVAL(answer->data) == EOK)
+		(void) ipc_phone_connect(phone, &TASK->answerbox);
+
+	return EOK;
+}
+
+static int answer_process(call_t *answer)
+{
+	if (IPC_GET_RETVAL(answer->data))
+		phone_dealloc(answer->priv);
+	else
+		IPC_SET_ARG5(answer->data, answer->priv);
+	
+	return EOK;
+}
+
+sysipc_ops_t ipc_m_connect_me_to_ops = {
+	.request_preprocess = request_preprocess,
+	.request_forget = request_forget,
+	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
+	.answer_preprocess = answer_preprocess,
+	.answer_process = answer_process,
+};
+
+/** @}
+ */
Index: kernel/generic/src/ipc/ops/concttome.c
===================================================================
--- kernel/generic/src/ipc/ops/concttome.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/src/ipc/ops/concttome.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/sysipc_ops.h>
+#include <ipc/ipc.h>
+#include <ipc/ipcrsc.h>
+#include <abi/errno.h>
+#include <arch.h>
+
+static int request_process(call_t *call, answerbox_t *box)
+{
+	int phoneid = phone_alloc(TASK);
+
+	IPC_SET_ARG5(call->data, phoneid);
+	
+	return EOK;
+}
+
+static int answer_cleanup(call_t *answer, ipc_data_t *olddata)
+{
+	int phoneid = (int) IPC_GET_ARG5(*olddata);
+
+	if (phoneid >= 0)
+		phone_dealloc(phoneid);
+
+	return EOK;
+}
+
+static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
+{
+	int phoneid = (int) IPC_GET_ARG5(*olddata);
+
+	if (IPC_GET_RETVAL(answer->data) != EOK) {
+		/* The connection was not accepted */
+		answer_cleanup(answer, olddata);
+	} else if (phoneid >= 0) {
+		/* The connection was accepted */
+		if (phone_connect(phoneid, &answer->sender->answerbox)) {
+			/* Set 'phone hash' as arg5 of response */
+			IPC_SET_ARG5(answer->data,
+			    (sysarg_t) &TASK->phones[phoneid]);
+		} else {
+			/* The answerbox is shutting down. */
+			IPC_SET_RETVAL(answer->data, ENOENT);
+			answer_cleanup(answer, olddata);
+		}
+	} else {
+		IPC_SET_RETVAL(answer->data, ELIMIT);
+	}
+
+	return EOK;
+}
+
+
+sysipc_ops_t ipc_m_connect_to_me_ops = {
+	.request_preprocess = null_request_preprocess,
+	.request_forget = null_request_forget,
+	.request_process = request_process,
+	.answer_cleanup = answer_cleanup,
+	.answer_preprocess = answer_preprocess,
+	.answer_process = null_answer_process,
+};
+
+/** @}
+ */
Index: kernel/generic/src/ipc/ops/connclone.c
===================================================================
--- kernel/generic/src/ipc/ops/connclone.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/src/ipc/ops/connclone.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,144 @@
+/*
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/sysipc_ops.h>
+#include <ipc/ipc.h>
+#include <ipc/ipcrsc.h>
+#include <synch/mutex.h>
+#include <abi/errno.h>
+#include <arch.h>
+
+static void phones_lock(phone_t *p1, phone_t *p2)
+{
+	if (p1 < p2) {
+		mutex_lock(&p1->lock);
+		mutex_lock(&p2->lock);
+	} else if (p1 > p2) {
+		mutex_lock(&p2->lock);
+		mutex_lock(&p1->lock);
+	} else
+		mutex_lock(&p1->lock);
+}
+
+static void phones_unlock(phone_t *p1, phone_t *p2)
+{
+	mutex_unlock(&p1->lock);
+	if (p1 != p2)
+		mutex_unlock(&p2->lock);
+}
+
+static int request_preprocess(call_t *call, phone_t *phone)
+{
+	phone_t *cloned_phone;
+
+	if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
+		return ENOENT;
+		
+	phones_lock(cloned_phone, phone);
+		
+	if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
+	    phone->state != IPC_PHONE_CONNECTED) {
+		phones_unlock(cloned_phone, phone);
+		return EINVAL;
+	}
+		
+	/*
+	 * We can be pretty sure now that both tasks exist and we are
+	 * connected to them. As we continue to hold the phone locks,
+	 * we are effectively preventing them from finishing their
+	 * potential cleanup.
+	 *
+	 */
+	int newphid = phone_alloc(phone->callee->task);
+	if (newphid < 0) {
+		phones_unlock(cloned_phone, phone);
+		return ELIMIT;
+	}
+		
+	(void) ipc_phone_connect(&phone->callee->task->phones[newphid],
+	    cloned_phone->callee);
+	phones_unlock(cloned_phone, phone);
+		
+	/* Set the new phone for the callee. */
+	IPC_SET_ARG1(call->data, newphid);
+
+	return EOK;
+}
+
+static int answer_cleanup(call_t *answer, ipc_data_t *olddata)
+{
+	int phoneid = (int) IPC_GET_ARG1(*olddata);
+	phone_t *phone = &TASK->phones[phoneid];
+
+	/*
+	 * In this case, the connection was established at the request
+	 * time and therefore we need to slam the phone.  We don't
+	 * merely hangup as that would result in sending IPC_M_HUNGUP
+	 * to the third party on the other side of the cloned phone.
+	 */
+	mutex_lock(&phone->lock);
+	if (phone->state == IPC_PHONE_CONNECTED) {
+		irq_spinlock_lock(&phone->callee->lock, true);
+		list_remove(&phone->link);
+		phone->state = IPC_PHONE_SLAMMED;
+		irq_spinlock_unlock(&phone->callee->lock, true);
+	}
+	mutex_unlock(&phone->lock);
+
+	return EOK;
+}
+
+static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
+{
+	if (IPC_GET_RETVAL(answer->data) != EOK) {
+		/*
+		 * The recipient of the cloned phone rejected the offer.
+		 */
+		answer_cleanup(answer, olddata);
+	}
+
+	return EOK;
+}
+
+sysipc_ops_t ipc_m_connection_clone_ops = {
+	.request_preprocess = request_preprocess,
+	.request_forget = null_request_forget,
+	.request_process = null_request_process,
+	.answer_cleanup = answer_cleanup,
+	.answer_preprocess = answer_preprocess,
+	.answer_process = null_answer_process,
+};
+
+/** @}
+ */
Index: kernel/generic/src/ipc/ops/dataread.c
===================================================================
--- kernel/generic/src/ipc/ops/dataread.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/src/ipc/ops/dataread.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,121 @@
+/*
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/sysipc_ops.h>
+#include <ipc/ipc.h>
+#include <mm/slab.h>
+#include <abi/errno.h>
+#include <syscall/copy.h>
+#include <config.h>
+
+static int request_preprocess(call_t *call, phone_t *phone)
+{
+	size_t size = IPC_GET_ARG2(call->data);
+
+	if (size > DATA_XFER_LIMIT) {
+		int flags = IPC_GET_ARG3(call->data);
+
+		if (flags & IPC_XF_RESTRICT)
+			IPC_SET_ARG2(call->data, DATA_XFER_LIMIT);
+		else
+			return ELIMIT;
+	}
+
+	return EOK;
+}
+
+static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
+{
+	ASSERT(!answer->buffer);
+
+	if (!IPC_GET_RETVAL(answer->data)) {
+		/* The recipient agreed to send data. */
+		uintptr_t src = IPC_GET_ARG1(answer->data);
+		uintptr_t dst = IPC_GET_ARG1(*olddata);
+		size_t max_size = IPC_GET_ARG2(*olddata);
+		size_t size = IPC_GET_ARG2(answer->data);
+
+		if (size && size <= max_size) {
+			/*
+			 * Copy the destination VA so that this piece of
+			 * information is not lost.
+			 */
+			IPC_SET_ARG1(answer->data, dst);
+				
+			answer->buffer = malloc(size, 0);
+			int rc = copy_from_uspace(answer->buffer,
+			    (void *) src, size);
+			if (rc) {
+				IPC_SET_RETVAL(answer->data, rc);
+				/*
+				 * answer->buffer will be cleaned up in
+				 * ipc_call_free().
+				 */
+			}
+		} else if (!size) {
+			IPC_SET_RETVAL(answer->data, EOK);
+		} else {
+			IPC_SET_RETVAL(answer->data, ELIMIT);
+		}
+	}
+
+	return EOK;
+}
+
+static int answer_process(call_t *answer)
+{
+	if (answer->buffer) {
+		uintptr_t dst = IPC_GET_ARG1(answer->data);
+		size_t size = IPC_GET_ARG2(answer->data);
+		int rc;
+
+		rc = copy_to_uspace((void *) dst, answer->buffer, size);
+		if (rc)
+			IPC_SET_RETVAL(answer->data, rc);
+	}
+
+	return EOK;
+}
+
+sysipc_ops_t ipc_m_data_read_ops = {
+	.request_preprocess = request_preprocess,
+	.request_forget = null_request_forget,
+	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
+	.answer_preprocess = answer_preprocess,
+	.answer_process = answer_process,
+};
+
+/** @}
+ */
Index: kernel/generic/src/ipc/ops/datawrite.c
===================================================================
--- kernel/generic/src/ipc/ops/datawrite.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/src/ipc/ops/datawrite.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,104 @@
+/*
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/sysipc_ops.h>
+#include <ipc/ipc.h>
+#include <mm/slab.h>
+#include <abi/errno.h>
+#include <syscall/copy.h>
+#include <config.h>
+
+static int request_preprocess(call_t *call, phone_t *phone)
+{
+	uintptr_t src = IPC_GET_ARG1(call->data);
+	size_t size = IPC_GET_ARG2(call->data);
+
+	if (size > DATA_XFER_LIMIT) {
+		int flags = IPC_GET_ARG3(call->data);
+
+		if (flags & IPC_XF_RESTRICT) {
+			size = DATA_XFER_LIMIT;
+			IPC_SET_ARG2(call->data, size);
+		} else
+			return ELIMIT;
+	}
+
+	call->buffer = (uint8_t *) malloc(size, 0);
+	int rc = copy_from_uspace(call->buffer, (void *) src, size);
+	if (rc != 0) {
+		/*
+		 * call->buffer will be cleaned up in ipc_call_free() at the
+		 * latest.
+		 */
+		return rc;
+	}
+		
+	return EOK;
+}
+
+static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
+{
+	ASSERT(answer->buffer);
+
+	if (!IPC_GET_RETVAL(answer->data)) {
+		/* The recipient agreed to receive data. */
+		uintptr_t dst = (uintptr_t)IPC_GET_ARG1(answer->data);
+		size_t size = (size_t)IPC_GET_ARG2(answer->data);
+		size_t max_size = (size_t)IPC_GET_ARG2(*olddata);
+			
+		if (size <= max_size) {
+			int rc = copy_to_uspace((void *) dst,
+			    answer->buffer, size);
+			if (rc)
+				IPC_SET_RETVAL(answer->data, rc);
+		} else {
+			IPC_SET_RETVAL(answer->data, ELIMIT);
+		}
+	}
+
+	return EOK;
+}
+
+
+sysipc_ops_t ipc_m_data_write_ops = {
+	.request_preprocess = request_preprocess,
+	.request_forget = null_request_forget,
+	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
+	.answer_preprocess = answer_preprocess,
+	.answer_process = null_answer_process,
+};
+
+/** @}
+ */
Index: kernel/generic/src/ipc/ops/debug.c
===================================================================
--- kernel/generic/src/ipc/ops/debug.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/src/ipc/ops/debug.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2008 Jiri Svoboda 
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/sysipc_ops.h>
+#include <ipc/ipc.h>
+#include <udebug/udebug_ipc.h>
+#include <syscall/copy.h>
+#include <abi/errno.h>
+
+static int request_process(call_t *call, answerbox_t *box)
+{
+	return -1;
+}
+
+static int answer_process(call_t *answer)
+{
+	if (answer->buffer) {
+		uintptr_t dst = IPC_GET_ARG1(answer->data);
+		size_t size = IPC_GET_ARG2(answer->data);
+		int rc;
+
+		rc = copy_to_uspace((void *) dst, answer->buffer, size);
+		if (rc)
+			IPC_SET_RETVAL(answer->data, rc);
+	}
+
+	return EOK;
+}
+
+sysipc_ops_t ipc_m_debug_ops = {
+#ifdef CONFIG_UDEBUG
+	.request_preprocess = udebug_request_preprocess,
+#else
+	.request_preprocess = null_request_preprocess,
+#endif
+	.request_forget = null_request_forget,
+	.request_process = request_process,
+	.answer_cleanup = null_answer_cleanup,
+	.answer_preprocess = null_answer_preprocess,
+	.answer_process = answer_process,
+};
+
+/** @}
+ */
Index: kernel/generic/src/ipc/ops/sharein.c
===================================================================
--- kernel/generic/src/ipc/ops/sharein.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/src/ipc/ops/sharein.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,71 @@
+/*
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/sysipc_ops.h>
+#include <ipc/ipc.h>
+#include <mm/as.h>
+#include <synch/spinlock.h>
+#include <proc/task.h>
+#include <abi/errno.h>
+#include <arch.h>
+
+static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
+{
+	if (!IPC_GET_RETVAL(answer->data)) {
+		irq_spinlock_lock(&answer->sender->lock, true);
+		as_t *as = answer->sender->as;
+		irq_spinlock_unlock(&answer->sender->lock, true);
+			
+		uintptr_t dst_base = (uintptr_t) -1;
+		int rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
+		    IPC_GET_ARG1(*olddata), as, IPC_GET_ARG2(answer->data),
+		    &dst_base, IPC_GET_ARG3(answer->data));
+		IPC_SET_ARG4(answer->data, dst_base);
+		IPC_SET_RETVAL(answer->data, rc);
+	}
+	
+	return EOK;
+}
+
+sysipc_ops_t ipc_m_share_in_ops = {
+	.request_preprocess = null_request_preprocess,
+	.request_forget = null_request_forget,
+	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
+	.answer_preprocess = answer_preprocess,
+	.answer_process = null_answer_process,
+};
+
+/** @}
+ */
Index: kernel/generic/src/ipc/ops/shareout.c
===================================================================
--- kernel/generic/src/ipc/ops/shareout.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/src/ipc/ops/shareout.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,92 @@
+/*
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/sysipc_ops.h>
+#include <ipc/ipc.h>
+#include <mm/as.h>
+#include <synch/spinlock.h>
+#include <proc/task.h>
+#include <syscall/copy.h>
+#include <abi/errno.h>
+#include <arch.h>
+
+static int request_preprocess(call_t *call, phone_t *phone)
+{
+	size_t size = as_area_get_size(IPC_GET_ARG1(call->data));
+
+	if (!size)
+		return EPERM;
+	IPC_SET_ARG2(call->data, size);
+
+	return EOK;
+}
+
+static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
+{
+	int rc = EOK;
+
+	if (!IPC_GET_RETVAL(answer->data)) {
+		/* Accepted, handle as_area receipt */
+
+		irq_spinlock_lock(&answer->sender->lock, true);
+		as_t *as = answer->sender->as;
+		irq_spinlock_unlock(&answer->sender->lock, true);
+
+		uintptr_t dst_base = (uintptr_t) -1;
+		rc = as_area_share(as, IPC_GET_ARG1(*olddata),
+		    IPC_GET_ARG2(*olddata), AS, IPC_GET_ARG3(*olddata),
+		    &dst_base, IPC_GET_ARG1(answer->data));
+			
+		if (rc == EOK) {
+			rc = copy_to_uspace((void *) IPC_GET_ARG2(answer->data),
+			    &dst_base, sizeof(dst_base));
+		}
+			
+		IPC_SET_RETVAL(answer->data, rc);
+	}
+
+	return rc;
+}
+
+sysipc_ops_t ipc_m_share_out_ops = {
+	.request_preprocess = request_preprocess,
+	.request_forget = null_request_forget,
+	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
+	.answer_preprocess = answer_preprocess,
+	.answer_process = null_answer_process,
+};
+
+/** @}
+ */
Index: kernel/generic/src/ipc/ops/stchngath.c
===================================================================
--- kernel/generic/src/ipc/ops/stchngath.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/src/ipc/ops/stchngath.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,128 @@
+/*
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/sysipc_ops.h>
+#include <ipc/ipc.h>
+#include <ipc/ipcrsc.h>
+#include <synch/mutex.h>
+#include <proc/task.h>
+#include <abi/errno.h>
+#include <macros.h>
+
+static int request_preprocess(call_t *call, phone_t *phone)
+{
+	phone_t *sender_phone;
+	task_t *other_task_s;
+
+	if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK)
+		return ENOENT;
+
+	mutex_lock(&sender_phone->lock);
+	if (sender_phone->state != IPC_PHONE_CONNECTED) {
+		mutex_unlock(&sender_phone->lock);
+		return EINVAL;
+	}
+
+	other_task_s = sender_phone->callee->task;
+
+	mutex_unlock(&sender_phone->lock);
+
+	/* Remember the third party task hash. */
+	IPC_SET_ARG5(call->data, (sysarg_t) other_task_s);
+
+	return EOK;
+}
+
+static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
+{
+	int rc = EOK;
+
+	if (!IPC_GET_RETVAL(answer->data)) {
+		/* The recipient authorized the change of state. */
+		phone_t *recipient_phone;
+		task_t *other_task_s;
+		task_t *other_task_r;
+
+		rc = phone_get(IPC_GET_ARG1(answer->data),
+		    &recipient_phone);
+		if (rc != EOK) {
+			IPC_SET_RETVAL(answer->data, ENOENT);
+			return ENOENT;
+		}
+
+		mutex_lock(&recipient_phone->lock);
+		if (recipient_phone->state != IPC_PHONE_CONNECTED) {
+			mutex_unlock(&recipient_phone->lock);
+			IPC_SET_RETVAL(answer->data, EINVAL);
+			return EINVAL;
+		}
+
+		other_task_r = recipient_phone->callee->task;
+		other_task_s = (task_t *) IPC_GET_ARG5(*olddata);
+
+		/*
+		 * See if both the sender and the recipient meant the
+		 * same third party task.
+		 */
+		if (other_task_r != other_task_s) {
+			IPC_SET_RETVAL(answer->data, EINVAL);
+			rc = EINVAL;
+		} else {
+			rc = event_task_notify_5(other_task_r,
+			    EVENT_TASK_STATE_CHANGE, false,
+			    IPC_GET_ARG1(*olddata),
+			    IPC_GET_ARG2(*olddata),
+			    IPC_GET_ARG3(*olddata),
+			    LOWER32(olddata->task_id),
+			    UPPER32(olddata->task_id));
+			IPC_SET_RETVAL(answer->data, rc);
+		}
+
+		mutex_unlock(&recipient_phone->lock);
+	}
+
+	return rc;
+}
+
+sysipc_ops_t ipc_m_state_change_authorize_ops = {
+	.request_preprocess = request_preprocess,
+	.request_forget = null_request_forget,
+	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
+	.answer_preprocess = answer_preprocess,
+	.answer_process = null_answer_process,
+};
+
+/** @}
+ */
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/ipc/sysipc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -34,12 +34,11 @@
 
 #include <arch.h>
-#include <proc/task.h>
-#include <proc/thread.h>
 #include <errno.h>
 #include <memstr.h>
-#include <debug.h>
 #include <ipc/ipc.h>
 #include <abi/ipc/methods.h>
 #include <ipc/sysipc.h>
+#include <ipc/sysipc_ops.h>
+#include <ipc/sysipc_priv.h>
 #include <ipc/irq.h>
 #include <ipc/ipcrsc.h>
@@ -47,37 +46,12 @@
 #include <ipc/kbox.h>
 #include <synch/waitq.h>
-#include <udebug/udebug_ipc.h>
 #include <arch/interrupt.h>
 #include <syscall/copy.h>
 #include <security/cap.h>
 #include <console/console.h>
-#include <mm/as.h>
 #include <print.h>
 #include <macros.h>
 
-/**
- * Maximum buffer size allowed for IPC_M_DATA_WRITE and IPC_M_DATA_READ
- * requests.
- */
-#define DATA_XFER_LIMIT  (64 * 1024)
-
 #define STRUCT_TO_USPACE(dst, src)  copy_to_uspace((dst), (src), sizeof(*(src)))
-
-/** Get phone from the current task by ID.
- *
- * @param phoneid Phone ID.
- * @param phone   Place to store pointer to phone.
- *
- * @return EOK on success, EINVAL if ID is invalid.
- *
- */
-static int phone_get(sysarg_t phoneid, phone_t **phone)
-{
-	if (phoneid >= IPC_MAX_PHONES)
-		return EINVAL;
-	
-	*phone = &TASK->phones[phoneid];
-	return EOK;
-}
 
 /** Decide if the interface and method is a system method.
@@ -181,235 +155,59 @@
  * @param olddata Saved data of the request.
  *
- * @return Return 0 on success or an error code.
- *
- */
-static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata)
-{
+ * @return Return EOK on success or a negative error code.
+ *
+ */
+int answer_preprocess(call_t *answer, ipc_data_t *olddata)
+{
+	int rc = EOK;
+
+	spinlock_lock(&answer->forget_lock);
+	if (answer->forget) {
+		/*
+		 * This is a forgotten call and answer->sender is not valid.
+		 */
+		spinlock_unlock(&answer->forget_lock);
+
+		SYSIPC_OP(answer_cleanup, answer, olddata);
+		return rc;
+	} else {
+		ASSERT(answer->active);
+
+		/*
+		 * Mark the call as inactive to prevent _ipc_answer_free_call()
+		 * from attempting to remove the call from the active list
+		 * itself.
+		 */
+		answer->active = false;
+
+		/*
+		 * Remove the call from the sender's active call list.
+		 * We enforce this locking order so that any potential
+		 * concurrently executing forget operation is forced to
+		 * release its active_calls_lock and lose the race to
+		 * forget this soon to be answered call. 
+		 */
+		spinlock_lock(&answer->sender->active_calls_lock);
+		list_remove(&answer->ta_link);
+		spinlock_unlock(&answer->sender->active_calls_lock);
+	}
+	spinlock_unlock(&answer->forget_lock);
+
 	if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) {
-		/* In case of forward, hangup the forwared phone,
-		 * not the originator
-		 */
-		mutex_lock(&answer->data.phone->lock);
-		irq_spinlock_lock(&TASK->answerbox.lock, true);
-		if (answer->data.phone->state == IPC_PHONE_CONNECTED) {
-			list_remove(&answer->data.phone->link);
-			answer->data.phone->state = IPC_PHONE_SLAMMED;
+		phone_t *phone = answer->caller_phone;
+		mutex_lock(&phone->lock);
+		if (phone->state == IPC_PHONE_CONNECTED) {
+			irq_spinlock_lock(&phone->callee->lock, true);
+			list_remove(&phone->link);
+			phone->state = IPC_PHONE_SLAMMED;
+			irq_spinlock_unlock(&phone->callee->lock, true);
 		}
-		irq_spinlock_unlock(&TASK->answerbox.lock, true);
-		mutex_unlock(&answer->data.phone->lock);
+		mutex_unlock(&phone->lock);
 	}
 	
 	if (!olddata)
-		return 0;
-	
-	if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECTION_CLONE) {
-		int phoneid = IPC_GET_ARG1(*olddata);
-		phone_t *phone = &TASK->phones[phoneid];
-		
-		if (IPC_GET_RETVAL(answer->data) != EOK) {
-			/*
-			 * The recipient of the cloned phone rejected the offer.
-			 * In this case, the connection was established at the
-			 * request time and therefore we need to slam the phone.
-			 * We don't merely hangup as that would result in
-			 * sending IPC_M_HUNGUP to the third party on the
-			 * other side of the cloned phone.
-			 */
-			mutex_lock(&phone->lock);
-			if (phone->state == IPC_PHONE_CONNECTED) {
-				irq_spinlock_lock(&phone->callee->lock, true);
-				list_remove(&phone->link);
-				phone->state = IPC_PHONE_SLAMMED;
-				irq_spinlock_unlock(&phone->callee->lock, true);
-			}
-			mutex_unlock(&phone->lock);
-		}
-	} else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CLONE_ESTABLISH) {
-		phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
-		
-		if (IPC_GET_RETVAL(answer->data) != EOK) {
-			/*
-			 * The other party on the cloned phoned rejected our
-			 * request for connection on the protocol level.
-			 * We need to break the connection without sending
-			 * IPC_M_HUNGUP back.
-			 */
-			mutex_lock(&phone->lock);
-			if (phone->state == IPC_PHONE_CONNECTED) {
-				irq_spinlock_lock(&phone->callee->lock, true);
-				list_remove(&phone->link);
-				phone->state = IPC_PHONE_SLAMMED;
-				irq_spinlock_unlock(&phone->callee->lock, true);
-			}
-			mutex_unlock(&phone->lock);
-		}
-	} else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
-		int phoneid = IPC_GET_ARG5(*olddata);
-		
-		if (IPC_GET_RETVAL(answer->data) != EOK) {
-			/* The connection was not accepted */
-			phone_dealloc(phoneid);
-		} else {
-			/* The connection was accepted */
-			phone_connect(phoneid, &answer->sender->answerbox);
-			/* Set 'phone hash' as arg5 of response */
-			IPC_SET_ARG5(answer->data,
-			    (sysarg_t) &TASK->phones[phoneid]);
-		}
-	} else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_ME_TO) {
-		/* If the users accepted call, connect */
-		if (IPC_GET_RETVAL(answer->data) == EOK) {
-			ipc_phone_connect((phone_t *) IPC_GET_ARG5(*olddata),
-			    &TASK->answerbox);
-		}
-	} else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_OUT) {
-		if (!IPC_GET_RETVAL(answer->data)) {
-			/* Accepted, handle as_area receipt */
-			
-			irq_spinlock_lock(&answer->sender->lock, true);
-			as_t *as = answer->sender->as;
-			irq_spinlock_unlock(&answer->sender->lock, true);
-			
-			uintptr_t dst_base = (uintptr_t) -1;
-			int rc = as_area_share(as, IPC_GET_ARG1(*olddata),
-			    IPC_GET_ARG2(*olddata), AS, IPC_GET_ARG3(*olddata),
-			    &dst_base, IPC_GET_ARG1(answer->data));
-			
-			if (rc == EOK)
-				rc = copy_to_uspace((void *) IPC_GET_ARG2(answer->data),
-				    &dst_base, sizeof(dst_base));
-			
-			IPC_SET_RETVAL(answer->data, rc);
-			return rc;
-		}
-	} else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_IN) {
-		if (!IPC_GET_RETVAL(answer->data)) {
-			irq_spinlock_lock(&answer->sender->lock, true);
-			as_t *as = answer->sender->as;
-			irq_spinlock_unlock(&answer->sender->lock, true);
-			
-			uintptr_t dst_base = (uintptr_t) -1;
-			int rc = as_area_share(AS, IPC_GET_ARG1(answer->data),
-			    IPC_GET_ARG1(*olddata), as, IPC_GET_ARG2(answer->data),
-			    &dst_base, IPC_GET_ARG3(answer->data));
-			IPC_SET_ARG4(answer->data, dst_base);
-			IPC_SET_RETVAL(answer->data, rc);
-		}
-	} else if (IPC_GET_IMETHOD(*olddata) == IPC_M_DATA_READ) {
-		ASSERT(!answer->buffer);
-		if (!IPC_GET_RETVAL(answer->data)) {
-			/* The recipient agreed to send data. */
-			uintptr_t src = IPC_GET_ARG1(answer->data);
-			uintptr_t dst = IPC_GET_ARG1(*olddata);
-			size_t max_size = IPC_GET_ARG2(*olddata);
-			size_t size = IPC_GET_ARG2(answer->data);
-			if (size && size <= max_size) {
-				/*
-				 * Copy the destination VA so that this piece of
-				 * information is not lost.
-				 */
-				IPC_SET_ARG1(answer->data, dst);
-				
-				answer->buffer = malloc(size, 0);
-				int rc = copy_from_uspace(answer->buffer,
-				    (void *) src, size);
-				if (rc) {
-					IPC_SET_RETVAL(answer->data, rc);
-					free(answer->buffer);
-					answer->buffer = NULL;
-				}
-			} else if (!size) {
-				IPC_SET_RETVAL(answer->data, EOK);
-			} else {
-				IPC_SET_RETVAL(answer->data, ELIMIT);
-			}
-		}
-	} else if (IPC_GET_IMETHOD(*olddata) == IPC_M_DATA_WRITE) {
-		ASSERT(answer->buffer);
-		if (!IPC_GET_RETVAL(answer->data)) {
-			/* The recipient agreed to receive data. */
-			uintptr_t dst = (uintptr_t)IPC_GET_ARG1(answer->data);
-			size_t size = (size_t)IPC_GET_ARG2(answer->data);
-			size_t max_size = (size_t)IPC_GET_ARG2(*olddata);
-			
-			if (size <= max_size) {
-				int rc = copy_to_uspace((void *) dst,
-				    answer->buffer, size);
-				if (rc)
-					IPC_SET_RETVAL(answer->data, rc);
-			} else {
-				IPC_SET_RETVAL(answer->data, ELIMIT);
-			}
-		}
-		free(answer->buffer);
-		answer->buffer = NULL;
-	} else if (IPC_GET_IMETHOD(*olddata) == IPC_M_STATE_CHANGE_AUTHORIZE) {
-		if (!IPC_GET_RETVAL(answer->data)) {
-			/* The recipient authorized the change of state. */
-			phone_t *recipient_phone;
-			task_t *other_task_s;
-			task_t *other_task_r;
-			int rc;
-
-			rc = phone_get(IPC_GET_ARG1(answer->data),
-			    &recipient_phone);
-			if (rc != EOK) {
-				IPC_SET_RETVAL(answer->data, ENOENT);
-				return ENOENT;
-			}
-
-			mutex_lock(&recipient_phone->lock);
-			if (recipient_phone->state != IPC_PHONE_CONNECTED) {
-				mutex_unlock(&recipient_phone->lock);
-				IPC_SET_RETVAL(answer->data, EINVAL);
-				return EINVAL;
-			}
-
-			other_task_r = recipient_phone->callee->task;
-			other_task_s = (task_t *) IPC_GET_ARG5(*olddata);
-
-			/*
-			 * See if both the sender and the recipient meant the
-			 * same third party task.
-			 */
-			if (other_task_r != other_task_s) {
-				IPC_SET_RETVAL(answer->data, EINVAL);
-				rc = EINVAL;
-			} else {
-				rc = event_task_notify_5(other_task_r,
-				    EVENT_TASK_STATE_CHANGE, false,
-				    IPC_GET_ARG1(*olddata),
-				    IPC_GET_ARG2(*olddata),
-				    IPC_GET_ARG3(*olddata),
-				    LOWER32(olddata->task_id),
-				    UPPER32(olddata->task_id));
-				IPC_SET_RETVAL(answer->data, rc);
-			}
-
-			mutex_unlock(&recipient_phone->lock);
-			return rc;
-		}
-	}
-	
-	return 0;
-}
-
-static void phones_lock(phone_t *p1, phone_t *p2)
-{
-	if (p1 < p2) {
-		mutex_lock(&p1->lock);
-		mutex_lock(&p2->lock);
-	} else if (p1 > p2) {
-		mutex_lock(&p2->lock);
-		mutex_lock(&p1->lock);
-	} else
-		mutex_lock(&p1->lock);
-}
-
-static void phones_unlock(phone_t *p1, phone_t *p2)
-{
-	mutex_unlock(&p1->lock);
-	if (p1 != p2)
-		mutex_unlock(&p2->lock);
+		return rc;
+
+	return SYSIPC_OP(answer_preprocess, answer, olddata);
 }
 
@@ -424,124 +222,6 @@
 static int request_preprocess(call_t *call, phone_t *phone)
 {
-	switch (IPC_GET_IMETHOD(call->data)) {
-	case IPC_M_CONNECTION_CLONE: {
-		phone_t *cloned_phone;
-		if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK)
-			return ENOENT;
-		
-		phones_lock(cloned_phone, phone);
-		
-		if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
-		    phone->state != IPC_PHONE_CONNECTED) {
-			phones_unlock(cloned_phone, phone);
-			return EINVAL;
-		}
-		
-		/*
-		 * We can be pretty sure now that both tasks exist and we are
-		 * connected to them. As we continue to hold the phone locks,
-		 * we are effectively preventing them from finishing their
-		 * potential cleanup.
-		 *
-		 */
-		int newphid = phone_alloc(phone->callee->task);
-		if (newphid < 0) {
-			phones_unlock(cloned_phone, phone);
-			return ELIMIT;
-		}
-		
-		ipc_phone_connect(&phone->callee->task->phones[newphid],
-		    cloned_phone->callee);
-		phones_unlock(cloned_phone, phone);
-		
-		/* Set the new phone for the callee. */
-		IPC_SET_ARG1(call->data, newphid);
-		break;
-	}
-	case IPC_M_CLONE_ESTABLISH:
-		IPC_SET_ARG5(call->data, (sysarg_t) phone);
-		break;
-	case IPC_M_CONNECT_ME_TO: {
-		int newphid = phone_alloc(TASK);
-		if (newphid < 0)
-			return ELIMIT;
-		
-		/* Set arg5 for server */
-		IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]);
-		call->flags |= IPC_CALL_CONN_ME_TO;
-		call->priv = newphid;
-		break;
-	}
-	case IPC_M_SHARE_OUT: {
-		size_t size = as_area_get_size(IPC_GET_ARG1(call->data));
-		if (!size)
-			return EPERM;
-		
-		IPC_SET_ARG2(call->data, size);
-		break;
-	}
-	case IPC_M_DATA_READ: {
-		size_t size = IPC_GET_ARG2(call->data);
-		if (size > DATA_XFER_LIMIT) {
-			int flags = IPC_GET_ARG3(call->data);
-			if (flags & IPC_XF_RESTRICT)
-				IPC_SET_ARG2(call->data, DATA_XFER_LIMIT);
-			else
-				return ELIMIT;
-		}
-		break;
-	}
-	case IPC_M_DATA_WRITE: {
-		uintptr_t src = IPC_GET_ARG1(call->data);
-		size_t size = IPC_GET_ARG2(call->data);
-		
-		if (size > DATA_XFER_LIMIT) {
-			int flags = IPC_GET_ARG3(call->data);
-			if (flags & IPC_XF_RESTRICT) {
-				size = DATA_XFER_LIMIT;
-				IPC_SET_ARG2(call->data, size);
-			} else
-				return ELIMIT;
-		}
-		
-		call->buffer = (uint8_t *) malloc(size, 0);
-		int rc = copy_from_uspace(call->buffer, (void *) src, size);
-		if (rc != 0) {
-			free(call->buffer);
-			return rc;
-		}
-		
-		break;
-	}
-	case IPC_M_STATE_CHANGE_AUTHORIZE: {
-		phone_t *sender_phone;
-		task_t *other_task_s;
-
-		if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK)
-			return ENOENT;
-
-		mutex_lock(&sender_phone->lock);
-		if (sender_phone->state != IPC_PHONE_CONNECTED) {
-			mutex_unlock(&sender_phone->lock);
-			return EINVAL;
-		}
-
-		other_task_s = sender_phone->callee->task;
-
-		mutex_unlock(&sender_phone->lock);
-
-		/* Remember the third party task hash. */
-		IPC_SET_ARG5(call->data, (sysarg_t) other_task_s);
-		break;
-	}
-#ifdef CONFIG_UDEBUG
-	case IPC_M_DEBUG:
-		return udebug_request_preprocess(call, phone);
-#endif
-	default:
-		break;
-	}
-	
-	return 0;
+	call->request_method = IPC_GET_IMETHOD(call->data);
+	return SYSIPC_OP(request_preprocess, call, phone);
 }
 
@@ -561,26 +241,7 @@
 		IPC_SET_RETVAL(call->data, EFORWARD);
 	
-	if (call->flags & IPC_CALL_CONN_ME_TO) {
-		if (IPC_GET_RETVAL(call->data))
-			phone_dealloc(call->priv);
-		else
-			IPC_SET_ARG5(call->data, call->priv);
-	}
-	
-	if (call->buffer) {
-		/*
-		 * This must be an affirmative answer to IPC_M_DATA_READ
-		 * or IPC_M_DEBUG/UDEBUG_M_MEM_READ...
-		 *
-		 */
-		uintptr_t dst = IPC_GET_ARG1(call->data);
-		size_t size = IPC_GET_ARG2(call->data);
-		int rc = copy_to_uspace((void *) dst, call->buffer, size);
-		if (rc)
-			IPC_SET_RETVAL(call->data, rc);
-		free(call->buffer);
-		call->buffer = NULL;
-	}
-}
+	SYSIPC_OP(answer_process, call);
+}
+
 
 /** Do basic kernel processing of received call request.
@@ -595,142 +256,5 @@
 static int process_request(answerbox_t *box, call_t *call)
 {
-	if (IPC_GET_IMETHOD(call->data) == IPC_M_CONNECT_TO_ME) {
-		int phoneid = phone_alloc(TASK);
-		if (phoneid < 0) {  /* Failed to allocate phone */
-			IPC_SET_RETVAL(call->data, ELIMIT);
-			ipc_answer(box, call);
-			return -1;
-		}
-		
-		IPC_SET_ARG5(call->data, phoneid);
-	}
-	
-	switch (IPC_GET_IMETHOD(call->data)) {
-	case IPC_M_DEBUG:
-		return -1;
-	default:
-		break;
-	}
-	
-	return 0;
-}
-
-/** Make a fast call over IPC, wait for reply and return to user.
- *
- * This function can handle only three arguments of payload, but is faster than
- * the generic function (i.e. sys_ipc_call_sync_slow()).
- *
- * @param phoneid Phone handle for the call.
- * @param imethod Interface and method of the call.
- * @param arg1    Service-defined payload argument.
- * @param arg2    Service-defined payload argument.
- * @param arg3    Service-defined payload argument.
- * @param data    Address of user-space structure where the reply call will
- *                be stored.
- *
- * @return 0 on success.
- * @return ENOENT if there is no such phone handle.
- *
- */
-sysarg_t sys_ipc_call_sync_fast(sysarg_t phoneid, sysarg_t imethod,
-    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, ipc_data_t *data)
-{
-	phone_t *phone;
-	if (phone_get(phoneid, &phone) != EOK)
-		return ENOENT;
-	
-	call_t *call = ipc_call_alloc(0);
-	IPC_SET_IMETHOD(call->data, imethod);
-	IPC_SET_ARG1(call->data, arg1);
-	IPC_SET_ARG2(call->data, arg2);
-	IPC_SET_ARG3(call->data, arg3);
-	
-	/*
-	 * To achieve deterministic behavior, zero out arguments that are beyond
-	 * the limits of the fast version.
-	 */
-	IPC_SET_ARG4(call->data, 0);
-	IPC_SET_ARG5(call->data, 0);
-	
-	int res = request_preprocess(call, phone);
-	int rc;
-	
-	if (!res) {
-#ifdef CONFIG_UDEBUG
-		udebug_stoppable_begin();
-#endif
-		rc = ipc_call_sync(phone, call);
-#ifdef CONFIG_UDEBUG
-		udebug_stoppable_end();
-#endif
-		
-		if (rc != EOK) {
-			/* The call will be freed by ipc_cleanup(). */
-			return rc;
-		}
-		
-		process_answer(call);
-	} else
-		IPC_SET_RETVAL(call->data, res);
-	
-	rc = STRUCT_TO_USPACE(&data->args, &call->data.args);
-	ipc_call_free(call);
-	if (rc != 0)
-		return rc;
-	
-	return 0;
-}
-
-/** Make a synchronous IPC call allowing to transmit the entire payload.
- *
- * @param phoneid Phone handle for the call.
- * @param request User-space address of call data with the request.
- * @param reply   User-space address of call data where to store the
- *                answer.
- *
- * @return Zero on success or an error code.
- *
- */
-sysarg_t sys_ipc_call_sync_slow(sysarg_t phoneid, ipc_data_t *request,
-    ipc_data_t *reply)
-{
-	phone_t *phone;
-	if (phone_get(phoneid, &phone) != EOK)
-		return ENOENT;
-	
-	call_t *call = ipc_call_alloc(0);
-	int rc = copy_from_uspace(&call->data.args, &request->args,
-	    sizeof(call->data.args));
-	if (rc != 0) {
-		ipc_call_free(call);
-		return (sysarg_t) rc;
-	}
-	
-	int res = request_preprocess(call, phone);
-	
-	if (!res) {
-#ifdef CONFIG_UDEBUG
-		udebug_stoppable_begin();
-#endif
-		rc = ipc_call_sync(phone, call);
-#ifdef CONFIG_UDEBUG
-		udebug_stoppable_end();
-#endif
-		
-		if (rc != EOK) {
-			/* The call will be freed by ipc_cleanup(). */
-			return rc;
-		}
-		
-		process_answer(call);
-	} else
-		IPC_SET_RETVAL(call->data, res);
-	
-	rc = STRUCT_TO_USPACE(&reply->args, &call->data.args);
-	ipc_call_free(call);
-	if (rc != 0)
-		return rc;
-	
-	return 0;
+	return SYSIPC_OP(request_process, call, box);
 }
 
@@ -864,21 +388,27 @@
 {
 	call_t *call = get_call(callid);
+	phone_t *phone;
+	bool need_old = answer_need_old(call);
+	bool after_forward = false;
+	ipc_data_t old;
+	int rc;
+
 	if (!call)
 		return ENOENT;
-	
+
+	if (need_old)
+		old = call->data;
+	
+	if (phone_get(phoneid, &phone) != EOK) {
+		rc = ENOENT;
+		goto error;
+	}
+	
+	if (!method_is_forwardable(IPC_GET_IMETHOD(call->data))) {
+		rc = EPERM;
+		goto error;
+	}
+
 	call->flags |= IPC_CALL_FORWARDED;
-	
-	phone_t *phone;
-	if (phone_get(phoneid, &phone) != EOK) {
-		IPC_SET_RETVAL(call->data, EFORWARD);
-		ipc_answer(&TASK->answerbox, call);
-		return ENOENT;
-	}
-	
-	if (!method_is_forwardable(IPC_GET_IMETHOD(call->data))) {
-		IPC_SET_RETVAL(call->data, EFORWARD);
-		ipc_answer(&TASK->answerbox, call);
-		return EPERM;
-	}
 	
 	/*
@@ -916,5 +446,21 @@
 	}
 	
-	return ipc_forward(call, phone, &TASK->answerbox, mode);
+	rc = ipc_forward(call, phone, &TASK->answerbox, mode);
+	if (rc != EOK) {
+		after_forward = true;
+		goto error;
+	}
+
+	return EOK;
+
+error:
+	IPC_SET_RETVAL(call->data, EFORWARD);
+	(void) answer_preprocess(call, need_old ? &old : NULL);
+	if (after_forward)
+		_ipc_answer_free_call(call, false);
+	else
+		ipc_answer(&TASK->answerbox, call);
+
+	return rc;
 }
 
Index: kernel/generic/src/ipc/sysipc_ops.c
===================================================================
--- kernel/generic/src/ipc/sysipc_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ kernel/generic/src/ipc/sysipc_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,112 @@
+/*
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#include <ipc/sysipc_ops.h>
+#include <abi/ipc/methods.h>
+#include <abi/errno.h>
+
+/* Forward declarations. */
+sysipc_ops_t ipc_m_connection_clone_ops;
+sysipc_ops_t ipc_m_clone_establish_ops;
+sysipc_ops_t ipc_m_connect_to_me_ops;
+sysipc_ops_t ipc_m_connect_me_to_ops;
+sysipc_ops_t ipc_m_share_out_ops;
+sysipc_ops_t ipc_m_share_in_ops;
+sysipc_ops_t ipc_m_data_write_ops;
+sysipc_ops_t ipc_m_data_read_ops;
+sysipc_ops_t ipc_m_state_change_authorize_ops;
+sysipc_ops_t ipc_m_debug_ops;
+
+static sysipc_ops_t *sysipc_ops[] = {
+	[IPC_M_CONNECTION_CLONE] = &ipc_m_connection_clone_ops,
+	[IPC_M_CLONE_ESTABLISH] = &ipc_m_clone_establish_ops,
+	[IPC_M_CONNECT_TO_ME] = &ipc_m_connect_to_me_ops,
+	[IPC_M_CONNECT_ME_TO] = &ipc_m_connect_me_to_ops,
+	[IPC_M_SHARE_OUT] = &ipc_m_share_out_ops,
+	[IPC_M_SHARE_IN] = &ipc_m_share_in_ops,
+	[IPC_M_DATA_WRITE] = &ipc_m_data_write_ops,
+	[IPC_M_DATA_READ] = &ipc_m_data_read_ops,
+	[IPC_M_STATE_CHANGE_AUTHORIZE] = &ipc_m_state_change_authorize_ops,
+	[IPC_M_DEBUG] = &ipc_m_debug_ops
+};
+
+static sysipc_ops_t null_ops = {
+	.request_preprocess = null_request_preprocess,
+	.request_forget = null_request_forget,
+	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
+	.answer_preprocess = null_answer_preprocess,
+	.answer_process = null_answer_process,
+};
+
+int null_request_preprocess(call_t *call, phone_t *phone)
+{
+	return EOK;
+}
+
+int null_request_forget(call_t *call)
+{
+	return EOK;
+}
+
+int null_request_process(call_t *call, answerbox_t *box)
+{
+	return EOK;
+}
+
+int null_answer_cleanup(call_t *call, ipc_data_t *data)
+{
+	return EOK;
+}
+
+int null_answer_preprocess(call_t *call, ipc_data_t *data)
+{
+	return EOK;
+}
+
+int null_answer_process(call_t *call)
+{
+	return EOK;
+}
+
+sysipc_ops_t *sysipc_ops_get(sysarg_t imethod)
+{
+	if (imethod < sizeof(sysipc_ops) / (sizeof(sysipc_ops_t *)))
+		return sysipc_ops[imethod] ? sysipc_ops[imethod] : &null_ops;
+
+	return &null_ops;
+}
+
+/** @}
+ */
Index: kernel/generic/src/lib/ra.c
===================================================================
--- kernel/generic/src/lib/ra.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/lib/ra.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -424,5 +424,5 @@
 void ra_init(void)
 {
-	ra_segment_cache = slab_cache_create("segment_cache",
+	ra_segment_cache = slab_cache_create("ra_segment_t",
 	    sizeof(ra_segment_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED);
 }
Index: kernel/generic/src/lib/str.c
===================================================================
--- kernel/generic/src/lib/str.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/lib/str.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -456,12 +456,17 @@
  *
  * Do a char-by-char comparison of two NULL-terminated strings.
- * The strings are considered equal iff they consist of the same
- * characters on the minimum of their lengths.
+ * The strings are considered equal iff their length is equal
+ * and both strings consist of the same sequence of characters.
+ *
+ * A string S1 is less than another string S2 if it has a character with
+ * lower value at the first character position where the strings differ.
+ * If the strings differ in length, the shorter one is treated as if
+ * padded by characters with a value of zero.
  *
  * @param s1 First string to compare.
  * @param s2 Second string to compare.
  *
- * @return 0 if the strings are equal, -1 if first is smaller,
- *         1 if second smaller.
+ * @return 0 if the strings are equal, -1 if the first is less than the second,
+ *         1 if the second is less than the first.
  *
  */
@@ -494,6 +499,14 @@
  *
  * Do a char-by-char comparison of two NULL-terminated strings.
- * The strings are considered equal iff they consist of the same
- * characters on the minimum of their lengths and the length limit.
+ * The strings are considered equal iff
+ * min(str_length(s1), max_len) == min(str_length(s2), max_len)
+ * and both strings consist of the same sequence of characters,
+ * up to max_len characters.
+ *
+ * A string S1 is less than another string S2 if it has a character with
+ * lower value at the first character position where the strings differ.
+ * If the strings differ in length, the shorter one is treated as if
+ * padded by characters with a value of zero. Only the first max_len
+ * characters are considered.
  *
  * @param s1      First string to compare.
@@ -501,6 +514,6 @@
  * @param max_len Maximum number of characters to consider.
  *
- * @return 0 if the strings are equal, -1 if first is smaller,
- *         1 if second smaller.
+ * @return 0 if the strings are equal, -1 if the first is less than the second,
+ *         1 if the second is less than the first.
  *
  */
Index: kernel/generic/src/main/kinit.c
===================================================================
--- kernel/generic/src/main/kinit.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/main/kinit.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -69,4 +69,5 @@
 #include <str.h>
 #include <sysinfo/stats.h>
+#include <sysinfo/sysinfo.h>
 #include <align.h>
 
@@ -116,9 +117,8 @@
 		 * Just a beautification.
 		 */
-		thread = thread_create(kmp, NULL, TASK, THREAD_FLAG_WIRED, "kmp", true);
+		thread = thread_create(kmp, NULL, TASK,
+		    THREAD_FLAG_UNCOUNTED, "kmp");
 		if (thread != NULL) {
-			irq_spinlock_lock(&thread->lock, false);
-			thread->cpu = &cpus[0];
-			irq_spinlock_unlock(&thread->lock, false);
+			thread_wire(thread, &cpus[0]);
 			thread_ready(thread);
 		} else
@@ -134,9 +134,8 @@
 		
 		for (i = 0; i < config.cpu_count; i++) {
-			thread = thread_create(kcpulb, NULL, TASK, THREAD_FLAG_WIRED, "kcpulb", true);
+			thread = thread_create(kcpulb, NULL, TASK,
+			    THREAD_FLAG_UNCOUNTED, "kcpulb");
 			if (thread != NULL) {
-				irq_spinlock_lock(&thread->lock, false);
-				thread->cpu = &cpus[i];
-				irq_spinlock_unlock(&thread->lock, false);
+				thread_wire(thread, &cpus[i]);
 				thread_ready(thread);
 			} else
@@ -152,5 +151,6 @@
 	
 	/* Start thread computing system load */
-	thread = thread_create(kload, NULL, TASK, 0, "kload", false);
+	thread = thread_create(kload, NULL, TASK, THREAD_FLAG_NONE,
+	    "kload");
 	if (thread != NULL)
 		thread_ready(thread);
@@ -163,5 +163,6 @@
 		 * Create kernel console.
 		 */
-		thread = thread_create(kconsole_thread, NULL, TASK, 0, "kconsole", false);
+		thread = thread_create(kconsole_thread, NULL, TASK,
+		    THREAD_FLAG_NONE, "kconsole");
 		if (thread != NULL)
 			thread_ready(thread);
@@ -179,4 +180,26 @@
 	program_t programs[CONFIG_INIT_TASKS];
 	
+	// FIXME: do not propagate arguments through sysinfo
+	// but pass them directly to the tasks
+	for (i = 0; i < init.cnt; i++) {
+		const char *arguments = init.tasks[i].arguments;
+		if (str_length(arguments) == 0)
+			continue;
+		if (str_length(init.tasks[i].name) == 0)
+			continue;
+		size_t arguments_size = str_size(arguments);
+
+		void *arguments_copy = malloc(arguments_size, 0);
+		if (arguments_copy == NULL)
+			continue;
+		memcpy(arguments_copy, arguments, arguments_size);
+
+		char item_name[CONFIG_TASK_NAME_BUFLEN + 15];
+		snprintf(item_name, CONFIG_TASK_NAME_BUFLEN + 15,
+		    "init_args.%s", init.tasks[i].name);
+
+		sysinfo_set_item_data(item_name, NULL, arguments_copy, arguments_size);
+	}
+
 	for (i = 0; i < init.cnt; i++) {
 		if (init.tasks[i].paddr % FRAME_SIZE) {
Index: kernel/generic/src/main/main.c
===================================================================
--- kernel/generic/src/main/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/main/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -276,6 +276,6 @@
 	 * Create the first thread.
 	 */
-	thread_t *kinit_thread =
-	    thread_create(kinit, NULL, kernel, 0, "kinit", true);
+	thread_t *kinit_thread = thread_create(kinit, NULL, kernel,
+	    THREAD_FLAG_UNCOUNTED, "kinit");
 	if (!kinit_thread)
 		panic("Cannot create kinit thread.");
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/mm/as.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -130,5 +130,5 @@
 	as_arch_init();
 	
-	as_slab = slab_cache_create("as_slab", sizeof(as_t), 0,
+	as_slab = slab_cache_create("as_t", sizeof(as_t), 0,
 	    as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED);
 	
@@ -285,8 +285,9 @@
 /** Check area conflicts with other areas.
  *
- * @param as    Address space.
- * @param addr  Starting virtual address of the area being tested.
- * @param count Number of pages in the area being tested.
- * @param avoid Do not touch this area.
+ * @param as      Address space.
+ * @param addr    Starting virtual address of the area being tested.
+ * @param count   Number of pages in the area being tested.
+ * @param guarded True if the area being tested is protected by guard pages.
+ * @param avoid   Do not touch this area.
  *
  * @return True if there is no conflict, false otherwise.
@@ -294,8 +295,15 @@
  */
 NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr,
-    size_t count, as_area_t *avoid)
+    size_t count, bool guarded, as_area_t *avoid)
 {
 	ASSERT((addr % PAGE_SIZE) == 0);
 	ASSERT(mutex_locked(&as->lock));
+
+	/*
+	 * If the addition of the supposed area address and size overflows,
+	 * report conflict.
+	 */
+	if (overflows_into_positive(addr, P2SZ(count)))
+		return false;
 	
 	/*
@@ -304,5 +312,5 @@
 	if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE))
 		return false;
-	
+
 	/*
 	 * The leaf node is found in O(log n), where n is proportional to
@@ -328,6 +336,51 @@
 		if (area != avoid) {
 			mutex_lock(&area->lock);
-			
+
+			/*
+			 * If at least one of the two areas are protected
+			 * by the AS_AREA_GUARD flag then we must be sure
+			 * that they are separated by at least one unmapped
+			 * page.
+			 */
+			int const gp = (guarded || 
+			    (area->flags & AS_AREA_GUARD)) ? 1 : 0;
+			
+			/*
+			 * The area comes from the left neighbour node, which
+			 * means that there already are some areas in the leaf
+			 * node, which in turn means that adding gp is safe and
+			 * will not cause an integer overflow.
+			 */
 			if (overlaps(addr, P2SZ(count), area->base,
+			    P2SZ(area->pages + gp))) {
+				mutex_unlock(&area->lock);
+				return false;
+			}
+			
+			mutex_unlock(&area->lock);
+		}
+	}
+	
+	node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
+	if (node) {
+		area = (as_area_t *) node->value[0];
+		
+		if (area != avoid) {
+			int gp;
+
+			mutex_lock(&area->lock);
+
+			gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0;
+			if (gp && overflows(addr, P2SZ(count))) {
+				/*
+				 * Guard page not needed if the supposed area
+				 * is adjacent to the end of the address space.
+				 * We already know that the following test is
+				 * going to fail...
+				 */
+				gp--;
+			}
+			
+			if (overlaps(addr, P2SZ(count + gp), area->base,
 			    P2SZ(area->pages))) {
 				mutex_unlock(&area->lock);
@@ -339,25 +392,10 @@
 	}
 	
-	node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
-	if (node) {
-		area = (as_area_t *) node->value[0];
-		
-		if (area != avoid) {
-			mutex_lock(&area->lock);
-			
-			if (overlaps(addr, P2SZ(count), area->base,
-			    P2SZ(area->pages))) {
-				mutex_unlock(&area->lock);
-				return false;
-			}
-			
-			mutex_unlock(&area->lock);
-		}
-	}
-	
 	/* Second, check the leaf node. */
 	btree_key_t i;
 	for (i = 0; i < leaf->keys; i++) {
 		area = (as_area_t *) leaf->value[i];
+		int agp;
+		int gp;
 		
 		if (area == avoid)
@@ -365,7 +403,18 @@
 		
 		mutex_lock(&area->lock);
-		
-		if (overlaps(addr, P2SZ(count), area->base,
-		    P2SZ(area->pages))) {
+
+		gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0;
+		agp = gp;
+
+		/*
+		 * Sanitize the two possible unsigned integer overflows.
+		 */
+		if (gp && overflows(addr, P2SZ(count)))
+			gp--;
+		if (agp && overflows(area->base, P2SZ(area->pages)))
+			agp--;
+
+		if (overlaps(addr, P2SZ(count + gp), area->base,
+		    P2SZ(area->pages + agp))) {
 			mutex_unlock(&area->lock);
 			return false;
@@ -392,7 +441,8 @@
  * this function.
  *
- * @param as    Address space.
- * @param bound Lowest address bound.
- * @param size  Requested size of the allocation.
+ * @param as      Address space.
+ * @param bound   Lowest address bound.
+ * @param size    Requested size of the allocation.
+ * @param guarded True if the allocation must be protected by guard pages.
  *
  * @return Address of the beginning of unmapped address space area.
@@ -401,5 +451,5 @@
  */
 NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound,
-    size_t size)
+    size_t size, bool guarded)
 {
 	ASSERT(mutex_locked(&as->lock));
@@ -423,7 +473,15 @@
 	/* First check the bound address itself */
 	uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE);
-	if ((addr >= bound) &&
-	    (check_area_conflicts(as, addr, pages, NULL)))
-		return addr;
+	if (addr >= bound) {
+		if (guarded) {
+			/* Leave an unmapped page between the lower
+			 * bound and the area's start address.
+			 */
+			addr += P2SZ(1);
+		}
+
+		if (check_area_conflicts(as, addr, pages, guarded, NULL))
+			return addr;
+	}
 	
 	/* Eventually check the addresses behind each area */
@@ -439,7 +497,15 @@
 			addr =
 			    ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE);
+
+			if (guarded || area->flags & AS_AREA_GUARD) {
+				/* We must leave an unmapped page
+				 * between the two areas.
+				 */
+				addr += P2SZ(1);
+			}
+
 			bool avail =
 			    ((addr >= bound) && (addr >= area->base) &&
-			    (check_area_conflicts(as, addr, pages, area)));
+			    (check_area_conflicts(as, addr, pages, guarded, area)));
 			
 			mutex_unlock(&area->lock);
@@ -481,5 +547,5 @@
 	if (size == 0)
 		return NULL;
-	
+
 	size_t pages = SIZE2FRAMES(size);
 	
@@ -487,9 +553,11 @@
 	if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
 		return NULL;
+
+	bool const guarded = flags & AS_AREA_GUARD;
 	
 	mutex_lock(&as->lock);
 	
 	if (*base == (uintptr_t) -1) {
-		*base = as_get_unmapped_area(as, bound, size);
+		*base = as_get_unmapped_area(as, bound, size, guarded);
 		if (*base == (uintptr_t) -1) {
 			mutex_unlock(&as->lock);
@@ -497,6 +565,9 @@
 		}
 	}
-	
-	if (!check_area_conflicts(as, *base, pages, NULL)) {
+
+	if (overflows_into_positive(*base, size))
+		return NULL;
+
+	if (!check_area_conflicts(as, *base, pages, guarded, NULL)) {
 		mutex_unlock(&as->lock);
 		return NULL;
@@ -665,10 +736,4 @@
 		
 		page_table_lock(as, false);
-		
-		/*
-		 * Start TLB shootdown sequence.
-		 */
-		ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
-		    area->base + P2SZ(pages), area->pages - pages);
 		
 		/*
@@ -726,4 +791,20 @@
 				}
 				
+				/*
+				 * Start TLB shootdown sequence.
+				 *
+				 * The sequence is rather short and can be
+				 * repeated multiple times. The reason is that
+				 * we don't want to have used_space_remove()
+				 * inside the sequence as it may use a blocking
+				 * memory allocation for its B+tree. Blocking
+				 * while holding the tlblock spinlock is
+				 * forbidden and would hit a kernel assertion.
+				 */
+
+				ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES,
+				    as->asid, area->base + P2SZ(pages),
+				    area->pages - pages);
+		
 				for (; i < size; i++) {
 					pte_t *pte = page_mapping_find(as,
@@ -743,29 +824,37 @@
 					page_mapping_remove(as, ptr + P2SZ(i));
 				}
+		
+				/*
+				 * Finish TLB shootdown sequence.
+				 */
+		
+				tlb_invalidate_pages(as->asid,
+				    area->base + P2SZ(pages),
+				    area->pages - pages);
+		
+				/*
+				 * Invalidate software translation caches
+				 * (e.g. TSB on sparc64, PHT on ppc32).
+				 */
+				as_invalidate_translation_cache(as,
+				    area->base + P2SZ(pages),
+				    area->pages - pages);
+				tlb_shootdown_finalize(ipl);
 			}
 		}
-		
-		/*
-		 * Finish TLB shootdown sequence.
-		 */
-		
-		tlb_invalidate_pages(as->asid, area->base + P2SZ(pages),
-		    area->pages - pages);
-		
-		/*
-		 * Invalidate software translation caches
-		 * (e.g. TSB on sparc64, PHT on ppc32).
-		 */
-		as_invalidate_translation_cache(as, area->base + P2SZ(pages),
-		    area->pages - pages);
-		tlb_shootdown_finalize(ipl);
-		
 		page_table_unlock(as, false);
 	} else {
 		/*
 		 * Growing the area.
+		 */
+
+		if (overflows_into_positive(address, P2SZ(pages)))
+			return EINVAL;
+
+		/*
 		 * Check for overlaps with other address space areas.
 		 */
-		if (!check_area_conflicts(as, address, pages, area)) {
+		bool const guarded = area->flags & AS_AREA_GUARD;
+		if (!check_area_conflicts(as, address, pages, guarded, area)) {
 			mutex_unlock(&area->lock);
 			mutex_unlock(&as->lock);
Index: kernel/generic/src/mm/slab.c
===================================================================
--- kernel/generic/src/mm/slab.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/mm/slab.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -891,5 +891,5 @@
 {
 	/* Initialize magazine cache */
-	_slab_cache_create(&mag_cache, "slab_magazine",
+	_slab_cache_create(&mag_cache, "slab_magazine_t",
 	    sizeof(slab_magazine_t) + SLAB_MAG_SIZE * sizeof(void*),
 	    sizeof(uintptr_t), NULL, NULL, SLAB_CACHE_NOMAGAZINE |
@@ -897,10 +897,10 @@
 	
 	/* Initialize slab_cache cache */
-	_slab_cache_create(&slab_cache_cache, "slab_cache",
+	_slab_cache_create(&slab_cache_cache, "slab_cache_cache",
 	    sizeof(slab_cache_cache), sizeof(uintptr_t), NULL, NULL,
 	    SLAB_CACHE_NOMAGAZINE | SLAB_CACHE_SLINSIDE);
 	
 	/* Initialize external slab cache */
-	slab_extern_cache = slab_cache_create("slab_extern", sizeof(slab_t), 0,
+	slab_extern_cache = slab_cache_create("slab_t", sizeof(slab_t), 0,
 	    NULL, NULL, SLAB_CACHE_SLINSIDE | SLAB_CACHE_MAGDEFERRED);
 	
Index: kernel/generic/src/mm/tlb.c
===================================================================
--- kernel/generic/src/mm/tlb.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/mm/tlb.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -162,5 +162,5 @@
 	
 	size_t i;
-	for (i = 0; i < CPU->tlb_messages_count; CPU->tlb_messages_count--) {
+	for (i = 0; i < CPU->tlb_messages_count; i++) {
 		tlb_invalidate_type_t type = CPU->tlb_messages[i].type;
 		asid_t asid = CPU->tlb_messages[i].asid;
@@ -188,4 +188,5 @@
 	}
 	
+	CPU->tlb_messages_count = 0;
 	irq_spinlock_unlock(&CPU->lock, false);
 	CPU->tlb_active = true;
Index: kernel/generic/src/proc/program.c
===================================================================
--- kernel/generic/src/proc/program.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/proc/program.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -102,5 +102,5 @@
 	 */
 	prg->main_thread = thread_create(uinit, kernel_uarg, prg->task,
-	    THREAD_FLAG_USPACE, "uinit", false);
+	    THREAD_FLAG_USPACE, "uinit");
 	if (!prg->main_thread) {
 		free(kernel_uarg);
Index: kernel/generic/src/proc/scheduler.c
===================================================================
--- kernel/generic/src/proc/scheduler.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/proc/scheduler.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -98,5 +98,5 @@
 	else {
 		fpu_init();
-		THREAD->fpu_context_exists = 1;
+		THREAD->fpu_context_exists = true;
 	}
 #endif
@@ -142,5 +142,5 @@
 		
 		/* Don't prevent migration */
-		CPU->fpu_owner->fpu_context_engaged = 0;
+		CPU->fpu_owner->fpu_context_engaged = false;
 		irq_spinlock_unlock(&CPU->fpu_owner->lock, false);
 		CPU->fpu_owner = NULL;
@@ -163,9 +163,9 @@
 		}
 		fpu_init();
-		THREAD->fpu_context_exists = 1;
+		THREAD->fpu_context_exists = true;
 	}
 	
 	CPU->fpu_owner = THREAD;
-	THREAD->fpu_context_engaged = 1;
+	THREAD->fpu_context_engaged = true;
 	irq_spinlock_unlock(&THREAD->lock, false);
 	
@@ -248,8 +248,8 @@
 		
 		/*
-		 * Clear the THREAD_FLAG_STOLEN flag so that t can be migrated
+		 * Clear the stolen flag so that it can be migrated
 		 * when load balancing needs emerge.
 		 */
-		thread->flags &= ~THREAD_FLAG_STOLEN;
+		thread->stolen = false;
 		irq_spinlock_unlock(&thread->lock, false);
 		
@@ -630,8 +630,7 @@
 				irq_spinlock_lock(&thread->lock, false);
 				
-				if (!(thread->flags & THREAD_FLAG_WIRED) &&
-				    !(thread->flags & THREAD_FLAG_STOLEN) &&
-				    !thread->nomigrate &&
-				    !thread->fpu_context_engaged) {
+				if ((!thread->wired) && (!thread->stolen) &&
+				    (!thread->nomigrate) &&
+				    (!thread->fpu_context_engaged)) {
 					/*
 					 * Remove thread from ready queue.
@@ -670,5 +669,5 @@
 #endif
 				
-				thread->flags |= THREAD_FLAG_STOLEN;
+				thread->stolen = true;
 				thread->state = Entering;
 				
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/proc/task.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -90,5 +90,5 @@
 	TASK = NULL;
 	avltree_create(&tasks_tree);
-	task_slab = slab_cache_create("task_slab", sizeof(task_t), 0,
+	task_slab = slab_cache_create("task_t", sizeof(task_t), 0,
 	    tsk_constructor, NULL, 0);
 }
@@ -156,5 +156,4 @@
 	
 	list_initialize(&task->threads);
-	list_initialize(&task->sync_boxes);
 	
 	ipc_answerbox_init(&task->answerbox, task);
@@ -162,5 +161,8 @@
 	size_t i;
 	for (i = 0; i < IPC_MAX_PHONES; i++)
-		ipc_phone_init(&task->phones[i]);
+		ipc_phone_init(&task->phones[i], task);
+
+	spinlock_initialize(&task->active_calls_lock, "active_calls_lock");
+	list_initialize(&task->active_calls);
 	
 #ifdef CONFIG_UDEBUG
@@ -204,4 +206,6 @@
 	event_task_init(task);
 	
+	task->answerbox.active = true;
+
 #ifdef CONFIG_UDEBUG
 	/* Init debugging stuff */
@@ -209,4 +213,5 @@
 	
 	/* Init kbox stuff */
+	task->kb.box.active = true;
 	task->kb.finished = false;
 #endif
@@ -214,5 +219,5 @@
 	if ((ipc_phone_0) &&
 	    (container_check(ipc_phone_0->task->container, task->container)))
-		ipc_phone_connect(&task->phones[0], ipc_phone_0);
+		(void) ipc_phone_connect(&task->phones[0], ipc_phone_0);
 	
 	btree_create(&task->futexes);
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/proc/thread.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -191,5 +191,5 @@
 	kmflags |= FRAME_LOWMEM;
 	kmflags &= ~FRAME_HIGHMEM;
-
+	
 	thread->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags);
 	if (!thread->kstack) {
@@ -236,10 +236,10 @@
 	
 	atomic_set(&nrdy, 0);
-	thread_slab = slab_cache_create("thread_slab", sizeof(thread_t), 0,
+	thread_slab = slab_cache_create("thread_t", sizeof(thread_t), 0,
 	    thr_constructor, thr_destructor, 0);
 	
 #ifdef CONFIG_FPU
-	fpu_context_slab = slab_cache_create("fpu_slab", sizeof(fpu_context_t),
-	    FPU_CONTEXT_ALIGN, NULL, NULL, 0);
+	fpu_context_slab = slab_cache_create("fpu_context_t",
+	    sizeof(fpu_context_t), FPU_CONTEXT_ALIGN, NULL, NULL, 0);
 #endif
 	
@@ -247,4 +247,17 @@
 }
 
+/** Wire thread to the given CPU
+ *
+ * @param cpu CPU to wire the thread to.
+ *
+ */
+void thread_wire(thread_t *thread, cpu_t *cpu)
+{
+	irq_spinlock_lock(&thread->lock, true);
+	thread->cpu = cpu;
+	thread->wired = true;
+	irq_spinlock_unlock(&thread->lock, true);
+}
+
 /** Make thread ready
  *
@@ -260,12 +273,14 @@
 	ASSERT(thread->state != Ready);
 	
-	int i = (thread->priority < RQ_COUNT - 1)
-	    ? ++thread->priority : thread->priority;
-	
-	cpu_t *cpu = CPU;
-	if (thread->flags & THREAD_FLAG_WIRED) {
+	int i = (thread->priority < RQ_COUNT - 1) ?
+	    ++thread->priority : thread->priority;
+	
+	cpu_t *cpu;
+	if (thread->wired || thread->nomigrate || thread->fpu_context_engaged) {
 		ASSERT(thread->cpu != NULL);
 		cpu = thread->cpu;
-	}
+	} else
+		cpu = CPU;
+	
 	thread->state = Ready;
 	
@@ -298,6 +313,4 @@
  * @param flags     Thread flags.
  * @param name      Symbolic name (a copy is made).
- * @param uncounted Thread's accounting doesn't affect accumulated task
- *                  accounting.
  *
  * @return New thread's structure on success, NULL on failure.
@@ -305,5 +318,5 @@
  */
 thread_t *thread_create(void (* func)(void *), void *arg, task_t *task,
-    unsigned int flags, const char *name, bool uncounted)
+    thread_flags_t flags, const char *name)
 {
 	thread_t *thread = (thread_t *) slab_alloc(thread_slab, 0);
@@ -335,8 +348,13 @@
 	thread->ucycles = 0;
 	thread->kcycles = 0;
-	thread->uncounted = uncounted;
+	thread->uncounted =
+	    ((flags & THREAD_FLAG_UNCOUNTED) == THREAD_FLAG_UNCOUNTED);
 	thread->priority = -1;          /* Start in rq[0] */
 	thread->cpu = NULL;
-	thread->flags = flags;
+	thread->wired = false;
+	thread->stolen = false;
+	thread->uspace =
+	    ((flags & THREAD_FLAG_USPACE) == THREAD_FLAG_USPACE);
+	
 	thread->nomigrate = 0;
 	thread->state = Entering;
@@ -356,6 +374,6 @@
 	thread->task = task;
 	
-	thread->fpu_context_exists = 0;
-	thread->fpu_context_engaged = 0;
+	thread->fpu_context_exists = false;
+	thread->fpu_context_engaged = false;
 	
 	avltree_node_initialize(&thread->threads_tree_node);
@@ -371,5 +389,5 @@
 	thread_create_arch(thread);
 	
-	if (!(flags & THREAD_FLAG_NOATTACH))
+	if ((flags & THREAD_FLAG_NOATTACH) != THREAD_FLAG_NOATTACH)
 		thread_attach(thread, task);
 	
@@ -437,5 +455,5 @@
 	
 	/* Must not count kbox thread into lifecount */
-	if (thread->flags & THREAD_FLAG_USPACE)
+	if (thread->uspace)
 		atomic_inc(&task->lifecount);
 	
@@ -459,9 +477,9 @@
 void thread_exit(void)
 {
-	if (THREAD->flags & THREAD_FLAG_USPACE) {
+	if (THREAD->uspace) {
 #ifdef CONFIG_UDEBUG
 		/* Generate udebug THREAD_E event */
 		udebug_thread_e_event();
-
+		
 		/*
 		 * This thread will not execute any code or system calls from
@@ -506,5 +524,5 @@
 {
 	ASSERT(THREAD);
-
+	
 	THREAD->nomigrate++;
 }
@@ -515,6 +533,7 @@
 	ASSERT(THREAD);
 	ASSERT(THREAD->nomigrate > 0);
-
-	THREAD->nomigrate--;
+	
+	if (THREAD->nomigrate > 0)
+		THREAD->nomigrate--;
 }
 
@@ -865,5 +884,5 @@
 	
 	thread_t *thread = thread_create(uinit, kernel_uarg, TASK,
-	    THREAD_FLAG_USPACE | THREAD_FLAG_NOATTACH, namebuf, false);
+	    THREAD_FLAG_USPACE | THREAD_FLAG_NOATTACH, namebuf);
 	if (thread) {
 		if (uspace_thread_id != NULL) {
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/syscall/syscall.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -151,6 +151,4 @@
 	
 	/* IPC related syscalls. */
-	(syshandler_t) sys_ipc_call_sync_fast,
-	(syshandler_t) sys_ipc_call_sync_slow,
 	(syshandler_t) sys_ipc_call_async_fast,
 	(syshandler_t) sys_ipc_call_async_slow,
Index: kernel/generic/src/sysinfo/sysinfo.c
===================================================================
--- kernel/generic/src/sysinfo/sysinfo.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/sysinfo/sysinfo.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -97,5 +97,5 @@
 void sysinfo_init(void)
 {
-	sysinfo_item_slab = slab_cache_create("sysinfo_item_slab",
+	sysinfo_item_slab = slab_cache_create("sysinfo_item_t",
 	    sizeof(sysinfo_item_t), 0, sysinfo_item_constructor,
 	    sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED);
Index: kernel/generic/src/udebug/udebug.c
===================================================================
--- kernel/generic/src/udebug/udebug.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/udebug/udebug.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -410,8 +410,7 @@
 		
 		mutex_lock(&thread->udebug.lock);
-		unsigned int flags = thread->flags;
 		
 		/* Only process userspace threads. */
-		if ((flags & THREAD_FLAG_USPACE) != 0) {
+		if (thread->uspace) {
 			/* Prevent any further debug activity in thread. */
 			thread->udebug.active = false;
Index: kernel/generic/src/udebug/udebug_ops.c
===================================================================
--- kernel/generic/src/udebug/udebug_ops.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/generic/src/udebug/udebug_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -95,5 +95,5 @@
 	
 	/* Verify that 'thread' is a userspace thread. */
-	if ((thread->flags & THREAD_FLAG_USPACE) == 0) {
+	if (!thread->uspace) {
 		/* It's not, deny its existence */
 		irq_spinlock_unlock(&thread->lock, true);
@@ -200,5 +200,5 @@
 		
 		mutex_lock(&thread->udebug.lock);
-		if ((thread->flags & THREAD_FLAG_USPACE) != 0) {
+		if (thread->uspace) {
 			thread->udebug.active = true;
 			mutex_unlock(&thread->udebug.lock);
@@ -393,9 +393,9 @@
 		
 		irq_spinlock_lock(&thread->lock, false);
-		int flags = thread->flags;
+		bool uspace = thread->uspace;
 		irq_spinlock_unlock(&thread->lock, false);
 		
 		/* Not interested in kernel threads. */
-		if ((flags & THREAD_FLAG_USPACE) == 0)
+		if (!uspace)
 			continue;
 		
Index: kernel/test/mm/falloc1.c
===================================================================
--- kernel/test/mm/falloc1.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/test/mm/falloc1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,32 +37,31 @@
 #include <align.h>
 
-#define MAX_FRAMES  1024
+#define MAX_FRAMES  1024U
 #define MAX_ORDER   8
 #define TEST_RUNS   2
 
-const char *test_falloc1(void) {
-	uintptr_t *frames
-	    = (uintptr_t *) malloc(MAX_FRAMES * sizeof(uintptr_t), 0);
-	int results[MAX_ORDER + 1];
-	
-	int i, order, run;
-	int allocated;
-	
+const char *test_falloc1(void)
+{
 	if (TEST_RUNS < 2)
 		return "Test is compiled with TEST_RUNS < 2";
 	
+	uintptr_t *frames = (uintptr_t *)
+	    malloc(MAX_FRAMES * sizeof(uintptr_t), 0);
 	if (frames == NULL)
 		return "Unable to allocate frames";
 	
-	for (run = 0; run < TEST_RUNS; run++) {
-		for (order = 0; order <= MAX_ORDER; order++) {
-			TPRINTF("Allocating %d frames blocks ... ", 1 << order);
+	unsigned int results[MAX_ORDER + 1];
+	for (unsigned int run = 0; run < TEST_RUNS; run++) {
+		for (unsigned int order = 0; order <= MAX_ORDER; order++) {
+			TPRINTF("Allocating %u frames blocks ... ", 1 << order);
 			
-			allocated = 0;
-			for (i = 0; i < MAX_FRAMES >> order; i++) {
-				frames[allocated] = (uintptr_t) frame_alloc(order, FRAME_ATOMIC | FRAME_KA);
+			unsigned int allocated = 0;
+			for (unsigned int i = 0; i < (MAX_FRAMES >> order); i++) {
+				frames[allocated] = (uintptr_t)
+				    frame_alloc(order, FRAME_ATOMIC | FRAME_KA);
 				
-				if (ALIGN_UP(frames[allocated], FRAME_SIZE << order) != frames[allocated]) {
-					TPRINTF("Block at address %p (size %dK) is not aligned\n",
+				if (ALIGN_UP(frames[allocated], FRAME_SIZE << order) !=
+				    frames[allocated]) {
+					TPRINTF("Block at address %p (size %u) is not aligned\n",
 					    (void *) frames[allocated], (FRAME_SIZE << order) >> 10);
 					return "Test failed";
@@ -87,5 +86,5 @@
 			TPRINTF("Deallocating ... ");
 			
-			for (i = 0; i < allocated; i++)
+			for (unsigned int i = 0; i < allocated; i++)
 				frame_free(KA2PA(frames[i]));
 			
Index: kernel/test/mm/falloc2.c
===================================================================
--- kernel/test/mm/falloc2.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/test/mm/falloc2.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,5 +40,5 @@
 #include <arch.h>
 
-#define MAX_FRAMES  256
+#define MAX_FRAMES  256U
 #define MAX_ORDER   8
 
@@ -51,11 +51,11 @@
 static void falloc(void *arg)
 {
-	int order, run, allocated, i;
 	uint8_t val = THREAD->tid % THREADS;
-	size_t k;
 	
-	void **frames =  (void **) malloc(MAX_FRAMES * sizeof(void *), FRAME_ATOMIC);
+	void **frames = (void **)
+	    malloc(MAX_FRAMES * sizeof(void *), FRAME_ATOMIC);
 	if (frames == NULL) {
-		TPRINTF("Thread #%" PRIu64 " (cpu%u): Unable to allocate frames\n", THREAD->tid, CPU->id);
+		TPRINTF("Thread #%" PRIu64 " (cpu%u): "
+		    "Unable to allocate frames\n", THREAD->tid, CPU->id);
 		atomic_inc(&thread_fail);
 		atomic_dec(&thread_count);
@@ -65,11 +65,14 @@
 	thread_detach(THREAD);
 	
-	for (run = 0; run < THREAD_RUNS; run++) {
-		for (order = 0; order <= MAX_ORDER; order++) {
-			TPRINTF("Thread #%" PRIu64 " (cpu%u): Allocating %d frames blocks ... \n", THREAD->tid, CPU->id, 1 << order);
+	for (unsigned int run = 0; run < THREAD_RUNS; run++) {
+		for (unsigned int order = 0; order <= MAX_ORDER; order++) {
+			TPRINTF("Thread #%" PRIu64 " (cpu%u): "
+			    "Allocating %u frames blocks ... \n", THREAD->tid,
+			    CPU->id, 1 << order);
 			
-			allocated = 0;
-			for (i = 0; i < (MAX_FRAMES >> order); i++) {
-				frames[allocated] = frame_alloc(order, FRAME_ATOMIC | FRAME_KA);
+			unsigned int allocated = 0;
+			for (unsigned int i = 0; i < (MAX_FRAMES >> order); i++) {
+				frames[allocated] =
+				    frame_alloc(order, FRAME_ATOMIC | FRAME_KA);
 				if (frames[allocated]) {
 					memsetb(frames[allocated], FRAME_SIZE << order, val);
@@ -79,12 +82,18 @@
 			}
 			
-			TPRINTF("Thread #%" PRIu64 " (cpu%u): %d blocks allocated.\n", THREAD->tid, CPU->id, allocated);
-			TPRINTF("Thread #%" PRIu64 " (cpu%u): Deallocating ... \n", THREAD->tid, CPU->id);
+			TPRINTF("Thread #%" PRIu64 " (cpu%u): "
+			    "%u blocks allocated.\n", THREAD->tid, CPU->id,
+			    allocated);
+			TPRINTF("Thread #%" PRIu64 " (cpu%u): "
+			    "Deallocating ... \n", THREAD->tid, CPU->id);
 			
-			for (i = 0; i < allocated; i++) {
-				for (k = 0; k <= (((size_t) FRAME_SIZE << order) - 1); k++) {
+			for (unsigned int i = 0; i < allocated; i++) {
+				for (size_t k = 0; k <= (((size_t) FRAME_SIZE << order) - 1);
+				    k++) {
 					if (((uint8_t *) frames[i])[k] != val) {
-						TPRINTF("Thread #%" PRIu64 " (cpu%u): Unexpected data (%c) in block %p offset %zu\n",
-						    THREAD->tid, CPU->id, ((char *) frames[i])[k], frames[i], k);
+						TPRINTF("Thread #%" PRIu64 " (cpu%u): "
+						    "Unexpected data (%c) in block %p offset %zu\n",
+						    THREAD->tid, CPU->id, ((char *) frames[i])[k],
+						    frames[i], k);
 						atomic_inc(&thread_fail);
 						goto cleanup;
@@ -94,5 +103,6 @@
 			}
 			
-			TPRINTF("Thread #%" PRIu64 " (cpu%u): Finished run.\n", THREAD->tid, CPU->id);
+			TPRINTF("Thread #%" PRIu64 " (cpu%u): "
+			    "Finished run.\n", THREAD->tid, CPU->id);
 		}
 	}
@@ -101,5 +111,6 @@
 	free(frames);
 	
-	TPRINTF("Thread #%" PRIu64 " (cpu%u): Exiting\n", THREAD->tid, CPU->id);
+	TPRINTF("Thread #%" PRIu64 " (cpu%u): Exiting\n",
+	    THREAD->tid, CPU->id);
 	atomic_dec(&thread_count);
 }
@@ -107,11 +118,10 @@
 const char *test_falloc2(void)
 {
-	unsigned int i;
-	
 	atomic_set(&thread_count, THREADS);
 	atomic_set(&thread_fail, 0);
 	
-	for (i = 0; i < THREADS; i++) {
-		thread_t * thrd = thread_create(falloc, NULL, TASK, 0, "falloc", false);
+	for (unsigned int i = 0; i < THREADS; i++) {
+		thread_t *thrd = thread_create(falloc, NULL, TASK,
+		    THREAD_FLAG_NONE, "falloc2");
 		if (!thrd) {
 			TPRINTF("Could not create thread %u\n", i);
@@ -122,5 +132,6 @@
 	
 	while (atomic_get(&thread_count) > 0) {
-		TPRINTF("Threads left: %" PRIua "\n", atomic_get(&thread_count));
+		TPRINTF("Threads left: %" PRIua "\n",
+		    atomic_get(&thread_count));
 		thread_sleep(1);
 	}
Index: kernel/test/mm/slab1.c
===================================================================
--- kernel/test/mm/slab1.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/test/mm/slab1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -155,6 +155,6 @@
 	
 	semaphore_initialize(&thr_sem, 0);
-	for (i = 0; i < THREADS; i++) {  
-		if (!(t = thread_create(slabtest, (void *) (sysarg_t) i, TASK, 0, "slabtest", false))) {
+	for (i = 0; i < THREADS; i++) {
+		if (!(t = thread_create(slabtest, (void *) (sysarg_t) i, TASK, THREAD_FLAG_NONE, "slabtest"))) {
 			TPRINTF("Could not create thread %d\n", i);
 		} else
Index: kernel/test/mm/slab2.c
===================================================================
--- kernel/test/mm/slab2.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/test/mm/slab2.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -52,6 +52,6 @@
 	void *olddata1 = NULL, *olddata2 = NULL;
 	
-	cache1 = slab_cache_create("cache1_tst", ITEM_SIZE, 0, NULL, NULL, 0);
-	cache2 = slab_cache_create("cache2_tst", ITEM_SIZE, 0, NULL, NULL, 0);
+	cache1 = slab_cache_create("test_cache1", ITEM_SIZE, 0, NULL, NULL, 0);
+	cache2 = slab_cache_create("test_cache2", ITEM_SIZE, 0, NULL, NULL, 0);
 	
 	TPRINTF("Allocating...");
@@ -210,6 +210,6 @@
 	thr_cache = slab_cache_create("thread_cache", size, 0, NULL, NULL, 0);
 	semaphore_initialize(&thr_sem,0);
-	for (i = 0; i < THREADS; i++) {  
-		if (!(t = thread_create(slabtest, NULL, TASK, 0, "slabtest", false))) {
+	for (i = 0; i < THREADS; i++) {
+		if (!(t = thread_create(slabtest, NULL, TASK, THREAD_FLAG_NONE, "slabtest"))) {
 			TPRINTF("Could not create thread %d\n", i);
 		} else
Index: kernel/test/synch/semaphore1.c
===================================================================
--- kernel/test/synch/semaphore1.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/test/synch/semaphore1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -93,5 +93,6 @@
 		for (j = 0; j < (CONSUMERS + PRODUCERS) / 2; j++) {
 			for (k = 0; k < i; k++) {
-				thrd = thread_create(consumer, NULL, TASK, 0, "consumer", false);
+				thrd = thread_create(consumer, NULL, TASK,
+				    THREAD_FLAG_NONE, "consumer");
 				if (thrd)
 					thread_ready(thrd);
@@ -100,5 +101,6 @@
 			}
 			for (k = 0; k < (4 - i); k++) {
-				thrd = thread_create(producer, NULL, TASK, 0, "producer", false);
+				thrd = thread_create(producer, NULL, TASK,
+				    THREAD_FLAG_NONE, "producer");
 				if (thrd)
 					thread_ready(thrd);
Index: kernel/test/synch/semaphore2.c
===================================================================
--- kernel/test/synch/semaphore2.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/test/synch/semaphore2.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -93,5 +93,6 @@
 	TPRINTF("Creating %" PRIu32 " consumers\n", k);
 	for (i = 0; i < k; i++) {
-		thrd = thread_create(consumer, NULL, TASK, 0, "consumer", false);
+		thrd = thread_create(consumer, NULL, TASK,
+		    THREAD_FLAG_NONE, "consumer");
 		if (thrd)
 			thread_ready(thrd);
Index: kernel/test/thread/thread1.c
===================================================================
--- kernel/test/thread/thread1.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ kernel/test/thread/thread1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -63,5 +63,6 @@
 	for (i = 0; i < THREADS; i++) {
 		thread_t *t;
-		if (!(t = thread_create(threadtest, NULL, TASK, 0, "threadtest", false))) {
+		if (!(t = thread_create(threadtest, NULL, TASK,
+		    THREAD_FLAG_NONE, "threadtest"))) {
 			TPRINTF("Could not create thread %d\n", i);
 			break;
Index: release/Makefile
===================================================================
--- release/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ release/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,5 +33,5 @@
 
 PROFILES = amd64 arm32/GXemul arm32/integratorcp arm32/gta02 ia32 \
-    ia64/i460GX ia64/ski mips32/GXemul mips32/msim sparc64/niagara \
+    ia64/i460GX ia64/ski mips32/GXemul mips32/msim ppc32 \
     sparc64/ultra
 
@@ -71,5 +71,5 @@
 release: src_rel
 	for profile in $(PROFILES); do \
-		$(MAKE) -C $(EXPORT_DIR) clean ; \
+		$(MAKE) -C $(EXPORT_DIR) distclean ; \
 		$(MAKE) -C $(EXPORT_DIR) PROFILE=$$profile ; \
 		$(MAKE) PROFILE=$$profile releasefile ; \
@@ -79,5 +79,5 @@
 	rm -rf $(EXPORT_DIR)
 	mkdir -p $(EXPORT_DIR)
-	$(BZR) export $(EXPORT_DIR)
+	$(BZR) export $(EXPORT_DIR) ../
 
 src_rel $(SRC_ARCHIVE): export
Index: tools/mkext4.py
===================================================================
--- tools/mkext4.py	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ tools/mkext4.py	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1 @@
+mkext2.py
Index: tools/toolchain.sh
===================================================================
--- tools/toolchain.sh	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ tools/toolchain.sh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -43,6 +43,6 @@
 MPFR_MAIN=<<EOF
 #if MPFR_VERSION < MPFR_VERSION_NUM(2, 4, 2)
-choke me
-	#endif
+	choke me
+#endif
 EOF
 
@@ -55,6 +55,6 @@
 BINUTILS_VERSION="2.22"
 BINUTILS_RELEASE=""
-GCC_VERSION="4.7.0"
-GDB_VERSION="7.4"
+GCC_VERSION="4.7.2"
+GDB_VERSION="7.5"
 
 BASEDIR="`pwd`"
@@ -192,4 +192,5 @@
 	echo " - SED, AWK, Flex, Bison, gzip, bzip2, Bourne Shell"
 	echo " - gettext, zlib, Texinfo, libelf, libgomp"
+	echo " - terminfo"
 	echo " - GNU Multiple Precision Library (GMP)"
 	echo " - GNU Make"
@@ -274,6 +275,6 @@
 	
 	download_fetch "${BINUTILS_SOURCE}" "${BINUTILS}" "ee0f10756c84979622b992a4a61ea3f5"
-	download_fetch "${GCC_SOURCE}" "${GCC}" "2a0f1d99fda235c29d40b561f81d9a77"
-	download_fetch "${GDB_SOURCE}" "${GDB}" "95a9a8305fed4d30a30a6dc28ff9d060"
+	download_fetch "${GCC_SOURCE}" "${GCC}" "cc308a0891e778cfda7a151ab8a6e762"
+	download_fetch "${GDB_SOURCE}" "${GDB}" "24a6779a9fe0260667710de1b082ef61"
 }
 
@@ -319,5 +320,5 @@
 	
 	change_title "binutils: configure (${PLATFORM})"
-	CFLAGS=-Wno-error ./configure "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --disable-nls
+	CFLAGS=-Wno-error ./configure "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --disable-nls --disable-werror
 	check_error $? "Error configuring binutils."
 	
@@ -331,5 +332,5 @@
 	
 	change_title "GCC: configure (${PLATFORM})"
-	"${GCCDIR}/configure" "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --with-gnu-as --with-gnu-ld --disable-nls --disable-threads --enable-languages=c,objc,c++,obj-c++ --disable-multilib --disable-libgcj --without-headers --disable-shared --enable-lto
+	"${GCCDIR}/configure" "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --with-gnu-as --with-gnu-ld --disable-nls --disable-threads --enable-languages=c,objc,c++,obj-c++ --disable-multilib --disable-libgcj --without-headers --disable-shared --enable-lto --disable-werror
 	check_error $? "Error configuring GCC."
 	
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,4 +35,5 @@
 DIRS = \
 	app/bdsh \
+	app/bithenge \
 	app/blkdump \
 	app/bnchmark \
@@ -47,5 +48,5 @@
 	app/klog \
 	app/loc \
-	app/lsusb \
+	app/logset \
 	app/mkfat \
 	app/mkexfat \
@@ -59,4 +60,5 @@
 	app/tester \
 	app/testread \
+	app/testwrit \
 	app/tetris \
 	app/trace \
@@ -71,7 +73,12 @@
 	app/sysinfo \
 	app/mkbd \
+	app/date \
 	app/websrv \
+	app/vdemo \
+	app/vlaunch \
+	app/vterm \
 	srv/clipboard \
 	srv/locsrv \
+	srv/logger \
 	srv/devman \
 	srv/loader \
@@ -86,4 +93,5 @@
 	srv/vfs \
 	srv/bd/ata_bd \
+	srv/bd/sata_bd \
 	srv/bd/file_bd \
 	srv/bd/gxe_bd \
@@ -92,4 +100,5 @@
 	srv/bd/part/mbr_part \
 	srv/fs/exfat \
+	srv/fs/udf \
 	srv/fs/fat \
 	srv/fs/cdfs \
@@ -98,12 +107,16 @@
 	srv/fs/locfs \
 	srv/fs/ext2fs \
+	srv/fs/ext4fs \
+	srv/hid/compositor \
 	srv/hid/console \
 	srv/hid/s3c24xx_ts \
-	srv/hid/fb \
+	srv/hid/isdv4_tablet \
 	srv/hid/input \
+	srv/hid/output \
 	srv/hid/remcons \
 	srv/hw/char/s3c24xx_uart \
 	drv/infrastructure/root \
 	drv/infrastructure/rootvirt \
+	drv/block/ahci \
 	drv/char/i8042 \
 	drv/char/ps2mouse \
@@ -112,4 +125,5 @@
 	drv/test/test2 \
 	drv/test/test3 \
+	drv/fb/kfb \
 	drv/bus/usb/ehci \
 	drv/bus/usb/ohci \
@@ -124,5 +138,5 @@
 	drv/nic/ne2k \
 	drv/nic/e1k \
-	drv/nic/rtl8139
+	drv/nic/rtl8139 \
 
 ifeq ($(CONFIG_PCC),y)
@@ -153,4 +167,5 @@
 		drv/bus/isa \
 		drv/char/ns8250 \
+		drv/time/cmos-rtc \
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259
@@ -163,4 +178,5 @@
 		drv/bus/isa \
 		drv/char/ns8250 \
+		drv/time/cmos-rtc \
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259
@@ -170,4 +186,5 @@
 	DIRS += \
 		drv/infrastructure/rootmac \
+		drv/bus/pci/pciintel \
 		srv/hw/bus/cuda_adb
 endif
@@ -191,8 +208,12 @@
 	lib/softfloat \
 	lib/drv \
-	lib/fb \
+	lib/graph \
+	lib/gui \
+	lib/softrend \
+	lib/draw \
 	lib/net \
 	lib/nic \
 	lib/ext2 \
+	lib/ext4 \
 	lib/usb \
 	lib/usbhost \
@@ -200,4 +221,5 @@
 	lib/usbhid \
 	lib/usbvirt \
+	lib/bithenge \
 	lib/posix
 
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/Makefile.common	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -110,9 +110,14 @@
 LIBBLOCK_PREFIX = $(LIB_PREFIX)/block
 LIBFS_PREFIX = $(LIB_PREFIX)/fs
-LIBFB_PREFIX = $(LIB_PREFIX)/fb
 LIBCLUI_PREFIX = $(LIB_PREFIX)/clui
 LIBFMTUTIL_PREFIX = $(LIB_PREFIX)/fmtutil
 
+LIBGRAPH_PREFIX = $(LIB_PREFIX)/graph
+LIBSOFTREND_PREFIX = $(LIB_PREFIX)/softrend
+LIBDRAW_PREFIX = $(LIB_PREFIX)/draw
+LIBGUI_PREFIX = $(LIB_PREFIX)/gui
+
 LIBEXT2_PREFIX = $(LIB_PREFIX)/ext2
+LIBEXT4_PREFIX = $(LIB_PREFIX)/ext4
 
 LIBUSB_PREFIX = $(LIB_PREFIX)/usb
@@ -128,4 +133,6 @@
 
 LIBSCSI_PREFIX = $(LIB_PREFIX)/scsi
+
+LIBBITHENGE_PREFIX = $(LIB_PREFIX)/bithenge
 
 ifeq ($(STATIC_NEEDED),y)
@@ -220,5 +227,5 @@
 
 ifeq ($(POSIX_COMPAT),y)
-	CFLAGS = -I$(LIBPOSIX_PREFIX)
+	CFLAGS = -I$(LIBPOSIX_PREFIX)/include/posix  -I$(LIBPOSIX_PREFIX)/include/
 	LIBS += $(LIBPOSIX_PREFIX)/libposix.a
 endif
Index: uspace/app/bdsh/Makefile
===================================================================
--- uspace/app/bdsh/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/bdsh/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -53,4 +53,5 @@
 	cmds/modules/unmount/unmount.c \
 	cmds/modules/kcon/kcon.c \
+	cmds/modules/cmp/cmp.c \
 	cmds/builtins/batch/batch.c \
 	cmds/builtins/exit/exit.c \
Index: uspace/app/bdsh/cmds/modules/bdd/bdd.c
===================================================================
--- uspace/app/bdsh/cmds/modules/bdd/bdd.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/bdsh/cmds/modules/bdd/bdd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,5 +38,5 @@
 #include "cmds.h"
 
-#include <libblock.h>
+#include <block.h>
 #include <loc.h>
 #include <errno.h>
Index: uspace/app/bdsh/cmds/modules/cat/cat.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/bdsh/cmds/modules/cat/cat.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -62,4 +62,5 @@
 static sysarg_t console_rows = 0;
 static bool should_quit = false;
+static bool dash_represents_stdin = false;
 
 static console_ctrl_t *console = NULL;
@@ -73,4 +74,5 @@
 	{ "more", no_argument, 0, 'm' },
 	{ "hex", no_argument, 0, 'x' },
+	{ "stdin", no_argument, 0, 's' },
 	{ 0, 0, 0, 0 }
 };
@@ -93,4 +95,5 @@
 		"  -m, --more       Pause after each screen full\n"
 		"  -x, --hex        Print bytes as hex values\n"
+		"  -s  --stdin      Treat `-' in file list as standard input\n"
 		"Currently, %s is under development, some options don't work.\n",
 		cmdname, cmdname);
@@ -172,5 +175,13 @@
 	off64_t file_size = 0, length = 0;
 
-	fd = open(fname, O_RDONLY);
+	bool reading_stdin = dash_represents_stdin && (str_cmp(fname, "-") == 0);
+	
+	if (reading_stdin) {
+		fd = fileno(stdin);
+		/* Allow storing the whole UTF-8 character. */
+		blen = STR_BOUNDS(1);
+	} else
+		fd = open(fname, O_RDONLY);
+	
 	if (fd < 0) {
 		printf("Unable to open %s\n", fname);
@@ -207,8 +218,17 @@
 
 	do {
-		bytes = read(fd, buff + copied_bytes, (
-			(length != CAT_FULL_FILE && length - (off64_t)count <= (off64_t)(blen - copied_bytes)) ?
-			(size_t)(length - count) :
-			(blen - copied_bytes) ) );
+		size_t bytes_to_read;
+		if (reading_stdin) {
+			bytes_to_read = 1;
+		} else {
+			if ((length != CAT_FULL_FILE) &&
+			    (length - (off64_t)count <= (off64_t)(blen - copied_bytes))) {
+				bytes_to_read = (size_t) (length - count);
+			} else {
+				bytes_to_read = blen - copied_bytes;
+			}
+		}
+		
+		bytes = read(fd, buff + copied_bytes, bytes_to_read);
 		bytes += copied_bytes;
 		copied_bytes = 0;
@@ -242,4 +262,7 @@
 			reads++;
 		}
+		
+		if (reading_stdin)
+			fflush(stdout);
 	} while (bytes > 0 && !should_quit && (count < length || length == CAT_FULL_FILE));
 
@@ -284,5 +307,5 @@
 
 	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
-		c = getopt_long(argc, argv, "xhvmH:t:b:", long_options, &opt_ind);
+		c = getopt_long(argc, argv, "xhvmH:t:b:s", long_options, &opt_ind);
 		switch (c) {
 		case 'h':
@@ -318,4 +341,7 @@
 			hex = true;
 			break;
+		case 's':
+			dash_represents_stdin = true;
+			break;
 		}
 	}
Index: uspace/app/bdsh/cmds/modules/cmp/cmp.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cmp/cmp.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/bdsh/cmds/modules/cmp/cmp.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <mem.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <vfs/vfs.h>
+
+#include "cmds.h"
+#include "cmp.h"
+#include "config.h"
+#include "entry.h"
+#include "errors.h"
+#include "util.h"
+
+static const char *cmdname = "cmp";
+#define CMP_VERSION "0.0.1"
+#define CMP_BUFLEN 1024
+
+static struct option const long_options[] = {
+	{ "help", no_argument, 0, 'h' },
+	{ "version", no_argument, 0, 'v' },
+	{ 0, 0, 0, 0 }
+};
+
+/* Dispays help for cat in various levels */
+void help_cmd_cmp(unsigned int level)
+{
+	if (level == HELP_SHORT) {
+		printf("`%s' compares the contents of two files\n", cmdname);
+	} else {
+		help_cmd_cmp(HELP_SHORT);
+		printf(
+		"Usage:  %s [options] <file1> <file2>\n"
+		"Options:\n"
+		"  -h, --help       A short option summary\n"
+		"  -v, --version    Print version information and exit\n"
+		"No output is printed; the return code is 1 if the files differ.\n",
+		cmdname);
+	}
+
+	return;
+}
+
+static int cmp_files(const char *fn0, const char *fn1)
+{
+	int rc = 0;
+	const char *fn[2] = {fn0, fn1};
+	int fd[2] = {-1, -1};
+	char buffer[2][CMP_BUFLEN];
+	ssize_t offset[2];
+
+	for (int i = 0; i < 2; i++) {
+		fd[i] = open(fn[i], O_RDONLY);
+		if (fd[i] < 0) {
+			rc = errno;
+			printf("Unable to open %s\n", fn[i]);
+			goto end;
+		}
+	}
+
+	do {
+		for (int i = 0; i < 2; i++) {
+			offset[i] = 0;
+			ssize_t size;
+			do {
+				size = read(fd[i], buffer[i] + offset[i],
+				    CMP_BUFLEN - offset[i]);
+				if (size < 0) {
+					rc = errno;
+					printf("Error reading from %s\n",
+					    fn[i]);
+					goto end;
+				}
+				offset[i] += size;
+			} while (size && offset[i] < CMP_BUFLEN);
+		}
+
+		if (offset[0] != offset[1] ||
+		    bcmp(buffer[0], buffer[1], offset[0])) {
+			rc = 1;
+			goto end;
+		}
+	} while (offset[0] == CMP_BUFLEN);
+
+end:
+	if (fd[0] >= 0)
+		close(fd[0]);
+	if (fd[1] >= 0)
+		close(fd[1]);
+	return rc;
+}
+
+/* Main entry point for cmd, accepts an array of arguments */
+int cmd_cmp(char **argv)
+{
+	int rc;
+	unsigned int argc;
+	int c, opt_ind;
+	
+	argc = cli_count_args(argv);
+
+	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
+		c = getopt_long(argc, argv, "hv", long_options, &opt_ind);
+		switch (c) {
+		case 'h':
+			help_cmd_cmp(HELP_LONG);
+			return CMD_SUCCESS;
+		case 'v':
+			printf("%s\n", CMP_VERSION);
+			return CMD_SUCCESS;
+		}
+	}
+
+	if (argc - optind != 2) {
+		printf("%s - incorrect number of arguments. Try `%s --help'\n",
+			cmdname, cmdname);
+		return CMD_FAILURE;
+	}
+
+	rc = cmp_files(argv[optind], argv[optind + 1]);
+	if (rc)
+		return CMD_FAILURE;
+	else
+		return CMD_SUCCESS;
+}
Index: uspace/app/bdsh/cmds/modules/cmp/cmp.h
===================================================================
--- uspace/app/bdsh/cmds/modules/cmp/cmp.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/bdsh/cmds/modules/cmp/cmp.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,7 @@
+#ifndef CMP_H
+#define CMP_H
+
+/* Prototypes for the cmp command, excluding entry points */
+
+#endif /* CMP_H */
+
Index: uspace/app/bdsh/cmds/modules/cmp/cmp_def.h
===================================================================
--- uspace/app/bdsh/cmds/modules/cmp/cmp_def.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/bdsh/cmds/modules/cmp/cmp_def.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,7 @@
+{
+	"cmp",
+	"Compare the contents of two files",
+	&cmd_cmp,
+	&help_cmd_cmp,
+},
+
Index: uspace/app/bdsh/cmds/modules/cmp/entry.h
===================================================================
--- uspace/app/bdsh/cmds/modules/cmp/entry.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/bdsh/cmds/modules/cmp/entry.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,9 @@
+#ifndef CMP_ENTRY_H
+#define CMP_ENTRY_H
+
+/* Entry points for the cat command */
+extern int cmd_cmp(char **);
+extern void help_cmd_cmp(unsigned int);
+
+#endif /* CAT_ENTRY_H */
+
Index: uspace/app/bdsh/cmds/modules/modules.h
===================================================================
--- uspace/app/bdsh/cmds/modules/modules.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/bdsh/cmds/modules/modules.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -63,4 +63,5 @@
 #include "printf/entry.h"
 #include "echo/entry.h"
+#include "cmp/entry.h"
 
 /* Each .def function fills the module_t struct with the individual name, entry
@@ -86,4 +87,5 @@
 #include "printf/printf_def.h"
 #include "echo/echo_def.h"
+#include "cmp/cmp_def.h"
 
 	{NULL, NULL, NULL, NULL}
Index: uspace/app/bdsh/config.h
===================================================================
--- uspace/app/bdsh/config.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/bdsh/config.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -55,6 +55,3 @@
 #define PACKAGE_STRING "The brain dead shell"
 #define PACKAGE_TARNAME "bdsh"
-#define PACKAGE_VERSION "0.0.1"
-
-
-
+#define PACKAGE_VERSION "0.1.0"
Index: uspace/app/bdsh/errors.h
===================================================================
--- uspace/app/bdsh/errors.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/bdsh/errors.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -30,4 +30,6 @@
 #define ERRORS_H
 
+#include <io/verify.h>
+
 /* Various error levels */
 #define CL_EFATAL  -1
@@ -46,5 +48,6 @@
 extern volatile int cli_errno;
 
-extern void cli_error(int, const char *, ...);
+extern void cli_error(int, const char *, ...)
+    PRINTF_ATTRIBUTE(2, 3);
 
 #endif
Index: uspace/app/bdsh/input.c
===================================================================
--- uspace/app/bdsh/input.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/bdsh/input.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -67,7 +67,8 @@
 int process_input(cliuser_t *usr)
 {
-	token_t *tokens = calloc(WORD_MAX, sizeof(token_t));
-	if (tokens == NULL)
+	token_t *tokens_buf = calloc(WORD_MAX, sizeof(token_t));
+	if (tokens_buf == NULL)
 		return ENOMEM;
+	token_t *tokens = tokens_buf;
 	
 	char *cmd[WORD_MAX];
@@ -80,5 +81,5 @@
 
 	if (usr->line == NULL) {
-		free(tokens);
+		free(tokens_buf);
 		return CL_EFAIL;
 	}
@@ -213,5 +214,5 @@
 	}
 	tok_fini(&tok);
-	free(tokens);
+	free(tokens_buf);
 
 	return rc;
@@ -268,4 +269,5 @@
 	if (rc != EOK) {
 		/* Error in communication with console */
+		cli_quit = 1;
 		return;
 	}
Index: uspace/app/bithenge/Makefile
===================================================================
--- uspace/app/bithenge/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/bithenge/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2012 Sean Bartell
+# 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 = $(LIBBITHENGE_PREFIX)/libbithenge.a $(LIBBLOCK_PREFIX)/libblock.a
+EXTRA_CFLAGS = -I$(LIBBITHENGE_PREFIX)/include -D__HELENOS__
+BINARY = bithenge
+
+SOURCES = \
+	test.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/bithenge/Makefile.linux
===================================================================
--- uspace/app/bithenge/Makefile.linux	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/bithenge/Makefile.linux	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2012 Sean Bartell
+# 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.
+#
+
+CFLAGS += -fexec-charset=UTF-8 -finput-charset=UTF-8 -std=gnu99 -pipe
+CFLAGS += -Wall -Wextra -Werror -Wno-clobbered -Wno-unused-parameter -Wmissing-prototypes -Werror-implicit-function-declaration -Wwrite-strings
+CFLAGS += -ftrapv
+CFLAGS += -g
+
+LIBBITHENGE_PREFIX = ../../lib/bithenge
+CFLAGS += -I$(LIBBITHENGE_PREFIX)/include
+LIBS += $(LIBBITHENGE_PREFIX)/libbithenge.a
+
+BINARY = bithenge
+
+SOURCES = \
+	test.c
+
+ifdef COVERAGE
+	CFLAGS += -fprofile-arcs -ftest-coverage
+endif
+
+OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
+
+$(BINARY): $(OBJECTS)
+	$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
+
+clean:
+	find . -name '*.o' -follow -exec rm \{\} \;
+	rm -f $(BINARY)
Index: uspace/app/bithenge/test.c
===================================================================
--- uspace/app/bithenge/test.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/bithenge/test.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Simple program to test Bithenge.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <bithenge/blob.h>
+#include <bithenge/source.h>
+#include <bithenge/print.h>
+#include <bithenge/script.h>
+#include <bithenge/transform.h>
+#include <bithenge/tree.h>
+#include <bithenge/os.h>
+
+#ifdef __HELENOS__
+#include <str_error.h>
+#else
+#include <string.h>
+#define str_error strerror
+#endif
+
+int main(int argc, char *argv[])
+{
+	int rc;
+	if (argc < 3) {
+		fprintf(stderr, "Usage: %s <script> <source>\n", argv[0]);
+		return 1;
+	} else {
+		bithenge_scope_t *scope = NULL;
+		bithenge_transform_t *transform = NULL;
+		bithenge_node_t *node = NULL, *node2 = NULL;
+
+		rc = bithenge_scope_new(&scope, NULL);
+		if (rc != EOK) {
+			printf("Error creating scope: %s\n", str_error(rc));
+			scope = NULL;
+			goto error;
+		}
+
+		rc = bithenge_parse_script(argv[1], &transform);
+		if (rc != EOK) {
+			printf("Error parsing script: %s\n", str_error(rc));
+			transform = NULL;
+			goto error;
+		}
+
+		rc = bithenge_node_from_source(&node, argv[2]);
+		if (rc != EOK) {
+			printf("Error creating node from source: %s\n", str_error(rc));
+			node = NULL;
+			goto error;
+		}
+
+		rc = bithenge_transform_apply(transform, scope, node, &node2);
+		if (rc != EOK) {
+			const char *message = bithenge_scope_get_error(scope);
+			printf("Error applying transform: %s\n",
+			    message ? message : str_error(rc));
+			node2 = NULL;
+			goto error;
+		}
+
+		bithenge_node_dec_ref(node);
+		node = NULL;
+		bithenge_transform_dec_ref(transform);
+		transform = NULL;
+
+		rc = bithenge_print_node(BITHENGE_PRINT_PYTHON, node2);
+		if (rc != EOK) {
+			const char *message = bithenge_scope_get_error(scope);
+			printf("Error printing node: %s\n",
+			    message ? message : str_error(rc));
+			goto error;
+		}
+		bithenge_node_dec_ref(node2);
+		node2 = NULL;
+		bithenge_scope_dec_ref(scope);
+		scope = NULL;
+		printf("\n");
+
+		return 0;
+
+error:
+		bithenge_node_dec_ref(node);
+		bithenge_node_dec_ref(node2);
+		bithenge_transform_dec_ref(transform);
+		bithenge_scope_dec_ref(scope);
+		return 1;
+	}
+
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/blkdump/blkdump.c
===================================================================
--- uspace/app/blkdump/blkdump.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/blkdump/blkdump.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,5 +40,5 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <libblock.h>
+#include <block.h>
 #include <mem.h>
 #include <loc.h>
Index: uspace/app/date/Makefile
===================================================================
--- uspace/app/date/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/date/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2012 Maurizio Lombardi
+# 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 = date
+
+SOURCES = \
+	date.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/date/date.c
===================================================================
--- uspace/app/date/date.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/date/date.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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.
+ */
+
+
+#include <stdio.h>
+#include <device/clock_dev.h>
+#include <errno.h>
+#include <loc.h>
+#include <time.h>
+#include <malloc.h>
+#include <getopt.h>
+#include <ctype.h>
+
+#define NAME   "date"
+
+static int read_date_from_arg(char *wdate, struct tm *t);
+static int read_time_from_arg(char *wdate, struct tm *t);
+static int tm_sanity_check(struct tm *t);
+static bool is_leap_year(int year);
+
+static void usage(void);
+
+static int days_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+int
+main(int argc, char **argv)
+{
+	int rc, c;
+	category_id_t cat_id;
+	size_t        svc_cnt;
+	service_id_t  *svc_ids = NULL;
+	service_id_t  svc_id;
+	char          *svc_name = NULL;
+	bool          read_only = true;
+	char          *wdate = NULL;
+	char          *wtime = NULL;
+	struct tm     t;
+	int           n_args = argc;
+
+	while ((c = getopt(argc, argv, "hd:t:")) != -1) {
+		switch (c) {
+		case 'h':
+			usage();
+			return 0;
+		case 'd':
+			if (wdate) {
+				usage();
+				return 1;
+			}
+			wdate = (char *)optarg;
+			read_only = false;
+			n_args -= 2;
+			break;
+		case 't':
+			if (wtime) {
+				usage();
+				return 1;
+			}
+			wtime = (char *)optarg;
+			read_only = false;
+			n_args -= 2;
+			break;
+		case '?':
+			usage();
+			return 1;
+		}
+	}
+
+	if (n_args != 1) {
+		printf(NAME ": Unrecognized parameter\n");
+		usage();
+		return 1;
+	}
+
+	/* Get the id of the clock category */
+	rc = loc_category_get_id("clock", &cat_id, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		printf(NAME ": Cannot get clock category id\n");
+		goto exit;
+	}
+
+	/* Get the list of available services in the clock category */
+	rc = loc_category_get_svcs(cat_id, &svc_ids, &svc_cnt);
+	if (rc != EOK) {
+		printf(NAME ": Cannot get the list of services in the clock "
+		    "category\n");
+		goto exit;
+	}
+
+	/* Check if there are available services in the clock category */
+	if (svc_cnt == 0) {
+		printf(NAME ": No available service found in "
+		    "the clock category\n");
+		goto exit;
+	}
+
+	/* Get the name of the clock service */
+	rc = loc_service_get_name(svc_ids[0], &svc_name);
+	if (rc != EOK) {
+		printf(NAME ": Cannot get the name of the service\n");
+		goto exit;
+	}
+
+	/* Get the service id for the device */
+	rc = loc_service_get_id(svc_name, &svc_id, 0);
+	if (rc != EOK) {
+		printf(NAME ": Cannot get the service id for device %s",
+		    svc_name);
+		goto exit;
+	}
+
+	/* Connect to the device */
+	async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE,
+	    svc_id, 0);
+	if (!sess) {
+		printf(NAME ": Cannot connect to the device\n");
+		goto exit;
+	}
+
+	/* Read the current date/time */
+	rc = clock_dev_time_get(sess, &t);
+	if (rc != EOK) {
+		printf(NAME ": Cannot read the current time\n");
+		goto exit;
+	}
+
+	if (read_only) {
+		/* Print the current time and exit */
+		printf("%02d/%02d/%d ", t.tm_mday,
+		    t.tm_mon + 1, 1900 + t.tm_year);
+		printf("%02d:%02d:%02d\n", t.tm_hour, t.tm_min, t.tm_sec);
+	} else {
+		if (wdate) {
+			rc = read_date_from_arg(wdate, &t);
+			if (rc != EOK) {
+				printf(NAME ": error, date format not "
+				    "recognized\n");
+				usage();
+				goto exit;
+			}
+		}
+		if (wtime) {
+			rc = read_time_from_arg(wtime, &t);
+			if (rc != EOK) {
+				printf(NAME ": error, time format not "
+				    "recognized\n");
+				usage();
+				goto exit;
+			}
+		}
+
+		rc = tm_sanity_check(&t);
+		if (rc != EOK) {
+			printf(NAME ": error, invalid date/time\n");
+			goto exit;
+		}
+
+		rc = clock_dev_time_set(sess, &t);
+		if (rc != EOK) {
+			printf(NAME ": error, Unable to set date/time\n");
+			goto exit;
+		}
+	}
+
+exit:
+	free(svc_name);
+	free(svc_ids);
+	return rc;
+}
+
+/** Read the day, month and year from a string
+ *  with the following format: DD/MM/YYYY
+ */
+static int
+read_date_from_arg(char *wdate, struct tm *t)
+{
+	int rc;
+	uint32_t tmp;
+
+	if (str_size(wdate) != 10) /* str_size("DD/MM/YYYY") == 10 */
+		return EINVAL;
+
+	if (wdate[2] != '/' ||
+	    wdate[5] != '/') {
+		return EINVAL;
+	}
+
+	rc = str_uint32_t(&wdate[0], NULL, 10, false, &tmp);
+	if (rc != EOK)
+		return rc;
+
+	t->tm_mday = tmp;
+
+	rc = str_uint32_t(&wdate[3], NULL, 10, false, &tmp);
+	if (rc != EOK)
+		return rc;
+
+	t->tm_mon = tmp - 1;
+
+	rc = str_uint32_t(&wdate[6], NULL, 10, false, &tmp);
+	t->tm_year = tmp - 1900;
+
+	return rc;
+}
+
+/** Read the hours, minutes and seconds from a string
+ *  with the following format: HH:MM:SS or HH:MM
+ */
+static int
+read_time_from_arg(char *wtime, struct tm *t)
+{
+	int rc;
+	size_t len = str_size(wtime);
+	bool sec_present = len == 8;
+	uint32_t tmp;
+
+	/* str_size("HH:MM") == 5 */
+	/* str_size("HH:MM:SS") == 8 */
+	if (len != 8 && len != 5)
+		return EINVAL;
+
+	if (sec_present && wtime[5] != ':')
+		return EINVAL;
+
+	if (wtime[2] != ':')
+		return EINVAL;
+
+	rc = str_uint32_t(&wtime[0], NULL, 10, false, &tmp);
+	if (rc != EOK)
+		return rc;
+
+	t->tm_hour = tmp;
+
+	rc = str_uint32_t(&wtime[3], NULL, 10, false, &tmp);
+	if (rc != EOK)
+		return rc;
+
+	t->tm_min = tmp;
+
+	if (sec_present) {
+		rc = str_uint32_t(&wtime[6], NULL, 10, false, &tmp);
+		t->tm_sec = tmp;
+	} else
+		t->tm_sec = 0;
+
+	return rc;
+}
+
+/** Check if the tm structure contains valid values
+ *
+ * @param t     The tm structure to check
+ *
+ * @return      EOK on success or EINVAL
+ */
+static int
+tm_sanity_check(struct tm *t)
+{
+	int ndays;
+
+	if (t->tm_sec < 0 || t->tm_sec > 59)
+		return EINVAL;
+	else if (t->tm_min < 0 || t->tm_min > 59)
+		return EINVAL;
+	else if (t->tm_hour < 0 || t->tm_hour > 23)
+		return EINVAL;
+	else if (t->tm_mday < 1 || t->tm_mday > 31)
+		return EINVAL;
+	else if (t->tm_mon < 0 || t->tm_mon > 11)
+		return EINVAL;
+	else if (t->tm_year < 0 || t->tm_year > 199)
+		return EINVAL;
+
+	if (t->tm_mon == 1/* FEB */ && is_leap_year(t->tm_year))
+		ndays = 29;
+	else
+		ndays = days_month[t->tm_mon];
+
+	if (t->tm_mday > ndays)
+		return EINVAL;
+
+	return EOK;
+}
+
+/** Check if a year is a leap year
+ *
+ * @param year   The year to check
+ *
+ * @return       true if it is a leap year, false otherwise
+ */
+static bool
+is_leap_year(int year)
+{
+	bool r = false;
+
+	if (year % 4 == 0) {
+		if (year % 100 == 0)
+			r = year % 400 == 0;
+		else
+			r = true;
+	}
+
+	return r;
+}
+
+static void
+usage(void)
+{
+	printf("Usage: date [-d DD/MM/YYYY] [-t HH:MM[:SS]]\n");
+	printf("       -d   Change the current date\n");
+	printf("       -t   Change the current time\n");
+	printf("       -h   Display this information\n");
+}
+
Index: uspace/app/devctl/devctl.c
===================================================================
--- uspace/app/devctl/devctl.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/devctl/devctl.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -151,5 +151,6 @@
 	rc = devman_fun_offline(funh);
 	if (rc != EOK) {
-		printf(NAME ": Failed to offline function '%s'.\n", path);
+		printf(NAME ": Failed to offline function '%s' (%s)\n", path,
+		    str_error(rc));
 		return rc;
 	}
Index: uspace/app/edit/Makefile
===================================================================
--- uspace/app/edit/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/edit/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,5 +33,6 @@
 SOURCES = \
 	edit.c \
-	sheet.c
+	sheet.c \
+	search.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/edit/edit.c
===================================================================
--- uspace/app/edit/edit.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/edit/edit.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2012 Martin Sucha
  * All rights reserved.
  *
@@ -49,4 +50,5 @@
 
 #include "sheet.h"
+#include "search.h"
 
 enum redraw_flags {
@@ -83,4 +85,7 @@
 	 */
 	int ideal_column;
+	
+	char *previous_search;
+	bool previous_search_reverse;
 } pane_t;
 
@@ -91,5 +96,5 @@
 typedef struct {
 	char *file_name;
-	sheet_t sh;
+	sheet_t *sh;
 } doc_t;
 
@@ -106,5 +111,4 @@
 #define BUF_SIZE 64
 #define TAB_WIDTH 8
-#define ED_INFTY 65536
 
 /** Maximum filename length that can be entered. */
@@ -126,6 +130,7 @@
 static int file_save_range(char const *fname, spt_t const *spos,
     spt_t const *epos);
-static char *filename_prompt(char const *prompt, char const *init_value);
 static char *range_get_str(spt_t const *spos, spt_t const *epos);
+
+static char *prompt(char const *prompt, char const *init_value);
 
 static void pane_text_display(void);
@@ -139,17 +144,22 @@
 static void delete_char_after(void);
 static void caret_update(void);
-static void caret_move(int drow, int dcolumn, enum dir_spec align_dir);
-static void caret_move_word_left(void);
-static void caret_move_word_right(void);
+static void caret_move_relative(int drow, int dcolumn, enum dir_spec align_dir, bool select);
+static void caret_move_absolute(int row, int column, enum dir_spec align_dir, bool select);
+static void caret_move(spt_t spt, bool select, bool update_ideal_column);
+static void caret_move_word_left(bool select);
+static void caret_move_word_right(bool select);
+static void caret_go_to_line_ask(void);
 
 static bool selection_active(void);
 static void selection_sel_all(void);
 static void selection_sel_range(spt_t pa, spt_t pb);
-static void selection_sel_prev_word(void);
-static void selection_sel_next_word(void);
 static void selection_get_points(spt_t *pa, spt_t *pb);
 static void selection_delete(void);
 static void selection_copy(void);
 static void insert_clipboard_data(void);
+
+static void search(char *pattern, bool reverse);
+static void search_prompt(bool reverse);
+static void search_repeat(void);
 
 static void pt_get_sof(spt_t *pt);
@@ -160,4 +170,7 @@
 static bool pt_is_delimiter(spt_t *pt);
 static bool pt_is_punctuation(spt_t *pt);
+static spt_t pt_find_word_left(spt_t spt);
+static spt_t pt_find_word_left(spt_t spt);
+
 static int tag_cmp(tag_t const *a, tag_t const *b);
 static int spt_cmp(spt_t const *a, spt_t const *b);
@@ -170,8 +183,6 @@
 {
 	kbd_event_t ev;
-	coord_t coord;
 	bool new_file;
-
-	spt_t pt;
+	int rc;
 
 	con = console_init(stdin, stdout);
@@ -186,11 +197,15 @@
 
 	/* Start with an empty sheet. */
-	sheet_init(&doc.sh);
+	rc = sheet_create(&doc.sh);
+	if (rc != EOK) {
+		printf("Out of memory.\n");
+		return -1;
+	}
 
 	/* Place caret at the beginning of file. */
-	coord.row = coord.column = 1;
-	sheet_get_cell_pt(&doc.sh, &coord, dir_before, &pt);
-	sheet_place_tag(&doc.sh, &pt, &pane.caret_pos);
-	pane.ideal_column = coord.column;
+	spt_t sof;
+	pt_get_sof(&sof);
+	sheet_place_tag(doc.sh, &sof, &pane.caret_pos);
+	pane.ideal_column = 1;
 
 	if (argc == 2) {
@@ -208,10 +223,10 @@
 		new_file = true;
 
+	/* Place selection start tag. */
+	sheet_place_tag(doc.sh, &sof, &pane.sel_start);
+
 	/* Move to beginning of file. */
-	caret_move(-ED_INFTY, -ED_INFTY, dir_before);
-
-	/* Place selection start tag. */
-	tag_get_pt(&pane.caret_pos, &pt);
-	sheet_place_tag(&doc.sh, &pt, &pane.sel_start);
+	pt_get_sof(&sof);
+	caret_move(sof, true, true);
 
 	/* Initial display */
@@ -361,4 +376,5 @@
 static void key_handle_ctrl(kbd_event_t const *ev)
 {
+	spt_t pt;
 	switch (ev->key) {
 	case KC_Q:
@@ -392,15 +408,26 @@
 		selection_sel_all();
 		break;
-	case KC_W:
-		if (selection_active())
-			break;
-		selection_sel_prev_word();
-		selection_delete();
-		break;
 	case KC_RIGHT:
-		caret_move_word_right();
+		caret_move_word_right(false);
 		break;
 	case KC_LEFT:
-		caret_move_word_left();
+		caret_move_word_left(false);
+		break;
+	case KC_L:
+		caret_go_to_line_ask();
+		break;
+	case KC_F:
+		search_prompt(false);
+		break;
+	case KC_N:
+		search_repeat();
+		break;
+	case KC_HOME:
+		pt_get_sof(&pt);
+		caret_move(pt, false, true);
+		break;
+	case KC_END:
+		pt_get_eof(&pt);
+		caret_move(pt, false, true);
 		break;
 	default:
@@ -411,10 +438,22 @@
 static void key_handle_shift_ctrl(kbd_event_t const *ev)
 {
+	spt_t pt;
 	switch(ev->key) {
 	case KC_LEFT:
-		selection_sel_prev_word();
+		caret_move_word_left(true);
 		break;
 	case KC_RIGHT:
-		selection_sel_next_word();
+		caret_move_word_right(true);
+		break;
+	case KC_F:
+		search_prompt(true);
+		break;
+	case KC_HOME:
+		pt_get_sof(&pt);
+		caret_move(pt, true, true);
+		break;
+	case KC_END:
+		pt_get_eof(&pt);
+		caret_move(pt, true, true);
 		break;
 	default:
@@ -423,56 +462,29 @@
 }
 
-static void key_handle_movement(unsigned int key, bool select)
-{
-	spt_t pt;
-	spt_t caret_pt;
+/** Move caret while preserving or resetting selection. */
+static void caret_move(spt_t new_caret_pt, bool select, bool update_ideal_column)
+{
+	spt_t old_caret_pt, old_sel_pt;
 	coord_t c_old, c_new;
 	bool had_sel;
 
 	/* Check if we had selection before. */
-	tag_get_pt(&pane.caret_pos, &caret_pt);
-	tag_get_pt(&pane.sel_start, &pt);
-	had_sel = !spt_equal(&caret_pt, &pt);
-
-	switch (key) {
-	case KC_LEFT:
-		caret_move(0, -1, dir_before);
-		break;
-	case KC_RIGHT:
-		caret_move(0, 0, dir_after);
-		break;
-	case KC_UP:
-		caret_move(-1, 0, dir_before);
-		break;
-	case KC_DOWN:
-		caret_move(+1, 0, dir_before);
-		break;
-	case KC_HOME:
-		caret_move(0, -ED_INFTY, dir_before);
-		break;
-	case KC_END:
-		caret_move(0, +ED_INFTY, dir_before);
-		break;
-	case KC_PAGE_UP:
-		caret_move(-pane.rows, 0, dir_before);
-		break;
-	case KC_PAGE_DOWN:
-		caret_move(+pane.rows, 0, dir_before);
-		break;
-	default:
-		break;
-	}
+	tag_get_pt(&pane.caret_pos, &old_caret_pt);
+	tag_get_pt(&pane.sel_start, &old_sel_pt);
+	had_sel = !spt_equal(&old_caret_pt, &old_sel_pt);
+
+	/* Place tag of the caret */
+	sheet_remove_tag(doc.sh, &pane.caret_pos);
+	sheet_place_tag(doc.sh, &new_caret_pt, &pane.caret_pos);
 
 	if (select == false) {
 		/* Move sel_start to the same point as caret. */
-		sheet_remove_tag(&doc.sh, &pane.sel_start);
-		tag_get_pt(&pane.caret_pos, &pt);
-		sheet_place_tag(&doc.sh, &pt, &pane.sel_start);
-	}
-
+		sheet_remove_tag(doc.sh, &pane.sel_start);
+		sheet_place_tag(doc.sh, &new_caret_pt, &pane.sel_start);
+	}
+
+	spt_get_coord(&new_caret_pt, &c_new);
 	if (select) {
-		tag_get_pt(&pane.caret_pos, &pt);
-		spt_get_coord(&caret_pt, &c_old);
-		spt_get_coord(&pt, &c_new);
+		spt_get_coord(&old_caret_pt, &c_old);
 
 		if (c_old.row == c_new.row)
@@ -485,4 +497,46 @@
 		pane.rflags |= REDRAW_TEXT;
 	}
+	
+	if (update_ideal_column)
+		pane.ideal_column = c_new.column;
+	
+	caret_update();
+}
+
+static void key_handle_movement(unsigned int key, bool select)
+{
+	spt_t pt;
+	switch (key) {
+	case KC_LEFT:
+		caret_move_relative(0, -1, dir_before, select);
+		break;
+	case KC_RIGHT:
+		caret_move_relative(0, 0, dir_after, select);
+		break;
+	case KC_UP:
+		caret_move_relative(-1, 0, dir_before, select);
+		break;
+	case KC_DOWN:
+		caret_move_relative(+1, 0, dir_before, select);
+		break;
+	case KC_HOME:
+		tag_get_pt(&pane.caret_pos, &pt);
+		pt_get_sol(&pt, &pt);
+		caret_move(pt, select, true);
+		break;
+	case KC_END:
+		tag_get_pt(&pane.caret_pos, &pt);
+		pt_get_eol(&pt, &pt);
+		caret_move(pt, select, true);
+		break;
+	case KC_PAGE_UP:
+		caret_move_relative(-pane.rows, 0, dir_before, select);
+		break;
+	case KC_PAGE_DOWN:
+		caret_move_relative(+pane.rows, 0, dir_before, select);
+		break;
+	default:
+		break;
+	}
 }
 
@@ -520,5 +574,5 @@
 	char *fname;
 	
-	fname = filename_prompt("Save As", old_fname);
+	fname = prompt("Save As", old_fname);
 	if (fname == NULL) {
 		status_display("Save cancelled.");
@@ -535,6 +589,6 @@
 }
 
-/** Ask for a file name. */
-static char *filename_prompt(char const *prompt, char const *init_value)
+/** Ask for a string. */
+static char *prompt(char const *prompt, char const *init_value)
 {
 	kbd_event_t ev;
@@ -657,5 +711,5 @@
 
 	do {
-		sheet_copy_out(&doc.sh, &sp, epos, buf, BUF_SIZE, &bep);
+		sheet_copy_out(doc.sh, &sp, epos, buf, BUF_SIZE, &bep);
 		bytes = str_size(buf);
 
@@ -692,5 +746,5 @@
 
 	while (true) {
-		sheet_copy_out(&doc.sh, &sp, epos, &buf[bpos], buf_size - bpos,
+		sheet_copy_out(doc.sh, &sp, epos, &buf[bpos], buf_size - bpos,
 		    &bep);
 		bytes = str_size(&buf[bpos]);
@@ -714,5 +768,5 @@
 	int sh_rows, rows;
 
-	sheet_get_num_rows(&doc.sh, &sh_rows);
+	sheet_get_num_rows(doc.sh, &sh_rows);
 	rows = min(sh_rows - pane.sh_row + 1, pane.rows);
 
@@ -784,13 +838,13 @@
 		rbc.row = pane.sh_row + i;
 		rbc.column = pane.sh_column;
-		sheet_get_cell_pt(&doc.sh, &rbc, dir_before, &rb);
+		sheet_get_cell_pt(doc.sh, &rbc, dir_before, &rb);
 
 		/* Ending point for row display */
 		rec.row = pane.sh_row + i;
 		rec.column = pane.sh_column + pane.columns;
-		sheet_get_cell_pt(&doc.sh, &rec, dir_before, &re);
+		sheet_get_cell_pt(doc.sh, &rec, dir_before, &re);
 
 		/* Copy the text of the row to the buffer. */
-		sheet_copy_out(&doc.sh, &rb, &re, row_buf, ROW_BUF_SIZE, &dep);
+		sheet_copy_out(doc.sh, &rb, &re, row_buf, ROW_BUF_SIZE, &dep);
 
 		/* Display text from the buffer. */
@@ -842,6 +896,6 @@
 		/* Fill until the end of display area. */
 
-		if (str_length(row_buf) < (unsigned) scr_columns)
-			fill = scr_columns - str_length(row_buf);
+		if ((unsigned)s_column - 1 < scr_columns)
+			fill = scr_columns - (s_column - 1);
 		else
 			fill = 0;
@@ -861,14 +915,17 @@
 	spt_t caret_pt;
 	coord_t coord;
+	int last_row;
 
 	tag_get_pt(&pane.caret_pos, &caret_pt);
 	spt_get_coord(&caret_pt, &coord);
 
+	sheet_get_num_rows(doc.sh, &last_row);
+
 	const char *fname = (doc.file_name != NULL) ? doc.file_name : "<unnamed>";
 
 	console_set_pos(con, 0, scr_rows - 1);
 	console_set_style(con, STYLE_INVERTED);
-	int n = printf(" %d, %d: File '%s'. Ctrl-Q Quit  Ctrl-S Save  "
-	    "Ctrl-E Save As", coord.row, coord.column, fname);
+	int n = printf(" %d, %d (%d): File '%s'. Ctrl-Q Quit  Ctrl-S Save  "
+	    "Ctrl-E Save As", coord.row, coord.column, last_row, fname);
 	
 	int pos = scr_columns - 1 - n;
@@ -906,5 +963,5 @@
 	cbuf[offs] = '\0';
 
-	(void) sheet_insert(&doc.sh, &pt, dir_before, cbuf);
+	(void) sheet_insert(doc.sh, &pt, dir_before, cbuf);
 
 	pane.rflags |= REDRAW_ROW;
@@ -923,7 +980,7 @@
 
 	coord.column -= 1;
-	sheet_get_cell_pt(&doc.sh, &coord, dir_before, &sp);
-
-	(void) sheet_delete(&doc.sh, &sp, &ep);
+	sheet_get_cell_pt(doc.sh, &coord, dir_before, &sp);
+
+	(void) sheet_delete(doc.sh, &sp, &ep);
 
 	pane.rflags |= REDRAW_ROW;
@@ -941,8 +998,8 @@
 	spt_get_coord(&sp, &sc);
 
-	sheet_get_cell_pt(&doc.sh, &sc, dir_after, &ep);
+	sheet_get_cell_pt(doc.sh, &sc, dir_after, &ep);
 	spt_get_coord(&ep, &ec);
 
-	(void) sheet_delete(&doc.sh, &sp, &ep);
+	(void) sheet_delete(doc.sh, &sp, &ep);
 
 	pane.rflags |= REDRAW_ROW;
@@ -991,5 +1048,5 @@
 }
 
-/** Change the caret position.
+/** Relatively move caret position.
  *
  * Moves caret relatively to the current position. Looking at the first
@@ -997,6 +1054,9 @@
  * to a new character cell, and thus a new character. Then we either go to the
  * point before the the character or after it, depending on @a align_dir.
+ *
+ * @param select true if the selection tag should stay where it is
  */
-static void caret_move(int drow, int dcolumn, enum dir_spec align_dir)
+static void caret_move_relative(int drow, int dcolumn, enum dir_spec align_dir,
+    bool select)
 {
 	spt_t pt;
@@ -1016,9 +1076,9 @@
 		else {
 			coord.row--;
-			sheet_get_row_width(&doc.sh, coord.row, &coord.column);
+			sheet_get_row_width(doc.sh, coord.row, &coord.column);
 		}
 	}
 	if (drow > 0) {
-		sheet_get_num_rows(&doc.sh, &num_rows);
+		sheet_get_num_rows(doc.sh, &num_rows);
 		if (coord.row > num_rows) coord.row = num_rows;
 	}
@@ -1033,47 +1093,231 @@
 	 * coordinates. The character can be wider than one cell (e.g. tab).
 	 */
-	sheet_get_cell_pt(&doc.sh, &coord, align_dir, &pt);
-	sheet_remove_tag(&doc.sh, &pane.caret_pos);
-	sheet_place_tag(&doc.sh, &pt, &pane.caret_pos);
+	sheet_get_cell_pt(doc.sh, &coord, align_dir, &pt);
 
 	/* For non-vertical movement set the new value for @c ideal_column. */
-	if (!pure_vertical) {
-		spt_get_coord(&pt, &coord);
-		pane.ideal_column = coord.column;
-	}
-
-	caret_update();
-}
-
-static void caret_move_word_left(void) 
-{
+	caret_move(pt, select, !pure_vertical);
+}
+
+/** Absolutely move caret position.
+ *
+ * Moves caret to a specified position. We get to a new character cell, and
+ * thus a new character. Then we either go to the point before the the character
+ * or after it, depending on @a align_dir.
+ *
+ * @param select true if the selection tag should stay where it is
+ */
+static void caret_move_absolute(int row, int column, enum dir_spec align_dir,
+    bool select)
+{
+	coord_t coord;
+	coord.row = row;
+	coord.column = column;
+	
 	spt_t pt;
-
+	sheet_get_cell_pt(doc.sh, &coord, align_dir, &pt);
+	
+	caret_move(pt, select, true);
+}
+
+/** Find beginning of a word to the left of spt */
+static spt_t pt_find_word_left(spt_t spt) 
+{
 	do {
-		caret_move(0, -1, dir_before);
-
-		tag_get_pt(&pane.caret_pos, &pt);
-
-		sheet_remove_tag(&doc.sh, &pane.sel_start);
-		sheet_place_tag(&doc.sh, &pt, &pane.sel_start);
-	} while (!pt_is_word_beginning(&pt));
-
-	pane.rflags |= REDRAW_TEXT;
-}
-
-static void caret_move_word_right(void) 
+		spt_prev_char(spt, &spt);
+	} while (!pt_is_word_beginning(&spt));
+	return spt;
+}
+
+/** Find beginning of a word to the right of spt */
+static spt_t pt_find_word_right(spt_t spt) 
+{
+	do {
+		spt_next_char(spt, &spt);
+	} while (!pt_is_word_beginning(&spt));
+	return spt;
+}
+
+static void caret_move_word_left(bool select) 
 {
 	spt_t pt;
-
-	do {
-		caret_move(0, 0, dir_after);
-
-		tag_get_pt(&pane.caret_pos, &pt);
-
-		sheet_remove_tag(&doc.sh, &pane.sel_start);
-		sheet_place_tag(&doc.sh, &pt, &pane.sel_start);
-	} while (!pt_is_word_beginning(&pt));
-
-	pane.rflags |= REDRAW_TEXT;
+	tag_get_pt(&pane.caret_pos, &pt);
+	spt_t word_left = pt_find_word_left(pt);
+	caret_move(word_left, select, true);
+}
+
+static void caret_move_word_right(bool select) 
+{
+	spt_t pt;
+	tag_get_pt(&pane.caret_pos, &pt);
+	spt_t word_right = pt_find_word_right(pt);
+	caret_move(word_right, select, true);
+}
+
+/** Ask for line and go to it. */
+static void caret_go_to_line_ask(void)
+{
+	char *sline;
+	
+	sline = prompt("Go to line", "");
+	if (sline == NULL) {
+		status_display("Go to line cancelled.");
+		return;
+	}
+	
+	char *endptr;
+	int line = strtol(sline, &endptr, 10);
+	if (*endptr != '\0') {
+		free(sline);
+		status_display("Invalid number entered.");
+		return;
+	}
+	free(sline);
+	
+	caret_move_absolute(line, pane.ideal_column, dir_before, false);
+}
+
+/* Search operations */
+static int search_spt_producer(void *data, wchar_t *ret)
+{
+	assert(data != NULL);
+	assert(ret != NULL);
+	spt_t *spt = data;
+	*ret = spt_next_char(*spt, spt);
+	return EOK;
+}
+
+static int search_spt_reverse_producer(void *data, wchar_t *ret)
+{
+	assert(data != NULL);
+	assert(ret != NULL);
+	spt_t *spt = data;
+	*ret = spt_prev_char(*spt, spt);
+	return EOK;
+}
+
+static int search_spt_mark(void *data, void **mark)
+{
+	assert(data != NULL);
+	assert(mark != NULL);
+	spt_t *spt = data;
+	spt_t *new = calloc(1, sizeof(spt_t));
+	*mark = new;
+	if (new == NULL)
+		return ENOMEM;
+	*new = *spt;
+	return EOK;
+}
+
+static void search_spt_mark_free(void *data)
+{
+	free(data);
+}
+
+static search_ops_t search_spt_ops = {
+	.equals = char_exact_equals,
+	.producer = search_spt_producer,
+	.mark = search_spt_mark,
+	.mark_free = search_spt_mark_free,
+};
+
+static search_ops_t search_spt_reverse_ops = {
+	.equals = char_exact_equals,
+	.producer = search_spt_reverse_producer,
+	.mark = search_spt_mark,
+	.mark_free = search_spt_mark_free,
+};
+
+/** Ask for line and go to it. */
+static void search_prompt(bool reverse)
+{
+	char *pattern;
+	
+	const char *prompt_text = "Find next";
+	if (reverse)
+		prompt_text = "Find previous";
+	
+	const char *default_value = "";
+	if (pane.previous_search)
+		default_value = pane.previous_search;
+	
+	pattern = prompt(prompt_text, default_value);
+	if (pattern == NULL) {
+		status_display("Search cancelled.");
+		return;
+	}
+	
+	if (pane.previous_search)
+		free(pane.previous_search);
+	pane.previous_search = pattern;
+	pane.previous_search_reverse = reverse;
+	
+	search(pattern, reverse);
+}
+
+static void search_repeat(void)
+{
+	if (pane.previous_search == NULL) {
+		status_display("No previous search to repeat.");
+		return;
+	}
+	
+	search(pane.previous_search, pane.previous_search_reverse);
+}
+
+static void search(char *pattern, bool reverse)
+{
+	status_display("Searching...");
+	
+	spt_t sp, producer_pos;
+	tag_get_pt(&pane.caret_pos, &sp);
+	
+	/* Start searching on the position before/after caret */
+	if (!reverse) {
+		spt_next_char(sp, &sp);
+	}
+	else {
+		spt_prev_char(sp, &sp);
+	}
+	producer_pos = sp;
+	
+	search_ops_t ops = search_spt_ops;
+	if (reverse)
+		ops = search_spt_reverse_ops;
+	
+	search_t *search = search_init(pattern, &producer_pos, ops, reverse);
+	if (search == NULL) {
+		status_display("Failed initializing search.");
+		return;
+	}
+	
+	match_t match;
+	int rc = search_next_match(search, &match);
+	if (rc != EOK) {
+		status_display("Failed searching.");
+		search_fini(search);
+	}
+	
+	if (match.end) {
+		status_display("Match found.");
+		assert(match.end != NULL);
+		spt_t *end = match.end;
+		caret_move(*end, false, true);
+		while (match.length > 0) {
+			match.length--;
+			if (reverse) {
+				spt_next_char(*end, end);
+			}
+			else {
+				spt_prev_char(*end, end);
+			}
+		}
+		caret_move(*end, true, true);
+		free(end);
+	}
+	else {
+		status_display("Not found.");
+	}
+	
+	search_fini(search);
 }
 
@@ -1115,7 +1359,7 @@
 
 	if (rel < 0)
-		sheet_delete(&doc.sh, &pa, &pb);
+		sheet_delete(doc.sh, &pa, &pb);
 	else
-		sheet_delete(&doc.sh, &pb, &pa);
+		sheet_delete(doc.sh, &pb, &pa);
 
 	if (ca.row == cb.row)
@@ -1139,45 +1383,11 @@
 static void selection_sel_range(spt_t pa, spt_t pb)
 {
-	sheet_remove_tag(&doc.sh, &pane.sel_start);
-	sheet_place_tag(&doc.sh, &pa, &pane.sel_start);
-	sheet_remove_tag(&doc.sh, &pane.caret_pos);
-	sheet_place_tag(&doc.sh, &pb, &pane.caret_pos);
+	sheet_remove_tag(doc.sh, &pane.sel_start);
+	sheet_place_tag(doc.sh, &pa, &pane.sel_start);
+	sheet_remove_tag(doc.sh, &pane.caret_pos);
+	sheet_place_tag(doc.sh, &pb, &pane.caret_pos);
 
 	pane.rflags |= REDRAW_TEXT;
 	caret_update();
-}
-
-/** Add the previous word to the selection */
-static void selection_sel_prev_word(void)
-{
-	spt_t cpt, wpt, spt, ept;
-
-	selection_get_points(&spt, &ept);
-
-	tag_get_pt(&pane.caret_pos, &cpt);
-	caret_move_word_left();
-	tag_get_pt(&pane.caret_pos, &wpt);
-
-	if (spt_cmp(&spt, &cpt) == 0)
-		selection_sel_range(ept, wpt);
-	else
-		selection_sel_range(spt, wpt);
-}
-
-/** Add the next word to the selection */
-static void selection_sel_next_word(void)
-{
-	spt_t cpt, wpt, spt, ept;
-
-	selection_get_points(&spt, &ept);
-
-	tag_get_pt(&pane.caret_pos, &cpt);
-	caret_move_word_right();
-	tag_get_pt(&pane.caret_pos, &wpt);
-
-	if (spt_cmp(&ept, &cpt) == 0)
-		selection_sel_range(spt, wpt);
-	else
-		selection_sel_range(ept, wpt);
 }
 
@@ -1225,5 +1435,5 @@
 
 	coord.row = coord.column = 1;
-	sheet_get_cell_pt(&doc.sh, &coord, dir_before, pt);
+	sheet_get_cell_pt(doc.sh, &coord, dir_before, pt);
 }
 
@@ -1234,9 +1444,9 @@
 	int num_rows;
 
-	sheet_get_num_rows(&doc.sh, &num_rows);
+	sheet_get_num_rows(doc.sh, &num_rows);
 	coord.row = num_rows + 1;
 	coord.column = 1;
 
-	sheet_get_cell_pt(&doc.sh, &coord, dir_after, pt);
+	sheet_get_cell_pt(doc.sh, &coord, dir_after, pt);
 }
 
@@ -1249,5 +1459,5 @@
 	coord.column = 1;
 
-	sheet_get_cell_pt(&doc.sh, &coord, dir_before, spt);
+	sheet_get_cell_pt(doc.sh, &coord, dir_before, spt);
 }
 
@@ -1259,8 +1469,8 @@
 
 	spt_get_coord(cpt, &coord);
-	sheet_get_row_width(&doc.sh, coord.row, &row_width);
+	sheet_get_row_width(doc.sh, coord.row, &row_width);
 	coord.column = row_width - 1;
 
-	sheet_get_cell_pt(&doc.sh, &coord, dir_after, ept);
+	sheet_get_cell_pt(doc.sh, &coord, dir_after, ept);
 }
 
@@ -1288,5 +1498,5 @@
 
 	coord.column -= 1;
-	sheet_get_cell_pt(&doc.sh, &coord, dir_before, &lp);
+	sheet_get_cell_pt(doc.sh, &coord, dir_before, &lp);
 
 	return pt_is_delimiter(&lp)
@@ -1310,5 +1520,5 @@
 
 	coord.column += 1;
-	sheet_get_cell_pt(&doc.sh, &coord, dir_after, &rp);
+	sheet_get_cell_pt(doc.sh, &coord, dir_after, &rp);
 
 	ch = range_get_str(pt, &rp);
@@ -1336,5 +1546,5 @@
 
 	coord.column += 1;
-	sheet_get_cell_pt(&doc.sh, &coord, dir_after, &rp);
+	sheet_get_cell_pt(doc.sh, &coord, dir_after, &rp);
 
 	ch = range_get_str(pt, &rp);
Index: uspace/app/edit/search.c
===================================================================
--- uspace/app/edit/search.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/edit/search.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2012 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 edit
+ * @{
+ */
+/**
+ * @file
+ * @brief Simple searching facility.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include "search.h"
+#include "search_impl.h"
+
+search_t *search_init(const char *pattern, void *client_data, search_ops_t ops,
+    bool reverse)
+{
+	search_t *search = calloc(1, sizeof(search_t));
+	if (search == NULL)
+		return NULL;
+	
+	wchar_t *p = str_to_awstr(pattern);
+	if (p == NULL) {
+		free(search);
+		return NULL;
+	}
+	
+	search->pattern_length = wstr_length(p);
+	
+	if (reverse) {
+		/* Reverse the pattern */
+		size_t pos, half;
+		half = search->pattern_length / 2;
+		for (pos = 0; pos < half; pos++) {
+			wchar_t tmp = p[pos];
+			p[pos] = p[search->pattern_length - pos - 1];
+			p[search->pattern_length - pos - 1] = tmp;
+		}
+	}
+	
+	search->pattern = p;
+	
+	search->client_data = client_data;
+	search->ops = ops;
+	search->back_table = calloc(search->pattern_length, sizeof(ssize_t));
+	if (search->back_table == NULL) {
+		free(search->pattern);
+		free(search);
+		return NULL;
+	}
+	
+	search->pattern_pos = 0;
+	
+	search->back_table[0] = -1;
+	search->back_table[1] = 0;
+	size_t table_idx = 2;
+	size_t pattern_idx = 0;
+	while (table_idx < search->pattern_length) {
+		if (ops.equals(search->pattern[table_idx - 1],
+		    search->pattern[pattern_idx])) {
+			pattern_idx++;
+			search->back_table[table_idx] = pattern_idx;
+			table_idx++;
+		}
+		else if (pattern_idx > 0) {
+			pattern_idx = search->back_table[pattern_idx];
+		}
+		else {
+			pattern_idx = 0;
+			table_idx++;
+		}
+	}
+	
+	return search;
+}
+
+int search_next_match(search_t *s, match_t *match)
+{
+	search_equals_fn eq = s->ops.equals;
+	
+	wchar_t cur_char;
+	int rc = EOK;
+	while ((rc = s->ops.producer(s->client_data, &cur_char)) == EOK && cur_char > 0) {
+		/* Deal with mismatches */
+		while (s->pattern_pos > 0 && !eq(cur_char, s->pattern[s->pattern_pos])) {
+			s->pattern_pos = s->back_table[s->pattern_pos];
+		}
+		/* Check if the character matched */
+		if (eq(cur_char, s->pattern[s->pattern_pos])) {
+			s->pattern_pos++;
+			if (s->pattern_pos == s->pattern_length) {
+				s->pattern_pos = s->back_table[s->pattern_pos];
+				rc = s->ops.mark(s->client_data, &match->end);
+				if (rc != EOK)
+					return rc;
+				match->length = s->pattern_length;
+				return EOK;
+			}
+		}
+	}
+	
+	match->end = NULL;
+	match->length = 0;
+	
+	return rc;
+}
+
+void search_fini(search_t *search)
+{
+	free(search->pattern);
+	free(search->back_table);
+	
+}
+
+bool char_exact_equals(const wchar_t a, const wchar_t b)
+{
+	return a == b;
+}
+
+/** @}
+ */
Index: uspace/app/edit/search.h
===================================================================
--- uspace/app/edit/search.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/edit/search.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012 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 edit
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef SEARCH_H__
+#define SEARCH_H__
+
+#include <str.h>
+
+struct search;
+typedef struct search search_t;
+typedef bool (*search_equals_fn)(const wchar_t, const wchar_t);
+typedef int (*search_producer_fn)(void *, wchar_t *);
+typedef int (*search_mark_fn)(void *, void **);
+typedef void (*search_mark_free_fn)(void *);
+
+typedef struct match {
+	aoff64_t length;
+	void *end;
+} match_t;
+
+typedef struct search_ops {
+	search_equals_fn equals;
+	search_producer_fn producer;
+	search_mark_fn mark;
+	search_mark_free_fn mark_free;
+} search_ops_t;
+
+extern bool char_exact_equals(const wchar_t, const wchar_t);
+extern search_t *search_init(const char *, void *, search_ops_t, bool);
+extern int search_next_match(search_t *, match_t *);
+extern void search_fini(search_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/app/edit/search_impl.h
===================================================================
--- uspace/app/edit/search_impl.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/edit/search_impl.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012 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 edit
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef SEARCH_IMPL_H__
+#define SEARCH_IMPL_H__
+
+#include "search.h"
+
+/** Search state */
+typedef struct search {
+	/* Note: This structure is opaque for the user. */
+
+	const wchar_t *pattern;
+	size_t pattern_length;
+	ssize_t *back_table;
+	size_t pattern_pos;
+	void *client_data;
+	search_ops_t ops;
+} search_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/app/edit/sheet.c
===================================================================
--- uspace/app/edit/sheet.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/edit/sheet.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -57,4 +57,5 @@
 
 #include "sheet.h"
+#include "sheet_impl.h"
 
 enum {
@@ -66,6 +67,12 @@
 
 /** Initialize an empty sheet. */
-int sheet_init(sheet_t *sh)
-{
+int sheet_create(sheet_t **rsh)
+{
+	sheet_t *sh;
+
+	sh = calloc(1, sizeof(sheet_t));
+	if (sh == NULL)
+		return ENOMEM;
+
 	sh->dbuf_size = INITIAL_SIZE;
 	sh->text_size = 0;
@@ -77,4 +84,5 @@
 	list_initialize(&sh->tags);
 
+	*rsh = sh;
 	return EOK;
 }
@@ -315,4 +323,21 @@
 }
 
+/** Get a character at spt and return next spt */
+wchar_t spt_next_char(spt_t spt, spt_t *next)
+{
+	wchar_t ch = str_decode(spt.sh->data, &spt.b_off, spt.sh->text_size);
+	if (next)
+		*next = spt;
+	return ch;
+}
+
+wchar_t spt_prev_char(spt_t spt, spt_t *prev)
+{
+	wchar_t ch = str_decode_reverse(spt.sh->data, &spt.b_off, spt.sh->text_size);
+	if (prev)
+		*prev = spt;
+	return ch;
+}
+
 /** Place a tag on the specified s-point. */
 void sheet_place_tag(sheet_t *sh, spt_t const *pt, tag_t *tag)
Index: uspace/app/edit/sheet.h
===================================================================
--- uspace/app/edit/sheet.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/edit/sheet.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -50,13 +50,6 @@
 
 /** Sheet */
-typedef struct {
-	/* Note: This structure is opaque for the user. */
-
-	size_t text_size;
-	size_t dbuf_size;
-	char *data;
-
-	list_t tags;
-} sheet_t;
+struct sheet;
+typedef struct sheet sheet_t;
 
 /** Character cell coordinates
@@ -97,5 +90,5 @@
 } tag_t;
 
-extern int sheet_init(sheet_t *);
+extern int sheet_create(sheet_t **);
 extern int sheet_insert(sheet_t *, spt_t *, enum dir_spec, char *);
 extern int sheet_delete(sheet_t *, spt_t *, spt_t *);
@@ -108,4 +101,6 @@
 extern void spt_get_coord(spt_t const *, coord_t *);
 extern bool spt_equal(spt_t const *, spt_t const *);
+extern wchar_t spt_next_char(spt_t, spt_t *);
+extern wchar_t spt_prev_char(spt_t, spt_t *);
 
 extern void sheet_place_tag(sheet_t *, spt_t const *, tag_t *);
Index: uspace/app/edit/sheet_impl.h
===================================================================
--- uspace/app/edit/sheet_impl.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/edit/sheet_impl.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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 edit
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef SHEET_IMPL_H__
+#define SHEET_IMPL_H__
+
+#include "sheet.h"
+
+/** Sheet */
+typedef struct sheet {
+	/* Note: This structure is opaque for the user. */
+
+	size_t text_size;
+	size_t dbuf_size;
+	char *data;
+
+	list_t tags;
+} sheet_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/app/ext2info/ext2info.c
===================================================================
--- uspace/app/ext2info/ext2info.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/ext2info/ext2info.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,5 +40,5 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <libblock.h>
+#include <block.h>
 #include <mem.h>
 #include <loc.h>
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/init/init.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,4 +37,5 @@
 #include <stdio.h>
 #include <unistd.h>
+#include <stdarg.h>
 #include <vfs/vfs.h>
 #include <bool.h>
@@ -65,4 +66,13 @@
 #define SRV_CONSOLE  "/srv/console"
 #define APP_GETTERM  "/app/getterm"
+
+#define SRV_COMPOSITOR  "/srv/compositor"
+
+#define HID_INPUT              "hid/input"
+#define HID_OUTPUT             "hid/output"
+#define HID_COMPOSITOR_SERVER  ":0"
+
+#define srv_start(path, ...) \
+	srv_startl(path, path, ##__VA_ARGS__, NULL)
 
 /** Print banner */
@@ -143,61 +153,66 @@
 }
 
-static void spawn(const char *fname)
-{
-	int rc;
+static int srv_startl(const char *path, ...)
+{
 	struct stat s;
-	
-	if (stat(fname, &s) == ENOENT)
-		return;
-	
-	printf("%s: Spawning %s\n", NAME, fname);
-	rc = task_spawnl(NULL, fname, fname, NULL);
-	if (rc != EOK) {
-		printf("%s: Error spawning %s (%s)\n", NAME, fname,
-		    str_error(rc));
-	}
-}
-
-static void srv_start(const char *fname)
-{
+	if (stat(path, &s) == ENOENT) {
+		printf("%s: Unable to stat %s\n", NAME, path);
+		return ENOENT;
+	}
+	
+	printf("%s: Starting %s\n", NAME, path);
+	
+	va_list ap;
+	const char *arg;
+	int cnt = 0;
+	
+	va_start(ap, path);
+	do {
+		arg = va_arg(ap, const char *);
+		cnt++;
+	} while (arg != NULL);
+	va_end(ap);
+	
+	va_start(ap, path);
 	task_id_t id;
+	int rc = task_spawn(&id, path, cnt, ap);
+	va_end(ap);
+	
+	if (rc != EOK) {
+		printf("%s: Error spawning %s (%s)\n", NAME, path,
+		    str_error(rc));
+		return rc;
+	}
+	
+	if (!id) {
+		printf("%s: Error spawning %s (invalid task id)\n", NAME,
+		    path);
+		return EINVAL;
+	}
+	
 	task_exit_t texit;
-	int rc, retval;
-	struct stat s;
-	
-	if (stat(fname, &s) == ENOENT)
-		return;
-	
-	printf("%s: Starting %s\n", NAME, fname);
-	rc = task_spawnl(&id, fname, fname, NULL);
-	if (!id) {
-		printf("%s: Error spawning %s (%s)\n", NAME, fname,
-		    str_error(rc));
-		return;
-	}
-	
+	int retval;
 	rc = task_wait(id, &texit, &retval);
 	if (rc != EOK) {
-		printf("%s: Error waiting for %s (%s)\n", NAME, fname,
-		    str_error(rc));
-		return;
+		printf("%s: Error waiting for %s (%s)\n", NAME, path,
+		    str_error(rc));
+		return rc;
 	}
 	
 	if (texit != TASK_EXIT_NORMAL) {
 		printf("%s: Server %s failed to start (unexpectedly "
-		    "terminated)\n", NAME, fname);
-		return;
-	}
-
-	if (retval != 0) {
+		    "terminated)\n", NAME, path);
+		return EINVAL;
+	}
+	
+	if (retval != 0)
 		printf("%s: Server %s failed to start (exit code %d)\n", NAME,
-			fname, retval);
-	}
-}
-
-static void console(const char *isvc, const char *fbsvc)
-{
-	printf("%s: Spawning %s %s %s\n", NAME, SRV_CONSOLE, isvc, fbsvc);
-	
+		    path, retval);
+	
+	return retval;
+}
+
+static int console(const char *isvc, const char *osvc)
+{
 	/* Wait for the input service to be ready */
 	service_id_t service_id;
@@ -206,20 +221,57 @@
 		printf("%s: Error waiting on %s (%s)\n", NAME, isvc,
 		    str_error(rc));
-		return;
-	}
-	
-	/* Wait for the framebuffer service to be ready */
-	rc = loc_service_get_id(fbsvc, &service_id, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		printf("%s: Error waiting on %s (%s)\n", NAME, fbsvc,
-		    str_error(rc));
-		return;
-	}
-	
-	rc = task_spawnl(NULL, SRV_CONSOLE, SRV_CONSOLE, isvc, fbsvc, NULL);
-	if (rc != EOK) {
-		printf("%s: Error spawning %s %s %s (%s)\n", NAME, SRV_CONSOLE,
-		    isvc, fbsvc, str_error(rc));
-	}
+		return rc;
+	}
+	
+	/* Wait for the output service to be ready */
+	rc = loc_service_get_id(osvc, &service_id, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		printf("%s: Error waiting on %s (%s)\n", NAME, osvc,
+		    str_error(rc));
+		return rc;
+	}
+	
+	return srv_start(SRV_CONSOLE, isvc, osvc);
+}
+
+static int compositor(const char *isvc, const char *name)
+{
+	/* Wait for the input service to be ready */
+	service_id_t service_id;
+	int rc = loc_service_get_id(isvc, &service_id, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		printf("%s: Error waiting on %s (%s)\n", NAME, isvc,
+		    str_error(rc));
+		return rc;
+	}
+	
+	return srv_start(SRV_COMPOSITOR, isvc, name);
+}
+
+static int gui_start(const char *app, const char *srv_name)
+{
+	char winreg[50];
+	snprintf(winreg, sizeof(winreg), "%s%s%s", "comp", srv_name, "/winreg");
+	
+	printf("%s: Spawning %s %s\n", NAME, app, winreg);
+	
+	task_id_t id;
+	int rc = task_spawnl(&id, app, app, winreg, NULL);
+	if (rc != EOK) {
+		printf("%s: Error spawning %s %s (%s)\n", NAME, app,
+		    winreg, str_error(rc));
+		return -1;
+	}
+	
+	task_exit_t texit;
+	int retval;
+	rc = task_wait(id, &texit, &retval);
+	if ((rc != EOK) || (texit != TASK_EXIT_NORMAL)) {
+		printf("%s: Error retrieving retval from %s (%s)\n", NAME,
+		    app, str_error(rc));
+		return -1;
+	}
+	
+	return retval;
 }
 
@@ -227,6 +279,4 @@
 {
 	char term[LOC_NAME_MAXLEN];
-	int rc;
-	
 	snprintf(term, LOC_NAME_MAXLEN, "%s/%s", LOCFS_MOUNT_POINT, svc);
 	
@@ -235,5 +285,5 @@
 	/* Wait for the terminal service to be ready */
 	service_id_t service_id;
-	rc = loc_service_get_id(svc, &service_id, IPC_FLAG_BLOCKING);
+	int rc = loc_service_get_id(svc, &service_id, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
 		printf("%s: Error waiting on %s (%s)\n", NAME, term,
@@ -279,42 +329,37 @@
 	if (!mount_root(STRING(RDFMT))) {
 		printf("%s: Exiting\n", NAME);
-		return -1;
+		return 1;
 	}
 	
 	/* Make sure tmpfs is running. */
-	if (str_cmp(STRING(RDFMT), "tmpfs") != 0) {
-		spawn("/srv/tmpfs");
-	}
-	
-	spawn("/srv/locfs");
-	spawn("/srv/taskmon");
+	if (str_cmp(STRING(RDFMT), "tmpfs") != 0)
+		srv_start("/srv/tmpfs");
+	
+	srv_start("/srv/locfs");
+	srv_start("/srv/taskmon");
 	
 	if (!mount_locfs()) {
 		printf("%s: Exiting\n", NAME);
-		return -2;
+		return 2;
 	}
 	
 	mount_tmpfs();
 	
-	spawn("/srv/devman");
-	spawn("/srv/apic");
-	spawn("/srv/i8259");
-	spawn("/srv/obio");
+	srv_start("/srv/devman");
+	srv_start("/srv/apic");
+	srv_start("/srv/i8259");
+	srv_start("/srv/obio");
 	srv_start("/srv/cuda_adb");
 	srv_start("/srv/s3c24xx_uart");
 	srv_start("/srv/s3c24xx_ts");
 	
-	spawn("/srv/loopip");
-	spawn("/srv/ethip");
-	spawn("/srv/inetsrv");
-	spawn("/srv/tcp");
-	spawn("/srv/udp");
-	
-	spawn("/srv/fb");
-	spawn("/srv/input");
-	console("hid/input", "hid/fb0");
-	
-	spawn("/srv/clipboard");
-	spawn("/srv/remcons");
+	srv_start("/srv/loopip");
+	srv_start("/srv/ethip");
+	srv_start("/srv/inetsrv");
+	srv_start("/srv/tcp");
+	srv_start("/srv/udp");
+	
+	srv_start("/srv/clipboard");
+	srv_start("/srv/remcons");
 	
 	/*
@@ -325,13 +370,11 @@
 	srv_start("/srv/ata_bd");
 	srv_start("/srv/gxe_bd");
-#else
-	(void) srv_start;
 #endif
 	
 #ifdef CONFIG_MOUNT_DATA
 	/* Make sure fat is running. */
-	if (str_cmp(STRING(RDFMT), "fat") != 0) {
+	if (str_cmp(STRING(RDFMT), "fat") != 0)
 		srv_start("/srv/fat");
-	}
+	
 	mount_data();
 #else
@@ -339,11 +382,23 @@
 #endif
 	
-	getterm("term/vc0", "/app/bdsh", true);
-	getterm("term/vc1", "/app/bdsh", false);
-	getterm("term/vc2", "/app/bdsh", false);
-	getterm("term/vc3", "/app/bdsh", false);
-	getterm("term/vc4", "/app/bdsh", false);
-	getterm("term/vc5", "/app/bdsh", false);
-	getterm("term/vc6", "/app/klog", false);
+	srv_start("/srv/input", HID_INPUT);
+	srv_start("/srv/output", HID_OUTPUT);
+	
+	int rc = compositor(HID_INPUT, HID_COMPOSITOR_SERVER);
+	if (rc == EOK) {
+		gui_start("/app/vlaunch", HID_COMPOSITOR_SERVER);
+		gui_start("/app/vterm", HID_COMPOSITOR_SERVER);
+	} else {
+		rc = console(HID_INPUT, HID_OUTPUT);
+		if (rc == EOK) {
+			getterm("term/vc0", "/app/bdsh", true);
+			getterm("term/vc1", "/app/bdsh", false);
+			getterm("term/vc2", "/app/bdsh", false);
+			getterm("term/vc3", "/app/bdsh", false);
+			getterm("term/vc4", "/app/bdsh", false);
+			getterm("term/vc5", "/app/bdsh", false);
+			getterm("term/vc6", "/app/klog", false);
+		}
+	}
 	
 	return 0;
Index: uspace/app/logset/Makefile
===================================================================
--- uspace/app/logset/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/logset/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2012 Vojtech Horky
+# 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 = logset
+
+SOURCES = \
+	main.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/logset/main.c
===================================================================
--- uspace/app/logset/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/logset/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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 logset
+ * @{
+ */
+/** @file Change logger behavior.
+ */
+#include <stdio.h>
+#include <async.h>
+#include <errno.h>
+#include <str_error.h>
+#include <io/logctl.h>
+
+static log_level_t parse_log_level_or_die(const char *log_level)
+{
+	log_level_t result;
+	int rc = log_level_from_str(log_level, &result);
+	if (rc != EOK) {
+		fprintf(stderr, "Unrecognised log level '%s': %s.\n",
+		    log_level, str_error(rc));
+		exit(2);
+	}
+	return result;
+}
+
+static void usage(const char *progname)
+{
+	fprintf(stderr, "Usage:\n");
+	fprintf(stderr, "  %s <default-logging-level>\n", progname);
+	fprintf(stderr, "  %s <log-name> <logging-level>\n", progname);
+}
+
+int main(int argc, char *argv[])
+{
+	if (argc == 2) {
+		log_level_t new_default_level = parse_log_level_or_die(argv[1]);
+		int rc = logctl_set_default_level(new_default_level);
+
+		if (rc != EOK) {
+			fprintf(stderr, "Failed to change default logging level: %s.\n",
+			    str_error(rc));
+			return 2;
+		}
+	} else if (argc == 3) {
+		log_level_t new_level = parse_log_level_or_die(argv[2]);
+		const char *logname = argv[1];
+		int rc = logctl_set_log_level(logname, new_level);
+
+		if (rc != EOK) {
+			fprintf(stderr, "Failed to change logging level: %s.\n",
+			    str_error(rc));
+			return 2;
+		}
+	} else {
+		usage(argv[0]);
+		return 1;
+	}
+
+	return 0;
+}
+
+/** @}
+ */
Index: pace/app/lsusb/Makefile
===================================================================
--- uspace/app/lsusb/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,44 +1,0 @@
-#
-# Copyright (c) 2011 Vojtech Horky
-# 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 = lsusb
-
-LIBS = \
-	$(LIBUSBDEV_PREFIX)/libusbdev.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS = \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-
-SOURCES = \
-	main.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/app/lsusb/main.c
===================================================================
--- uspace/app/lsusb/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,139 +1,0 @@
-/*
- * Copyright (c) 2010-2011 Vojtech Horky
- * 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 lsusb
- * @{
- */
-/**
- * @file
- * Listing of USB host controllers.
- */
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <str_error.h>
-#include <bool.h>
-#include <getopt.h>
-#include <devman.h>
-#include <loc.h>
-#include <usb/dev/hub.h>
-#include <usb/hc.h>
-
-#define NAME "lsusb"
-
-#define MAX_USB_ADDRESS USB11_ADDRESS_MAX
-#define MAX_PATH_LENGTH 1024
-
-static void print_found_hc(service_id_t sid, const char *path)
-{
-	printf("Bus %" PRIun ": %s\n", sid, path);
-}
-static void print_found_dev(usb_address_t addr, const char *path)
-{
-	printf("  Device %02d: %s\n", addr, path);
-}
-
-static void print_hc_devices(devman_handle_t hc_handle)
-{
-	int rc;
-	usb_hc_connection_t conn;
-
-	usb_hc_connection_initialize(&conn, hc_handle);
-	rc = usb_hc_connection_open(&conn);
-	if (rc != EOK) {
-		printf(NAME ": failed to connect to HC: %s.\n",
-		    str_error(rc));
-		return;
-	}
-	usb_address_t addr;
-	for (addr = 1; addr < MAX_USB_ADDRESS; addr++) {
-		devman_handle_t dev_handle;
-		rc = usb_hc_get_handle_by_address(&conn, addr, &dev_handle);
-		if (rc != EOK) {
-			continue;
-		}
-		char path[MAX_PATH_LENGTH];
-		rc = devman_fun_get_path(dev_handle, path, MAX_PATH_LENGTH);
-		if (rc != EOK) {
-			continue;
-		}
-		print_found_dev(addr, path);
-	}
-	usb_hc_connection_close(&conn);
-}
-
-int main(int argc, char *argv[])
-{
-	category_id_t usbhc_cat;
-	service_id_t *svcs;
-	size_t count;
-	size_t i;
-	int rc;
-
-	rc = loc_category_get_id(USB_HC_CATEGORY, &usbhc_cat, 0);
-	if (rc != EOK) {
-		printf(NAME ": Error resolving category '%s'",
-		    USB_HC_CATEGORY);
-		return 1;
-	}
-
-	rc = loc_category_get_svcs(usbhc_cat, &svcs, &count);
-	if (rc != EOK) {
-		printf(NAME ": Error getting list of host controllers.\n");
-		return 1;
-	}
-
-	for (i = 0; i < count; i++) {
-		devman_handle_t hc_handle = 0;
-		int rc = usb_ddf_get_hc_handle_by_sid(svcs[i], &hc_handle);
-		if (rc != EOK) {
-			printf(NAME ": Error resolving handle of HC with SID %"
-			    PRIun ", skipping.\n", svcs[i]);
-			continue;
-		}
-		char path[MAX_PATH_LENGTH];
-		rc = devman_fun_get_path(hc_handle, path, MAX_PATH_LENGTH);
-		if (rc != EOK) {
-			printf(NAME ": Error resolving path of HC with SID %"
-			    PRIun ", skipping.\n", svcs[i]);
-			continue;
-		}
-		print_found_hc(svcs[i], path);
-		print_hc_devices(hc_handle);
-	}
-
-	free(svcs);
-
-	return 0;
-}
-
-
-/** @}
- */
Index: uspace/app/mkexfat/mkexfat.c
===================================================================
--- uspace/app/mkexfat/mkexfat.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/mkexfat/mkexfat.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,5 +38,5 @@
 
 #include <stdio.h>
-#include <libblock.h>
+#include <block.h>
 #include <assert.h>
 #include <errno.h>
@@ -49,4 +49,5 @@
 #include <str.h>
 #include <getopt.h>
+#include <macros.h>
 #include "exfat.h"
 #include "upcase.h"
@@ -87,5 +88,4 @@
 #define FIRST_FREE_CLUSTER   2
 
-#define min(x, y) ((x) < (y) ? (x) : (y))
 
 typedef struct exfat_cfg {
Index: uspace/app/mkfat/mkfat.c
===================================================================
--- uspace/app/mkfat/mkfat.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/mkfat/mkfat.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,5 +40,5 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <libblock.h>
+#include <block.h>
 #include <mem.h>
 #include <loc.h>
Index: uspace/app/mkmfs/mkmfs.c
===================================================================
--- uspace/app/mkmfs/mkmfs.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/mkmfs/mkmfs.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -39,5 +39,5 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <libblock.h>
+#include <block.h>
 #include <unistd.h>
 #include <errno.h>
Index: uspace/app/msim/arch_helenos/input.c
===================================================================
--- uspace/app/msim/arch_helenos/input.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/msim/arch_helenos/input.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -32,4 +32,7 @@
 /** @file HelenOS specific functions for MSIM simulator.
  */
+
+/* Because of asprintf. */
+#define _GNU_SOURCE
 #include "../../io/input.h"
 #include "../../io/output.h"
@@ -38,4 +41,5 @@
 #include <tinput.h>
 #include <errno.h>
+#include <stdlib.h>
 
 static tinput_t *input_prompt;
Index: uspace/app/msim/arch_helenos/misc.c
===================================================================
--- uspace/app/msim/arch_helenos/misc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/msim/arch_helenos/misc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -44,4 +44,5 @@
 #include <ctype.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 /* Define when the dprinter device shall try to filter
Index: uspace/app/sportdmp/sportdmp.c
===================================================================
--- uspace/app/sportdmp/sportdmp.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/sportdmp/sportdmp.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,15 +37,25 @@
 static void syntax_print(void)
 {
-	fprintf(stderr, "Usage: sportdmp <baud> <device_service>\n");
+	fprintf(stderr, "Usage: sportdmp [--baud=<baud>] [device_service]\n");
 }
 
 int main(int argc, char **argv)
 {
-	const char* svc_path = "devices/\\hw\\pci0\\00:01.0\\com1\\a";
 	sysarg_t baud = 9600;
+	service_id_t svc_id;
 	
-	if (argc > 1) {
+	int arg = 1;
+	int rc;
+		
+	if (argc > arg && str_test_prefix(argv[arg], "--baud=")) {
+		size_t arg_offset = str_lsize(argv[arg], 7);
+		char* arg_str = argv[arg] + arg_offset;
+		if (str_length(arg_str) == 0) {
+			fprintf(stderr, "--baud requires an argument\n");
+			syntax_print();
+			return 1;
+		}
 		char *endptr;
-		baud = strtol(argv[1], &endptr, 10);
+		baud = strtol(arg_str, &endptr, 10);
 		if (*endptr != '\0') {
 			fprintf(stderr, "Invalid value for baud\n");
@@ -53,26 +63,55 @@
 			return 1;
 		}
+		arg++;
 	}
 	
-	if (argc > 2) {
-		svc_path = argv[2];
+	if (argc > arg) {
+		rc = loc_service_get_id(argv[arg], &svc_id, 0);
+		if (rc != EOK) {
+			fprintf(stderr, "Cannot find device service %s\n",
+			    argv[arg]);
+			return 1;
+		}
+		arg++;
+	}
+	else {
+		category_id_t serial_cat_id;
+		
+		rc = loc_category_get_id("serial", &serial_cat_id, 0);
+		if (rc != EOK) {
+			fprintf(stderr, "Failed getting id of category "
+			    "'serial'\n");
+			return 1;
+		}
+		
+		service_id_t *svc_ids;
+		size_t svc_count;
+		
+		rc = loc_category_get_svcs(serial_cat_id, &svc_ids, &svc_count);		if (rc != EOK) {
+			fprintf(stderr, "Failed getting list of services\n");
+			return 1;
+		}
+		
+		if (svc_count == 0) {
+			fprintf(stderr, "No service in category 'serial'\n");
+			free(svc_ids);
+			return 1;
+		}
+		
+		svc_id = svc_ids[0];
+		free(svc_ids);
 	}
 	
-	if (argc > 3) {
+	if (argc > arg) {
+		fprintf(stderr, "Too many arguments\n");
 		syntax_print();
 		return 1;
 	}
 	
-	service_id_t svc_id;
-	int rc = loc_service_get_id(svc_path, &svc_id, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		fprintf(stderr, "Cannot find device service %s\n", svc_path);
-		return 1;
-	}
 	
 	async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE, svc_id,
 	    IPC_FLAG_BLOCKING);
 	if (!sess) {
-		fprintf(stderr, "Failed connecting to service %s\n", svc_path);
+		fprintf(stderr, "Failed connecting to service\n");
 	}
 	
@@ -101,10 +140,7 @@
 		ssize_t i;
 		for (i = 0; i < read; i++) {
-			if ((buf[i] >= 32) && (buf[i] < 128))
-				putchar((wchar_t) buf[i]);
-			else
-				putchar('.');
-			fflush(stdout);
+			printf("%02hhx ", buf[i]);
 		}
+		fflush(stdout);
 	}
 	
Index: uspace/app/tester/Makefile
===================================================================
--- uspace/app/tester/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/tester/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -29,6 +29,6 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBEXT2_PREFIX)/libext2.a $(LIBBLOCK_PREFIX)/libblock.a
-EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBEXT2_PREFIX)
+LIBS = $(LIBEXT2_PREFIX)/libext2.a $(LIBBLOCK_PREFIX)/libblock.a $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBEXT2_PREFIX) -I$(LIBSOFTFLOAT_PREFIX)
 BINARY = tester
 
@@ -42,10 +42,15 @@
 	print/print4.c \
 	print/print5.c \
+	print/print6.c \
 	console/console1.c \
 	stdio/stdio1.c \
 	stdio/stdio2.c \
+	stdio/logger1.c \
+	stdio/logger2.c \
 	fault/fault1.c \
 	fault/fault2.c \
 	fault/fault3.c \
+	float/float1.c \
+	float/softfloat1.c \
 	vfs/vfs1.c \
 	ipc/ping_pong.c \
@@ -59,5 +64,5 @@
 	hw/misc/virtchar1.c \
 	hw/serial/serial1.c \
-	libext2/libext2_1.c
+	ext2/ext2_1.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/tester/ext2/ext2_1.c
===================================================================
--- uspace/app/tester/ext2/ext2_1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/tester/ext2/ext2_1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include "../tester.h"
+#include "../util.h"
+#include <libext2.h>
+#include <malloc.h>
+
+static ext2_superblock_t *fake_superblock1()
+{
+	uint8_t *buf;
+	int i;
+	
+	buf = malloc(EXT2_SUPERBLOCK_SIZE);
+	if (buf == NULL) {
+		return NULL;
+	}
+	
+	for (i = 0; i < EXT2_SUPERBLOCK_SIZE; i++) {
+		buf[i] = i % 256;
+	}
+	
+	return (ext2_superblock_t *) buf;
+}
+
+const char *test_ext2_1(void)
+{
+	ext2_superblock_t *fake1;
+	
+	TPRINTF("Testing ext2 superblock getters...\n");
+	TPRINTF("Simple test for correct position and byte order\n");
+	
+	fake1 = fake_superblock1();
+	if (fake1 == NULL) {
+		return "Failed allocating memory for test superblock 1";
+	}
+	
+	ASSERT_EQ_32(0x03020100, ext2_superblock_get_total_inode_count(fake1),
+	    "Failed getting total inode count");
+	ASSERT_EQ_32(0x07060504, ext2_superblock_get_total_block_count(fake1),
+	    "Failed getting total block count");
+	ASSERT_EQ_32(0x0B0A0908, ext2_superblock_get_reserved_block_count(fake1),
+	    "Failed getting reserved block count");
+	ASSERT_EQ_32(0x0F0E0D0C, ext2_superblock_get_free_block_count(fake1),
+	    "Failed getting free block count");
+	ASSERT_EQ_32(0x13121110, ext2_superblock_get_free_inode_count(fake1),
+	    "Failed getting free inode count");
+	ASSERT_EQ_32(0x17161514, ext2_superblock_get_first_block(fake1),
+	    "Failed getting first block number");
+	ASSERT_EQ_32(0x1B1A1918, ext2_superblock_get_block_size_log2(fake1),
+	    "Failed getting log block size");
+	ASSERT_EQ_32(0x1F1E1D1C, ext2_superblock_get_fragment_size_log2(fake1),
+	    "Failed getting log fragment size");
+	ASSERT_EQ_32(0x23222120, ext2_superblock_get_blocks_per_group(fake1),
+	    "Failed getting blocks per group");
+	ASSERT_EQ_32(0x27262524, ext2_superblock_get_fragments_per_group(fake1),
+	    "Failed getting fragments per group");
+	ASSERT_EQ_32(0x2B2A2928, ext2_superblock_get_inodes_per_group(fake1),
+	    "Failed getting inodes per group");
+	ASSERT_EQ_16(0x3938, ext2_superblock_get_magic(fake1),
+	    "Failed getting magic number");
+	ASSERT_EQ_16(0x3B3A, ext2_superblock_get_state(fake1),
+	    "Failed getting state");
+	ASSERT_EQ_16(0x3F3E, ext2_superblock_get_rev_minor(fake1),
+	    "Failed getting minor revision number");
+	ASSERT_EQ_32(0x4B4A4948, ext2_superblock_get_os(fake1),
+	    "Failed getting OS");
+	ASSERT_EQ_32(0x4F4E4D4C, ext2_superblock_get_rev_major(fake1),
+	    "Failed getting major revision number");
+	ASSERT_EQ_32(0x57565554, ext2_superblock_get_first_inode(fake1),
+	    "Failed getting first inode number");
+	ASSERT_EQ_16(0x5958, ext2_superblock_get_inode_size(fake1),
+	    "Failed getting size");
+	ASSERT_EQ_8(0x68, fake1->uuid[0], "UUID position is incorrect");
+	ASSERT_EQ_8(0x78, fake1->volume_name[0],
+	    "Volume name position is incorrect");
+	
+	return NULL;
+}
Index: uspace/app/tester/ext2/ext2_1.def
===================================================================
--- uspace/app/tester/ext2/ext2_1.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/tester/ext2/ext2_1.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,6 @@
+{
+	"ext2_1",
+	"Superblock getters test",
+	&test_ext2_1,
+	true
+},
Index: uspace/app/tester/float/float1.c
===================================================================
--- uspace/app/tester/float/float1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/tester/float/float1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2005 Jakub Vana
+ * Copyright (c) 2005 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <atomic.h>
+#include <thread.h>
+#include <inttypes.h>
+#include "../tester.h"
+
+#define THREADS   150
+#define ATTEMPTS  100
+
+#define E_10E8     UINT32_C(271828182)
+#define PRECISION  100000000
+
+static atomic_t threads_finished;
+static atomic_t threads_fault;
+
+static void e(void *data)
+{
+	for (unsigned int i = 0; i < ATTEMPTS; i++) {
+		double le = -1;
+		double e = 0;
+		double f = 1;
+		
+		for (double d = 1; e != le; d *= f, f += 1) {
+			le = e;
+			e = e + 1 / d;
+		}
+		
+		if ((uint32_t) (e * PRECISION) != E_10E8) {
+			atomic_inc(&threads_fault);
+			break;
+		}
+	}
+	
+	atomic_inc(&threads_finished);
+}
+
+const char *test_float1(void)
+{
+	atomic_count_t total = 0;
+	
+	atomic_set(&threads_finished, 0);
+	atomic_set(&threads_fault, 0);
+	
+	TPRINTF("Creating threads");
+	for (unsigned int i = 0; i < THREADS; i++) {
+		if (thread_create(e, NULL, "e", NULL) < 0) {
+			TPRINTF("\nCould not create thread %u\n", i);
+			break;
+		}
+		
+		TPRINTF(".");
+		total++;
+	}
+	
+	TPRINTF("\n");
+	
+	while (atomic_get(&threads_finished) < total) {
+		TPRINTF("Threads left: %" PRIua "\n",
+		    total - atomic_get(&threads_finished));
+		sleep(1);
+	}
+	
+	if (atomic_get(&threads_fault) == 0)
+		return NULL;
+	
+	return "Test failed";
+}
Index: uspace/app/tester/float/float1.def
===================================================================
--- uspace/app/tester/float/float1.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/tester/float/float1.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,6 @@
+{
+	"float1",
+	"Floating point computation",
+	&test_float1,
+	true
+},
Index: uspace/app/tester/float/softfloat1.c
===================================================================
--- uspace/app/tester/float/softfloat1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/tester/float/softfloat1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sftypes.h>
+#include <add.h>
+#include <sub.h>
+#include <mul.h>
+#include <div.h>
+#include <comparison.h>
+#include <bool.h>
+#include "../tester.h"
+
+#define OPERANDS  6 
+#define PRECISION  10000
+
+#define PRIdCMPTYPE  PRId32
+
+typedef int32_t cmptype_t;
+typedef void (* float_op_t)(float, float, float *, float_t *);
+typedef void (* double_op_t)(double, double, double *, double_t *);
+typedef void (* double_cmp_op_t)(double, double, cmptype_t *, cmptype_t *);
+typedef void (* template_t)(void *, unsigned, unsigned, cmptype_t *,
+    cmptype_t *);
+
+static float fop_a[OPERANDS] =
+	{3.5, -2.1, 100.0, 50.0, -1024.0, 0.0};
+
+static float fop_b[OPERANDS] =
+	{-2.1, 100.0, 50.0, -1024.0, 3.5, 0.0};
+
+static double dop_a[OPERANDS] =
+	{3.5, -2.1, 100.0, 50.0, -1024.0, 0.0};
+
+static double dop_b[OPERANDS] =
+	{-2.1, 100.0, 50.0, -1024.0, 3.5, 0.0};
+
+static cmptype_t cmpabs(cmptype_t a)
+{
+	if (a >= 0)
+		return a;
+	
+	return -a;
+}
+
+static int dcmp(double a, double b)
+{
+	if (a < b)
+		return -1;
+	else if (a > b)
+		return 1;
+
+	return 0;
+}
+
+static void
+float_template(void *f, unsigned i, unsigned j, cmptype_t *pic,
+    cmptype_t *pisc)
+{
+	float c;
+	float_t sc;
+
+	float_op_t op = (float_op_t) f;
+	
+	op(fop_a[i], fop_b[j], &c, &sc);
+
+	*pic = (cmptype_t) (c * PRECISION);
+	*pisc = (cmptype_t) (sc.val * PRECISION);
+}
+
+static void
+double_template(void *f, unsigned i, unsigned j, cmptype_t *pic,
+    cmptype_t *pisc)
+{
+	double c;
+	double_t sc;
+
+	double_op_t op = (double_op_t) f;
+	
+	op(dop_a[i], dop_b[j], &c, &sc);
+
+	*pic = (cmptype_t) (c * PRECISION);
+	*pisc = (cmptype_t) (sc.val * PRECISION);
+}
+
+static void
+double_compare_template(void *f, unsigned i, unsigned j, cmptype_t *pis,
+    cmptype_t *piss)
+{
+	double_cmp_op_t op = (double_cmp_op_t) f;
+	
+	op(dop_a[i], dop_b[j], pis, piss);
+}
+
+static bool test_template(template_t template, void *f)
+{
+	bool correct = true;
+	
+	for (unsigned int i = 0; i < OPERANDS; i++) {
+		for (unsigned int j = 0; j < OPERANDS; j++) {			
+			cmptype_t ic;
+			cmptype_t isc;
+
+			template(f, i, j, &ic, &isc);	
+			cmptype_t diff = cmpabs(ic - isc);
+			
+			if (diff != 0) {
+				TPRINTF("i=%u, j=%u diff=%" PRIdCMPTYPE "\n",
+				    i, j, diff);
+				correct = false;
+			}
+		}
+	}
+	
+	return correct;
+}
+
+static void float_add_operator(float a, float b, float *pc, float_t *psc)
+{
+	*pc = a + b;
+	
+	float_t sa;
+	float_t sb;
+	
+	sa.val = a;
+	sb.val = b;
+	if (sa.data.parts.sign == sb.data.parts.sign)
+		psc->data = add_float(sa.data, sb.data);
+	else if (sa.data.parts.sign) {
+		sa.data.parts.sign = 0;
+		psc->data = sub_float(sb.data, sa.data);
+	} else {
+		sb.data.parts.sign = 0;
+		psc->data = sub_float(sa.data, sb.data);
+	}
+}
+
+static void float_mul_operator(float a, float b, float *pc, float_t *psc)
+{
+	*pc = a * b;
+	
+	float_t sa;
+	float_t sb;
+	
+	sa.val = a;
+	sb.val = b;
+	psc->data = mul_float(sa.data, sb.data);
+}
+
+static void float_div_operator(float a, float b, float *pc, float_t *psc)
+{
+	if ((cmptype_t) b == 0) {
+		*pc = 0.0;
+		psc->val = 0.0;
+		return;
+	}
+
+	*pc = a / b;
+	
+	float_t sa;
+	float_t sb;
+	
+	sa.val = a;
+	sb.val = b;
+	psc->data = div_float(sa.data, sb.data);
+}
+
+static void double_add_operator(double a, double b, double *pc, double_t *psc)
+{
+	*pc = a + b;
+	
+	double_t sa;
+	double_t sb;
+	
+	sa.val = a;
+	sb.val = b;
+	if (sa.data.parts.sign == sb.data.parts.sign)
+		psc->data = add_double(sa.data, sb.data);
+	else if (sa.data.parts.sign) {
+		sa.data.parts.sign = 0;
+		psc->data = sub_double(sb.data, sa.data);
+	} else {
+		sb.data.parts.sign = 0;
+		psc->data = sub_double(sa.data, sb.data);
+	}
+}
+
+static void double_mul_operator(double a, double b, double *pc, double_t *psc)
+{
+	*pc = a * b;
+	
+	double_t sa;
+	double_t sb;
+	
+	sa.val = a;
+	sb.val = b;
+	psc->data = mul_double(sa.data, sb.data);
+}
+
+static void double_div_operator(double a, double b, double *pc, double_t *psc)
+{
+	if ((cmptype_t) b == 0) {
+		*pc = 0.0;
+		psc->val = 0.0;
+		return;
+	}
+
+	*pc = a / b;
+	
+	double_t sa;
+	double_t sb;
+	
+	sa.val = a;
+	sb.val = b;
+	psc->data = div_double(sa.data, sb.data);
+}
+
+static void
+double_cmp_operator(double a, double b, cmptype_t *pis, cmptype_t *piss)
+{
+	*pis = dcmp(a, b);
+
+	double_t sa;
+	double_t sb;
+
+	sa.val = a;
+	sb.val = b;
+
+	if (is_double_lt(sa.data, sb.data))
+		*piss = -1;
+	else if (is_double_gt(sa.data, sb.data))
+		*piss = 1;
+	else if (is_double_eq(sa.data, sb.data))
+		*piss = 0;
+	else
+		*piss = 42;
+}
+
+const char *test_softfloat1(void)
+{
+	const char *err = NULL;
+
+	if (!test_template(float_template, float_add_operator)) {
+		err = "Float addition failed";
+		TPRINTF("%s\n", err);
+	}
+	if (!test_template(float_template, float_mul_operator)) {
+		err = "Float multiplication failed";
+		TPRINTF("%s\n", err);
+	}
+	if (!test_template(float_template, float_div_operator)) {
+		err = "Float division failed";
+		TPRINTF("%s\n", err);
+	}
+	if (!test_template(double_template, double_add_operator)) {
+		err = "Double addition failed";
+		TPRINTF("%s\n", err);
+	}
+	if (!test_template(double_template, double_mul_operator)) {
+		err = "Double multiplication failed";
+		TPRINTF("%s\n", err);
+	}
+	if (!test_template(double_template, double_div_operator)) {
+		err = "Double division failed";
+		TPRINTF("%s\n", err);
+	}
+	if (!test_template(double_compare_template, double_cmp_operator)) {
+		err = "Double comparison failed";
+		TPRINTF("%s\n", err);
+	}
+	
+	return err;
+}
+
Index: uspace/app/tester/float/softfloat1.def
===================================================================
--- uspace/app/tester/float/softfloat1.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/tester/float/softfloat1.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,6 @@
+{
+	"softfloat1",
+	"Software floating point computation",
+	&test_softfloat1,
+	true
+},
Index: pace/app/tester/libext2/libext2_1.c
===================================================================
--- uspace/app/tester/libext2/libext2_1.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,106 +1,0 @@
-/*
- * Copyright (c) 2011 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.
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include "../tester.h"
-#include "../util.h"
-#include <libext2.h>
-#include <malloc.h>
-
-static ext2_superblock_t *fake_superblock1()
-{
-	uint8_t *buf;
-	int i;
-	
-	buf = malloc(EXT2_SUPERBLOCK_SIZE);
-	if (buf == NULL) {
-		return NULL;
-	}
-	
-	for (i = 0; i < EXT2_SUPERBLOCK_SIZE; i++) {
-		buf[i] = i % 256;
-	}
-	
-	return (ext2_superblock_t *) buf;
-}
-
-const char *test_libext2_1(void)
-{
-	ext2_superblock_t *fake1;
-	
-	TPRINTF("Testing libext2 superblock getters...\n");
-	TPRINTF("Simple test for correct position and byte order\n");
-	
-	fake1 = fake_superblock1();
-	if (fake1 == NULL) {
-		return "Failed allocating memory for test superblock 1";
-	}
-	
-	ASSERT_EQ_32(0x03020100, ext2_superblock_get_total_inode_count(fake1),
-	    "Failed getting total inode count");
-	ASSERT_EQ_32(0x07060504, ext2_superblock_get_total_block_count(fake1),
-	    "Failed getting total block count");
-	ASSERT_EQ_32(0x0B0A0908, ext2_superblock_get_reserved_block_count(fake1),
-	    "Failed getting reserved block count");
-	ASSERT_EQ_32(0x0F0E0D0C, ext2_superblock_get_free_block_count(fake1),
-	    "Failed getting free block count");
-	ASSERT_EQ_32(0x13121110, ext2_superblock_get_free_inode_count(fake1),
-	    "Failed getting free inode count");
-	ASSERT_EQ_32(0x17161514, ext2_superblock_get_first_block(fake1),
-	    "Failed getting first block number");
-	ASSERT_EQ_32(0x1B1A1918, ext2_superblock_get_block_size_log2(fake1),
-	    "Failed getting log block size");
-	ASSERT_EQ_32(0x1F1E1D1C, ext2_superblock_get_fragment_size_log2(fake1),
-	    "Failed getting log fragment size");
-	ASSERT_EQ_32(0x23222120, ext2_superblock_get_blocks_per_group(fake1),
-	    "Failed getting blocks per group");
-	ASSERT_EQ_32(0x27262524, ext2_superblock_get_fragments_per_group(fake1),
-	    "Failed getting fragments per group");
-	ASSERT_EQ_32(0x2B2A2928, ext2_superblock_get_inodes_per_group(fake1),
-	    "Failed getting inodes per group");
-	ASSERT_EQ_16(0x3938, ext2_superblock_get_magic(fake1),
-	    "Failed getting magic number");
-	ASSERT_EQ_16(0x3B3A, ext2_superblock_get_state(fake1),
-	    "Failed getting state");
-	ASSERT_EQ_16(0x3F3E, ext2_superblock_get_rev_minor(fake1),
-	    "Failed getting minor revision number");
-	ASSERT_EQ_32(0x4B4A4948, ext2_superblock_get_os(fake1),
-	    "Failed getting OS");
-	ASSERT_EQ_32(0x4F4E4D4C, ext2_superblock_get_rev_major(fake1),
-	    "Failed getting major revision number");
-	ASSERT_EQ_32(0x57565554, ext2_superblock_get_first_inode(fake1),
-	    "Failed getting first inode number");
-	ASSERT_EQ_16(0x5958, ext2_superblock_get_inode_size(fake1),
-	    "Failed getting size");
-	ASSERT_EQ_8(0x68, fake1->uuid[0], "UUID position is incorrect");
-	ASSERT_EQ_8(0x78, fake1->volume_name[0],
-	    "Volume name position is incorrect");
-	
-	return NULL;
-}
Index: pace/app/tester/libext2/libext2_1.def
===================================================================
--- uspace/app/tester/libext2/libext2_1.def	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,6 +1,0 @@
-{
-	"libext2_1",
-	"Superblock getters test",
-	&test_libext2_1,
-	true
-},
Index: uspace/app/tester/print/print5.def
===================================================================
--- uspace/app/tester/print/print5.def	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/tester/print/print5.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -1,6 +1,6 @@
 {
-	"print1",
-	"String printf test",
-	&test_print1,
+	"print5",
+	"Char printf test",
+	&test_print5,
 	true
 },
Index: uspace/app/tester/print/print6.c
===================================================================
--- uspace/app/tester/print/print6.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/tester/print/print6.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * 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.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include "../tester.h"
+
+#include <str.h>
+
+const char *test_print6(void)
+{
+	struct {
+		double val;
+		const char *fmt;
+		const char *exp_str;
+		const char *warn_str;
+	} pat[] = {
+		/* 
+		 * Generic 
+		 */
+		{ 2.0,         "%g",       "2", 0 },
+		{ 0,           "%g",       "0", 0 },
+		{ 0.1,         "%g",     "0.1", 0 },
+		{ 9e59,        "%g",   "9e+59", 0 },
+		{ -9e-59,      "%g",  "-9e-59", 0 },
+		{ 1e307,       "%g",  "1e+307", 0 },   
+		{ 0.09999999999999999, "%g",  "9.999999999999999e-02", 0 },   
+		{ 0.099999999999999999, "%g",  "0.1", 0 },   
+
+		/*
+		 * gcc and msvc convert "3.4567e-317" to different binary
+		 * doubles.
+		 */
+		{ 3.4567e-317, "%g",  "3.4567e-317", "3.456998e-317" },   
+		{ 3.4567e-318, "%g",  "3.4567e-318", 0 },   
+		{ 123456789012345.0, "%g",  "123456789012345", 0 },   
+		{ -123456789012345.0, "%g",  "-123456789012345", 0 },   
+
+		/* Special */
+		{ 1e300 * 1e300, "%g",  "inf", 0 },   
+		{ -1.0 /(1e300 * 1e300), "%g",  "-0", 0 },   
+
+		{ 1234567.8901, "%g",  "1234567.8901", 0 },   
+		{ 1234567.80012, "%g",  "1234567.80012", 0 },   
+		{ 112e-32, "%g",  "1.12e-30", 0 },   
+		{ 10.0e45, "%g",  "1e+46", 0 },   
+
+		/* rounding w/ trailing zero removal */
+		{ 0.01, "%10.6g",      "      0.01", 0 },   
+		{ 9.495, "%10.2g",     "       9.5", 0 },   
+		{ 9.495e30, "%10.2g",  "   9.5e+30", 0 },   
+		{ 9.495e30, "%10g",  " 9.495e+30", 0 },   
+		{ 9.495e30, "%10.6g",  " 9.495e+30", 0 },   
+
+		/*
+		 * Scientific 
+		 */
+		{ 1e05, "%e",  "1.000000e+05", 0 },   
+
+		/* full padding */
+
+		/* __PRINTF_FLAG_SHOWPLUS | __PRINTF_FLAG_ZEROPADDED */
+		{ 1e-1, "%+010.3e",  "+1.000e-01", 0 },
+		{ 1e-1, "%+10.3e",  "+1.000e-01", 0 },   
+		/* __PRINTF_FLAG_SHOWPLUS | __PRINTF_FLAG_LEFTALIGNED */
+		{ 1e-1, "%+-10.3e",  "+1.000e-01", 0 },
+
+		/* padding */
+
+		/* __PRINTF_FLAG_SHOWPLUS | __PRINTF_FLAG_ZEROPADDED */
+		{ 1e-1, "%+010.2e",  "+01.00e-01", 0 },
+		{ 1e-1, "%+10.2e",  " +1.00e-01", 0 },   
+		/* __PRINTF_FLAG_SHOWPLUS | __PRINTF_FLAG_LEFTALIGNED */
+		{ 1e-1, "%+-10.2e",  "+1.00e-01 ", 0 },
+		/* __PRINTF_FLAG_SPACESIGN | __PRINTF_FLAG_ZEROPADDED */
+		{ 1e-1, "% 010.2e",  " 01.00e-01", 0 },
+		/* __PRINTF_FLAG_ZEROPADDED */
+		{ 1e-1, "%010.2e",  "001.00e-01", 0 },
+		/* __PRINTF_FLAG_SPACESIGN */
+		{ 1e-1, "% 10.2e",  "  1.00e-01", 0 },
+		{ 1e-1, "%10.2e",  "  1.00e-01", 0 },   
+
+		/* padding fractionals */
+
+		/* __PRINTF_FLAG_SHOWPLUS | __PRINTF_FLAG_ZEROPADDED */
+		{ 1.08e29, "%+010.3e",  "+1.080e+29", 0 },
+		{ 1.08e29, "%+10.3e",  "+1.080e+29", 0 },  
+		/* __PRINTF_FLAG_SHOWPLUS | __PRINTF_FLAG_ZEROPADDED */
+		{ 1.08e29, "%+011.2e",  "+001.08e+29", 0 },
+		{ 1.085e29, "%11.2e", "   1.09e+29", 0 },   
+
+		/* rounding */
+
+		{ 1.345e2, "%+10.2e",  " +1.35e+02", 0 }, 
+		{ 9.995e2, "%+10.2e",  " +1.00e+03", 0 }, 
+		{ -9.99499999e2, "%10.2e",  " -9.99e+02", 0 },   
+		{ -9.99499999e2, "%10.0e",  "    -1e+03", 0 },   
+		/* __PRINTF_FLAG_DECIMALPT */
+		{ -9.99499999e2, "%#10.0e",  "   -1.e+03", 0 },
+		/* __PRINTF_FLAG_DECIMALPT */
+		{ -1.2345006789e+231, "%#10.10e",   "-1.2345006789e+231", 0 },
+		/* __PRINTF_FLAG_DECIMALPT */
+		{ -1.23450067995e+231, "%#10.10e",  "-1.2345006800e+231", 0 },
+			
+		/* special */
+
+		{ 1e300 * 1e300, "%10.5e",  "       inf", 0 },   
+		{ -1.0 /(1e300 * 1e300), "%10.2e",  " -0.00e+00", 0 },   
+		/* __PRINTF_FLAG_BIGCHARS */
+		{ 1e300 * 1e300, "%10.5E",  "       INF", 0 },
+		/* __PRINTF_FLAG_BIGCHARS */
+		{ -1.0 /(1e300 * 1e300), "%10.2E",  " -0.00E+00", 0 },
+
+		/*
+		 * Fixed
+		 */
+		 
+		/* padding */
+
+		/* __PRINTF_FLAG_SPACESIGN | __PRINTF_FLAG_ZEROPADDED */
+		{ 1e-1, "% 010.3f",  " 00000.100", 0 },
+		/*
+		 * __PRINTF_FLAG_SPACESIGN | __PRINTF_FLAG_ZEROPADDED |
+		 * __PRINTF_FLAG_LEFTALIGNED
+		 */
+		{ 1e-1, "% 0-10.3f",  " 0.100    ", 0 },
+		/* __PRINTF_FLAG_SPACESIGN | __PRINTF_FLAG_ZEROPADDED */
+		{ 1e-1, "% 010.3f",  " 00000.100", 0 },
+		{ 1e-1, "%10.3f",  "     0.100", 0 },   
+
+		/* rounding */
+
+		{ -0.0, "%10.0f",     "        -0", 0 },   
+		{ -0.099, "%+10.3f",   "    -0.099", 0 }, 
+		{ -0.0995, "%+10.3f",  "    -0.100", 0 }, 
+		{ -0.0994, "%+10.3f",  "    -0.099", 0 }, 
+		{ -99.995, "%+10.0f",  "      -100", 0 }, 
+		{ 3.5, "%+10.30f",  "+3.500000000000000000000000000000", 0 }, 
+		{ 3.5, "%+10.0f",      "        +4", 0 }, 
+		{ 0.1, "%+10.6f",      " +0.100000", 0 }, 
+
+		/*
+		 * The compiler will go for closer 0.10..055 instead of
+		 * 0.09..917
+		 */
+		{ 0.1, "%+10.20f",  "+0.10000000000000000550", 0 },  
+		/* Next closest to 0.1 */
+		{ 0.0999999999999999917, "%+10.20f", "+0.09999999999999999170",
+		    0 }, 
+		{ 0.0999999999999999917, "%+10f",    " +0.100000", 0 },
+		{ 0.0999999999999998945, "%10.20f",  "0.09999999999999989450",
+		    0 },   
+	};
+
+	int patterns_len = (int)(sizeof(pat) / sizeof(pat[0]));
+	int failed = 0;
+	const int buf_size = 256;
+	char buf[256 + 1] = { 0 };
+	
+	TPRINTF("Test printing of floating point numbers via "
+	    "printf(\"%%f\"):\n");
+	
+	for (int i = 0; i < patterns_len; ++i) {
+		
+		snprintf(buf, buf_size, pat[i].fmt, pat[i].val);
+		
+		if (!str_cmp(buf, pat[i].exp_str)) {
+			TPRINTF("ok:  %s |%s| == |%s|\n",
+			    pat[i].fmt, buf, pat[i].exp_str);
+		} else {
+			if (pat[i].warn_str && !str_cmp(buf, pat[i].warn_str)) {
+				TPRINTF("warn: %s |%s| != |%s|\n",
+				    pat[i].fmt, buf, pat[i].exp_str);
+			} else {
+				++failed;
+				TPRINTF("ERR: %s |%s| != |%s|\n",
+				    pat[i].fmt, buf, pat[i].exp_str);
+			}
+		}
+	}
+	
+	if (failed) {
+		return "Unexpectedly misprinted floating point numbers.";
+	} else {
+		return 0;
+	}
+}
+
Index: uspace/app/tester/print/print6.def
===================================================================
--- uspace/app/tester/print/print6.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/tester/print/print6.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,6 @@
+{
+	"print6",
+	"Floating point printf test",
+	&test_print6,
+	true
+},
Index: uspace/app/tester/stdio/logger1.c
===================================================================
--- uspace/app/tester/stdio/logger1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/tester/stdio/logger1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <io/log.h>
+#include "../tester.h"
+
+const char *test_logger1(void)
+{
+	for (log_level_t level = 0; level < LVL_LIMIT; level++) {
+		log_msg(LOG_DEFAULT, level, "Testing logger, level %d.", (int) level);
+	}
+
+	return NULL;
+}
Index: uspace/app/tester/stdio/logger1.def
===================================================================
--- uspace/app/tester/stdio/logger1.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/tester/stdio/logger1.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,6 @@
+{
+	"logger1",
+	"Logger printing test",
+	&test_logger1,
+	true
+},
Index: uspace/app/tester/stdio/logger2.c
===================================================================
--- uspace/app/tester/stdio/logger2.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/tester/stdio/logger2.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <io/log.h>
+#include <async.h>
+#include "../tester.h"
+
+const char *test_logger2(void)
+{
+	log_t log_alpha = log_create("alpha", LOG_DEFAULT);
+	log_t log_bravo = log_create("bravo", log_alpha);
+
+	TPRINTF("Alpha is %" PRIlogctx ".\n", log_alpha);
+	TPRINTF("Bravo is %" PRIlogctx ".\n", log_bravo);
+
+	while (true) {
+		/*
+		 * Intentionally skipping FATAL to allow muting
+		 * the output completely by setting visible level to FATAL.
+		 */
+		for (log_level_t level = LVL_ERROR; level < LVL_LIMIT; level++) {
+			log_msg(LOG_DEFAULT, level, "Printing level %d (%s).",
+			    (int) level, log_level_str(level));
+			log_msg(log_alpha, level,
+			    "Printing level %d (%s) into alpha log.",
+			    (int) level, log_level_str(level));
+			log_msg(log_bravo, level,
+			    "Printing level %d (%s) into bravo sub-log.",
+			    (int) level, log_level_str(level));
+			async_usleep(1000 * 100);
+		}
+	}
+
+	return NULL;
+}
Index: uspace/app/tester/stdio/logger2.def
===================================================================
--- uspace/app/tester/stdio/logger2.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/tester/stdio/logger2.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,6 @@
+{
+	"logger2",
+	"Logger endless test",
+	&test_logger2,
+	false
+},
Index: uspace/app/tester/tester.c
===================================================================
--- uspace/app/tester/tester.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/tester/tester.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -39,4 +39,5 @@
 #include <stdio.h>
 #include <str.h>
+#include <io/log.h>
 #include "tester.h"
 
@@ -52,10 +53,15 @@
 #include "print/print4.def"
 #include "print/print5.def"
+#include "print/print6.def"
 #include "console/console1.def"
 #include "stdio/stdio1.def"
 #include "stdio/stdio2.def"
+#include "stdio/logger1.def"
+#include "stdio/logger2.def"
 #include "fault/fault1.def"
 #include "fault/fault2.def"
 #include "fault/fault3.def"
+#include "float/float1.def"
+#include "float/softfloat1.def"
 #include "vfs/vfs1.def"
 #include "ipc/ping_pong.def"
@@ -68,5 +74,5 @@
 #include "hw/serial/serial1.def"
 #include "hw/misc/virtchar1.def"
-#include "libext2/libext2_1.def"
+#include "ext2/ext2_1.def"
 	{NULL, NULL, NULL, false}
 };
@@ -138,4 +144,6 @@
 	}
 	
+	log_init("tester");
+
 	test_quiet = false;
 	test_argc = argc - 2;
Index: uspace/app/tester/tester.h
===================================================================
--- uspace/app/tester/tester.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/tester/tester.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -85,10 +85,15 @@
 extern const char *test_print4(void);
 extern const char *test_print5(void);
+extern const char *test_print6(void);
 extern const char *test_console1(void);
 extern const char *test_stdio1(void);
 extern const char *test_stdio2(void);
+extern const char *test_logger1(void);
+extern const char *test_logger2(void);
 extern const char *test_fault1(void);
 extern const char *test_fault2(void);
 extern const char *test_fault3(void);
+extern const char *test_float1(void);
+extern const char *test_softfloat1(void);
 extern const char *test_vfs1(void);
 extern const char *test_ping_pong(void);
@@ -101,5 +106,5 @@
 extern const char *test_serial1(void);
 extern const char *test_virtchar1(void);
-extern const char *test_libext2_1(void);
+extern const char *test_ext2_1(void);
 extern const char *test_devman1(void);
 extern const char *test_devman2(void);
Index: uspace/app/testwrit/Makefile
===================================================================
--- uspace/app/testwrit/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/testwrit/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2011 Frantisek Princ
+# 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 = testwrit
+
+SOURCES = \
+	testwrit.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/testwrit/testwrit.c
===================================================================
--- uspace/app/testwrit/testwrit.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/testwrit/testwrit.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011 Frantisek Princ
+ * 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 test
+ * @{
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#define BUF_SIZE  1024
+
+int main(int argc, char *argv[])
+{
+	char buffer[BUF_SIZE];
+	uint64_t iterations, i;
+	FILE *file;
+	char *file_name;
+	
+	/* Prepare some example data */
+	memset(buffer, 0xcafebabe, BUF_SIZE);
+	
+	if (argc != 3) {
+		printf("syntax: testwrit <iterations> <target file>\n");
+		return 1;
+	}
+	
+	char *end;
+	iterations = strtoul(argv[1], &end, 10);
+	file_name = argv[2];
+	
+	/* Open target file */
+	file = fopen(file_name, "a");
+	if (file == NULL) {
+		printf("Failed opening file\n");
+		return 1;
+	}
+	
+	/* Writing loop */
+	for (i = 0; i < iterations; ++i) {
+		fwrite(buffer, 1, BUF_SIZE, file);
+	}
+	
+	fclose(file);
+	
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/app/top/screen.h
===================================================================
--- uspace/app/top/screen.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/top/screen.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,4 +36,5 @@
 
 #include <io/console.h>
+#include <io/verify.h>
 #include "top.h"
 
@@ -43,5 +44,6 @@
 extern void screen_done(void);
 extern void print_data(data_t *);
-extern void show_warning(const char *, ...);
+extern void show_warning(const char *, ...)
+    PRINTF_ATTRIBUTE(1, 2);
 
 extern int tgetchar(unsigned int);
Index: uspace/app/trace/ipcp.c
===================================================================
--- uspace/app/trace/ipcp.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/trace/ipcp.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,4 +38,5 @@
 #include <sys/typefmt.h>
 #include <abi/ipc/methods.h>
+#include <macros.h>
 #include "ipc_desc.h"
 #include "proto.h"
@@ -52,5 +53,5 @@
 	ipc_callid_t call_hash;
 
-	link_t link;
+	ht_link_t link;
 } pending_call_t;
 
@@ -64,6 +65,5 @@
 int have_conn[MAX_PHONE];
 
-#define PCALL_TABLE_CHAINS 32
-hash_table_t pending_calls;
+static hash_table_t pending_calls;
 
 /*
@@ -73,38 +73,32 @@
 proto_t	*proto_unknown;		/**< Protocol with no known methods. */
 
-static hash_index_t pending_call_hash(unsigned long key[]);
-static int pending_call_compare(unsigned long key[], hash_count_t keys,
-    link_t *item);
-static void pending_call_remove_callback(link_t *item);
-
-hash_table_operations_t pending_call_ops = {
+
+static size_t pending_call_key_hash(void *key)
+{
+	ipc_callid_t *call_id = (ipc_callid_t *)key;
+	return *call_id;
+}
+
+static size_t pending_call_hash(const ht_link_t *item)
+{
+	pending_call_t *hs = hash_table_get_inst(item, pending_call_t, link);
+	return hs->call_hash;
+}
+
+static bool pending_call_key_equal(void *key, const ht_link_t *item)
+{
+	ipc_callid_t *call_id = (ipc_callid_t *)key;
+	pending_call_t *hs = hash_table_get_inst(item, pending_call_t, link);
+
+	return *call_id == hs->call_hash;
+}
+
+static hash_table_ops_t pending_call_ops = {
 	.hash = pending_call_hash,
-	.compare = pending_call_compare,
-	.remove_callback = pending_call_remove_callback
+	.key_hash = pending_call_key_hash,
+	.key_equal = pending_call_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
 };
-
-
-static hash_index_t pending_call_hash(unsigned long key[])
-{
-//	printf("pending_call_hash\n");
-	return key[0] % PCALL_TABLE_CHAINS;
-}
-
-static int pending_call_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
-{
-	pending_call_t *hs;
-
-//	printf("pending_call_compare\n");
-	hs = hash_table_get_instance(item, pending_call_t, link);
-
-	// FIXME: this will fail if sizeof(long) < sizeof(void *).
-	return key[0] == hs->call_hash;
-}
-
-static void pending_call_remove_callback(link_t *item)
-{
-//	printf("pending_call_remove_callback\n");
-}
 
 
@@ -177,5 +171,6 @@
 	}
 
-	hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
+	bool ok = hash_table_create(&pending_calls, 0, 0, &pending_call_ops);
+	assert(ok);
 }
 
@@ -190,5 +185,4 @@
 	pending_call_t *pcall;
 	proto_t *proto;
-	unsigned long key[1];
 	oper_t *oper;
 	sysarg_t *args;
@@ -254,7 +248,5 @@
 	pcall->oper = oper;
 
-	key[0] = hash;
-
-	hash_table_insert(&pending_calls, key, &pcall->link);
+	hash_table_insert(&pending_calls, &pcall->link);
 }
 
@@ -334,7 +326,6 @@
 void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash)
 {
-	link_t *item;
+	ht_link_t *item;
 	pending_call_t *pcall;
-	unsigned long key[1];
 	
 	if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
@@ -347,7 +338,6 @@
 	
 	hash = hash & ~IPC_CALLID_ANSWERED;
-	key[0] = hash;
-	
-	item = hash_table_find(&pending_calls, key);
+	
+	item = hash_table_find(&pending_calls, &hash);
 	if (item == NULL)
 		return; /* No matching question found */
@@ -357,6 +347,6 @@
 	 */
 	
-	pcall = hash_table_get_instance(item, pending_call_t, link);
-	hash_table_remove(&pending_calls, key, 1);
+	pcall = hash_table_get_inst(item, pending_call_t, link);
+	hash_table_remove(&pending_calls, &hash);
 	
 	parse_answer(hash, pcall, call);
Index: uspace/app/trace/proto.c
===================================================================
--- uspace/app/trace/proto.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/trace/proto.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,117 +40,103 @@
 #include "proto.h"
 
-#define SRV_PROTO_TABLE_CHAINS 32
-#define METHOD_OPER_TABLE_CHAINS 32
-
-hash_table_t srv_proto;
+
+/* Maps service number to protocol */
+static hash_table_t srv_proto;
 
 typedef struct {
-	unsigned srv;
+	int srv;
 	proto_t *proto;
-	link_t link;
+	ht_link_t link;
 } srv_proto_t;
 
 typedef struct {
-	sysarg_t method;
+	int method;
 	oper_t *oper;
-	link_t link;
+	ht_link_t link;
 } method_oper_t;
 
-static hash_index_t srv_proto_hash(unsigned long key[]);
-static int srv_proto_compare(unsigned long key[], hash_count_t keys,
-    link_t *item);
-static void srv_proto_remove_callback(link_t *item);
-
-hash_table_operations_t srv_proto_ops = {
+/* Hash table operations. */
+
+static size_t srv_proto_key_hash(void *key)
+{
+	return *(int *)key;
+}
+
+static size_t srv_proto_hash(const ht_link_t *item)
+{
+	srv_proto_t *sp = hash_table_get_inst(item, srv_proto_t, link);
+	return sp->srv;
+}
+
+static bool srv_proto_key_equal(void *key, const ht_link_t *item)
+{
+	srv_proto_t *sp = hash_table_get_inst(item, srv_proto_t, link);
+	return sp->srv == *(int *)key;
+}
+
+static hash_table_ops_t srv_proto_ops = {
 	.hash = srv_proto_hash,
-	.compare = srv_proto_compare,
-	.remove_callback = srv_proto_remove_callback
+	.key_hash = srv_proto_key_hash,
+	.key_equal = srv_proto_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
 };
 
-static hash_index_t method_oper_hash(unsigned long key[]);
-static int method_oper_compare(unsigned long key[], hash_count_t keys,
-    link_t *item);
-static void method_oper_remove_callback(link_t *item);
-
-hash_table_operations_t method_oper_ops = {
+
+static size_t method_oper_key_hash(void *key)
+{
+	return *(int *)key;
+}
+
+static size_t method_oper_hash(const ht_link_t *item)
+{
+	method_oper_t *mo = hash_table_get_inst(item, method_oper_t, link);
+	return mo->method;
+}
+
+static bool method_oper_key_equal(void *key, const ht_link_t *item)
+{
+	method_oper_t *mo = hash_table_get_inst(item, method_oper_t, link);
+	return mo->method == *(int *)key;
+}
+
+static hash_table_ops_t method_oper_ops = {
 	.hash = method_oper_hash,
-	.compare = method_oper_compare,
-	.remove_callback = method_oper_remove_callback
+	.key_hash = method_oper_key_hash,
+	.key_equal = method_oper_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
 };
 
-static hash_index_t srv_proto_hash(unsigned long key[])
-{
-	return key[0] % SRV_PROTO_TABLE_CHAINS;
-}
-
-static int srv_proto_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
+
+void proto_init(void)
+{
+	/* todo: check return value. */
+	bool ok = hash_table_create(&srv_proto, 0, 0, &srv_proto_ops);
+	assert(ok);
+}
+
+void proto_cleanup(void)
+{
+	hash_table_destroy(&srv_proto);
+}
+
+void proto_register(int srv, proto_t *proto)
 {
 	srv_proto_t *sp;
-
-	sp = hash_table_get_instance(item, srv_proto_t, link);
-
-	return key[0] == sp->srv;
-}
-
-static void srv_proto_remove_callback(link_t *item)
-{
-}
-
-static hash_index_t method_oper_hash(unsigned long key[])
-{
-	return key[0] % METHOD_OPER_TABLE_CHAINS;
-}
-
-static int method_oper_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
-{
-	method_oper_t *mo;
-
-	mo = hash_table_get_instance(item, method_oper_t, link);
-
-	return key[0] == mo->method;
-}
-
-static void method_oper_remove_callback(link_t *item)
-{
-}
-
-
-void proto_init(void)
-{
-	hash_table_create(&srv_proto, SRV_PROTO_TABLE_CHAINS, 1,
-	    &srv_proto_ops);
-}
-
-void proto_cleanup(void)
-{
-	hash_table_destroy(&srv_proto);
-}
-
-void proto_register(int srv, proto_t *proto)
-{
-	srv_proto_t *sp;
-	unsigned long key;
 
 	sp = malloc(sizeof(srv_proto_t));
 	sp->srv = srv;
 	sp->proto = proto;
-	key = srv;
-
-	hash_table_insert(&srv_proto, &key, &sp->link);
+
+	hash_table_insert(&srv_proto, &sp->link);
 }
 
 proto_t *proto_get_by_srv(int srv)
 {
-	unsigned long key;
-	link_t *item;
-	srv_proto_t *sp;
-
-	key = srv;
-	item = hash_table_find(&srv_proto, &key);
+	ht_link_t *item = hash_table_find(&srv_proto, &srv);
 	if (item == NULL) return NULL;
 
-	sp = hash_table_get_instance(item, srv_proto_t, link);
+	srv_proto_t *sp = hash_table_get_inst(item, srv_proto_t, link);
 	return sp->proto;
 }
@@ -159,6 +145,7 @@
 {
 	proto->name = name;
-	hash_table_create(&proto->method_oper, SRV_PROTO_TABLE_CHAINS, 1,
-	    &method_oper_ops);
+	/* todo: check return value. */
+	bool ok = hash_table_create(&proto->method_oper, 0, 0, &method_oper_ops);
+	assert(ok);
 }
 
@@ -181,25 +168,18 @@
 {
 	method_oper_t *mo;
-	unsigned long key;
 
 	mo = malloc(sizeof(method_oper_t));
 	mo->method = method;
 	mo->oper = oper;
-	key = method;
-
-	hash_table_insert(&proto->method_oper, &key, &mo->link);	
+
+	hash_table_insert(&proto->method_oper, &mo->link);	
 }
 
 oper_t *proto_get_oper(proto_t *proto, int method)
 {
-	unsigned long key;
-	link_t *item;
-	method_oper_t *mo;
-
-	key = method;
-	item = hash_table_find(&proto->method_oper, &key);
+	ht_link_t *item = hash_table_find(&proto->method_oper, &method);
 	if (item == NULL) return NULL;
 
-	mo = hash_table_get_instance(item, method_oper_t, link);
+	method_oper_t *mo = hash_table_get_inst(item, method_oper_t, link);
 	return mo->oper;
 }
Index: uspace/app/trace/proto.h
===================================================================
--- uspace/app/trace/proto.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/trace/proto.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -62,6 +62,4 @@
 } proto_t;
 
-/* Maps service number to protocol */
-extern hash_table_t srv_proto;
 
 extern void proto_init(void);
Index: uspace/app/trace/syscalls.c
===================================================================
--- uspace/app/trace/syscalls.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/trace/syscalls.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -53,6 +53,4 @@
     [SYS_AS_AREA_DESTROY] = { "as_area_destroy",	1,	V_ERRNO },
 
-    [SYS_IPC_CALL_SYNC_FAST] = { "ipc_call_sync_fast",	6,	V_ERRNO },
-    [SYS_IPC_CALL_SYNC_SLOW] = { "ipc_call_sync_slow",	3,	V_ERRNO },
     [SYS_IPC_CALL_ASYNC_FAST] = { "ipc_call_async_fast", 6,	V_HASH },
     [SYS_IPC_CALL_ASYNC_SLOW] = { "ipc_call_async_slow", 2,	V_HASH },
Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/trace/trace.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -318,61 +318,4 @@
 }
 
-static void sc_ipc_call_sync_fast(sysarg_t *sc_args)
-{
-	ipc_call_t question, reply;
-	int rc;
-	int phoneid;
-
-	phoneid = sc_args[0];
-
-	IPC_SET_IMETHOD(question, sc_args[1]);
-	IPC_SET_ARG1(question, sc_args[2]);
-	IPC_SET_ARG2(question, sc_args[3]);
-	IPC_SET_ARG3(question, sc_args[4]);
-	IPC_SET_ARG4(question, 0);
-	IPC_SET_ARG5(question, 0);
-
-	memset(&reply, 0, sizeof(reply));
-	rc = udebug_mem_read(sess, &reply.args, sc_args[5], sizeof(reply.args));
-	if (rc < 0)
-		return;
-	
-	ipcp_call_sync(phoneid, &question, &reply);
-}
-
-static void sc_ipc_call_sync_slow_b(unsigned thread_id, sysarg_t *sc_args)
-{
-	ipc_call_t question;
-	int rc;
-
-	memset(&question, 0, sizeof(question));
-	rc = udebug_mem_read(sess, &question.args, sc_args[1],
-	    sizeof(question.args));
-
-	if (rc < 0) {
-		printf("Error: mem_read->%d\n", rc);
-		return;
-	}
-
-	thread_ipc_req[thread_id] = question;
-}
-
-static void sc_ipc_call_sync_slow_e(unsigned thread_id, sysarg_t *sc_args)
-{
-	ipc_call_t reply;
-	int rc;
-
-	memset(&reply, 0, sizeof(reply));
-	rc = udebug_mem_read(sess, &reply.args, sc_args[2],
-	    sizeof(reply.args));
-
-	if (rc < 0) {
-		printf("Error: mem_read->%d\n", rc);
-		return;
-	}
-
-	ipcp_call_sync(sc_args[0], &thread_ipc_req[thread_id], &reply);
-}
-
 static void sc_ipc_wait(sysarg_t *sc_args, int sc_rc)
 {
@@ -408,12 +351,4 @@
 		print_sc_args(sc_args, syscall_desc[sc_id].n_args);
 	}
-
-	switch (sc_id) {
-	case SYS_IPC_CALL_SYNC_SLOW:
-		sc_ipc_call_sync_slow_b(thread_id, sc_args);
-		break;
-	default:
-		break;
-	}
 }
 
@@ -447,10 +382,4 @@
 	case SYS_IPC_CALL_ASYNC_SLOW:
 		sc_ipc_call_async_slow(sc_args, sc_rc);
-		break;
-	case SYS_IPC_CALL_SYNC_FAST:
-		sc_ipc_call_sync_fast(sc_args);
-		break;
-	case SYS_IPC_CALL_SYNC_SLOW:
-		sc_ipc_call_sync_slow_e(thread_id, sc_args);
 		break;
 	case SYS_IPC_WAIT:
Index: uspace/app/usbinfo/Makefile
===================================================================
--- uspace/app/usbinfo/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/usbinfo/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,4 +47,5 @@
 	hid.c \
 	info.c \
+	list.c \
 	main.c
 
Index: uspace/app/usbinfo/list.c
===================================================================
--- uspace/app/usbinfo/list.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/usbinfo/list.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2010-2011 Vojtech Horky
+ * 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 lsusb
+ * @{
+ */
+/**
+ * @file
+ * Listing of USB host controllers.
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+#include <getopt.h>
+#include <devman.h>
+#include <loc.h>
+#include <usb/dev/hub.h>
+#include <usb/hc.h>
+
+#include "usbinfo.h"
+
+#define MAX_USB_ADDRESS USB11_ADDRESS_MAX
+#define MAX_PATH_LENGTH 1024
+
+static void print_found_hc(service_id_t sid, const char *path)
+{
+	printf("Bus %" PRIun ": %s\n", sid, path);
+}
+static void print_found_dev(usb_address_t addr, const char *path)
+{
+	printf("  Device %02d: %s\n", addr, path);
+}
+
+static void print_hc_devices(devman_handle_t hc_handle)
+{
+	int rc;
+	usb_hc_connection_t conn;
+
+	usb_hc_connection_initialize(&conn, hc_handle);
+	rc = usb_hc_connection_open(&conn);
+	if (rc != EOK) {
+		printf(NAME ": failed to connect to HC: %s.\n",
+		    str_error(rc));
+		return;
+	}
+	usb_address_t addr;
+	for (addr = 1; addr < MAX_USB_ADDRESS; addr++) {
+		devman_handle_t dev_handle;
+		rc = usb_hc_get_handle_by_address(&conn, addr, &dev_handle);
+		if (rc != EOK) {
+			continue;
+		}
+		char path[MAX_PATH_LENGTH];
+		rc = devman_fun_get_path(dev_handle, path, MAX_PATH_LENGTH);
+		if (rc != EOK) {
+			continue;
+		}
+		print_found_dev(addr, path);
+	}
+	usb_hc_connection_close(&conn);
+}
+
+void list(void)
+{
+	category_id_t usbhc_cat;
+	service_id_t *svcs;
+	size_t count;
+	size_t i;
+	int rc;
+
+	rc = loc_category_get_id(USB_HC_CATEGORY, &usbhc_cat, 0);
+	if (rc != EOK) {
+		printf(NAME ": Error resolving category '%s'",
+		    USB_HC_CATEGORY);
+		return;
+	}
+
+	rc = loc_category_get_svcs(usbhc_cat, &svcs, &count);
+	if (rc != EOK) {
+		printf(NAME ": Error getting list of host controllers.\n");
+		return;
+	}
+
+	for (i = 0; i < count; i++) {
+		devman_handle_t hc_handle = 0;
+		int rc = usb_ddf_get_hc_handle_by_sid(svcs[i], &hc_handle);
+		if (rc != EOK) {
+			printf(NAME ": Error resolving handle of HC with SID %"
+			    PRIun ", skipping.\n", svcs[i]);
+			continue;
+		}
+		char path[MAX_PATH_LENGTH];
+		rc = devman_fun_get_path(hc_handle, path, MAX_PATH_LENGTH);
+		if (rc != EOK) {
+			printf(NAME ": Error resolving path of HC with SID %"
+			    PRIun ", skipping.\n", svcs[i]);
+			continue;
+		}
+		print_found_hc(svcs[i], path);
+		print_hc_devices(hc_handle);
+	}
+
+	free(svcs);
+}
+
+
+/** @}
+ */
Index: uspace/app/usbinfo/main.c
===================================================================
--- uspace/app/usbinfo/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/usbinfo/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -62,4 +62,5 @@
 
 	_OPTION("-h --help", "Print this help and exit.");
+	_OPTION("-l --list", "Print a list of host controllers and devices.");
 	_OPTION("-i --identification", "Brief device identification.");
 	_OPTION("-m --match-ids", "Print match ids generated for the device.");
@@ -82,4 +83,5 @@
 	{"help", no_argument, NULL, 'h'},
 	{"identification", no_argument, NULL, 'i'},
+	{"list", no_argument, NULL, 'l'},
 	{"match-ids", no_argument, NULL, 'm'},
 	{"descriptor-tree", no_argument, NULL, 't'},
@@ -91,5 +93,5 @@
 	{0, 0, NULL, 0}
 };
-static const char *short_options = "himtTsSrR";
+static const char *short_options = "hilmtTsSrR";
 
 static usbinfo_action_t actions[] = {
@@ -146,4 +148,5 @@
 	}
 
+	bool something_active = false;
 	/*
 	 * Process command-line options. They determine what shall be
@@ -156,4 +159,7 @@
 		switch (opt) {
 			case -1:
+				break;
+			case 'l':
+				list();
 				break;
 			case '?':
@@ -168,4 +174,5 @@
 					if (actions[idx].opt == opt) {
 						actions[idx].active = true;
+						something_active = true;
 						break;
 					}
@@ -178,13 +185,4 @@
 
 	/* Set the default action. */
-	int idx = 0;
-	bool something_active = false;
-	while (actions[idx].opt != 0) {
-		if (actions[idx].active) {
-			something_active = true;
-			break;
-		}
-		idx++;
-	}
 	if (!something_active) {
 		actions[0].active = true;
Index: uspace/app/usbinfo/usbinfo.h
===================================================================
--- uspace/app/usbinfo/usbinfo.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/usbinfo/usbinfo.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -79,4 +79,5 @@
     dump_descriptor_in_tree_t, size_t, void *);
 
+void list(void);
 
 void dump_short_device_identification(usbinfo_device_t *);
Index: uspace/app/vdemo/Makefile
===================================================================
--- uspace/app/vdemo/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/vdemo/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2012 Petr Koupy
+# 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 = $(LIBGUI_PREFIX)/libgui.a $(LIBDRAW_PREFIX)/libdraw.a \
+	$(LIBSOFTREND_PREFIX)/libsoftrend.a $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
+EXTRA_CFLAGS += -I$(LIBGUI_PREFIX) -I$(LIBDRAW_PREFIX) \
+	-I$(LIBSOFTREND_PREFIX)
+BINARY = vdemo
+
+SOURCES = \
+	vdemo.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/vdemo/vdemo.c
===================================================================
--- uspace/app/vdemo/vdemo.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/vdemo/vdemo.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 vdemo
+ * @{
+ */
+/** @file
+ */
+
+#include <bool.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <io/pixel.h>
+#include <task.h>
+
+#include <window.h>
+#include <grid.h>
+#include <button.h>
+#include <label.h>
+
+#define NAME "vdemo"
+
+typedef struct my_label {
+	label_t label;
+	slot_t confirm;
+	slot_t cancel;
+} my_label_t;
+
+static void deinit_my_label(my_label_t *lbl)
+{
+	deinit_label(&lbl->label);
+}
+
+static void my_label_destroy(widget_t *widget)
+{
+	my_label_t *lbl = (my_label_t *) widget;
+
+	deinit_my_label(lbl);
+
+	free(lbl);
+}
+
+static void on_confirm(widget_t *widget, void *data)
+{
+	my_label_t *lbl = (my_label_t *) widget;
+	const char *confirmed = "Confirmed";
+	lbl->label.rewrite(&lbl->label.widget, (void *) confirmed);
+}
+
+static void on_cancel(widget_t *widget, void *data)
+{
+	my_label_t *lbl = (my_label_t *) widget;
+	const char *cancelled = "Cancelled";
+	lbl->label.rewrite(&lbl->label.widget, (void *) cancelled);
+}
+
+static bool init_my_label(my_label_t *lbl, widget_t *parent,
+    const char *caption, uint16_t points, pixel_t background, pixel_t foreground)
+{
+	lbl->confirm = on_confirm;
+	lbl->cancel = on_cancel;
+	bool initialized = init_label(
+	    &lbl->label, parent, caption, points, background, foreground);
+	lbl->label.widget.destroy = my_label_destroy;
+	return initialized;
+}
+
+static my_label_t *create_my_label(widget_t *parent,
+    const char *caption, uint16_t points, pixel_t background, pixel_t foreground)
+{
+	my_label_t *lbl = (my_label_t *) malloc(sizeof(my_label_t));
+	if (!lbl) {
+		return NULL;
+	}
+
+	if (init_my_label(lbl, parent, caption, points, background, foreground)) {
+		return lbl;
+	} else {
+		free(lbl);
+		return NULL;
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	if (argc >= 2) {
+		window_t *main_window = window_open(argv[1], true, true, "vdemo");
+		if (!main_window) {
+			printf("Cannot open main window.\n");
+			return 1;
+		}
+
+		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 lbl_bg = PIXEL(255, 240, 240, 240);
+		pixel_t lbl_fg = 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);
+		grid_t *grid = create_grid(window_root(main_window), 2, 2, grd_bg);
+		if (!lbl_action || !btn_confirm || !btn_cancel || !grid) {
+			window_close(main_window);
+			printf("Cannot create widgets.\n");
+			return 1;
+		}
+
+		sig_connect(
+		    &btn_confirm->clicked,
+		    &lbl_action->label.widget,
+		    lbl_action->confirm);
+		sig_connect(
+		    &btn_cancel->clicked,
+		    &lbl_action->label.widget,
+		    lbl_action->cancel);
+
+		grid->add(grid, &lbl_action->label.widget, 0, 0, 1, 2);
+		grid->add(grid, &btn_confirm->widget, 1, 0, 1, 1);
+		grid->add(grid, &btn_cancel->widget, 1, 1, 1, 1);
+		window_resize(main_window, 200, 70);
+
+		window_exec(main_window);
+		task_retval(0);
+		async_manager();
+		return 1;
+	} else {
+		printf("Compositor server not specified.\n");
+		return 1;
+	}
+}
+
+/** @}
+ */
Index: uspace/app/vlaunch/Makefile
===================================================================
--- uspace/app/vlaunch/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/vlaunch/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2012 Petr Koupy
+# 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 = $(LIBGUI_PREFIX)/libgui.a $(LIBDRAW_PREFIX)/libdraw.a \
+	$(LIBSOFTREND_PREFIX)/libsoftrend.a $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
+EXTRA_CFLAGS += -I$(LIBGUI_PREFIX) -I$(LIBDRAW_PREFIX) \
+	-I$(LIBSOFTREND_PREFIX)
+BINARY = vlaunch
+
+SOURCES = \
+	vlaunch.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/vlaunch/vlaunch.c
===================================================================
--- uspace/app/vlaunch/vlaunch.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/vlaunch/vlaunch.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 vlaunch
+ * @{
+ */
+/** @file
+ */
+
+#include <bool.h>
+#include <errno.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <io/pixel.h>
+#include <task.h>
+#include <str.h>
+#include <str_error.h>
+
+#include <window.h>
+#include <grid.h>
+#include <button.h>
+#include <label.h>
+
+#define NAME "vlaunch"
+
+static char *winreg = NULL;
+
+static int app_launch(const char *app)
+{
+	int rc;
+	printf("%s: Spawning %s %s \n", NAME, app, winreg);
+
+	task_id_t id;
+	task_exit_t texit;
+	int retval;
+	rc = task_spawnl(&id, app, app, winreg, NULL);
+	if (rc != EOK) {
+		printf("%s: Error spawning %s %s (%s)\n", NAME, app,
+		    winreg, str_error(rc));
+		return -1;
+	}
+	rc = task_wait(id, &texit, &retval);
+	if (rc != EOK || texit != TASK_EXIT_NORMAL) {
+		printf("%s: Error retrieving retval from %s (%s)\n", NAME,
+		    app, str_error(rc));
+		return -1;
+	}
+
+	return retval;
+}
+
+static void on_vterm(widget_t *widget, void *data)
+{
+	app_launch("/app/vterm");
+}
+
+static void on_vdemo(widget_t *widget, void *data)
+{
+	app_launch("/app/vdemo");
+}
+
+static void on_vlaunch(widget_t *widget, void *data)
+{
+	app_launch("/app/vlaunch");
+}
+
+int main(int argc, char *argv[])
+{
+	if (argc < 2) {
+		printf("Compositor server not specified.\n");
+		return 1;
+	}
+	
+	winreg = argv[1];
+	window_t *main_window = window_open(argv[1], true, true, "vlaunch");
+	if (!main_window) {
+		printf("Cannot open main window.\n");
+		return 1;
+	}
+	
+	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 lbl_bg = PIXEL(255, 240, 240, 240);
+	pixel_t lbl_fg = PIXEL(255, 0, 0, 0);
+	
+	label_t *lbl_caption = create_label(NULL, "Launch application:", 16,
+	    lbl_bg, lbl_fg);
+	button_t *btn_vterm = create_button(NULL, "vterm", 16, btn_bg,
+	    btn_fg);
+	button_t *btn_vdemo = create_button(NULL, "vdemo", 16, btn_bg,
+	    btn_fg);
+	button_t *btn_vlaunch = create_button(NULL, "vlaunch", 16, btn_bg,
+	    btn_fg);
+	grid_t *grid = create_grid(window_root(main_window), 4, 1, grd_bg);
+	
+	if ((!lbl_caption) || (!btn_vterm) || (!btn_vdemo) ||
+	    (!btn_vlaunch) || (!grid)) {
+		window_close(main_window);
+		printf("Cannot create widgets.\n");
+		return 1;
+	}
+	
+	sig_connect(&btn_vterm->clicked, NULL, on_vterm);
+	sig_connect(&btn_vdemo->clicked, NULL, on_vdemo);
+	sig_connect(&btn_vlaunch->clicked, NULL, on_vlaunch);
+	
+	grid->add(grid, &lbl_caption->widget, 0, 0, 1, 1);
+	grid->add(grid, &btn_vterm->widget, 1, 0, 1, 1);
+	grid->add(grid, &btn_vdemo->widget, 2, 0, 1, 1);
+	grid->add(grid, &btn_vlaunch->widget, 3, 0, 1, 1);
+	
+	window_resize(main_window, 180, 130);
+	window_exec(main_window);
+	task_retval(0);
+	async_manager();
+	
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/vterm/Makefile
===================================================================
--- uspace/app/vterm/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/vterm/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2012 Petr Koupy
+# 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 = $(LIBGUI_PREFIX)/libgui.a $(LIBDRAW_PREFIX)/libdraw.a \
+	$(LIBSOFTREND_PREFIX)/libsoftrend.a $(LIBGRAPH_PREFIX)/libgraph.a \
+	$(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
+EXTRA_CFLAGS += -I$(LIBGUI_PREFIX) -I$(LIBDRAW_PREFIX) \
+	-I$(LIBSOFTREND_PREFIX) -I$(LIBGRAPH_PREFIX)
+BINARY = vterm
+
+SOURCES = \
+	vterm.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/vterm/vterm.c
===================================================================
--- uspace/app/vterm/vterm.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/app/vterm/vterm.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 vterm
+ * @{
+ */
+/** @file
+ */
+
+#include <bool.h>
+#include <stdio.h>
+#include <io/pixel.h>
+#include <task.h>
+#include <window.h>
+#include <terminal.h>
+
+#define NAME  "vterm"
+
+int main(int argc, char *argv[])
+{
+	if (argc < 2) {
+		printf("%s: Compositor server not specified.\n", NAME);
+		return 1;
+	}
+	
+	window_t *main_window = window_open(argv[1], true, true, "vterm");
+	if (!main_window) {
+		printf("%s: Cannot open main window.\n", NAME);
+		return 2;
+	}
+	
+	window_resize(main_window, 650, 510);
+	terminal_t *terminal_widget =
+	    create_terminal(window_root(main_window), 640, 480);
+	if (!terminal_widget) {
+		window_close(main_window);
+		printf("%s: Cannot create widgets.\n", NAME);
+		return 3;
+	}
+	
+	window_exec(main_window);
+	task_retval(0);
+	async_manager();
+	
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/vuhid/main.c
===================================================================
--- uspace/app/vuhid/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/app/vuhid/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -155,5 +155,5 @@
 	int rc;
 
-	usb_log_enable(USB_LOG_LEVEL_DEBUG2, "vusbhid");
+	log_init("vuhid");
 
 	fibril_mutex_initialize(&vuhid_data.iface_count_mutex);
Index: uspace/dist/src/bithenge/basic.bh
===================================================================
--- uspace/dist/src/bithenge/basic.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/basic.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,11 @@
+transform main = struct {
+	.u8 <- uint8;
+	.u16le <- uint16le;
+	.u16be <- uint16be;
+	.u32le <- uint32le;
+	.u32be <- uint32be;
+	.u64le <- uint64le;
+	.u64be <- uint64be;
+	.empty_blob <- known_length(0);
+	.ascii <- ascii <- known_length(8);
+};
Index: uspace/dist/src/bithenge/basic.dat
===================================================================
--- uspace/dist/src/bithenge/basic.dat	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/basic.dat	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,2 @@
+ªðð!CeeC!þÜºvT22TvºÜþ0~
+\"'	
Index: uspace/dist/src/bithenge/basic.out
===================================================================
--- uspace/dist/src/bithenge/basic.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/basic.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,11 @@
+{
+    "u8": 170,
+    "u16le": 4080,
+    "u16be": 4080,
+    "u32le": 2271560481,
+    "u32be": 2271560481,
+    "u64le": 1167088121787636990,
+    "u64be": 1167088121787636990,
+    "empty_blob": b"",
+    "ascii": "0~\u000a\\\"'\u0009\u001b"
+}
Index: uspace/dist/src/bithenge/bits.bh
===================================================================
--- uspace/dist/src/bithenge/bits.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/bits.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,25 @@
+transform main = struct {
+	.bits_le <- repeat(8) { bit } <- bits_le <- known_length(1);
+	.bits_be <- repeat(8) { bit } <- bits_be <- known_length(1);
+	<- struct {
+		.le0 <- uint_le(0);
+		.le1 <- uint_le(1);
+		.le2 <- uint_le(2);
+		.le3 <- uint_le(3);
+		.le4 <- uint_le(4);
+		.le5 <- uint_le(5);
+		.le6 <- uint_le(6);
+		.le7 <- uint_le(7);
+		.le8 <- uint_le(8);
+
+		.be8 <- uint_be(8);
+		.be7 <- uint_be(7);
+		.be6 <- uint_be(6);
+		.be5 <- uint_be(5);
+		.be4 <- uint_be(4);
+		.be3 <- uint_be(3);
+		.be2 <- uint_be(2);
+		.be1 <- uint_be(1);
+		.be0 <- uint_be(0);
+	} <- bits_be <- known_length(9);
+};
Index: uspace/dist/src/bithenge/bits.dat
===================================================================
--- uspace/dist/src/bithenge/bits.dat	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/bits.dat	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1 @@
+ee¤BB%
Index: uspace/dist/src/bithenge/bits.out
===================================================================
--- uspace/dist/src/bithenge/bits.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/bits.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,40 @@
+{
+    "bits_le": {
+        0: True,
+        1: False,
+        2: True,
+        3: False,
+        4: False,
+        5: True,
+        6: True,
+        7: False
+    },
+    "bits_be": {
+        0: False,
+        1: True,
+        2: True,
+        3: False,
+        4: False,
+        5: True,
+        6: False,
+        7: True
+    },
+    "le0": 0,
+    "le1": 1,
+    "le2": 2,
+    "le3": 4,
+    "le4": 8,
+    "le5": 16,
+    "le6": 32,
+    "le7": 64,
+    "le8": 128,
+    "be8": 128,
+    "be7": 64,
+    "be6": 32,
+    "be5": 16,
+    "be4": 8,
+    "be3": 4,
+    "be2": 2,
+    "be1": 1,
+    "be0": 0
+}
Index: uspace/dist/src/bithenge/cond.bh
===================================================================
--- uspace/dist/src/bithenge/cond.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/cond.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,36 @@
+transform pascal_string = struct {
+	<- struct { # An inner struct for testing purposes
+		.len <- uint8;
+	};
+	.string <- ascii <- known_length(.len);
+};
+
+transform u32(little_endian) =
+	if (little_endian) {
+		uint32le
+	} else {
+		uint32be
+	};
+
+transform item(little_endian, len) = struct {
+	.type <- (3 * in + 1) <- u32(little_endian);
+	.name <- pascal_string;
+	switch (.type) {
+		10: {
+			.val <- u32(little_endian);
+		};
+		11: {
+			.text <- ascii <- known_length(len);
+		};
+		else: {
+			.unknown <- known_length(len);
+		};
+	}
+};
+
+transform main() = struct {
+	.first_len <- (3);
+	.second_len <- (6 - 2);
+	.first_item <- item(true, .first_len);
+	.second_item <- item(false, .second_len);
+};
Index: uspace/dist/src/bithenge/cond.out
===================================================================
--- uspace/dist/src/bithenge/cond.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/cond.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,20 @@
+{
+    "first_len": 3,
+    "second_len": 4,
+    "first_item": {
+        "type": 52,
+        "name": {
+            "len": 6,
+            "string": "Item 1"
+        },
+        "unknown": b"\xcf\x80\x78"
+    },
+    "second_item": {
+        "type": 10,
+        "name": {
+            "len": 6,
+            "string": "Item 2"
+        },
+        "val": 12345
+    }
+}
Index: uspace/dist/src/bithenge/expression.bh
===================================================================
--- uspace/dist/src/bithenge/expression.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/expression.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,54 @@
+transform compare_ints(a, b) = struct {
+	.l <- (a < b);
+	.g <- (a > b);
+	.ge <- (a >= b);
+	.le <- (a <= b);
+	.eq <- (a == b);
+	.ne <- (a != b);
+};
+
+transform arithmetic(a, b) = struct {
+	.sum <- (a + b);
+	.difference <- (a - b);
+	.product <- (a * b);
+	if (b > 0) {
+		.quotient <- (a // b);
+		.remainder <- (a % b);
+	}
+};
+
+transform concat_bits(a, b) = uint_le(24) <- (in.concat_bits) <- struct {
+	.bits0 <- bits_le <- (a);
+	.bits1 <- bits_be <- (b);
+	.concat_bits <- (.bits0 ++ (.bits1 ++ .bits0));
+};
+
+transform equality(bytes0, bytes1, str0, str1) = struct {
+	.neqs <- ((0 != 1) != (2 != 3));
+	.bytes0_eq_bytes1 <- (bytes0 == bytes1);
+	.bytes0_ne_bytes0 <- (bytes0 != bytes0);
+	.str0_ne_str1 <- (str0 != str1);
+	.str1_eq_str1 <- (str1 == str1);
+	.bytes1_eq_1 <- (bytes1 == 1);
+};
+
+transform subblob(bytes0) = struct {
+	.subblob <- (bytes0[0:][0,1][0:1]);
+};
+
+transform main = struct {
+	.bytes0 <- known_length(1);
+	.bytes1 <- known_length(1);
+	.str0 <- ascii <- (.bytes0);
+	.str1 <- ascii <- (.bytes1);
+	.compare_ints_0_1 <- compare_ints(0, 1);
+	.compare_ints_0_0 <- compare_ints(0, 0);
+	.compare_ints_1_0 <- compare_ints(1, 0);
+	.arithmetic_0_1 <- arithmetic(0, 1);
+	.arithmetic_17_n3 <- arithmetic(17, 0 - 3);
+	.arithmetic_n17_3 <- arithmetic(0 - 17, 3);
+	.concat_bytes <- (.bytes0 ++ (.bytes1 ++ .bytes0));
+	.concat_bits <- concat_bits(.bytes0, .bytes1);
+	.equality <- equality(.bytes0, .bytes1, .str0, .str1);
+	.subblob <- subblob(.bytes0);
+};
Index: uspace/dist/src/bithenge/expression.dat
===================================================================
--- uspace/dist/src/bithenge/expression.dat	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/expression.dat	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1 @@
+17
Index: uspace/dist/src/bithenge/expression.out
===================================================================
--- uspace/dist/src/bithenge/expression.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/expression.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,62 @@
+{
+    "bytes0": b"\x31",
+    "bytes1": b"\x37",
+    "str0": "1",
+    "str1": "7",
+    "compare_ints_0_1": {
+        "l": True,
+        "g": False,
+        "ge": False,
+        "le": True,
+        "eq": False,
+        "ne": True
+    },
+    "compare_ints_0_0": {
+        "l": False,
+        "g": False,
+        "ge": True,
+        "le": True,
+        "eq": True,
+        "ne": False
+    },
+    "compare_ints_1_0": {
+        "l": False,
+        "g": True,
+        "ge": True,
+        "le": False,
+        "eq": False,
+        "ne": True
+    },
+    "arithmetic_0_1": {
+        "sum": 1,
+        "difference": -1,
+        "product": 0,
+        "quotient": 0,
+        "remainder": 0
+    },
+    "arithmetic_17_n3": {
+        "sum": 14,
+        "difference": 20,
+        "product": -51
+    },
+    "arithmetic_n17_3": {
+        "sum": -14,
+        "difference": -20,
+        "product": -51,
+        "quotient": -6,
+        "remainder": 1
+    },
+    "concat_bytes": b"\x31\x37\x31",
+    "concat_bits": 3271729,
+    "equality": {
+        "neqs": False,
+        "bytes0_eq_bytes1": False,
+        "bytes0_ne_bytes0": False,
+        "str0_ne_str1": True,
+        "str1_eq_str1": True,
+        "bytes1_eq_1": False
+    },
+    "subblob": {
+        "subblob": b"\x31"
+    }
+}
Index: uspace/dist/src/bithenge/fat.bh
===================================================================
--- uspace/dist/src/bithenge/fat.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/fat.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,168 @@
+# Copyright (c) 2012 Sean Bartell
+# 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.
+
+# FAT filesystem script.
+# Largely based on https://en.wikipedia.org/wiki/File_Allocation_Table
+# Currently only FAT12 and FAT16 are supported.
+
+transform u8 = uint8;
+transform u16 = uint16le;
+transform u32 = uint32le;
+
+transform fat_attributes = struct {
+	.read_only <- bit;
+	.hidden <- bit;
+	.system <- bit;
+	.volume_label <- bit;
+	.subdirectory <- bit;
+	.archive <- bit;
+	.device <- bit;
+	.reserved <- bit;
+} <- bits_le <- known_length(1);
+
+transform file_data(data, bits, fat, cluster_size, start) = (in.data) <- struct {
+	.cluster <- (data[(start-2)*cluster_size, cluster_size]);
+	.last_cluster_number <- switch (bits) {
+		12: (488);       # 0x00000ff8
+		16: (65528);     # 0x0000fff8
+		32: (268435448); # 0x0ffffff8
+	};
+	.next <- (fat[start]);
+	if (.next == 0 || .next >= .last_cluster_number) {
+		.data <- (.cluster);
+	} else {
+		.rest <- file_data(data, bits, fat, cluster_size, .next) <- known_length(0);
+		.data <- (.cluster ++ .rest);
+	}
+};
+
+transform fat_dir_entry(data, bits, fat, cluster_size, self_start, parent) = struct {
+	.filename <- known_length(8);
+	.extension <- known_length(3);
+	.attrs <- fat_attributes;
+	.flags <- u8;
+	.ctime_fine <- u8;
+	.ctime <- u16;
+	.cdate <- u16;
+	.adate <- u16;
+	.permissions <- u16;
+	.mtime <- u16;
+	.mdate <- u16;
+	.start <- u16;
+	.size <- u32;
+	.size_shown <- if (.size > 32) { (32) } else { (.size) };
+
+	if (.start != 0 && .start != self_start && .start != parent && .filename[0] != 229) {
+		.data
+		    <- if (.attrs.subdirectory) {
+		        repeat { fat_dir_entry(data, bits, fat, cluster_size, .start, self_start) }
+		    } else {
+		        (in[0,.size_shown])
+		    }
+		    <- if (.size != 0) { (in[0,.size]) } else { (in) }
+		    <- file_data(data, bits, fat, cluster_size, .start);
+	}
+};
+
+transform fat_table(bits, num_clusters) = switch (bits) {
+	12: partial {repeat(num_clusters) { uint_le(12) }} <- bits_le;
+	16: partial {repeat(num_clusters) { u16 }};
+	32: partial {repeat(num_clusters) { u32 }};
+};
+
+transform fat_super(disk) = struct {
+	.jump_instruction <- known_length(3);
+	.oem_name <- ascii <- known_length(8);
+
+	# DOS 2.0 BPB
+	.bytes_per_sector <- u16; # must be power of two, at least 32
+	.sectors_per_cluster <- u8; # must be power of two
+	.num_reserved_sectors <- u16;
+	.num_fats <- u8; # at least 1
+	.num_root_entries <- u16; # 0 for FAT32
+	.num_sectors_16 <- u16;
+	.media_descriptor <- u8;
+	.sectors_per_fat <- u16; # 0 for FAT32
+
+	# DOS 3.0/3.2/3.31 BPB
+	.sectors_per_track <- u16;
+	.num_heads <- u16;
+
+	# DOS 3.31 BPB
+	.bpb331 <- struct {
+		.ignore <- nonzero_boolean <- (.num_sectors_16);
+		.num_hidden_sectors <- u32;
+		.num_sectors_32 <- u32;
+	};
+
+	.drive_number <- u8;
+	.chkdsk_flags <- u8;
+	.extended_boot_signature <- u8;
+	if (.extended_boot_signature == 41) {
+		.volume_id <- u32;
+		.volume_label <- ascii <- known_length(11);
+		.type <- ascii <- known_length(8);
+	}
+
+	.boot_signature <- (disk[510,2]); # b"\x55\xaa"; TODO: what if .bytes_per_sector < 512?
+};
+
+transform fat_filesystem_tree(disk) = struct {
+	.super <- partial{fat_super(disk)} <- (disk);
+
+	.num_sectors <- if (.super.bpb331.ignore) {
+		(.super.num_sectors_16)
+	} else {
+		(.super.bpb331.num_sectors_32)
+	};
+
+	.cluster_size <- (.super.sectors_per_cluster * .super.bytes_per_sector);
+	.first_root_sector <- (.super.num_reserved_sectors + .super.num_fats * .super.sectors_per_fat);
+	.first_data_sector <- (.first_root_sector +
+	    (.super.num_root_entries * 32 + .super.bytes_per_sector - 1) //
+	    .super.bytes_per_sector);
+	.num_clusters <- (2 + (.num_sectors - .first_data_sector) // .super.sectors_per_cluster);
+	.bits <- if (.num_clusters < 4085) { (12) }
+	    else { if (.num_clusters < 65525) { (16) } else { (32) } };
+
+	.fats <- partial(.super.num_reserved_sectors * .super.bytes_per_sector) {
+		repeat(.super.num_fats) {
+			fat_table(.bits, .num_clusters) <-
+				known_length(.super.sectors_per_fat * .super.bytes_per_sector)
+		}
+	} <- (disk);
+
+	.root <- partial(.first_root_sector * .super.bytes_per_sector) {
+		repeat(.super.num_root_entries) {
+			fat_dir_entry(disk[.first_data_sector * .super.bytes_per_sector:],
+			    .bits, .fats[0], .cluster_size, 0, 0)
+		}
+	} <- (disk);
+};
+
+transform fat_filesystem = partial {fat_filesystem_tree(in)};
+
+transform main = fat_filesystem;
Index: uspace/dist/src/bithenge/fat.out
===================================================================
--- uspace/dist/src/bithenge/fat.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/fat.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,908 @@
+{
+    "super": {
+        "jump_instruction": b"\xeb\x3c\x90",
+        "oem_name": "mkdosfs",
+        "bytes_per_sector": 512,
+        "sectors_per_cluster": 1,
+        "num_reserved_sectors": 1,
+        "num_fats": 1,
+        "num_root_entries": 16,
+        "num_sectors_16": 66,
+        "media_descriptor": 248,
+        "sectors_per_fat": 1,
+        "sectors_per_track": 32,
+        "num_heads": 64,
+        "bpb331": {
+            "ignore": True,
+            "num_hidden_sectors": 0,
+            "num_sectors_32": 0
+        },
+        "drive_number": 0,
+        "chkdsk_flags": 0,
+        "extended_boot_signature": 41,
+        "volume_id": 1045880152,
+        "volume_label": "Test       ",
+        "type": "FAT12   ",
+        "boot_signature": b"\x55\xaa"
+    },
+    "num_sectors": 66,
+    "cluster_size": 512,
+    "first_root_sector": 2,
+    "first_data_sector": 3,
+    "num_clusters": 65,
+    "bits": 12,
+    "fats": {
+        0: {
+            0: 4088,
+            1: 4095,
+            2: 0,
+            3: 4095,
+            4: 0,
+            5: 0,
+            6: 0,
+            7: 0,
+            8: 0,
+            9: 0,
+            10: 0,
+            11: 0,
+            12: 0,
+            13: 0,
+            14: 0,
+            15: 0,
+            16: 0,
+            17: 0,
+            18: 0,
+            19: 0,
+            20: 0,
+            21: 0,
+            22: 0,
+            23: 0,
+            24: 0,
+            25: 0,
+            26: 0,
+            27: 0,
+            28: 0,
+            29: 0,
+            30: 0,
+            31: 0,
+            32: 0,
+            33: 0,
+            34: 0,
+            35: 0,
+            36: 0,
+            37: 38,
+            38: 4095,
+            39: 0,
+            40: 0,
+            41: 0,
+            42: 0,
+            43: 0,
+            44: 0,
+            45: 0,
+            46: 0,
+            47: 0,
+            48: 0,
+            49: 0,
+            50: 0,
+            51: 0,
+            52: 0,
+            53: 0,
+            54: 0,
+            55: 0,
+            56: 0,
+            57: 0,
+            58: 0,
+            59: 0,
+            60: 0,
+            61: 0,
+            62: 0,
+            63: 0,
+            64: 0
+        }
+    },
+    "root": {
+        0: {
+            "filename": b"\x54\x65\x73\x74\x20\x20\x20\x20",
+            "extension": b"\x20\x20\x20",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": True,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 35030,
+            "cdate": 16658,
+            "adate": 16658,
+            "permissions": 0,
+            "mtime": 35030,
+            "mdate": 16658,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        1: {
+            "filename": b"\x41\x73\x00\x75\x00\x62\x00\x64",
+            "extension": b"\x00\x69\x00",
+            "attrs": {
+                "read_only": True,
+                "hidden": True,
+                "system": True,
+                "volume_label": True,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 173,
+            "ctime": 114,
+            "cdate": 0,
+            "adate": 65535,
+            "permissions": 65535,
+            "mtime": 65535,
+            "mdate": 65535,
+            "start": 0,
+            "size": 4294967295,
+            "size_shown": 32
+        },
+        2: {
+            "filename": b"\x53\x55\x42\x44\x49\x52\x20\x20",
+            "extension": b"\x20\x20\x20",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": True,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 100,
+            "ctime": 43267,
+            "cdate": 16658,
+            "adate": 16658,
+            "permissions": 0,
+            "mtime": 43290,
+            "mdate": 16658,
+            "start": 3,
+            "size": 0,
+            "size_shown": 0,
+            "data": {
+                0: {
+                    "filename": b"\x2e\x20\x20\x20\x20\x20\x20\x20",
+                    "extension": b"\x20\x20\x20",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": True,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 100,
+                    "ctime": 43236,
+                    "cdate": 16658,
+                    "adate": 16658,
+                    "permissions": 0,
+                    "mtime": 43236,
+                    "mdate": 16658,
+                    "start": 3,
+                    "size": 0,
+                    "size_shown": 0
+                },
+                1: {
+                    "filename": b"\x2e\x2e\x20\x20\x20\x20\x20\x20",
+                    "extension": b"\x20\x20\x20",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": True,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 100,
+                    "ctime": 43236,
+                    "cdate": 16658,
+                    "adate": 16658,
+                    "permissions": 0,
+                    "mtime": 43236,
+                    "mdate": 16658,
+                    "start": 0,
+                    "size": 0,
+                    "size_shown": 0
+                },
+                2: {
+                    "filename": b"\xe5\x2e\x00\x66\x00\x69\x00\x6c",
+                    "extension": b"\x00\x65\x00",
+                    "attrs": {
+                        "read_only": True,
+                        "hidden": True,
+                        "system": True,
+                        "volume_label": True,
+                        "subdirectory": False,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 103,
+                    "ctime": 46,
+                    "cdate": 116,
+                    "adate": 120,
+                    "permissions": 116,
+                    "mtime": 46,
+                    "mdate": 115,
+                    "start": 0,
+                    "size": 7340151,
+                    "size_shown": 32
+                },
+                3: {
+                    "filename": b"\xe5\x49\x4c\x45\x54\x58\x7e\x31",
+                    "extension": b"\x53\x57\x50",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": False,
+                        "archive": True,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 0,
+                    "ctime": 43287,
+                    "cdate": 16658,
+                    "adate": 16658,
+                    "permissions": 0,
+                    "mtime": 43287,
+                    "mdate": 16658,
+                    "start": 13,
+                    "size": 12288,
+                    "size_shown": 32
+                },
+                4: {
+                    "filename": b"\x41\x66\x00\x69\x00\x6c\x00\x65",
+                    "extension": b"\x00\x2e\x00",
+                    "attrs": {
+                        "read_only": True,
+                        "hidden": True,
+                        "system": True,
+                        "volume_label": True,
+                        "subdirectory": False,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 25,
+                    "ctime": 116,
+                    "cdate": 120,
+                    "adate": 116,
+                    "permissions": 0,
+                    "mtime": 65535,
+                    "mdate": 65535,
+                    "start": 0,
+                    "size": 4294967295,
+                    "size_shown": 32
+                },
+                5: {
+                    "filename": b"\x46\x49\x4c\x45\x20\x20\x20\x20",
+                    "extension": b"\x54\x58\x54",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": False,
+                        "archive": True,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 0,
+                    "ctime": 43290,
+                    "cdate": 16658,
+                    "adate": 16658,
+                    "permissions": 0,
+                    "mtime": 43290,
+                    "mdate": 16658,
+                    "start": 37,
+                    "size": 951,
+                    "size_shown": 32,
+                    "data": b"\x22\x4a\x61\x62\x62\x65\x72\x77\x6f\x63\x6b\x79\x22\x0a\x0a\x27\x54\x77\x61\x73\x20\x62\x72\x69\x6c\x6c\x69\x67\x2c\x20\x61\x6e"
+                },
+                6: {
+                    "filename": b"\xe5\x2e\x00\x66\x00\x69\x00\x6c",
+                    "extension": b"\x00\x65\x00",
+                    "attrs": {
+                        "read_only": True,
+                        "hidden": True,
+                        "system": True,
+                        "volume_label": True,
+                        "subdirectory": False,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 111,
+                    "ctime": 46,
+                    "cdate": 116,
+                    "adate": 120,
+                    "permissions": 116,
+                    "mtime": 46,
+                    "mdate": 115,
+                    "start": 0,
+                    "size": 7864439,
+                    "size_shown": 32
+                },
+                7: {
+                    "filename": b"\xe5\x49\x4c\x45\x54\x58\x7e\x31",
+                    "extension": b"\x53\x57\x58",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": False,
+                        "archive": True,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 100,
+                    "ctime": 43267,
+                    "cdate": 16658,
+                    "adate": 16658,
+                    "permissions": 0,
+                    "mtime": 43267,
+                    "mdate": 16658,
+                    "start": 0,
+                    "size": 0,
+                    "size_shown": 0
+                },
+                8: {
+                    "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+                    "extension": b"\x00\x00\x00",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": False,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 0,
+                    "ctime": 0,
+                    "cdate": 0,
+                    "adate": 0,
+                    "permissions": 0,
+                    "mtime": 0,
+                    "mdate": 0,
+                    "start": 0,
+                    "size": 0,
+                    "size_shown": 0
+                },
+                9: {
+                    "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+                    "extension": b"\x00\x00\x00",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": False,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 0,
+                    "ctime": 0,
+                    "cdate": 0,
+                    "adate": 0,
+                    "permissions": 0,
+                    "mtime": 0,
+                    "mdate": 0,
+                    "start": 0,
+                    "size": 0,
+                    "size_shown": 0
+                },
+                10: {
+                    "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+                    "extension": b"\x00\x00\x00",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": False,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 0,
+                    "ctime": 0,
+                    "cdate": 0,
+                    "adate": 0,
+                    "permissions": 0,
+                    "mtime": 0,
+                    "mdate": 0,
+                    "start": 0,
+                    "size": 0,
+                    "size_shown": 0
+                },
+                11: {
+                    "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+                    "extension": b"\x00\x00\x00",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": False,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 0,
+                    "ctime": 0,
+                    "cdate": 0,
+                    "adate": 0,
+                    "permissions": 0,
+                    "mtime": 0,
+                    "mdate": 0,
+                    "start": 0,
+                    "size": 0,
+                    "size_shown": 0
+                },
+                12: {
+                    "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+                    "extension": b"\x00\x00\x00",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": False,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 0,
+                    "ctime": 0,
+                    "cdate": 0,
+                    "adate": 0,
+                    "permissions": 0,
+                    "mtime": 0,
+                    "mdate": 0,
+                    "start": 0,
+                    "size": 0,
+                    "size_shown": 0
+                },
+                13: {
+                    "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+                    "extension": b"\x00\x00\x00",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": False,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 0,
+                    "ctime": 0,
+                    "cdate": 0,
+                    "adate": 0,
+                    "permissions": 0,
+                    "mtime": 0,
+                    "mdate": 0,
+                    "start": 0,
+                    "size": 0,
+                    "size_shown": 0
+                },
+                14: {
+                    "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+                    "extension": b"\x00\x00\x00",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": False,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 0,
+                    "ctime": 0,
+                    "cdate": 0,
+                    "adate": 0,
+                    "permissions": 0,
+                    "mtime": 0,
+                    "mdate": 0,
+                    "start": 0,
+                    "size": 0,
+                    "size_shown": 0
+                },
+                15: {
+                    "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+                    "extension": b"\x00\x00\x00",
+                    "attrs": {
+                        "read_only": False,
+                        "hidden": False,
+                        "system": False,
+                        "volume_label": False,
+                        "subdirectory": False,
+                        "archive": False,
+                        "device": False,
+                        "reserved": False
+                    },
+                    "flags": 0,
+                    "ctime_fine": 0,
+                    "ctime": 0,
+                    "cdate": 0,
+                    "adate": 0,
+                    "permissions": 0,
+                    "mtime": 0,
+                    "mdate": 0,
+                    "start": 0,
+                    "size": 0,
+                    "size_shown": 0
+                }
+            }
+        },
+        3: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        4: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        5: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        6: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        7: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        8: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        9: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        10: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        11: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        12: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        13: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        14: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        },
+        15: {
+            "filename": b"\x00\x00\x00\x00\x00\x00\x00\x00",
+            "extension": b"\x00\x00\x00",
+            "attrs": {
+                "read_only": False,
+                "hidden": False,
+                "system": False,
+                "volume_label": False,
+                "subdirectory": False,
+                "archive": False,
+                "device": False,
+                "reserved": False
+            },
+            "flags": 0,
+            "ctime_fine": 0,
+            "ctime": 0,
+            "cdate": 0,
+            "adate": 0,
+            "permissions": 0,
+            "mtime": 0,
+            "mdate": 0,
+            "start": 0,
+            "size": 0,
+            "size_shown": 0
+        }
+    }
+}
Index: uspace/dist/src/bithenge/gif/gif.bh
===================================================================
--- uspace/dist/src/bithenge/gif/gif.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/gif/gif.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,148 @@
+#
+# Copyright (c) 2012 Vojtech Horky
+# 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.
+#
+
+#
+# Graphics Interchange Format (image/gif)
+#
+
+
+transform chars(len) = ascii <- known_length(len);
+transform word = uint16le;
+
+
+
+transform gif_signature = chars(3);
+
+transform gif_version = chars(3);
+
+transform gif_color_map_entry = struct {
+	.red <- uint8;
+	.green <- uint8;
+	.blue <- uint8;
+};
+
+transform gif_color_map(length) = repeat(length) {
+	gif_color_map_entry
+};
+
+transform gif_color_map_from_bits_per_pixel(bits_per_pixel) = struct {
+	# We need to emulate missing << operator
+	switch (bits_per_pixel) {
+		1: { <- gif_color_map(2); };
+		2: { <- gif_color_map(4); };
+		3: { <- gif_color_map(8); };
+		4: { <- gif_color_map(16); };
+		5: { <- gif_color_map(32); };
+		6: { <- gif_color_map(64); };
+		7: { <- gif_color_map(128); };
+		8: { <- gif_color_map(256); };
+	}
+};
+
+
+# Process GIF data block:
+#  - first byte denotes block size (.length)
+#  - followed by .length bytes of the actual data (not processed here)
+#  - followed by next block or terminator (zero)
+transform generic_data_block = do {
+	struct {
+		.length <- uint8;
+		.has_next <- nonzero_boolean <- (.length);
+		if (.has_next) {
+			.data <- known_length(.length);
+		}
+	}
+} while (.has_next);
+
+
+transform gif_image_block = struct {
+	.left <- word;
+	.top <- word;
+	.width <- word;
+	.height <- word;
+	
+	<- struct {
+		.use_local_color_map <- bit;
+		.interlacing <- bit;
+		.reserved_bits <- uint_be(3);
+		.bits_per_pixel <- (in + 1) <- uint_be(3);
+	} <- bits_be <- known_length(1);
+	
+	if (.use_local_color_map) {
+		.local_color_map <- gif_color_map_from_bits_per_pixel(.bits_per_pixel);
+	}
+	
+	.lzw_initial_size <- uint8;
+	.lzw_data <- generic_data_block;	
+};
+
+# TODO: interpret known extensions
+transform gif_extension = struct {
+	.function <- uint8;
+	.data <- generic_data_block;
+};
+
+# Switch over known blocks (image, extensions, end)
+transform gif_block = struct {
+	.kind <- uint8;
+	switch (.kind) {
+		33: { # exclamation mark -> extension block
+			.extension <- gif_extension;
+		};
+		44: { # comma -> image
+			.image <- gif_image_block;
+		};
+		59: { # semicolon -> terminator
+			.after_terminator <- repeat { uint8 };
+		};
+		else: {
+			.unknown <- repeat { uint8 };
+		};
+	}
+}; 
+
+transform main = struct {
+	.signature <- gif_signature;
+	.version <- gif_version;
+	.width <- word;
+	.height <- word;
+	<- struct {
+		.global_color_map_exists <- bit;
+		.color_resolution <- uint_be(3);
+		.reserved_bit <- uint_be(1);
+		.bits_per_pixel <- (in + 1) <- uint_be(3);
+	} <- bits_be <- known_length(1);
+	.background_color_index <- uint8;
+	.reserved <- uint8;
+	if (.global_color_map_exists) {
+		.global_color_map <- gif_color_map_from_bits_per_pixel(.bits_per_pixel);
+	}
+	.blocks <- repeat {
+		gif_block
+	}; 
+};
Index: uspace/dist/src/bithenge/gif/readme
===================================================================
--- uspace/dist/src/bithenge/gif/readme	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/gif/readme	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,9 @@
+
+File `loader.gif' was retrieved from
+   http://www.ajaxload.info/
+using default settings.
+
+File `blue_1x1.gif' was generated with ImageMagick using command
+   convert -size 1x1 xc:blue gif87:blue_1x1.gif
+
+File `helenos.gif' is a converted uspace/srv/hid/console/gfx/helenos.tga.
Index: uspace/dist/src/bithenge/repeat.bh
===================================================================
--- uspace/dist/src/bithenge/repeat.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/repeat.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,27 @@
+transform with_count = struct {
+	.none <- repeat(0) { uint8 };
+	.one <- repeat(1) { uint8 };
+	.count <- uint8;
+	if (true) { # test whether .count is still accessible
+		.many <- repeat(.count) { uint8 };
+	}
+};
+
+transform without_count = struct {
+	.until_error <- repeat { uint8 <- zero_terminated };
+	.until_end <- repeat { uint8 };
+};
+
+transform do_while = do {
+	struct {
+		.valid <- nonzero_boolean <- uint8;
+		.val <- uint8;
+	}
+} while (.valid);
+
+transform main = struct {
+	.with_count <- with_count;
+	.without_count <- without_count <- known_length(9);
+	.do_while <- do_while;
+	.do_while_item <- (.do_while[1]);
+};
Index: uspace/dist/src/bithenge/repeat.out
===================================================================
--- uspace/dist/src/bithenge/repeat.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/repeat.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,48 @@
+{
+    "with_count": {
+        "none": {},
+        "one": {
+            0: 127
+        },
+        "count": 7,
+        "many": {
+            0: 2,
+            1: 3,
+            2: 5,
+            3: 7,
+            4: 11,
+            5: 13,
+            6: 17
+        }
+    },
+    "without_count": {
+        "until_error": {
+            0: 2,
+            1: 4,
+            2: 8
+        },
+        "until_end": {
+            0: 16,
+            1: 32,
+            2: 64
+        }
+    },
+    "do_while": {
+        0: {
+            "valid": True,
+            "val": 1
+        },
+        1: {
+            "valid": True,
+            "val": 4
+        },
+        2: {
+            "valid": False,
+            "val": 9
+        }
+    },
+    "do_while_item": {
+        "valid": True,
+        "val": 4
+    }
+}
Index: uspace/dist/src/bithenge/test.bdsh
===================================================================
--- uspace/dist/src/bithenge/test.bdsh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/test.bdsh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,25 @@
+bithenge basic.bh basic.dat | to /tmp/bithenge-test.out
+cmp basic.out /tmp/bithenge-test.out
+
+bithenge bits.bh bits.dat | to /tmp/bithenge-test.out
+cmp bits.out /tmp/bithenge-test.out
+
+bithenge cond.bh cond.dat | to /tmp/bithenge-test.out
+cmp cond.out /tmp/bithenge-test.out
+
+bithenge expression.bh expression.dat | to /tmp/bithenge-test.out
+cmp expression.out /tmp/bithenge-test.out
+
+bithenge fat.bh fat.dat | to /tmp/bithenge-test.out
+cmp fat.out /tmp/bithenge-test.out
+
+bithenge repeat.bh repeat.dat | to /tmp/bithenge-test.out
+cmp repeat.out /tmp/bithenge-test.out
+
+bithenge trip.bh trip.dat | to /tmp/bithenge-test.out
+cmp trip.out /tmp/bithenge-test.out
+
+bithenge usbdesc.bh usbdesc.kbd.dat | to /tmp/bithenge-test.out
+cmp usbdesc.kbd.out /tmp/bithenge-test.out
+
+echo Success
Index: uspace/dist/src/bithenge/test.sh
===================================================================
--- uspace/dist/src/bithenge/test.sh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/test.sh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,33 @@
+#!/bin/bash
+shopt -s nullglob
+set -e
+
+BITHENGE=../../../app/bithenge/bithenge
+
+if type valgrind >/dev/null 2>&1
+then
+	BITHENGE="valgrind -q --show-reachable=yes --error-exitcode=64 ${BITHENGE}"
+else
+	echo "Valgrind not found."
+fi
+
+test_file() {
+	echo "Testing $1 on $2..."
+	${BITHENGE} $1 $2 2>&1|diff $3 -
+}
+
+for BH in *.bh
+do
+	for DAT in $(basename ${BH} .bh).dat $(basename ${BH} .bh).*.dat
+	do
+		OUT=$(basename ${DAT} .dat).out
+		[ -e ${DAT} ] || continue
+		[ -e ${OUT} ] || continue
+		test_file ${BH} ${DAT} ${OUT}
+	done
+done
+
+test_file trip.bh file:trip.dat trip.out
+test_file repeat.bh hex:7f07020305070b0D11020004000800102040010101040009 repeat.out
+
+echo "Done!"
Index: uspace/dist/src/bithenge/trip.bh
===================================================================
--- uspace/dist/src/bithenge/trip.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/trip.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,15 @@
+transform point = struct {
+	.lat <- uint32le;
+	.lon <- uint32le;
+};
+
+transform named_point = struct {
+	.name <- ascii <- zero_terminated;
+	<- point;
+};
+
+transform main = struct {
+	.from <- named_point;
+	.to <- named_point;
+	.distance <- uint32le; # in kilometers
+};
Index: uspace/dist/src/bithenge/trip.out
===================================================================
--- uspace/dist/src/bithenge/trip.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/trip.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,13 @@
+{
+    "from": {
+        "name": "Raleigh",
+        "lat": 36,
+        "lon": 79
+    },
+    "to": {
+        "name": "Denver",
+        "lat": 40,
+        "lon": 105
+    },
+    "distance": 2353
+}
Index: uspace/dist/src/bithenge/usbdesc.bh
===================================================================
--- uspace/dist/src/bithenge/usbdesc.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/usbdesc.bh	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,68 @@
+##
+##
+## USB DESCRIPTORS
+##
+##
+
+# Originally by Vojtech Horky.
+
+# Block prefixed with a byte length
+transform block = (in.data) <- struct {
+	.bLength <- uint8;
+	.data <- known_length(.bLength - 1);
+};
+
+# USB configuration descriptor
+# This is not the full configuration descriptor (i.e. with interface
+# and endpoint descriptors included) but only the header. 
+transform usb_configuration_descriptor_bare = struct {
+	.wTotalLength <- uint16le;
+	.bNumInterfaces <- uint8;
+	.bConfigurationValue <- uint8;
+	.iConfiguration <- uint8;
+	.bmAttributes <- uint8;
+	.MaxPower <- uint8;
+};
+
+# USB interface descriptor
+transform usb_interface_descriptor = struct {
+	.bInterfaceNumber <- uint8;
+	.bAlternateSetting <- uint8;
+	.bNumEndpoints <- uint8;
+	.bInterfaceClass <- uint8;
+	.bInterfaceSubClass <- uint8;
+	.bInterfaceProtocol <- uint8;
+	.iInterface <- uint8;
+};
+
+# USB endpoint descriptor
+transform usb_endpoint_descriptor = struct {
+	.bEndpointAddress  <- uint8;
+	.bmAttributes <- uint8;
+	.wMaxPacketSize <- uint16le;
+	.bInterval <- uint8;
+};
+
+# USB HID descriptor
+transform usb_hid_descriptor = struct {
+	.bcdHID <- uint16le;
+	.bCountryCode <- uint8;
+	.bNumDescriptors <- uint8;
+	<- repeat(.bNumDescriptors) { struct {
+		.bDescriptorType <- uint8;
+		.wDescriptorLength <- uint16le;
+	} };
+};
+
+# USB descriptor
+transform usb_descriptor = struct {
+	.bDescriptorType <- uint8;
+	<- switch (.bDescriptorType) {
+		 2: usb_configuration_descriptor_bare;
+		 4: usb_interface_descriptor;
+		 5: usb_endpoint_descriptor;
+		33: usb_hid_descriptor;
+	};
+} <- block;
+
+transform main = repeat { usb_descriptor };
Index: uspace/dist/src/bithenge/usbdesc.kbd.out
===================================================================
--- uspace/dist/src/bithenge/usbdesc.kbd.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/dist/src/bithenge/usbdesc.kbd.out	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,38 @@
+{
+    0: {
+        "bDescriptorType": 2,
+        "wTotalLength": 34,
+        "bNumInterfaces": 1,
+        "bConfigurationValue": 1,
+        "iConfiguration": 8,
+        "bmAttributes": 160,
+        "MaxPower": 50
+    },
+    1: {
+        "bDescriptorType": 4,
+        "bInterfaceNumber": 0,
+        "bAlternateSetting": 0,
+        "bNumEndpoints": 1,
+        "bInterfaceClass": 9,
+        "bInterfaceSubClass": 1,
+        "bInterfaceProtocol": 1,
+        "iInterface": 0
+    },
+    2: {
+        "bDescriptorType": 33,
+        "bcdHID": 273,
+        "bCountryCode": 0,
+        "bNumDescriptors": 1,
+        0: {
+            "bDescriptorType": 34,
+            "wDescriptorLength": 63
+        }
+    },
+    3: {
+        "bDescriptorType": 5,
+        "bEndpointAddress": 129,
+        "bmAttributes": 3,
+        "wMaxPacketSize": 8,
+        "bInterval": 10
+    }
+}
Index: uspace/dist/src/c/demos/top/screen.h
===================================================================
--- uspace/dist/src/c/demos/top/screen.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/dist/src/c/demos/top/screen.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,4 +36,5 @@
 
 #include <io/console.h>
+#include <io/verify.h>
 #include "top.h"
 
@@ -43,5 +44,6 @@
 extern void screen_done(void);
 extern void print_data(data_t *);
-extern void print_warning(const char *, ...);
+extern void print_warning(const char *, ...)
+    PRINTF_ATTRIBUTE(1, 2);
 
 extern int tgetchar(unsigned int);
Index: uspace/drv/block/ahci/Makefile
===================================================================
--- uspace/drv/block/ahci/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/block/ahci/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2012 Petr Jerman
+# 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 = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = ahci
+
+SOURCES = \
+	ahci.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/block/ahci/ahci.c
===================================================================
--- uspace/drv/block/ahci/ahci.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/block/ahci/ahci.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1345 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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.
+ */
+
+/** @file
+ * AHCI SATA driver implementation.
+ */
+
+#include <as.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ddf/interrupt.h>
+#include <ddf/log.h>
+#include <device/hw_res_parsed.h>
+#include <device/pci.h>
+#include <sysinfo.h>
+#include <ipc/irc.h>
+#include <ns.h>
+#include <ahci_iface.h>
+#include "ahci.h"
+#include "ahci_hw.h"
+#include "ahci_sata.h"
+
+#define NAME  "ahci"
+
+#define LO(ptr) \
+	((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) & 0xffffffff))
+
+#define HI(ptr) \
+	((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) >> 32))
+
+/** Interrupt pseudocode for a single port
+ *
+ * The interrupt handling works as follows:
+ *
+ * 1. Port interrupt status register is read
+ *    (stored as arg2).
+ * 2. If port interrupt is indicated, then:
+ *    3. Port interrupt status register is cleared.
+ *    4. Global interrupt status register is read
+ *       and cleared (any potential interrupts from
+ *       other ports are reasserted automatically).
+ *    5. Port number is stored as arg1.
+ *    6. The interrupt is accepted.
+ *
+ */
+#define AHCI_PORT_CMDS(port) \
+	{ \
+		/* Read port interrupt status register */ \
+		.cmd = CMD_PIO_READ_32, \
+		.addr = NULL, \
+		.dstarg = 2 \
+	}, \
+	{ \
+		/* Check if port asserted interrupt */ \
+		.cmd = CMD_PREDICATE, \
+		.value = 5, \
+		.srcarg = 2, \
+	}, \
+	{ \
+		/* Clear port interrupt status register */ \
+		.cmd = CMD_PIO_WRITE_A_32, \
+		.addr = NULL, \
+		.srcarg = 2 \
+	}, \
+	{ \
+		/* Read global interrupt status register */ \
+		.cmd = CMD_PIO_READ_32, \
+		.addr = NULL, \
+		.dstarg = 0 \
+	}, \
+	{ \
+		/* Clear global interrupt status register */ \
+		.cmd = CMD_PIO_WRITE_A_32, \
+		.addr = NULL, \
+		.srcarg = 0 \
+	}, \
+	{ \
+		/* Indicate port interrupt assertion */ \
+		.cmd = CMD_LOAD, \
+		.value = (port), \
+		.dstarg = 1 \
+	}, \
+	{ \
+		/* Accept the interrupt */ \
+		.cmd = CMD_ACCEPT \
+	}
+
+static int ahci_get_sata_device_name(ddf_fun_t *, size_t, char *);
+static int ahci_get_num_blocks(ddf_fun_t *, uint64_t *);
+static int ahci_get_block_size(ddf_fun_t *, size_t *);
+static int ahci_read_blocks(ddf_fun_t *, uint64_t, size_t, void *);
+static int ahci_write_blocks(ddf_fun_t *, uint64_t, size_t, void *);
+
+static int ahci_identify_device(sata_dev_t *);
+static int ahci_set_highest_ultra_dma_mode(sata_dev_t *);
+static int ahci_rb_fpdma(sata_dev_t *, void *, uint64_t);
+static int ahci_wb_fpdma(sata_dev_t *, void *, uint64_t);
+
+static void ahci_sata_devices_create(ahci_dev_t *, ddf_dev_t *);
+static ahci_dev_t *ahci_ahci_create(ddf_dev_t *);
+static void ahci_ahci_hw_start(ahci_dev_t *);
+
+static int ahci_dev_add(ddf_dev_t *);
+
+static void ahci_get_model_name(uint16_t *, char *);
+static int ahci_enable_interrupt(int);
+
+static fibril_mutex_t sata_devices_count_lock;
+static int sata_devices_count = 0;
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI Interface ----------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+static ahci_iface_t ahci_interface = {
+	.get_sata_device_name = &ahci_get_sata_device_name,
+	.get_num_blocks = &ahci_get_num_blocks,
+	.get_block_size = &ahci_get_block_size,
+	.read_blocks = &ahci_read_blocks,
+	.write_blocks = &ahci_write_blocks
+};
+
+static ddf_dev_ops_t ahci_ops = {
+	.interfaces[AHCI_DEV_IFACE] = &ahci_interface
+};
+
+static driver_ops_t driver_ops = {
+	.dev_add = &ahci_dev_add
+};
+
+static driver_t ahci_driver = {
+	.name = NAME,
+	.driver_ops = &driver_ops
+};
+
+/** Get SATA structure from DDF function. */
+static sata_dev_t *fun_sata_dev(ddf_fun_t *fun)
+{
+	return ddf_fun_data_get(fun);
+}
+
+/** Get AHCI structure from DDF device. */
+static ahci_dev_t *dev_ahci_dev(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
+}
+
+/** Get SATA device name.
+ *
+ * @param fun                  Device function handling the call.
+ * @param sata_dev_name_length Length of the sata_dev_name buffer.
+ * @param sata_dev_name        Buffer for SATA device name.
+ *
+ * @return EOK.
+ *
+ */
+static int ahci_get_sata_device_name(ddf_fun_t *fun,
+    size_t sata_dev_name_length, char *sata_dev_name)
+{
+	sata_dev_t *sata = fun_sata_dev(fun);
+	str_cpy(sata_dev_name, sata_dev_name_length, sata->model);
+	return EOK;
+}
+
+/** Get Number of blocks in SATA device.
+ *
+ * @param fun    Device function handling the call.
+ * @param blocks Return number of blocks in SATA device.
+ *
+ * @return EOK.
+ *
+ */
+static int ahci_get_num_blocks(ddf_fun_t *fun, uint64_t *num_blocks)
+{
+	sata_dev_t *sata = fun_sata_dev(fun);
+	*num_blocks = sata->blocks;
+	return EOK;
+}
+
+/** Get SATA device block size.
+ *
+ * @param fun        Device function handling the call.
+ * @param block_size Return block size.
+ *
+ * @return EOK.
+ *
+ */
+static int ahci_get_block_size(ddf_fun_t *fun, size_t *block_size)
+{
+	sata_dev_t *sata = fun_sata_dev(fun);
+	*block_size = sata->block_size;
+	return EOK;
+}
+
+/** Read data blocks into SATA device.
+ *
+ * @param fun      Device function handling the call.
+ * @param blocknum Number of first block.
+ * @param count    Number of blocks to read.
+ * @param buf      Buffer for data.
+ *
+ * @return EOK if succeed, error code otherwise
+ *
+ */
+static int ahci_read_blocks(ddf_fun_t *fun, uint64_t blocknum,
+    size_t count, void *buf)
+{
+	sata_dev_t *sata = fun_sata_dev(fun);
+	
+	void *phys;
+	void *ibuf;
+	int rc = dmamem_map_anonymous(sata->block_size, AS_AREA_READ | AS_AREA_WRITE,
+	    0, &phys, (void **) &ibuf);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Cannot allocate read buffer.");
+		return rc;
+	}
+	
+	bzero(buf, sata->block_size);
+	
+	fibril_mutex_lock(&sata->lock);
+	
+	for (size_t cur = 0; cur < count; cur++) {
+		rc = ahci_rb_fpdma(sata, phys, blocknum + cur);
+		if (rc != EOK)
+			break;
+		
+		memcpy((void *) (((uint8_t *) buf) + (sata->block_size * cur)),
+		    ibuf, sata->block_size);
+	}
+	
+	fibril_mutex_unlock(&sata->lock);
+	dmamem_unmap_anonymous(ibuf);
+	
+	return rc;
+}
+
+/** Write data blocks into SATA device.
+ *
+ * @param fun      Device function handling the call.
+ * @param blocknum Number of first block.
+ * @param count    Number of blocks to write.
+ * @param buf      Buffer with data.
+ *
+ * @return EOK if succeed, error code otherwise
+ *
+ */
+static int ahci_write_blocks(ddf_fun_t *fun, uint64_t blocknum,
+    size_t count, void *buf)
+{
+	sata_dev_t *sata = fun_sata_dev(fun);
+	
+	void *phys;
+	void *ibuf;
+	int rc = dmamem_map_anonymous(sata->block_size, AS_AREA_READ | AS_AREA_WRITE,
+	    0, &phys, (void **) &ibuf);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Cannot allocate write buffer.");
+		return rc;
+	}
+	
+	fibril_mutex_lock(&sata->lock);
+	
+	for (size_t cur = 0; cur < count; cur++) {
+		memcpy(ibuf, (void *) (((uint8_t *) buf) + (sata->block_size * cur)),
+		    sata->block_size);
+		rc = ahci_wb_fpdma(sata, phys, blocknum + cur);
+		if (rc != EOK)
+			break;
+	}
+	
+	fibril_mutex_unlock(&sata->lock);
+	dmamem_unmap_anonymous(ibuf);
+	
+	return rc;
+}
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI Commands -----------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Wait for interrupt event.
+ *
+ * @param sata SATA device structure.
+ *
+ * @return Value of interrupt state register.
+ *
+ */
+static ahci_port_is_t ahci_wait_event(sata_dev_t *sata)
+{
+	fibril_mutex_lock(&sata->event_lock);
+	
+	sata->event_pxis = 0;
+	while (sata->event_pxis == 0)
+		fibril_condvar_wait(&sata->event_condvar, &sata->event_lock);
+	
+	ahci_port_is_t pxis = sata->event_pxis;
+	
+	if (ahci_port_is_permanent_error(pxis))
+		sata->is_invalid_device = true;
+	
+	fibril_mutex_unlock(&sata->event_lock);
+	
+	return pxis;
+}
+
+/** Set AHCI registers for identifying SATA device.
+ *
+ * @param sata SATA device structure.
+ * @param phys Physical address of working buffer.
+ *
+ */
+static void ahci_identify_device_cmd(sata_dev_t *sata, void *phys)
+{
+	volatile sata_std_command_frame_t *cmd =
+	    (sata_std_command_frame_t *) sata->cmd_table;
+	
+	cmd->fis_type = SATA_CMD_FIS_TYPE;
+	cmd->c = SATA_CMD_FIS_COMMAND_INDICATOR;
+	cmd->command = 0xec;
+	cmd->features = 0;
+	cmd->lba_lower = 0;
+	cmd->device = 0;
+	cmd->lba_upper = 0;
+	cmd->features_upper = 0;
+	cmd->count = 0;
+	cmd->reserved1 = 0;
+	cmd->control = 0;
+	cmd->reserved2 = 0;
+	
+	volatile ahci_cmd_prdt_t *prdt =
+	    (ahci_cmd_prdt_t *) (&sata->cmd_table[0x20]);
+	
+	prdt->data_address_low = LO(phys);
+	prdt->data_address_upper = HI(phys);
+	prdt->reserved1 = 0;
+	prdt->dbc = SATA_IDENTIFY_DEVICE_BUFFER_LENGTH - 1;
+	prdt->reserved2 = 0;
+	prdt->ioc = 0;
+	
+	sata->cmd_header->prdtl = 1;
+	sata->cmd_header->flags =
+	    AHCI_CMDHDR_FLAGS_CLEAR_BUSY_UPON_OK |
+	    AHCI_CMDHDR_FLAGS_2DWCMD;
+	sata->cmd_header->bytesprocessed = 0;
+	
+	/* Run command. */
+	sata->port->pxsact |= 1;
+	sata->port->pxci |= 1;
+}
+
+/** Set AHCI registers for identifying packet SATA device.
+ *
+ * @param sata SATA device structure.
+ * @param phys Physical address of working buffer.
+ *
+ */
+static void ahci_identify_packet_device_cmd(sata_dev_t *sata, void *phys)
+{
+	volatile sata_std_command_frame_t *cmd =
+	    (sata_std_command_frame_t *) sata->cmd_table;
+	
+	cmd->fis_type = SATA_CMD_FIS_TYPE;
+	cmd->c = SATA_CMD_FIS_COMMAND_INDICATOR;
+	cmd->command = 0xa1;
+	cmd->features = 0;
+	cmd->lba_lower = 0;
+	cmd->device = 0;
+	cmd->lba_upper = 0;
+	cmd->features_upper = 0;
+	cmd->count = 0;
+	cmd->reserved1 = 0;
+	cmd->control = 0;
+	cmd->reserved2 = 0;
+	
+	volatile ahci_cmd_prdt_t *prdt =
+	    (ahci_cmd_prdt_t *) (&sata->cmd_table[0x20]);
+	
+	prdt->data_address_low = LO(phys);
+	prdt->data_address_upper = HI(phys);
+	prdt->reserved1 = 0;
+	prdt->dbc = SATA_IDENTIFY_DEVICE_BUFFER_LENGTH - 1;
+	prdt->reserved2 = 0;
+	prdt->ioc = 0;
+	
+	sata->cmd_header->prdtl = 1;
+	sata->cmd_header->flags =
+	    AHCI_CMDHDR_FLAGS_CLEAR_BUSY_UPON_OK |
+	    AHCI_CMDHDR_FLAGS_2DWCMD;
+	sata->cmd_header->bytesprocessed = 0;
+	
+	/* Run command. */
+	sata->port->pxsact |= 1;
+	sata->port->pxci |= 1;
+}
+
+/** Fill device identification in SATA device structure.
+ *
+ * @param sata SATA device structure.
+ *
+ * @return EOK if succeed, error code otherwise.
+ *
+ */
+static int ahci_identify_device(sata_dev_t *sata)
+{
+	if (sata->is_invalid_device) {
+		ddf_msg(LVL_ERROR,
+		    "Identify command device on invalid device");
+		return EINTR;
+	}
+	
+	void *phys;
+	sata_identify_data_t *idata;
+	int rc = dmamem_map_anonymous(SATA_IDENTIFY_DEVICE_BUFFER_LENGTH,
+	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, (void **) &idata);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Cannot allocate buffer to identify device.");
+		return rc;
+	}
+	
+	bzero(idata, SATA_IDENTIFY_DEVICE_BUFFER_LENGTH);
+	
+	fibril_mutex_lock(&sata->lock);
+	
+	ahci_identify_device_cmd(sata, phys);
+	ahci_port_is_t pxis = ahci_wait_event(sata);
+	
+	if (sata->is_invalid_device) {
+		ddf_msg(LVL_ERROR,
+		    "Unrecoverable error during ata identify device");
+		goto error;
+	}
+	
+	if (ahci_port_is_tfes(pxis)) {
+		ahci_identify_packet_device_cmd(sata, phys);
+		pxis = ahci_wait_event(sata);
+		
+		if ((sata->is_invalid_device) || (ahci_port_is_error(pxis))) {
+			ddf_msg(LVL_ERROR,
+			    "Unrecoverable error during ata identify packet device");
+			goto error;
+		}
+		
+		sata->is_packet_device = true;
+	}
+	
+	ahci_get_model_name(idata->model_name, sata->model);
+	
+	/*
+	 * Due to QEMU limitation (as of 2012-06-22),
+	 * only NCQ FPDMA mode is supported.
+	 */
+	if ((idata->sata_cap & sata_np_cap_ncq) == 0) {
+		ddf_msg(LVL_ERROR, "%s: NCQ must be supported", sata->model);
+		goto error;
+	}
+	
+	uint16_t logsec = idata->physical_logic_sector_size;
+	if ((logsec & 0xc000) == 0x4000) {
+		/* Length of sector may be larger than 512 B */
+		if (logsec & 0x0100) {
+			/* Size of sector is larger than 512 B */
+			ddf_msg(LVL_ERROR,
+			    "%s: Sector length other than 512 B not supported",
+			    sata->model);
+			goto error;
+		}
+		
+		if ((logsec & 0x0200) && ((logsec & 0x000f) != 0)) {
+			/* Physical sectors per logical sector is greather than 1 */
+			ddf_msg(LVL_ERROR,
+			    "%s: Sector length other than 512 B not supported",
+			    sata->model);
+			goto error;
+		}
+	}
+	
+	if (sata->is_packet_device) {
+		/*
+		 * Due to QEMU limitation (as of 2012-06-22),
+		 * only NCQ FPDMA mode supported - block size is
+		 * 512 B, not 2048 B!
+		 */
+		sata->block_size = SATA_DEFAULT_SECTOR_SIZE;
+		sata->blocks = 0;
+	} else {
+		sata->block_size = SATA_DEFAULT_SECTOR_SIZE;
+		
+		if ((idata->caps & sata_rd_cap_lba) == 0) {
+			ddf_msg(LVL_ERROR, "%s: LBA for NCQ must be supported",
+			    sata->model);
+			goto error;
+		} else if ((idata->cmd_set1 & sata_cs1_addr48) == 0) {
+			sata->blocks = (uint32_t) idata->total_lba28_0 |
+			    ((uint32_t) idata->total_lba28_1 << 16);
+		} else {
+			/* Device supports LBA-48 addressing. */
+			sata->blocks = (uint64_t) idata->total_lba48_0 |
+			    ((uint64_t) idata->total_lba48_1 << 16) |
+			    ((uint64_t) idata->total_lba48_2 << 32) |
+			    ((uint64_t) idata->total_lba48_3 << 48);
+		}
+	}
+	
+	uint8_t udma_mask = idata->udma & 0x007f;
+	sata->highest_udma_mode = (uint8_t) -1;
+	if (udma_mask == 0) {
+		ddf_msg(LVL_ERROR,
+		    "%s: UDMA mode for NCQ FPDMA mode must be supported",
+		    sata->model);
+		goto error;
+	} else {
+		for (uint8_t i = 0; i < 7; i++) {
+			if (udma_mask & (1 << i))
+				sata->highest_udma_mode = i;
+		}
+	}
+	
+	fibril_mutex_unlock(&sata->lock);
+	dmamem_unmap_anonymous(idata);
+	
+	return EOK;
+	
+error:
+	fibril_mutex_unlock(&sata->lock);
+	dmamem_unmap_anonymous(idata);
+	
+	return EINTR;
+}
+
+/** Set AHCI registers for setting SATA device transfer mode.
+ *
+ * @param sata SATA device structure.
+ * @param phys Physical address of working buffer.
+ * @param mode Required mode.
+ *
+ */
+static void ahci_set_mode_cmd(sata_dev_t *sata, void* phys, uint8_t mode)
+{
+	volatile sata_std_command_frame_t *cmd =
+	    (sata_std_command_frame_t *) sata->cmd_table;
+	
+	cmd->fis_type = SATA_CMD_FIS_TYPE;
+	cmd->c = SATA_CMD_FIS_COMMAND_INDICATOR; 
+	cmd->command = 0xef;
+	cmd->features = 0x03;
+	cmd->lba_lower = 0;
+	cmd->device = 0;
+	cmd->lba_upper = 0;
+	cmd->features_upper = 0;
+	cmd->count = mode;
+	cmd->reserved1 = 0;
+	cmd->control = 0;
+	cmd->reserved2 = 0;
+	
+	volatile ahci_cmd_prdt_t *prdt =
+	    (ahci_cmd_prdt_t *) (&sata->cmd_table[0x20]);
+	
+	prdt->data_address_low = LO(phys);
+	prdt->data_address_upper = HI(phys);
+	prdt->reserved1 = 0;
+	prdt->dbc = SATA_SET_FEATURE_BUFFER_LENGTH - 1;
+	prdt->reserved2 = 0;
+	prdt->ioc = 0;
+	
+	sata->cmd_header->prdtl = 1;
+	sata->cmd_header->flags =
+	    AHCI_CMDHDR_FLAGS_CLEAR_BUSY_UPON_OK |
+	    AHCI_CMDHDR_FLAGS_2DWCMD;
+	sata->cmd_header->bytesprocessed = 0;
+	
+	/* Run command. */
+	sata->port->pxsact |= 1;
+	sata->port->pxci |= 1;
+}
+
+/** Set highest ultra DMA mode supported by SATA device.
+ *
+ * @param sata SATA device structure.
+ *
+ * @return EOK if succeed, error code otherwise
+ *
+ */
+static int ahci_set_highest_ultra_dma_mode(sata_dev_t *sata)
+{
+	if (sata->is_invalid_device) {
+		ddf_msg(LVL_ERROR,
+		    "%s: Setting highest UDMA mode on invalid device",
+		    sata->model);
+		return EINTR;
+	}
+	
+	if (sata->highest_udma_mode == (uint8_t) -1) {
+		ddf_msg(LVL_ERROR,
+		    "%s: No AHCI UDMA support.", sata->model);
+		return EINTR;
+	}
+	
+	if (sata->highest_udma_mode > 6) {
+		ddf_msg(LVL_ERROR,
+		    "%s: Unknown AHCI UDMA mode.", sata->model);
+		return EINTR;
+	}
+	
+	void *phys;
+	sata_identify_data_t *idata;
+	int rc = dmamem_map_anonymous(SATA_SET_FEATURE_BUFFER_LENGTH,
+	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, (void **) &idata);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Cannot allocate buffer for device set mode.");
+		return rc;
+	}
+	
+	bzero(idata, SATA_SET_FEATURE_BUFFER_LENGTH);
+	
+	fibril_mutex_lock(&sata->lock);
+	
+	uint8_t mode = 0x40 | (sata->highest_udma_mode & 0x07);
+	ahci_set_mode_cmd(sata, phys, mode);
+	ahci_port_is_t pxis = ahci_wait_event(sata);
+	
+	if (sata->is_invalid_device) {
+		ddf_msg(LVL_ERROR,
+		    "%s: Unrecoverable error during set highest UDMA mode",
+		    sata->model);
+		goto error;
+	}
+	
+	if (ahci_port_is_error(pxis)) {
+		ddf_msg(LVL_ERROR,
+		    "%s: Error during set highest UDMA mode", sata->model);
+		goto error;
+	}
+	
+	fibril_mutex_unlock(&sata->lock);
+	dmamem_unmap_anonymous(idata);
+	
+	return EOK;
+	
+error:
+	fibril_mutex_unlock(&sata->lock);
+	dmamem_unmap_anonymous(idata);
+	
+	return EINTR;
+}
+
+/** Set AHCI registers for reading one sector from the SATA device using FPDMA.
+ *
+ * @param sata     SATA device structure.
+ * @param phys     Physical address of buffer for sector data.
+ * @param blocknum Block number to read.
+ *
+ */
+static void ahci_rb_fpdma_cmd(sata_dev_t *sata, void *phys, uint64_t blocknum)
+{
+	volatile sata_ncq_command_frame_t *cmd =
+	    (sata_ncq_command_frame_t *) sata->cmd_table;
+	
+	cmd->fis_type = SATA_CMD_FIS_TYPE;
+	cmd->c = SATA_CMD_FIS_COMMAND_INDICATOR;
+	cmd->command = 0x60;
+	cmd->tag = 0;
+	cmd->control = 0;
+	
+	cmd->reserved1 = 0;
+	cmd->reserved2 = 0;
+	cmd->reserved3 = 0;
+	cmd->reserved4 = 0;
+	cmd->reserved5 = 0;
+	cmd->reserved6 = 0;
+	
+	cmd->sector_count_low = 1;
+	cmd->sector_count_high = 0;
+	
+	cmd->lba0 = blocknum & 0xff;
+	cmd->lba1 = (blocknum >> 8) & 0xff;
+	cmd->lba2 = (blocknum >> 16) & 0xff;
+	cmd->lba3 = (blocknum >> 24) & 0xff;
+	cmd->lba4 = (blocknum >> 32) & 0xff;
+	cmd->lba5 = (blocknum >> 40) & 0xff;
+	
+	volatile ahci_cmd_prdt_t *prdt =
+	    (ahci_cmd_prdt_t *) (&sata->cmd_table[0x20]);
+	
+	prdt->data_address_low = LO(phys);
+	prdt->data_address_upper = HI(phys);
+	prdt->reserved1 = 0;
+	prdt->dbc = sata->block_size - 1;
+	prdt->reserved2 = 0;
+	prdt->ioc = 0;
+	
+	sata->cmd_header->prdtl = 1;
+	sata->cmd_header->flags =
+	    AHCI_CMDHDR_FLAGS_CLEAR_BUSY_UPON_OK |
+	    AHCI_CMDHDR_FLAGS_5DWCMD;
+	sata->cmd_header->bytesprocessed = 0;
+	
+	sata->port->pxsact |= 1;
+	sata->port->pxci |= 1;
+}
+
+/** Read one sector from the SATA device using FPDMA.
+ *
+ * @param sata     SATA device structure.
+ * @param phys     Physical address of buffer for sector data.
+ * @param blocknum Block number to read.
+ *
+ * @return EOK if succeed, error code otherwise
+ *
+ */
+static int ahci_rb_fpdma(sata_dev_t *sata, void *phys, uint64_t blocknum)
+{
+	if (sata->is_invalid_device) {
+		ddf_msg(LVL_ERROR,
+		    "%s: FPDMA read from invalid device", sata->model);
+		return EINTR;
+	}
+	
+	ahci_rb_fpdma_cmd(sata, phys, blocknum);
+	ahci_port_is_t pxis = ahci_wait_event(sata);
+	
+	if ((sata->is_invalid_device) || (ahci_port_is_error(pxis))) {
+		ddf_msg(LVL_ERROR,
+		    "%s: Unrecoverable error during FPDMA read", sata->model);
+		return EINTR;
+	}
+	
+	return EOK;
+}
+
+/** Set AHCI registers for writing one sector to the SATA device, use FPDMA.
+ *
+ * @param sata     SATA device structure.
+ * @param phys     Physical address of buffer with sector data.
+ * @param blocknum Block number to write.
+ *
+ * @return EOK if succeed, error code otherwise
+ *
+ */
+static void ahci_wb_fpdma_cmd(sata_dev_t *sata, void *phys, uint64_t blocknum)
+{
+	volatile sata_ncq_command_frame_t *cmd =
+	    (sata_ncq_command_frame_t *) sata->cmd_table;
+	
+	cmd->fis_type = SATA_CMD_FIS_TYPE;
+	cmd->c = SATA_CMD_FIS_COMMAND_INDICATOR;
+	cmd->command = 0x61;
+	cmd->tag = 0;
+	cmd->control = 0;
+	
+	cmd->reserved1 = 0;
+	cmd->reserved2 = 0;
+	cmd->reserved3 = 0;
+	cmd->reserved4 = 0;
+	cmd->reserved5 = 0;
+	cmd->reserved6 = 0;
+	
+	cmd->sector_count_low = 1;
+	cmd->sector_count_high = 0;
+	
+	cmd->lba0 = blocknum & 0xff;
+	cmd->lba1 = (blocknum >> 8) & 0xff;
+	cmd->lba2 = (blocknum >> 16) & 0xff;
+	cmd->lba3 = (blocknum >> 24) & 0xff;
+	cmd->lba4 = (blocknum >> 32) & 0xff;
+	cmd->lba5 = (blocknum >> 40) & 0xff;
+	
+	volatile ahci_cmd_prdt_t *prdt =
+	    (ahci_cmd_prdt_t *) (&sata->cmd_table[0x20]);
+	
+	prdt->data_address_low = LO(phys);
+	prdt->data_address_upper = HI(phys);
+	prdt->reserved1 = 0;
+	prdt->dbc = sata->block_size - 1;
+	prdt->reserved2 = 0;
+	prdt->ioc = 0;
+	
+	sata->cmd_header->prdtl = 1;
+	sata->cmd_header->flags =
+	    AHCI_CMDHDR_FLAGS_CLEAR_BUSY_UPON_OK |
+	    AHCI_CMDHDR_FLAGS_WRITE |
+	    AHCI_CMDHDR_FLAGS_5DWCMD;
+	sata->cmd_header->bytesprocessed = 0;
+	
+	sata->port->pxsact |= 1;
+	sata->port->pxci |= 1;
+}
+
+/** Write one sector into the SATA device, use FPDMA.
+ *
+ * @param sata     SATA device structure.
+ * @param phys     Physical addres of buffer with sector data.
+ * @param blocknum Block number to write.
+ *
+ * @return EOK if succeed, error code otherwise
+ *
+ */
+static int ahci_wb_fpdma(sata_dev_t *sata, void *phys, uint64_t blocknum)
+{
+	if (sata->is_invalid_device) {
+		ddf_msg(LVL_ERROR,
+		    "%s: FPDMA write to invalid device", sata->model);
+		return EINTR;
+	}
+	
+	ahci_wb_fpdma_cmd(sata, phys, blocknum);
+	ahci_port_is_t pxis = ahci_wait_event(sata);
+	
+	if ((sata->is_invalid_device) || (ahci_port_is_error(pxis))) {
+		ddf_msg(LVL_ERROR,
+		    "%s: Unrecoverable error during FPDMA write", sata->model);
+		return EINTR;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/*-- Interrupts handling -----------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+static irq_pio_range_t ahci_ranges[] = {
+	{
+		.base = 0,
+		.size = 0,
+	}
+};
+
+static irq_cmd_t ahci_cmds[] = {
+	AHCI_PORT_CMDS(0),
+	AHCI_PORT_CMDS(1),
+	AHCI_PORT_CMDS(2),
+	AHCI_PORT_CMDS(3),
+	AHCI_PORT_CMDS(4),
+	AHCI_PORT_CMDS(5),
+	AHCI_PORT_CMDS(6),
+	AHCI_PORT_CMDS(7),
+	AHCI_PORT_CMDS(8),
+	AHCI_PORT_CMDS(9),
+	AHCI_PORT_CMDS(10),
+	AHCI_PORT_CMDS(11),
+	AHCI_PORT_CMDS(12),
+	AHCI_PORT_CMDS(13),
+	AHCI_PORT_CMDS(14),
+	AHCI_PORT_CMDS(15),
+	AHCI_PORT_CMDS(16),
+	AHCI_PORT_CMDS(17),
+	AHCI_PORT_CMDS(18),
+	AHCI_PORT_CMDS(19),
+	AHCI_PORT_CMDS(20),
+	AHCI_PORT_CMDS(21),
+	AHCI_PORT_CMDS(22),
+	AHCI_PORT_CMDS(23),
+	AHCI_PORT_CMDS(24),
+	AHCI_PORT_CMDS(25),
+	AHCI_PORT_CMDS(26),
+	AHCI_PORT_CMDS(27),
+	AHCI_PORT_CMDS(28),
+	AHCI_PORT_CMDS(29),
+	AHCI_PORT_CMDS(30),
+	AHCI_PORT_CMDS(31)
+};
+
+/** AHCI interrupt handler.
+ *
+ * @param dev   DDF device structure.
+ * @param iid   The IPC call id.
+ * @param icall The IPC call structure.
+ *
+ */
+static void ahci_interrupt(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
+{
+	ahci_dev_t *ahci = dev_ahci_dev(dev);
+	unsigned int port = IPC_GET_ARG1(*icall);
+	ahci_port_is_t pxis = IPC_GET_ARG2(*icall);
+	
+	if (port >= AHCI_MAX_PORTS)
+		return;
+	
+	sata_dev_t *sata = (sata_dev_t *) ahci->sata_devs[port];
+	if (sata == NULL)
+		return;
+	
+	/* Evaluate port event */
+	if ((ahci_port_is_end_of_operation(pxis)) ||
+	    (ahci_port_is_error(pxis))) {
+		fibril_mutex_lock(&sata->event_lock);
+		
+		sata->event_pxis = pxis;
+		fibril_condvar_signal(&sata->event_condvar);
+		
+		fibril_mutex_unlock(&sata->event_lock);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI and SATA device creating and initializing routines -----------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Allocate SATA device structure with buffers for hardware.
+ *
+ * @param port AHCI port structure
+ *
+ * @return SATA device structure if succeed, NULL otherwise.
+ *
+ */
+static sata_dev_t *ahci_sata_allocate(ahci_dev_t *ahci, volatile ahci_port_t *port)
+{
+	size_t size = 4096;
+	void *phys = NULL;
+	void *virt_fb = NULL;
+	void *virt_cmd = NULL;
+	void *virt_table = NULL;
+	ddf_fun_t *fun;
+	
+	fun = ddf_fun_create(ahci->dev, fun_exposed, NULL);
+	
+	sata_dev_t *sata = ddf_fun_data_alloc(fun, sizeof(sata_dev_t));
+	if (sata == NULL)
+		return NULL;
+	
+	sata->fun = fun;
+	sata->port = port;
+	
+	/* Allocate and init retfis structure. */
+	int rc = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE, 0,
+	    &phys, &virt_fb);
+	if (rc != EOK)
+		goto error_retfis;
+	
+	bzero(virt_fb, size);
+	sata->port->pxfbu = HI(phys);
+	sata->port->pxfb = LO(phys);
+	
+	/* Allocate and init command header structure. */
+	rc = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE, 0,
+	    &phys, &virt_cmd);
+	if (rc != EOK)
+		goto error_cmd;
+	
+	bzero(virt_cmd, size);
+	sata->port->pxclbu = HI(phys);
+	sata->port->pxclb = LO(phys);
+	sata->cmd_header = (ahci_cmdhdr_t *) virt_cmd;
+	
+	/* Allocate and init command table structure. */
+	rc = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE, 0,
+	    &phys, &virt_table);
+	if (rc != EOK)
+		goto error_table;
+	
+	bzero(virt_table, size);
+	sata->cmd_header->cmdtableu = HI(phys);
+	sata->cmd_header->cmdtable = LO(phys);
+	sata->cmd_table = (uint32_t*) virt_table;
+	
+	return sata;
+	
+error_table:
+	dmamem_unmap(virt_cmd, size);
+error_cmd:
+	dmamem_unmap(virt_fb, size);
+error_retfis:
+	free(sata);
+	return NULL;
+}
+
+/** Initialize and start SATA hardware device.
+ *
+ * @param sata SATA device structure.
+ *
+ */
+static void ahci_sata_hw_start(sata_dev_t *sata)
+{
+	ahci_port_cmd_t pxcmd;
+	
+	pxcmd.u32 = sata->port->pxcmd;
+	
+	/* Frame receiver disabled. */
+	pxcmd.fre = 0;
+	
+	/* Disable process the command list. */
+	pxcmd.st = 0;
+	
+	sata->port->pxcmd = pxcmd.u32;
+	
+	/* Clear interrupt status. */
+	sata->port->pxis = 0xffffffff;
+	
+	/* Clear error status. */
+	sata->port->pxserr = 0xffffffff;
+	
+	/* Enable all interrupts. */
+	sata->port->pxie = 0xffffffff;
+	
+	/* Frame receiver enabled. */
+	pxcmd.fre = 1;
+	
+	/* Enable process the command list. */
+	pxcmd.st = 1;
+	
+	sata->port->pxcmd = pxcmd.u32;
+}
+
+/** Create and initialize connected SATA structure device
+ *
+ * @param ahci     AHCI device structure.
+ * @param dev      DDF device structure.
+ * @param port     AHCI port structure.
+ * @param port_num Number of AHCI port with existing SATA device.
+ *
+ * @return EOK if succeed, error code otherwise.
+ *
+ */
+static int ahci_sata_create(ahci_dev_t *ahci, ddf_dev_t *dev,
+    volatile ahci_port_t *port, unsigned int port_num)
+{
+	ddf_fun_t *fun = NULL;
+	int rc;
+	
+	sata_dev_t *sata = ahci_sata_allocate(ahci, port);
+	if (sata == NULL)
+		return EINTR;
+	
+	/* Set pointers between SATA and AHCI structures. */
+	sata->ahci = ahci;
+	sata->port_num = port_num;
+	ahci->sata_devs[port_num] = sata;
+	
+	/* Initialize synchronization structures */
+	fibril_mutex_initialize(&sata->lock);
+	fibril_mutex_initialize(&sata->event_lock);
+	fibril_condvar_initialize(&sata->event_condvar);
+	
+	ahci_sata_hw_start(sata);
+	
+	/* Identify device. */
+	if (ahci_identify_device(sata) != EOK)
+		goto error;
+	
+	/* Set required UDMA mode */
+	if (ahci_set_highest_ultra_dma_mode(sata) != EOK)
+		goto error;
+	
+	/* Add device to the system */
+	char sata_dev_name[16];
+	snprintf(sata_dev_name, 16, "ahci_%u", sata_devices_count);
+	
+	fibril_mutex_lock(&sata_devices_count_lock);
+	sata_devices_count++;
+	fibril_mutex_unlock(&sata_devices_count_lock);
+	
+	rc= ddf_fun_set_name(sata->fun, sata_dev_name);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed setting function name.");
+		goto error;
+	}
+	
+	ddf_fun_set_ops(fun, &ahci_ops);
+	
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function.");
+		goto error;
+	}
+	
+	return EOK;
+	
+error:
+	sata->is_invalid_device = true;
+	if (fun != NULL)
+		ddf_fun_destroy(fun);
+	
+	return EINTR;
+}
+
+/** Create and initialize all SATA structure devices for connected SATA drives.
+ *
+ * @param ahci AHCI device structure.
+ * @param dev  DDF device structure.
+ *
+ */
+static void ahci_sata_devices_create(ahci_dev_t *ahci, ddf_dev_t *dev)
+{
+	for (unsigned int port_num = 0; port_num < AHCI_MAX_PORTS; port_num++) {
+		/* Active ports only */
+		if (!(ahci->memregs->ghc.pi & (1 << port_num)))
+			continue;
+		
+		volatile ahci_port_t *port = ahci->memregs->ports + port_num;
+		
+		/* Active devices only */
+		ahci_port_ssts_t pxssts;
+		pxssts.u32 = port->pxssts;
+		if (pxssts.det != AHCI_PORT_SSTS_DET_ACTIVE)
+			continue;
+		
+		ahci_sata_create(ahci, dev, port, port_num);
+	}
+}
+
+/** Create AHCI device structure, intialize it and register interrupt routine.
+ *
+ * @param dev DDF device structure.
+ *
+ * @return AHCI device structure if succeed, NULL otherwise.
+ *
+ */
+static ahci_dev_t *ahci_ahci_create(ddf_dev_t *dev)
+{
+	ahci_dev_t *ahci = ddf_dev_data_alloc(dev, sizeof(ahci_dev_t));
+	if (!ahci)
+		return NULL;
+	
+	/* Connect to parent device */
+	ahci->parent_sess = ddf_dev_parent_sess_create(dev, EXCHANGE_SERIALIZE);
+	if (ahci->parent_sess == NULL)
+		return NULL;
+	
+	ahci->dev = dev;
+	
+	hw_res_list_parsed_t hw_res_parsed;
+	hw_res_list_parsed_init(&hw_res_parsed);
+	if (hw_res_get_list_parsed(ahci->parent_sess, &hw_res_parsed, 0) != EOK)
+		goto error_get_res_parsed;
+	
+	/* Map AHCI registers. */
+	ahci->memregs = NULL;
+	
+	physmem_map((void *) (size_t) (hw_res_parsed.mem_ranges.ranges[0].address),
+	    AHCI_MEMREGS_PAGES_COUNT, AS_AREA_READ | AS_AREA_WRITE,
+	    (void **) &ahci->memregs);
+	if (ahci->memregs == NULL)
+		goto error_map_registers;
+	
+	/* Register interrupt handler */
+	ahci_ranges[0].base = (size_t) hw_res_parsed.mem_ranges.ranges[0].address;
+	ahci_ranges[0].size = sizeof(ahci_memregs_t);
+	
+	for (unsigned int port = 0; port < AHCI_MAX_PORTS; port++) {
+		size_t base = port * 7;
+		
+		ahci_cmds[base].addr =
+		    ((uint32_t *) (size_t) hw_res_parsed.mem_ranges.ranges[0].address) +
+		    AHCI_PORTS_REGISTERS_OFFSET + port * AHCI_PORT_REGISTERS_SIZE +
+		    AHCI_PORT_IS_REGISTER_OFFSET;
+		ahci_cmds[base + 2].addr = ahci_cmds[base].addr;
+		
+		ahci_cmds[base + 3].addr =
+		    ((uint32_t *) (size_t) hw_res_parsed.mem_ranges.ranges[0].address) +
+		    AHCI_GHC_IS_REGISTER_OFFSET;
+		ahci_cmds[base + 4].addr = ahci_cmds[base + 3].addr;
+	}
+	
+	irq_code_t ct;
+	ct.cmdcount = sizeof(ahci_cmds) / sizeof(irq_cmd_t);
+	ct.cmds = ahci_cmds;
+	ct.rangecount = sizeof(ahci_ranges) / sizeof(irq_pio_range_t);
+	ct.ranges = ahci_ranges;
+	
+	int rc = register_interrupt_handler(dev, hw_res_parsed.irqs.irqs[0],
+	    ahci_interrupt, &ct);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed registering interrupt handler.");
+		goto error_register_interrupt_handler;
+	}
+	
+	rc = ahci_enable_interrupt(hw_res_parsed.irqs.irqs[0]);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed enable interupt.");
+		goto error_enable_interrupt;
+	}
+	
+	hw_res_list_parsed_clean(&hw_res_parsed);
+	return ahci;
+	
+error_enable_interrupt:
+	unregister_interrupt_handler(dev, hw_res_parsed.irqs.irqs[0]);
+	
+error_register_interrupt_handler:
+	// FIXME: unmap physical memory
+	
+error_map_registers:
+	hw_res_list_parsed_clean(&hw_res_parsed);
+	
+error_get_res_parsed:
+	free(ahci);
+	return NULL;
+}
+
+/** Initialize and start AHCI hardware device.
+ *
+ * @param ahci AHCI device.
+ *
+ */
+static void ahci_ahci_hw_start(ahci_dev_t *ahci)
+{
+	/* Disable command completion coalescing feature */
+	ahci_ghc_ccc_ctl_t ccc;
+	
+	ccc.u32 = ahci->memregs->ghc.ccc_ctl;
+	ccc.en = 0;
+	ahci->memregs->ghc.ccc_ctl = ccc.u32;
+	
+	/* Set master latency timer. */
+	pci_config_space_write_8(ahci->parent_sess, AHCI_PCI_MLT, 32);
+	
+	/* Enable PCI interrupt and bus mastering */
+	ahci_pcireg_cmd_t cmd;
+	
+	pci_config_space_read_16(ahci->parent_sess, AHCI_PCI_CMD, &cmd.u16);
+	cmd.id = 0;
+	cmd.bme = 1;
+	pci_config_space_write_16(ahci->parent_sess, AHCI_PCI_CMD, cmd.u16);
+	
+	/* Enable AHCI and interrupt. */
+	ahci->memregs->ghc.ghc = AHCI_GHC_GHC_AE | AHCI_GHC_GHC_IE;
+}
+
+/** AHCI device driver initialization
+ *
+ * Create and initialize all SATA structure devices for connected
+ * SATA drives.
+ *
+ * @param dev DDF device structure.
+ *
+ * @return EOK if succeed, error code otherwise.
+ *
+ */
+static int ahci_dev_add(ddf_dev_t *dev)	
+{
+	ahci_dev_t *ahci = ahci_ahci_create(dev);
+	if (ahci == NULL)
+		goto error;
+	
+	/* Start AHCI hardware. */
+	ahci_ahci_hw_start(ahci);
+	
+	/* Create device structures for sata devices attached to AHCI. */
+	ahci_sata_devices_create(ahci, dev);
+	
+	return EOK;
+	
+error:
+	return EINTR;
+}
+
+/*----------------------------------------------------------------------------*/
+/*-- Helpers and utilities ---------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Convert SATA model name
+ *
+ * Convert SATA model name from machine format returned by
+ * identify device command to human readable form.
+ *
+ * @param src Source buffer with device name in machine format.
+ * @param dst Buffer for human readable string, minimum size is 41 chars.
+ *
+ */
+static void ahci_get_model_name(uint16_t *src, char *dst)
+{
+	uint8_t model[40];
+	bzero(model, 40);
+	
+	for (unsigned int i = 0; i < 20; i++) {
+		uint16_t w = src[i];
+		model[2 * i] = w >> 8;
+		model[2 * i + 1] = w & 0x00ff;
+	}
+	
+	uint32_t len = 40;
+	while ((len > 0) && (model[len - 1] == 0x20))
+		len--;
+	
+	size_t pos = 0;
+	for (unsigned int i = 0; i < len; i++) {
+		uint8_t c = model[i];
+		if (c >= 0x80)
+			c = '?';
+		
+		chr_encode(c, dst, &pos, 40);
+	}
+	
+	dst[pos] = '\0';
+}
+
+/** Enable interrupt using SERVICE_IRC.
+ *
+ * @param irq Requested irq number.
+ *
+ * @return EOK if succeed, error code otherwise.
+ *
+ */
+static int ahci_enable_interrupt(int irq)
+{
+	async_sess_t *irc_sess = NULL;
+	irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_IRC, 0, 0);
+	if (!irc_sess)
+		return EINTR;
+	
+	async_exch_t *exch = async_exchange_begin(irc_sess);
+	const int rc = async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq);
+	async_exchange_end(exch);
+	
+	async_hangup(irc_sess);
+	return rc;
+}
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI Main routine -------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+	printf("%s: HelenOS AHCI device driver\n", NAME);
+	ddf_log_init(NAME);
+	fibril_mutex_initialize(&sata_devices_count_lock);
+	return ddf_driver_main(&ahci_driver);
+}
Index: uspace/drv/block/ahci/ahci.h
===================================================================
--- uspace/drv/block/ahci/ahci.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/block/ahci/ahci.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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.
+ */
+
+/** @file
+ * Header for AHCI driver.
+ */
+
+#ifndef __AHCI_H__
+#define __AHCI_H__
+
+#include <async.h>
+#include <sys/types.h>
+#include <devman.h>
+#include <ddf/interrupt.h>
+#include <stdio.h>
+#include "ahci_hw.h"
+
+/** AHCI Device. */
+typedef struct {
+	/** Pointer to ddf device. */
+	ddf_dev_t *dev;
+	
+	/** Pointer to AHCI memory registers. */
+	volatile ahci_memregs_t *memregs;
+	
+	/** Pointers to sata devices. */
+	void *sata_devs[AHCI_MAX_PORTS];
+
+	/** Parent session */
+	async_sess_t *parent_sess;
+} ahci_dev_t;
+
+/** SATA Device. */
+typedef struct {
+	/** Pointer to AHCI device. */
+	ahci_dev_t *ahci;
+	
+	/** Pointer to ddf function. */
+	ddf_fun_t *fun;
+	
+	/** SATA port number (0-31). */
+	uint8_t port_num;
+	
+	/** Device in invalid state (disconnected and so on). */
+	bool is_invalid_device;
+	
+	/** Pointer to SATA port. */
+	volatile ahci_port_t *port;
+	
+	/** Pointer to command header. */
+	volatile ahci_cmdhdr_t *cmd_header;
+	
+	/** Pointer to command table. */
+	volatile uint32_t *cmd_table;
+	
+	/** Mutex for single operation on device. */
+	fibril_mutex_t lock;
+	
+	/** Mutex for event signaling condition variable. */
+	fibril_mutex_t event_lock;
+	
+	/** Event signaling condition variable. */
+	fibril_condvar_t event_condvar;
+	
+	/** Event interrupt state. */
+	ahci_port_is_t event_pxis;
+	
+	/** Block device service id. */
+	service_id_t service_id;
+	
+	/** Number of device data blocks. */
+	uint64_t blocks;
+	
+	/** Size of device data blocks. */
+	size_t block_size;
+	
+	/** Name of SATA device. */
+	char model[STR_BOUNDS(40) + 1];
+	
+	/** Device in invalid state (disconnected and so on). */
+	bool is_packet_device;
+	
+	/** Highest UDMA mode supported. */
+	uint8_t highest_udma_mode;
+} sata_dev_t;
+
+#endif
Index: uspace/drv/block/ahci/ahci.ma
===================================================================
--- uspace/drv/block/ahci/ahci.ma	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/block/ahci/ahci.ma	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,3 @@
+10 pci/ven=8086&dev=2922
+10 pci/ven=8086&dev=2829
+10 pci/ven=1002&dev=4391
Index: uspace/drv/block/ahci/ahci_hw.h
===================================================================
--- uspace/drv/block/ahci/ahci_hw.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/block/ahci/ahci_hw.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1050 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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.
+ */
+
+/** @file
+ * Header for AHCI driver (AHCI 1.3 specification).
+ */
+
+#ifndef __AHCI_HW_H__
+#define __AHCI_HW_H__
+
+#include <sys/types.h>
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI standard constants -------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** AHCI standard 1.3 - maximum ports. */
+#define AHCI_MAX_PORTS  32
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI PCI Registers ------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** AHCI PCI register Identifiers offset. */
+#define AHCI_PCI_ID     0x00
+/** AHCI PCI register Command offset. */
+#define AHCI_PCI_CMD    0x04
+/** AHCI PCI register Device Status offset. */
+#define AHCI_PCI_STS    0x06
+/** AHCI PCI register Revision ID offset. */
+#define AHCI_PCI_RID    0x08
+/** AHCI PCI register Class Codes offset. */
+#define AHCI_PCI_CC     0x09
+/** AHCI PCI register Cache Line Size offset. */
+#define AHCI_PCI_CLS    0x0C
+/** AHCI PCI register Master Latency Timer offset. */
+#define AHCI_PCI_MLT    0x0D
+/** AHCI PCI register Header Type offset. */
+#define AHCI_PCI_HTYPE  0x0E
+/** AHCI PCI register Built In Self Test (Optional) offset. */
+#define AHCI_PCI_BIST   0x0F
+/** AHCI PCI register Other Base Address Registres (Optional). */
+#define AHCI_PCI_BAR0   0x10
+/** AHCI PCI register Other Base Address Registres (Optional). */
+#define AHCI_PCI_BAR1   0x14
+/** AHCI PCI register Other Base Address Registres (Optional). */
+#define AHCI_PCI_BAR2   0x18
+/** AHCI PCI register Other Base Address Registres (Optional). */
+#define AHCI_PCI_BAR3   0x1C
+/** AHCI PCI register Other Base Address Registres (Optional). */
+#define AHCI_PCI_BAR4   0x20
+/** AHCI PCI register AHCI Base Address offset. */
+#define AHCI_PCI_ABAR   0x24
+/** AHCI PCI register Subsystem Identifiers offset. */
+#define AHCI_PCI_SS     0x2C
+/** AHCI PCI register Expansion ROM Base Address (Optional) offset. */
+#define AHCI_PCI_EROM   0x30
+/** AHCI PCI register Capabilities Pointer offset. */
+#define AHCI_PCI_CAP    0x34
+/** AHCI PCI register Interrupt Information offset. */
+#define AHCI_PCI_INTR   0x3C
+/** AHCI PCI register Min Grant (Optional) offset. */
+#define AHCI_PCI_MGNT   0x3E
+/** AHCI PCI register Max Latency (Optional) offset. */
+#define AHCI_PCI_MLAT   0x3F
+
+/** AHCI PCI register Identifiers. */
+typedef struct {
+	/** Indicates the company vendor assigned by the PCI SIG. */
+	uint16_t vendorid;
+	/** Indicates what device number assigned by the vendor */
+	uint16_t deviceid;
+} ahci_pcireg_id_t;
+
+/** AHCI PCI register Command. */
+typedef union {
+	struct {
+		/** I/O Space Enable. */
+		unsigned int iose : 1;
+		/** Memory Space Enable. */
+		unsigned int mse : 1;
+		/** Bus Master Enable. */
+		unsigned int bme : 1;
+		/** Special Cycle Enable. */
+		unsigned int sce : 1;
+		/** Memory Write and Invalidate Enable. */
+		unsigned int mwie : 1;
+		/** VGA Palette Snooping Enable. */
+		unsigned int vga : 1;
+		/** Parity Error Response Enable. */
+		unsigned int pee : 1;
+		/** Wait Cycle Enable. */
+		unsigned int wcc : 1;
+		/** SERR# Enable. */
+		unsigned int see : 1;
+		/** Fast Back-to-Back Enable. */
+		unsigned int fbe : 1;
+		/** Interrupt Disable - disables the HBA from generating interrupts.
+		 * This bit does not have any effect on MSI operation.
+		 */
+		unsigned int id : 1;
+		/** Reserved. */
+		unsigned int reserved : 5;
+	};
+	uint16_t u16;
+} ahci_pcireg_cmd_t;
+
+/** AHCI PCI register Command - Interrupt Disable bit. */
+#define AHCI_PCIREG_CMD_ID  0x0400
+
+/** AHCI PCI register Command - Bus Master Enable bit. */
+#define AHCI_PCIREG_CMD_BME  0x0004
+
+/** AHCI PCI register Device status. */
+typedef union {
+	struct {
+		/** Reserved. */
+		unsigned int reserved1 : 3;
+		/** Indicate the interrupt status of the device (1 = asserted). */
+		unsigned int is : 1;
+		/** Indicates presence of capatibility list. */
+		unsigned int cl : 1;
+		/** 66 Mhz capable. */
+		unsigned int c66 : 1;
+		/** Reserved. */
+		unsigned int reserved2 : 1;
+		/** Fast back to back capable. */
+		unsigned int fbc : 1;
+		/** Master data parity error detected. */
+		unsigned int dpd : 1;
+		/** Device select timing. */
+		unsigned int devt : 2;
+		/** Signaled target abort. */
+		unsigned int sta : 1;
+		/** Received target abort. */
+		unsigned int rta : 1;
+		/** Received master abort. */
+		unsigned int rma : 1;
+		/** Signaled system error. */
+		unsigned int sse : 1;
+		/** Detected parity error. */
+		unsigned int dpe : 1;
+	};
+	uint16_t u16;
+} ahci_pcireg_sts_t;
+
+/** AHCI PCI register Revision ID. */
+typedef struct {
+	/** Indicates stepping of the HBA hardware. */
+	uint8_t u8;
+} ahci_pcireg_rid_t;
+
+/** AHCI PCI register Class Codes. */
+typedef struct {
+	/** Programing interface, when set to 01h and the scc is set to 06h,
+	 * indicates that this an AHCI HBA major revision 1.
+	 */
+	uint8_t pi;
+	/** When set to 06h, indicates that is a SATA device. */
+	uint8_t scc;
+	/** Value 01 indicates that is a mass storage device. */
+	uint8_t bcc;
+} ahci_pcireg_cc_t_t;
+
+/** AHCI PCI register Cache Line Size. */
+typedef struct {
+	/** Cache line size for use with the memory write and invalidate command. */
+	uint8_t u8;
+} ahci_pcireg_cls_t;
+
+/** AHCI PCI register Master Latency Timer. */
+typedef struct {
+	/** Master latency timer,indicates the number of clocks the HBA is allowed
+	 * to acts as master on PCI.
+	 */
+	uint8_t u8;
+} ahci_pcireg_mlt_t;
+
+/** AHCI PCI register Header Type. */
+typedef union {
+	struct {
+		/** Header layout. */
+		unsigned int hl : 7;
+		/** Multi function device flag. */
+		unsigned int mfd : 1;
+	};
+	uint8_t u8;
+} ahci_pciregs_htype_t;
+
+/** AHCI PCI register Built in self test. */
+typedef union {
+	struct {
+	/** Indicates the completion status of BIST
+	 * non-zero value indicates a failure.
+	 */
+	unsigned int cc : 4;
+	/** Reserved. */
+	unsigned int reserved : 2;
+	/** Software sets this bit to 1 to invoke BIST,
+	 * the HBA clears this bit to 0 when BIST is complete.
+	 */
+	unsigned int sb : 1;
+	/** BIST capable. */
+	unsigned int bc : 1;
+	};
+	uint8_t u8;
+} ahci_pciregs_bist_t;
+
+/** AHCI PCI register AHCI Base Address <BAR 5>. */
+typedef union {
+	struct {
+		/** Indicates a request for register memory space. */
+		unsigned int rte : 1;
+		/** Indicates the this range can be mapped anywhere in 32-bit address
+		 * space.
+		 */
+		unsigned int tp : 2;
+		/** Indicate that this range is not prefetchable. */
+		unsigned int pf : 1;
+		/** Reserved. */
+		unsigned int reserved : 9;
+		/** Base address of registry memory space. */
+		unsigned int ba : 19;
+	};
+	uint32_t u32;
+} ahci_pciregs_abar_t;
+
+/** AHCI PCI register Subsystem Identifiers. */
+typedef struct
+{
+	/** Sub system vendor identifier. */
+	uint8_t ssvid;
+	/** Sub system identifier. */
+	uint8_t ssid;
+} ahci_pcireg_ss_t;
+
+/** AHCI PCI registers Expansion ROM Base Address. */
+typedef struct
+{
+	/** Indicates the base address of the HBA expansion ROM. */
+	uint32_t u32;
+} ahci_pcireg_erom_t;
+
+/** AHCI PCI register Capabilities Pointer. */
+typedef struct
+{
+	/** Indicates the first capability pointer offset. */
+	uint8_t u8;
+} ahci_pcireg_cap_t;
+
+/** AHCI PCI register Interrupt Information. */
+typedef struct
+{
+	/* Software written value to indicate which interrupt vector
+	 * the interrupt is connected to.
+	 */
+	uint8_t iline;
+	/** This indicates the interrupt pin the HBA uses. */
+	uint8_t ipin;
+} ahci_pcireg_intr;
+
+/** AHCI PCI register Min Grant (Optional). */
+typedef struct
+{
+	/** Indicates the minimum grant time that the device
+	 * wishes grant asserted.
+	 */
+	uint8_t u8;
+} ahci_pcireg_mgnt_t;
+
+/** AHCI PCI register Max Latency (Optional). */
+typedef struct
+{
+	/** Indicates the maximum latency that the device can withstand. */
+	uint8_t u8;
+} ahci_pcireg_mlat_t;
+
+/*----------------------------------------------------------------------------*/
+/*-- AHCI Memory Registers ---------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Number of pages for ahci memory registers. */
+#define AHCI_MEMREGS_PAGES_COUNT  8
+
+/** AHCI Memory register Generic Host Control - HBA Capabilities. */
+typedef union {
+	struct {
+		/** Number of Ports. */
+		unsigned int np : 5;
+		/** Supports External SATA. */
+		unsigned int sxs : 1;
+		/** Enclosure Management Supported. */
+		unsigned int ems : 1;
+		/** Command Completion Coalescing Supported. */
+		unsigned int cccs : 1;
+		/** Number of Command Slots. */
+		unsigned int ncs : 5;
+		/** Partial State Capable. */
+		unsigned int psc : 1;
+		/** Slumber State Capable. */
+		unsigned int ssc : 1;
+		/** PIO Multiple DRQ Block. */
+		unsigned int pmd : 1;
+		/** FIS-based Switching Supported. */
+		unsigned int fbss : 1;
+		/** Supports Port Multiplier. */
+		unsigned int spm : 1;
+		/** Supports AHCI mode only. */
+		unsigned int sam : 1;
+		/** Reserved. */
+		unsigned int reserved : 1;
+		/** Interface Speed Support. */
+		unsigned int iss : 4;
+		/** Supports Command List Override. */
+		unsigned int sclo : 1;
+		/** Supports Activity LED. */
+		unsigned int sal : 1;
+		/** Supports Aggressive Link Power Management. */
+		unsigned int salp : 1;
+		/** Supports Staggered Spin-up. */
+		unsigned int sss : 1;
+		/** Supports Mechanical Presence Switch. */
+		unsigned int smps : 1;
+		/** Supports SNotification Register. */
+		unsigned int ssntf : 1;
+		/** Supports Native Command Queuing. */
+		unsigned int sncq : 1;
+		/** Supports 64-bit Addressing. */
+		unsigned int s64a : 1;
+	};
+	uint32_t u32;
+} ahci_ghc_cap_t;
+
+/** AHCI Memory register Generic Host Control Global Host Control. */
+typedef union {
+	struct {
+		/** HBA Reset. */
+		unsigned int hr : 1;
+		/** Interrupt Enable. */
+		unsigned int ie : 1;
+		/** MSI Revert to Single Message. */
+		unsigned int mrsm : 1;
+		/** Reserved. */
+		unsigned int reserved : 28;
+		/** AHCI Enable. */
+		unsigned int ae : 1;
+	};
+	uint32_t u32;
+} ahci_ghc_ghc_t;
+
+/** AHCI Enable mask bit. */
+#define AHCI_GHC_GHC_AE  0x80000000
+
+/** AHCI Interrupt Enable mask bit. */
+#define AHCI_GHC_GHC_IE  0x00000002
+
+/** AHCI Memory register Interrupt pending register. */
+typedef uint32_t ahci_ghc_is_t;
+
+/** AHCI GHC register offset. */
+#define AHCI_GHC_IS_REGISTER_OFFSET  2
+
+/** AHCI ports registers offset. */
+#define AHCI_PORTS_REGISTERS_OFFSET  64
+
+/** AHCI port registers size. */
+#define AHCI_PORT_REGISTERS_SIZE  32
+
+/** AHCI port IS register offset. */
+#define AHCI_PORT_IS_REGISTER_OFFSET  4
+
+/** AHCI Memory register Ports implemented. */
+typedef struct {
+	/** If a bit is set to 1, the corresponding port
+	 * is available for software use.
+	 */
+	uint32_t u32;
+} ahci_ghc_pi_t;
+
+/** AHCI Memory register AHCI version. */
+typedef struct {
+	/** Indicates the minor version */
+	uint16_t mnr;
+	/** Indicates the major version */
+	uint16_t mjr;
+} ahci_ghc_vs_t;
+
+/** AHCI Memory register Command completion coalesce control. */
+typedef union {
+	struct {
+		/** Enable CCC features. */
+		unsigned int en : 1;
+		/** Reserved. */
+		unsigned int reserved : 2;
+		/** Interrupt number for CCC. */
+		unsigned int intr : 5;
+		/** Number of command completions that are necessary to cause
+		 * a CCC interrupt.
+		 */
+		uint8_t cc;
+		/** Timeout value in  ms. */
+		uint16_t tv;
+	};
+	uint32_t u32;
+} ahci_ghc_ccc_ctl_t;
+
+/** AHCI Memory register Command completion coalescing ports. */
+typedef struct
+{
+	/** If a bit is set to 1, the corresponding port is
+	 * part of the command completion coalescing feature.
+	 */
+	uint32_t u32;
+} ahci_ghc_ccc_ports_t;
+
+/** AHCI Memory register Enclosure management location. */
+typedef struct
+{
+	/** Size of the transmit message buffer area in dwords. */
+	uint16_t sz;
+	/*
+	 * Offset of the transmit message buffer area in dwords
+	 * from the beginning of ABAR
+	 */
+	uint16_t ofst;
+} ahci_ghc_em_loc;
+
+/** AHCI Memory register Enclosure management control. */
+typedef union {
+	struct {
+		/** Message received. */
+		unsigned int mr : 1;
+		/** Reserved. */
+		unsigned int reserved : 7;
+		/** Transmit message. */
+		unsigned int tm : 1;
+		/** Reset. */
+		unsigned int rst : 1;
+		/** Reserved. */
+		unsigned int reserved2 : 6;
+		/** LED message types. */
+		unsigned int led : 1;
+		/** Support SAFT-TE message type. */
+		unsigned int safte : 1;
+		/** Support SES-2 message type. */
+		unsigned int ses2 : 1;
+		/** Support SGPIO register. */
+		unsigned int sgpio : 1;
+		/** Reserved. */
+		unsigned int reserved3 : 4;
+		/** Single message buffer. */
+		unsigned int smb : 1;
+		/**  Support transmitting only. */
+		unsigned int xmt : 1;
+		/** Activity LED hardware driven. */
+		unsigned int alhd : 1;
+		/** Port multiplier support. */
+		unsigned int pm : 1;
+		/** Reserved. */
+		unsigned int reserved4 : 4;
+	};
+	uint32_t u32;
+} ahci_ghc_em_ctl_t;
+
+/** AHCI Memory register HBA capatibilities extended. */
+typedef union {
+	struct {
+		/** HBA support BIOS/OS handoff mechanism,
+		 * implemented BOHC register.
+		 */
+		unsigned int boh : 1;
+		/** Support for NVMHCI register. */
+		unsigned int nvmp : 1;
+		/** Automatic partial to slumber transition support. */
+		unsigned int apst : 1;
+		/** Reserved. */
+		unsigned int reserved : 29;
+	};
+	uint32_t u32;
+} ahci_ghc_cap2_t;
+
+/** AHCI Memory register BIOS/OS Handoff control and status. */
+typedef union {
+	struct {
+		/** BIOS Owned semaphore. */
+		unsigned int bos : 1;
+		/** OS Owned semaphore. */
+		unsigned int oos : 1;
+		/** SMI on OS ownership change enable. */
+		unsigned int sooe : 1;
+		/** OS ownership change. */
+		unsigned int ooc : 1;
+		/** BIOS Busy. */
+		unsigned int bb : 1;
+		/** Reserved. */
+		unsigned int reserved : 27;
+	};
+	uint32_t u32;
+} ahci_ghc_bohc_t;
+
+/** AHCI Memory register Generic Host Control. */
+typedef struct
+{
+	/** Host Capabilities */
+	uint32_t cap;
+	/** Global Host Control */
+	uint32_t ghc;
+	/** Interrupt Status */
+	ahci_ghc_is_t is;
+	/** Ports Implemented */
+	uint32_t pi;
+	/** Version */
+	uint32_t vs;
+	/** Command Completion Coalescing Control */
+	uint32_t ccc_ctl;
+	/** Command Completion Coalescing Ports */
+	uint32_t ccc_ports;
+	/** Enclosure Management Location */
+	uint32_t em_loc;
+	/** Enclosure Management Control */
+	uint32_t em_ctl;
+	/** Host Capabilities Extended */
+	uint32_t cap2;
+	/** BIOS/OS Handoff Control and Status */
+	uint32_t bohc;
+} ahci_ghc_t;
+
+/** AHCI Memory register Port x Command List Base Address. */
+typedef union {
+	struct {
+		/** Reserved. */
+		unsigned int reserved : 10;
+		/** Command List Base Address (CLB) - Indicates the 32-bit base physical
+		 * address for the command list for this port. This base is used when
+		 * fetching commands to execute. The structure pointed to by this
+		 * address range is 1K-bytes in length. This address must be 1K-byte
+		 * aligned as indicated by bits 09:00 being read only.
+		 */
+		unsigned int clb : 22;
+	};
+	uint32_t u32;
+} ahci_port_clb_t;
+
+/** AHCI Memory register Port x Command List Base Address Upper 32-Bits. */
+typedef struct {
+	/** Command List Base Address Upper (CLBU): Indicates the upper 32-bits
+	 * for the command list base physical address for this port. This base
+	 * is used when fetching commands to execute. This register shall
+	 * be read only for HBAs that do not support 64-bit addressing.
+	 */
+	uint32_t u32;
+} ahci_port_clbu_t;
+
+/** AHCI Memory register Port x FIS Base Address. */
+typedef union {
+	struct {
+		/** Reserved. */
+		unsigned int reserved : 8;
+		/** FIS Base Address (FB) - Indicates the 32-bit base physical address
+		 * for received FISes. The structure pointed to by this address range
+		 * is 256 bytes in length. This address must be 256-byte aligned as
+		 * indicated by bits 07:00 being read only. When FIS-based switching
+		 * is in use, this structure is 4KB in length and the address shall be
+		 * 4KB aligned.
+		 */
+		unsigned int fb : 24;
+	};
+	uint32_t u32;
+} ahci_port_fb_t;
+
+/** AHCI Memory register Port x FIS Base Address Upper 32-Bits. */
+typedef struct {
+	/** FIS Base Address Upper (FBU) - Indicates the upper 32-bits
+	 * for the received FIS base physical address for this port. This register
+	 * shall be read only for HBAs that do not support 64-bit addressing.
+	 */
+	uint32_t u32;
+} ahci_port_fbu_t;
+
+/** AHCI Memory register Port x Interrupt Status. */
+typedef uint32_t ahci_port_is_t;
+
+#define AHCI_PORT_IS_DHRS  (1 << 0)
+#define AHCI_PORT_IS_PSS   (1 << 1)
+#define AHCI_PORT_IS_DSS   (1 << 2)
+#define AHCI_PORT_IS_SDBS  (1 << 3)
+#define AHCI_PORT_IS_UFS   (1 << 4)
+#define AHCI_PORT_IS_DPS   (1 << 5)
+#define AHCI_PORT_IS_PCS   (1 << 6)
+#define AHCI_PORT_IS_DMPS  (1 << 7)
+
+#define AHCI_PORT_IS_PRCS  (1 << 22)
+#define AHCI_PORT_IS_IPMS  (1 << 23)
+#define AHCI_PORT_IS_OFS   (1 << 24)
+#define AHCI_PORT_IS_INFS  (1 << 26)
+#define AHCI_PORT_IS_IFS   (1 << 27)
+#define AHCI_PORT_IS_HDBS  (1 << 28)
+#define AHCI_PORT_IS_HBFS  (1 << 29)
+#define AHCI_PORT_IS_TFES  (1 << 30)
+#define AHCI_PORT_IS_CPDS  (1 << 31)
+
+#define AHCI_PORT_END_OF_OPERATION \
+	(AHCI_PORT_IS_DHRS | \
+	AHCI_PORT_IS_SDBS )
+
+#define AHCI_PORT_IS_ERROR \
+	(AHCI_PORT_IS_UFS | \
+	AHCI_PORT_IS_PCS | \
+	AHCI_PORT_IS_DMPS | \
+	AHCI_PORT_IS_PRCS | \
+	AHCI_PORT_IS_IPMS | \
+	AHCI_PORT_IS_OFS | \
+	AHCI_PORT_IS_INFS | \
+	AHCI_PORT_IS_IFS | \
+	AHCI_PORT_IS_HDBS | \
+	AHCI_PORT_IS_HBFS | \
+	AHCI_PORT_IS_TFES | \
+	AHCI_PORT_IS_CPDS)
+
+#define AHCI_PORT_IS_PERMANENT_ERROR \
+	(AHCI_PORT_IS_PCS | \
+	AHCI_PORT_IS_DMPS | \
+	AHCI_PORT_IS_PRCS | \
+	AHCI_PORT_IS_IPMS | \
+	AHCI_PORT_IS_CPDS )
+
+/** Evaluate end of operation status from port interrupt status.
+ *
+ * @param port_is Value of port interrupt status.
+ *
+ * @return Indicate end of operation status.
+ *
+ */
+static inline int ahci_port_is_end_of_operation(ahci_port_is_t port_is)
+{
+	return port_is & AHCI_PORT_END_OF_OPERATION;
+}
+
+/** Evaluate error status from port interrupt status.
+ *
+ * @param port_is Value of port interrupt status.
+ *
+ * @return Indicate error status.
+ *
+ */
+static inline int ahci_port_is_error(ahci_port_is_t port_is)
+{
+	return port_is & AHCI_PORT_IS_ERROR;
+}
+
+/** Evaluate permanent error status from port interrupt status.
+ *
+ * @param port_is Value of port interrupt status.
+ *
+ * @return Indicate permanent error status.
+ *
+ */
+static inline int ahci_port_is_permanent_error(ahci_port_is_t port_is)
+{
+	return port_is & AHCI_PORT_IS_PERMANENT_ERROR;
+}
+
+/** Evaluate task file error status from port interrupt status.
+ *
+ * @param port_is Value of port interrupt status.
+ *
+ * @return Indicate error status.
+ *
+ */
+static inline int ahci_port_is_tfes(ahci_port_is_t port_is)
+{
+	return port_is & AHCI_PORT_IS_TFES;
+}
+
+/** AHCI Memory register Port x Interrupt Enable. */
+typedef union {
+	struct {
+		/** Device to Host Register FIS Interrupt Enable. */
+		unsigned int dhre : 1;
+		/** PIO Setup FIS Interrupt Enable. */
+		unsigned int pse : 1;
+		/** DMA Setup FIS Interrupt Enable. */
+		unsigned int dse : 1;
+		/** Set Device Bits Interrupt Eenable. */
+		unsigned int sdbe : 1;
+		/** Unknown FIS Interrupt Enable. */
+		unsigned int ufe : 1;
+		/** Descriptor Processed Interrupt Enable. */
+		unsigned int dpe : 1;
+		/** Port Change Interrupt Enable. */
+		unsigned int pce : 1;
+		/** Device Mechanical Presence Enable. */
+		unsigned int dmpe : 1;
+		/** Reserved. */
+		unsigned int reserved1 : 14;
+		/** PhyRdy Change Interrupt Enable. */
+		unsigned int prce : 1;
+		/** Incorrect Port Multiplier Enable. */
+		unsigned int ipme : 1;
+		/** Overflow Status Enable. */
+		unsigned int ofe : 1;
+		/** Reserved. */
+		unsigned int reserved2 : 1;
+		/** Interface Non-fatal Error Enable. */
+		unsigned int infe : 1;
+		/** Interface Fatal Error Enable. */
+		unsigned int ife : 1;
+		/** Host Bus Data Error Enable. */
+		unsigned int hbde : 1;
+		/** Host Bus Fatal Error Enable. */
+		unsigned int hbfe : 1;
+		/** Task File Error Enable. */
+		unsigned int tfee : 1;
+		/** Cold Port Detect Enable. */
+		unsigned int cpde : 1;
+	};
+	uint32_t u32;
+} ahci_port_ie_t;
+
+/** AHCI Memory register Port x Command and Status. */
+typedef union {
+	struct {
+		/** Start - when set, the HBA may process the command list. */
+		unsigned int st : 1;
+		/** Spin-Up Device. */
+		unsigned int sud : 1;
+		/** Power On Device. */
+		unsigned int pod : 1;
+		/** Command List Override. */
+		unsigned int clo : 1;
+		/** FIS Receive Enable. */
+		unsigned int fre : 1;
+		/** Reserved. */
+		unsigned int reserved : 3;
+		/** Current Command Slot. */
+		unsigned int ccs : 5;
+		/** Mechanical Presence Switch State. */
+		unsigned int mpss : 1;
+		/** FIS Receive Running. */
+		unsigned int fr : 1;
+		/** Command List Running. */
+		unsigned int cr : 1;
+		/** Cold Presence State. */
+		unsigned int cps : 1;
+		/** Port Multiplier Attached. */
+		unsigned int pma : 1;
+		/** Hot Plug Capable Port. */
+		unsigned int hpcp : 1;
+		/** Mechanical Presence Switch Attached to Port. */
+		unsigned int mpsp : 1;
+		/** Cold Presence Detection. */
+		unsigned int cpd : 1;
+		/** External SATA Port. */
+		unsigned int esp : 1;
+		/** FIS-based Switching Capable Port. */
+		unsigned int fbscp : 1;
+		/** Automatic Partial to Slumber Transitions Enabled. */
+		unsigned int apste : 1;
+		/** Device is ATAPI. */
+		unsigned int atapi : 1;
+		/** Drive LED on ATAPI Enable. */
+		unsigned int dlae : 1;
+		/** Aggressive Link Power Management Enable. */
+		unsigned int alpe : 1;
+		/** Aggressive Slumber / Partial. */
+		unsigned int asp : 1;
+		/** Interface Communication Control.
+		 * Values:
+		 * 7h - fh Reserved,
+		 * 6h Slumber - This shall cause the HBA to request a transition
+		 * of the interface to the Slumber state,
+		 * 3h - 5h Reserved,
+		 * 2h Partial - This shall cause the HBA to request a transition
+		 * of the interface to the Partial state,
+		 * 1h Active,
+		 * 0h No-Op / Idle.
+		 */
+		unsigned int icc : 4;
+	};
+	uint32_t u32;
+} ahci_port_cmd_t;
+
+/** AHCI Memory register Port x Task File Data. */
+typedef union {
+	struct {
+		/** Status (STS): Contains the latest copy of the task file
+		 * status register.
+		 */
+		uint8_t sts;
+		/** Error (ERR) - Contains the latest copy of the task file
+		 * error register.
+		 */
+		uint8_t err;
+		/** Reserved. */
+		uint16_t reserved;
+	};
+	uint32_t u32;
+} ahci_port_tfd_t;
+
+/** AHCI Memory register Port x Signature. */
+typedef union {
+	struct {
+		/** Sector Count Register */
+		uint8_t sector_count;
+		/** LBA Low Register */
+		uint8_t lba_lr;
+		/** LBA Mid Register */
+		uint8_t lba_mr;
+		/** LBA High Register */
+		uint8_t lba_hr;
+	};
+	uint32_t u32;
+} ahci_port_sig_t;
+
+/** AHCI Memory register Port x Serial ATA Status (SCR0: SStatus). */
+typedef union {
+	struct {
+		/** Device Detection */
+		unsigned int det : 4;
+		/** Current Interface Speed */
+		unsigned int spd : 4;
+		/** Interface Power Management */
+		unsigned int ipm : 4;
+		/** Reserved. */
+		unsigned int reserved : 20;
+	};
+	uint32_t u32;
+} ahci_port_ssts_t;
+
+/** Device detection active status. */
+#define AHCI_PORT_SSTS_DET_ACTIVE  3
+
+/** AHCI Memory register Port x Serial ATA Control (SCR2: SControl). */
+typedef union {
+	struct {
+		/** Device Detection Initialization */
+		unsigned int det : 4;
+		/** Speed Allowed */
+		unsigned int spd : 4;
+		/** Interface Power Management Transitions Allowed */
+		unsigned int ipm : 4;
+		/** Reserved. */
+		unsigned int reserved : 20;
+	};
+	uint32_t u32;
+} ahci_port_sctl_t;
+
+/** AHCI Memory register Port x Port x Serial ATA Error (SCR1: SError). */
+typedef struct {
+	/** Error (ERR) - The ERR field contains error information for use
+	 * by host software in determining the appropriate response to the
+	 * error condition.
+	 */
+	uint16_t err;
+	/** Diagnostics (DIAG) - Contains diagnostic error information for use
+	 * by diagnostic software in validating correct operation or isolating
+	 * failure modes.
+	 */
+	uint16_t diag;
+} ahci_port_serr_t;
+
+/** AHCI Memory register Port x Serial ATA Active (SCR3: SActive). */
+typedef struct {
+	/** Device Status - Each bit corresponds to the TAG and
+	 * command slot of a native queued command, where bit 0 corresponds
+	 * to TAG 0 and command slot 0.
+	 */
+	uint32_t u32;
+} ahci_port_sact_t;
+
+/** AHCI Memory register Port x Command Issue. */
+typedef struct {
+	/** Commands Issued - Each bit corresponds to a command slot,
+	 *  where bit 0 corresponds to command slot 0.
+	 */
+	uint32_t u32;
+} ahci_port_ci_t;
+
+/** AHCI Memory register Port x Serial ATA Notification
+ * (SCR4: SNotification).
+ */
+typedef struct {
+	/** PM Notify (PMN): This field indicates whether a particular device with
+	 * the corresponding PM Port number issued a Set Device Bits FIS
+	 * to the host with the Notification bit set.
+	 */
+	uint16_t pmn;
+	/** Reserved. */
+	uint16_t reserved;
+} ahci_port_sntf_t;
+
+/** AHCI Memory register Port x FIS-based Switching Control.
+ * This register is used to control and obtain status
+ * for Port Multiplier FIS-based switching.
+ */
+typedef union {
+	struct {
+		/** Enable */
+		unsigned int en : 1;
+		/** Device Error Clear */
+		unsigned int dec : 1;
+		/** Single Device Error */
+		unsigned int sde : 1;
+		/** Reserved. */
+		unsigned int reserved1 : 5;
+		/** Device To Issue */
+		unsigned int dev : 1;
+		/** Active Device Optimization */
+		unsigned int ado : 1;
+		/** Device With Error */
+		unsigned int dwe : 1;
+		/** Reserved. */
+		unsigned int reserved2 : 1;
+	};
+	uint32_t u32;
+} ahci_port_fbs_t;
+
+/** AHCI Memory register Port. */
+typedef volatile struct
+{
+	/** Port x Command List Base Address. */
+	uint32_t pxclb;
+	/** Port x Command List Base Address Upper 32-Bits. */
+	uint32_t pxclbu;
+	/** Port x FIS Base Address. */
+	uint32_t pxfb;
+	/** Port x FIS Base Address Upper 32-Bits. */
+	uint32_t pxfbu;
+	/** Port x Interrupt Status. */
+	ahci_port_is_t pxis;
+	/** Port x Interrupt Enable. */
+	uint32_t pxie;
+	/** Port x Command and Status. */
+	uint32_t pxcmd;
+	/** Reserved. */
+	uint32_t reserved1;
+	/** Port x Task File Data. */
+	uint32_t pxtfd;
+	/**  Port x Signature. */
+	uint32_t pxsig;
+	/** Port x Serial ATA Status (SCR0: SStatus). */
+	uint32_t pxssts;
+	/** Port x Serial ATA Control (SCR2: SControl). */
+	uint32_t pxsctl;
+	/** Port x Serial ATA Error (SCR1: SError). */
+	uint32_t pxserr;
+	/** Port x Serial ATA Active (SCR3: SActive). */
+	uint32_t pxsact;
+	/** Port x Command Issue. */
+	uint32_t pxci;
+	/** Port x Serial ATA Notification (SCR4: SNotification). */
+	uint32_t pxsntf;
+	/** Port x FIS-based Switching Control. */
+	uint32_t pxfbs;
+	/** Reserved. */
+	uint32_t reserved2[11];
+	/** Port x Vendor Specific. */
+	uint32_t pxvs[4];
+} ahci_port_t;
+
+/** AHCI Memory Registers. */
+typedef volatile struct {
+	/** Generic Host Control. */
+	ahci_ghc_t ghc;
+	/** Reserved. */
+	uint32_t reserved[13];
+	/** Reserved for NVMHCI. */
+	uint32_t reservedfornvmhci[16];
+	/** Vendor Specific registers. */
+	uint32_t vendorspecificsregs[24];
+	/** Ports. */
+	ahci_port_t ports[AHCI_MAX_PORTS];
+} ahci_memregs_t;
+
+/** AHCI Command header entry.
+ *
+ * This structure is not an AHCI register.
+ *
+ */
+typedef volatile struct {
+	/** Flags. */
+	uint16_t flags;
+	/** Physical Region Descriptor Table Length. */
+	uint16_t prdtl;
+	/** Physical Region Descriptor Byte Count. */
+	uint32_t bytesprocessed;
+	 /** Command Table Descriptor Base Address. */
+	uint32_t cmdtable;
+	/** Command Table Descriptor Base Address Upper 32-bits. */
+	uint32_t cmdtableu;
+} ahci_cmdhdr_t;
+
+/** Clear Busy upon R_OK (C) flag. */
+#define AHCI_CMDHDR_FLAGS_CLEAR_BUSY_UPON_OK  0x0400
+
+/** Write operation flag. */
+#define AHCI_CMDHDR_FLAGS_WRITE  0x0040
+
+/** 2 DW length command flag. */
+#define AHCI_CMDHDR_FLAGS_2DWCMD  0x0002
+
+/** 5 DW length command flag. */
+#define AHCI_CMDHDR_FLAGS_5DWCMD  0x0005
+
+/** AHCI Command Physical Region Descriptor entry.
+ *
+ * This structure is not an AHCI register.
+ *
+ */
+typedef volatile struct {
+	/** Word aligned 32-bit data base address. */
+	uint32_t data_address_low;
+	/** Upper data base address, valid only for 64-bit HBA addressing. */
+	uint32_t data_address_upper;
+	/** Reserved. */
+	uint32_t reserved1;
+	/** Data byte count */
+	unsigned int dbc : 22;
+	/** Reserved */
+	unsigned int reserved2 : 9;
+	/** Set Interrupt on each operation completion */
+	unsigned int ioc : 1;
+} ahci_cmd_prdt_t;
+
+#endif
Index: uspace/drv/block/ahci/ahci_sata.h
===================================================================
--- uspace/drv/block/ahci/ahci_sata.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/block/ahci/ahci_sata.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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.
+ */
+
+/** @file
+ * Header for AHCI driver (SATA/ATA and related things).
+ */
+
+#ifndef __AHCI_SATA_H__
+#define __AHCI_SATA_H__
+
+#include <sys/types.h>
+
+/*----------------------------------------------------------------------------*/
+/*-- SATA Buffer Lengths -----------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Default sector size in bytes. */
+#define SATA_DEFAULT_SECTOR_SIZE  512
+
+/** Size for set feature command buffer in bytes. */
+#define SATA_SET_FEATURE_BUFFER_LENGTH  512
+
+/** Size for indentify (packet) device buffer in bytes. */
+#define SATA_IDENTIFY_DEVICE_BUFFER_LENGTH  512
+
+/*----------------------------------------------------------------------------*/
+/*-- SATA Fis Frames ---------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Sata FIS Type number. */
+#define SATA_CMD_FIS_TYPE  0x27
+
+/** Sata FIS Type command indicator. */
+#define SATA_CMD_FIS_COMMAND_INDICATOR  0x80
+
+/** Standard Command frame. */
+typedef struct {
+	/** FIS type - always SATA_CMD_FIS_TYPE. */
+	unsigned int fis_type : 8;
+	/** Indicate that FIS is a Command - always SATA_CMD_FIS_COMMAND_INDICATOR. */
+	unsigned int c : 8;
+	/** Command - Identity device - 0xec, Set fetures - 0xef. */
+	unsigned int command : 8;
+	/** Features - subcommand for set features - set tranfer mode - 0x03. */
+	unsigned int features : 8;
+	/** 0:23 bits of LBA. */
+	unsigned int lba_lower : 24;
+	/** Device. */
+	unsigned int device : 8;
+	/** 24:47 bits of LBA. */
+	unsigned int lba_upper : 24;
+	/** Features - subcommand for set features - set tranfer mode - 0x03. */
+	unsigned int features_upper : 8;
+	/** Sector count - transfer mode for set transfer mode operation. */
+	unsigned int count : 16;
+	/** Reserved. */
+	unsigned int reserved1 : 8;
+	/** Control. */
+	unsigned int control : 8;
+	/** Reserved. */
+	unsigned int reserved2 : 32;
+} sata_std_command_frame_t;
+
+/** Command frame for NCQ data operation. */
+typedef struct {
+	/** FIS type - always 0x27. */
+	uint8_t fis_type;
+	/** Indicate that FIS is a Command - always SATA_CMD_FIS_COMMAND_INDICATOR. */
+	uint8_t c;
+	/** Command - FPDMA Read - 0x60, FPDMA Write - 0x61. */
+	uint8_t command;
+	/** bits 7:0 of sector count. */
+	uint8_t sector_count_low;
+	/** bits 7:0 of lba. */
+	uint8_t lba0;
+	/** bits 15:8 of lba. */
+	uint8_t lba1;
+	/** bits 23:16 of lba. */
+	uint8_t lba2;
+	uint8_t fua;
+	/** bits 31:24 of lba. */
+	uint8_t lba3;
+	/** bits 39:32 of lba. */
+	uint8_t lba4;
+	/** bits 47:40 of lba. */
+	uint8_t lba5;
+	/** bits 15:8 of sector count. */
+	uint8_t sector_count_high;
+	/** Tag number of NCQ operation. */
+	uint8_t tag;
+	/** Reserved. */
+	uint8_t reserved1;
+	/** Reserved. */
+	uint8_t reserved2;
+	/** Control. */
+	uint8_t control;
+	/** Reserved. */
+	uint8_t reserved3;
+	/** Reserved. */
+	uint8_t reserved4;
+	/** Reserved. */
+	uint8_t reserved5;
+	/** Reserved. */
+	uint8_t reserved6;
+} sata_ncq_command_frame_t;
+
+/*----------------------------------------------------------------------------*/
+/*-- SATA Identify device ----------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+
+/** Data returned from identify device and identify packet device command. */
+typedef struct {
+	uint16_t gen_conf;
+	uint16_t cylinders;
+	uint16_t reserved2;
+	uint16_t heads;
+	uint16_t _vs4;
+	uint16_t _vs5;
+	uint16_t sectors;
+	uint16_t _vs7;
+	uint16_t _vs8;
+	uint16_t _vs9;
+	
+	uint16_t serial_number[10];
+	uint16_t _vs20;
+	uint16_t _vs21;
+	uint16_t vs_bytes;
+	uint16_t firmware_rev[4];
+	uint16_t model_name[20];
+	
+	uint16_t max_rw_multiple;
+	uint16_t reserved48;
+	/* Different meaning for packet device. */
+	uint16_t caps;
+	uint16_t reserved50;
+	uint16_t pio_timing;
+	uint16_t dma_timing;
+	
+	uint16_t validity;
+	uint16_t cur_cyl;
+	uint16_t cur_heads;
+	uint16_t cur_sectors;
+	uint16_t cur_capacity0;
+	uint16_t cur_capacity1;
+	uint16_t mss;
+	uint16_t total_lba28_0;
+	uint16_t total_lba28_1;
+	uint16_t sw_dma;
+	uint16_t mw_dma;
+	uint16_t pio_modes;
+	uint16_t min_mw_dma_cycle;
+	uint16_t rec_mw_dma_cycle;
+	uint16_t min_raw_pio_cycle;
+	uint16_t min_iordy_pio_cycle;
+	
+	uint16_t reserved69;
+	uint16_t reserved70;
+	uint16_t reserved71;
+	uint16_t reserved72;
+	uint16_t reserved73;
+	uint16_t reserved74;
+	
+	uint16_t queue_depth;
+	/** SATA capatibilities - different meaning for packet device. */
+	uint16_t sata_cap;
+	/** SATA additional capatibilities - different meaning for packet device. */
+	uint16_t sata_cap2;
+	uint16_t reserved78[1 + 79 - 78];
+	uint16_t version_maj;
+	uint16_t version_min;
+	uint16_t cmd_set0;
+	uint16_t cmd_set1;
+	uint16_t csf_sup_ext;
+	uint16_t csf_enabled0;
+	uint16_t csf_enabled1;
+	uint16_t csf_default;
+	uint16_t udma;
+	
+	uint16_t reserved89[1 + 99 - 89];
+	
+	/* Total number of blocks in LBA-48 addressing. */
+	uint16_t total_lba48_0;
+	uint16_t total_lba48_1;
+	uint16_t total_lba48_2;
+	uint16_t total_lba48_3;
+	
+	uint16_t reserved104[1 + 105 - 104];
+	uint16_t physical_logic_sector_size;
+	/* Note: more fields are defined in ATA/ATAPI-7. */
+	uint16_t reserved107[1 + 127 - 107];
+	uint16_t reserved128[1 + 159 - 128];
+	uint16_t reserved160[1 + 255 - 160];
+} sata_identify_data_t;
+
+/** Capability bits for register device. */
+enum sata_rd_caps {
+	sata_rd_cap_iordy = 0x0800,
+	sata_rd_cap_iordy_cbd = 0x0400,
+	sata_rd_cap_lba = 0x0200,
+	sata_rd_cap_dma = 0x0100
+};
+
+/** Bits of @c identify_data_t.cmd_set1. */
+enum sata_cs1 {
+	/** 48-bit address feature set. */
+	sata_cs1_addr48 = 0x0400
+};
+
+/** SATA capatibilities for not packet device - Serial ATA revision 3_1. */
+enum sata_np_caps {
+	/** Supports READ LOG DMA EXT. */
+	sata_np_cap_log_ext = 0x8000,
+	/** Supports Device Automatic Partial to Slumber transitions. */
+	sata_np_cap_dev_slm = 0x4000,
+	/** Supports Host Automatic Partial to Slumber transitions. */
+	sata_np_cap_host_slm = 0x2000,
+	/** Supports NCQ priority information. */
+	sata_np_cap_ncq_prio = 0x1000,
+	/** Supports Unload while NCQ command outstanding. */
+	sata_np_cap_unload_ncq = 0x0800,
+	/** Supports Phy event counters. */
+	sata_np_cap_phy_ctx = 0x0400,
+	/** Supports recepits of host-initiated interface power management. */
+	sata_np_cap_host_pmngmnt = 0x0200,
+	
+	/** Supports NCQ. */
+	sata_np_cap_ncq = 0x0100,
+	
+	/** Supports SATA 3. */
+	sata_np_cap_sata_3 = 0x0008,
+	/** Supports SATA 2. */
+	sata_np_cap_sata_2 = 0x0004,
+	/** Supports SATA 1. */
+	sata_np_cap_sata_1 = 0x0002
+};
+
+/** SATA capatibilities for packet device - Serial ATA revision 3_1. */
+enum sata_pt_caps {
+	/** Supports READ LOG DMA EXT. */
+	sata_pt_cap_log_ext = 0x8000,
+	/** Supports Device Automatic Partial to Slumber transitions. */
+	sata_pt_cap_dev_slm = 0x4000,
+	/** Supports Host Automatic Partial to Slumber transitions. */
+	sata_pt_cap_host_slm = 0x2000,
+	/** Supports Phy event counters. */
+	sata_pt_cap_phy_ctx = 0x0400,
+	/** Supports recepits of host-initiated interface power management. */
+	sata_pt_cap_host_pmngmnt = 0x0200,
+	
+	/** Supports SATA 3. */
+	sata_pt_cap_sat_3 = 0x0008,
+	/** Supports SATA 2. */
+	sata_pt_cap_sat_2 = 0x0004,
+	/** Supports SATA 1. */
+	sata_pt_cap_sat_1 = 0x0002
+};
+
+#endif
Index: uspace/drv/bus/isa/i8237.c
===================================================================
--- uspace/drv/bus/isa/i8237.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/isa/i8237.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -351,5 +351,6 @@
 	
 	/* 16 bit transfers are a bit special */
-	ddf_msg(LVL_DEBUG, "Unspoiled address: %p and size: %zu.", pa, size);
+	ddf_msg(LVL_DEBUG, "Unspoiled address %#" PRIx32 " (size %" PRIu16 ")",
+	    pa, size);
 	if (channel > 4) {
 		/* Size must be aligned to 16 bits */
@@ -367,6 +368,6 @@
 	const dma_channel_t dma_channel = controller_8237.channels[channel];
 	
-	ddf_msg(LVL_DEBUG, "Setting channel %u, to address %p(%zu), mode %hhx.",
-	    channel, pa, size, mode);
+	ddf_msg(LVL_DEBUG, "Setting channel %u to address %#" PRIx32 " "
+	    "(size %" PRIu16 "), mode %hhx.", channel, pa, size, mode);
 	
 	/* Mask DMA request */
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/isa/isa.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -73,10 +73,4 @@
 #define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
 
-/** Obtain soft-state from device node */
-#define ISA_BUS(dev) ((isa_bus_t *) ((dev)->driver_data))
-
-/** Obtain soft-state from function node */
-#define ISA_FUN(fun) ((isa_fun_t *) ((fun)->driver_data))
-
 #define ISA_MAX_HW_RES 5
 
@@ -95,7 +89,19 @@
 } isa_fun_t;
 
+/** Obtain soft-state from device node */
+static isa_bus_t *isa_bus(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
+}
+
+/** Obtain soft-state from function node */
+static isa_fun_t *isa_fun(ddf_fun_t *fun)
+{
+	return ddf_fun_data_get(fun);
+}
+
 static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
 {
-	isa_fun_t *fun = ISA_FUN(fnode);
+	isa_fun_t *fun = isa_fun(fnode);
 	assert(fun != NULL);
 
@@ -107,5 +113,5 @@
 	/* This is an old ugly way, copied from pci driver */
 	assert(fnode);
-	isa_fun_t *isa_fun = fnode->driver_data;
+	isa_fun_t *fun = isa_fun(fnode);
 
 	sysarg_t apic;
@@ -123,6 +129,5 @@
 		return false;
 
-	assert(isa_fun);
-	const hw_resource_list_t *res = &isa_fun->hw_resources;
+	const hw_resource_list_t *res = &fun->hw_resources;
 	assert(res);
 	for (size_t i = 0; i < res->count; ++i) {
@@ -150,6 +155,6 @@
 {
 	assert(fnode);
-	isa_fun_t *isa_fun = fnode->driver_data;
-	const hw_resource_list_t *res = &isa_fun->hw_resources;
+	isa_fun_t *fun = isa_fun(fnode);
+	const hw_resource_list_t *res = &fun->hw_resources;
 	assert(res);
 	
@@ -201,6 +206,8 @@
 
 	isa_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(isa_fun_t));
-	if (fun == NULL)
+	if (fun == NULL) {
+		ddf_fun_destroy(fnode);
 		return NULL;
+	}
 
 	fibril_mutex_initialize(&fun->mutex);
@@ -337,5 +344,5 @@
 
 		ddf_msg(LVL_NOTE, "Added irq 0x%x to function %s", irq,
-		    fun->fnode->name);
+		    ddf_fun_get_name(fun->fnode));
 	}
 }
@@ -353,5 +360,5 @@
 			fun->hw_resources.count++;
 			ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
-			    fun->fnode->name);
+			    ddf_fun_get_name(fun->fnode));
 			
 			return;
@@ -364,5 +371,5 @@
 			fun->hw_resources.count++;
 			ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma,
-			    fun->fnode->name);
+			    ddf_fun_get_name(fun->fnode));
 			
 			return;
@@ -370,5 +377,5 @@
 		
 		ddf_msg(LVL_WARN, "Skipped dma 0x%x for function %s", dma,
-		    fun->fnode->name);
+		    ddf_fun_get_name(fun->fnode));
 	}
 }
@@ -389,5 +396,5 @@
 		ddf_msg(LVL_NOTE, "Added io range (addr=0x%x, size=0x%x) to "
 		    "function %s", (unsigned int) addr, (unsigned int) len,
-		    fun->fnode->name);
+		    ddf_fun_get_name(fun->fnode));
 	}
 }
@@ -461,5 +468,5 @@
 	if (val == end) {
 		ddf_msg(LVL_ERROR, "Cannot read match score for function "
-		    "%s.", fun->fnode->name);
+		    "%s.", ddf_fun_get_name(fun->fnode));
 		return;
 	}
@@ -469,10 +476,10 @@
 	if (id == NULL) {
 		ddf_msg(LVL_ERROR, "Cannot read match ID for function %s.",
-		    fun->fnode->name);
+		    ddf_fun_get_name(fun->fnode));
 		return;
 	}
 
 	ddf_msg(LVL_DEBUG, "Adding match id '%s' with score %d to "
-	    "function %s", id, score, fun->fnode->name);
+	    "function %s", id, score, ddf_fun_get_name(fun->fnode));
 
 	rc = ddf_fun_add_match_id(fun->fnode, id, score);
@@ -552,6 +559,6 @@
 
 	isa_fun_t *fun = isa_fun_create(isa, fun_name);
+	free(fun_name);
 	if (fun == NULL) {
-		free(fun_name);
 		return NULL;
 	}
@@ -577,7 +584,7 @@
 
 	/* Set device operations to the device. */
-	fun->fnode->ops = &isa_fun_ops;
-
-	ddf_msg(LVL_DEBUG, "Binding function %s.", fun->fnode->name);
+	ddf_fun_set_ops(fun->fnode, &isa_fun_ops);
+
+	ddf_msg(LVL_DEBUG, "Binding function %s.", ddf_fun_get_name(fun->fnode));
 
 	/* XXX Handle error */
@@ -612,5 +619,5 @@
 
 	ddf_msg(LVL_DEBUG, "isa_dev_add, device handle = %d",
-	    (int) dev->handle);
+	    (int) ddf_dev_get_handle(dev));
 
 	isa = ddf_dev_data_alloc(dev, sizeof(isa_bus_t));
@@ -650,5 +657,5 @@
 static int isa_dev_remove(ddf_dev_t *dev)
 {
-	isa_bus_t *isa = ISA_BUS(dev);
+	isa_bus_t *isa = isa_bus(dev);
 	int rc;
 
@@ -662,5 +669,5 @@
 		if (rc != EOK) {
 			fibril_mutex_unlock(&isa->mutex);
-			ddf_msg(LVL_ERROR, "Failed offlining %s", fun->fnode->name);
+			ddf_msg(LVL_ERROR, "Failed offlining %s", ddf_fun_get_name(fun->fnode));
 			return rc;
 		}
@@ -669,5 +676,5 @@
 		if (rc != EOK) {
 			fibril_mutex_unlock(&isa->mutex);
-			ddf_msg(LVL_ERROR, "Failed unbinding %s", fun->fnode->name);
+			ddf_msg(LVL_ERROR, "Failed unbinding %s", ddf_fun_get_name(fun->fnode));
 			return rc;
 		}
@@ -705,5 +712,5 @@
 static void isa_init()
 {
-	ddf_log_init(NAME, LVL_ERROR);
+	ddf_log_init(NAME);
 	isa_fun_ops.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops;
 }
Index: uspace/drv/bus/isa/isa.dev
===================================================================
--- uspace/drv/bus/isa/isa.dev	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/isa/isa.dev	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -27,2 +27,6 @@
 	dma 1
 	dma 5
+
+cmos-rtc:
+	match 100 isa/cmos-rtc
+	io_range 70 2
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,4 +38,5 @@
 
 #include <assert.h>
+#include <byteorder.h>
 #include <stdio.h>
 #include <errno.h>
@@ -49,6 +50,4 @@
 #include <ddf/driver.h>
 #include <ddf/log.h>
-#include <devman.h>
-#include <ipc/devman.h>
 #include <ipc/dev_iface.h>
 #include <ipc/irc.h>
@@ -70,11 +69,22 @@
 
 /** Obtain PCI function soft-state from DDF function node */
-#define PCI_FUN(fnode) ((pci_fun_t *) (fnode)->driver_data)
+static pci_fun_t *pci_fun(ddf_fun_t *fnode)
+{
+	return ddf_fun_data_get(fnode);
+}
 
 /** Obtain PCI bus soft-state from DDF device node */
-#define PCI_BUS(dnode) ((pci_bus_t *) (dnode)->driver_data)
+#if 0
+static pci_bus_t *pci_bus(ddf_dev_t *dnode)
+{
+	return ddf_dev_data_get(dnode);
+}
+#endif
 
 /** Obtain PCI bus soft-state from function soft-state */
-#define PCI_BUS_FROM_FUN(fun) ((fun)->busptr)
+static pci_bus_t *pci_bus_from_fun(pci_fun_t *fun)
+{
+	return fun->busptr;
+}
 
 /** Max is 47, align to something nice. */
@@ -83,5 +93,5 @@
 static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode)
 {
-	pci_fun_t *fun = PCI_FUN(fnode);
+	pci_fun_t *fun = pci_fun(fnode);
 	
 	if (fun == NULL)
@@ -94,5 +104,5 @@
 	/* This is an old ugly way */
 	assert(fnode);
-	pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data;
+	pci_fun_t *dev_data = pci_fun(fnode);
 	
 	sysarg_t apic;
@@ -137,5 +147,5 @@
 	if (address > 252)
 		return EINVAL;
-	pci_conf_write_32(PCI_FUN(fun), address, data);
+	pci_conf_write_32(pci_fun(fun), address, data);
 	return EOK;
 }
@@ -146,5 +156,5 @@
 	if (address > 254)
 		return EINVAL;
-	pci_conf_write_16(PCI_FUN(fun), address, data);
+	pci_conf_write_16(pci_fun(fun), address, data);
 	return EOK;
 }
@@ -155,5 +165,5 @@
 	if (address > 255)
 		return EINVAL;
-	pci_conf_write_8(PCI_FUN(fun), address, data);
+	pci_conf_write_8(pci_fun(fun), address, data);
 	return EOK;
 }
@@ -164,5 +174,5 @@
 	if (address > 252)
 		return EINVAL;
-	*data = pci_conf_read_32(PCI_FUN(fun), address);
+	*data = pci_conf_read_32(pci_fun(fun), address);
 	return EOK;
 }
@@ -173,5 +183,5 @@
 	if (address > 254)
 		return EINVAL;
-	*data = pci_conf_read_16(PCI_FUN(fun), address);
+	*data = pci_conf_read_16(pci_fun(fun), address);
 	return EOK;
 }
@@ -182,5 +192,5 @@
 	if (address > 255)
 		return EINVAL;
-	*data = pci_conf_read_8(PCI_FUN(fun), address);
+	*data = pci_conf_read_8(pci_fun(fun), address);
 	return EOK;
 }
@@ -224,5 +234,5 @@
 static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
 {
-	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
+	pci_bus_t *bus = pci_bus_from_fun(fun);
 	
 	fibril_mutex_lock(&bus->conf_mutex);
@@ -231,15 +241,16 @@
 	void *addr = bus->conf_data_port + (reg & 3);
 	
-	pio_write_32(bus->conf_addr_port, conf_addr);
+	pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
 	
 	switch (len) {
 	case 1:
+		/* No endianness change for 1 byte */
 		buf[0] = pio_read_8(addr);
 		break;
 	case 2:
-		((uint16_t *) buf)[0] = pio_read_16(addr);
+		((uint16_t *) buf)[0] = uint16_t_le2host(pio_read_16(addr));
 		break;
 	case 4:
-		((uint32_t *) buf)[0] = pio_read_32(addr);
+		((uint32_t *) buf)[0] = uint32_t_le2host(pio_read_32(addr));
 		break;
 	}
@@ -250,23 +261,23 @@
 static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
 {
-	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
+	pci_bus_t *bus = pci_bus_from_fun(fun);
 	
 	fibril_mutex_lock(&bus->conf_mutex);
 	
-	uint32_t conf_addr;
-	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
+	const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
 	void *addr = bus->conf_data_port + (reg & 3);
 	
-	pio_write_32(bus->conf_addr_port, conf_addr);
+	pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr));
 	
 	switch (len) {
 	case 1:
+		/* No endianness change for 1 byte */
 		pio_write_8(addr, buf[0]);
 		break;
 	case 2:
-		pio_write_16(addr, ((uint16_t *) buf)[0]);
+		pio_write_16(addr, host2uint16_t_le(((uint16_t *) buf)[0]));
 		break;
 	case 4:
-		pio_write_32(addr, ((uint32_t *) buf)[0]);
+		pio_write_32(addr, host2uint32_t_le(((uint32_t *) buf)[0]));
 		break;
 	}
@@ -478,5 +489,5 @@
 	if (range_addr != 0) {
 		ddf_msg(LVL_DEBUG, "Function %s : address = %" PRIx64
-		    ", size = %x", fun->fnode->name, range_addr,
+		    ", size = %x", ddf_fun_get_name(fun->fnode), range_addr,
 		    (unsigned int) range_size);
 	}
@@ -504,5 +515,5 @@
 	hw_res_list->count++;
 	
-	ddf_msg(LVL_NOTE, "Function %s uses irq %x.", fun->fnode->name, irq);
+	ddf_msg(LVL_NOTE, "Function %s uses irq %x.", ddf_fun_get_name(fun->fnode), irq);
 }
 
@@ -521,6 +532,6 @@
 void pci_bus_scan(pci_bus_t *bus, int bus_num) 
 {
-	ddf_fun_t *fnode;
 	pci_fun_t *fun;
+	int rc;
 	
 	int child_bus = 0;
@@ -529,11 +540,12 @@
 	uint8_t header_type;
 	
-	fun = pci_fun_new(bus);
-	
 	for (dnum = 0; dnum < 32; dnum++) {
 		multi = true;
 		for (fnum = 0; multi && fnum < 8; fnum++) {
+			fun = pci_fun_new(bus);
+			
 			pci_fun_init(fun, bus_num, dnum, fnum);
 			if (fun->vendor_id == 0xffff) {
+				pci_fun_delete(fun);
 				/*
 				 * The device is not present, go on scanning the
@@ -557,15 +569,15 @@
 			if (fun_name == NULL) {
 				ddf_msg(LVL_ERROR, "Out of memory.");
+				pci_fun_delete(fun);
 				return;
 			}
 			
-			fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name);
+			rc = ddf_fun_set_name(fun->fnode, fun_name);
 			free(fun_name);
-			if (fnode == NULL) {
-				ddf_msg(LVL_ERROR, "Failed creating function.");
+			if (rc != EOK) {
+				ddf_msg(LVL_ERROR, "Failed setting function name.");
+				pci_fun_delete(fun);
 				return;
 			}
-			
-			fun->fnode = fnode;
 			
 			pci_alloc_resource_list(fun);
@@ -573,17 +585,14 @@
 			pci_read_interrupt(fun);
 			
-			fnode->ops = &pci_fun_ops;
-			fnode->driver_data = fun;
+			ddf_fun_set_ops(fun->fnode, &pci_fun_ops);
 			
 			ddf_msg(LVL_DEBUG, "Adding new function %s.",
-			    fnode->name);
+			    ddf_fun_get_name(fun->fnode));
 			
 			pci_fun_create_match_ids(fun);
 			
-			if (ddf_fun_bind(fnode) != EOK) {
+			if (ddf_fun_bind(fun->fnode) != EOK) {
 				pci_clean_resource_list(fun);
-				clean_match_ids(&fnode->match_ids);
-				free((char *) fnode->name);
-				fnode->name = NULL;
+				pci_fun_delete(fun);
 				continue;
 			}
@@ -599,12 +608,5 @@
 					pci_bus_scan(bus, child_bus);
 			}
-			
-			fun = pci_fun_new(bus);
 		}
-	}
-	
-	if (fun->vendor_id == 0xffff) {
-		/* Free the auxiliary function structure. */
-		pci_fun_delete(fun);
 	}
 }
@@ -615,8 +617,8 @@
 	ddf_fun_t *ctl = NULL;
 	bool got_res = false;
+	async_sess_t *sess;
 	int rc;
 	
 	ddf_msg(LVL_DEBUG, "pci_dev_add");
-	dnode->parent_sess = NULL;
 	
 	bus = ddf_dev_data_alloc(dnode, sizeof(pci_bus_t));
@@ -629,9 +631,7 @@
 
 	bus->dnode = dnode;
-	dnode->driver_data = bus;
-	
-	dnode->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-	    dnode->handle, IPC_FLAG_BLOCKING);
-	if (!dnode->parent_sess) {
+	
+	sess = ddf_dev_parent_sess_create(dnode, EXCHANGE_SERIALIZE);
+	if (sess == NULL) {
 		ddf_msg(LVL_ERROR, "pci_dev_add failed to connect to the "
 		    "parent driver.");
@@ -642,5 +642,5 @@
 	hw_resource_list_t hw_resources;
 	
-	rc = hw_res_get_resource_list(dnode->parent_sess, &hw_resources);
+	rc = hw_res_get_resource_list(sess, &hw_resources);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "pci_dev_add failed to get hw resources "
@@ -650,15 +650,23 @@
 	got_res = true;
 	
+	
+	assert(hw_resources.count > 1);
+	assert(hw_resources.resources[0].type == IO_RANGE);
+	assert(hw_resources.resources[0].res.io_range.size >= 4);
+	
+	assert(hw_resources.resources[1].type == IO_RANGE);
+	assert(hw_resources.resources[1].res.io_range.size >= 4);
+	
 	ddf_msg(LVL_DEBUG, "conf_addr = %" PRIx64 ".",
 	    hw_resources.resources[0].res.io_range.address);
-	
-	assert(hw_resources.count > 0);
-	assert(hw_resources.resources[0].type == IO_RANGE);
-	assert(hw_resources.resources[0].res.io_range.size == 8);
+	ddf_msg(LVL_DEBUG, "data_addr = %" PRIx64 ".",
+	    hw_resources.resources[1].res.io_range.address);
 	
 	bus->conf_io_addr =
 	    (uint32_t) hw_resources.resources[0].res.io_range.address;
-	
-	if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 8,
+	bus->conf_io_data =
+	    (uint32_t) hw_resources.resources[1].res.io_range.address;
+	
+	if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 4,
 	    &bus->conf_addr_port)) {
 		ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
@@ -666,5 +674,10 @@
 		goto fail;
 	}
-	bus->conf_data_port = (char *) bus->conf_addr_port + 4;
+	if (pio_enable((void *)(uintptr_t)bus->conf_io_data, 4,
+	    &bus->conf_data_port)) {
+		ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
+		rc = EADDRNOTAVAIL;
+		goto fail;
+	}
 	
 	/* Make the bus device more visible. It has no use yet. */
@@ -693,7 +706,4 @@
 	
 fail:
-	if (dnode->parent_sess)
-		async_hangup(dnode->parent_sess);
-	
 	if (got_res)
 		hw_res_clean_resource_list(&hw_resources);
@@ -719,5 +729,5 @@
 static void pciintel_init(void)
 {
-	ddf_log_init(NAME, LVL_ERROR);
+	ddf_log_init(NAME);
 	pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
 	pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;
@@ -727,10 +737,16 @@
 {
 	pci_fun_t *fun;
-	
-	fun = (pci_fun_t *) calloc(1, sizeof(pci_fun_t));
+	ddf_fun_t *fnode;
+	
+	fnode = ddf_fun_create(bus->dnode, fun_inner, NULL);
+	if (fnode == NULL)
+		return NULL;
+
+	fun = ddf_fun_data_alloc(fnode, sizeof(pci_fun_t));
 	if (fun == NULL)
 		return NULL;
 
 	fun->busptr = bus;
+	fun->fnode = fnode;
 	return fun;
 }
@@ -751,7 +767,7 @@
 void pci_fun_delete(pci_fun_t *fun)
 {
-	assert(fun != NULL);
 	hw_res_clean_resource_list(&fun->hw_resources);
-	free(fun);
+	if (fun->fnode != NULL)
+		ddf_fun_destroy(fun->fnode);
 }
 
Index: uspace/drv/bus/pci/pciintel/pci.h
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/pci/pciintel/pci.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -46,4 +46,5 @@
 	ddf_dev_t *dnode;
 	uint32_t conf_io_addr;
+	uint32_t conf_io_data;
 	void *conf_data_port;
 	void *conf_addr_port;
Index: uspace/drv/bus/usb/ehci/main.c
===================================================================
--- uspace/drv/bus/usb/ehci/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ehci/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -49,9 +49,9 @@
 
 static int ehci_dev_add(ddf_dev_t *device);
-/*----------------------------------------------------------------------------*/
+
 static driver_ops_t ehci_driver_ops = {
 	.dev_add = ehci_dev_add,
 };
-/*----------------------------------------------------------------------------*/
+
 static driver_t ehci_driver = {
 	.name = NAME,
@@ -62,5 +62,5 @@
 };
 
-/*----------------------------------------------------------------------------*/
+
 /** Initializes a new ddf driver instance of EHCI hcd.
  *
@@ -84,5 +84,5 @@
 	CHECK_RET_RETURN(ret,
 	    "Failed to get memory addresses for %" PRIun ": %s.\n",
-	    device->handle, str_error(ret));
+	    ddf_dev_get_handle(device), str_error(ret));
 	usb_log_info("Memory mapped regs at 0x%" PRIxn " (size %zu), IRQ %d.\n",
 	    reg_base, reg_size, irq);
@@ -104,5 +104,5 @@
 	/* High Speed, no bandwidth */
 	hcd_init(ehci_hc, USB_SPEED_HIGH, 0, NULL);
-	hc_fun->ops = &hc_ops;
+	ddf_fun_set_ops(hc_fun,  &hc_ops);
 
 	ret = ddf_fun_bind(hc_fun);
@@ -116,10 +116,10 @@
 
 	usb_log_info("Controlling new EHCI device `%s' (handle %" PRIun ").\n",
-	    device->name, device->handle);
+	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
 
 	return EOK;
 #undef CHECK_RET_RETURN
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initializes global driver structures (NONE).
  *
@@ -132,5 +132,5 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	log_init(NAME);
 	return ddf_driver_main(&ehci_driver);
 }
Index: uspace/drv/bus/usb/ehci/res.c
===================================================================
--- uspace/drv/bus/usb/ehci/res.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ehci/res.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -76,5 +76,5 @@
  * @return Error code.
  */
-int get_my_registers(const ddf_dev_t *dev,
+int get_my_registers(ddf_dev_t *dev,
     uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
 {
@@ -82,5 +82,5 @@
 	
 	async_sess_t *parent_sess = devman_parent_device_connect(
-	    EXCHANGE_SERIALIZE, dev->handle, IPC_FLAG_BLOCKING);
+	    EXCHANGE_SERIALIZE, ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
@@ -115,8 +115,8 @@
  * @return Error code.
  */
-int enable_interrupts(const ddf_dev_t *device)
+int enable_interrupts(ddf_dev_t *device)
 {
 	async_sess_t *parent_sess = devman_parent_device_connect(
-	    EXCHANGE_SERIALIZE, device->handle, IPC_FLAG_BLOCKING);
+	    EXCHANGE_SERIALIZE, ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
@@ -134,5 +134,5 @@
  * @return Error code.
  */
-static int disable_extended_caps(const ddf_dev_t *device, unsigned eecp)
+static int disable_extended_caps(ddf_dev_t *device, unsigned eecp)
 {
 	/* nothing to do */
@@ -141,5 +141,5 @@
 
 	async_sess_t *parent_sess = devman_parent_device_connect(
-	    EXCHANGE_SERIALIZE, device->handle, IPC_FLAG_BLOCKING);
+	    EXCHANGE_SERIALIZE, ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
@@ -234,5 +234,5 @@
 }
 
-int disable_legacy(const ddf_dev_t *device, uintptr_t reg_base, size_t reg_size)
+int disable_legacy(ddf_dev_t *device, uintptr_t reg_base, size_t reg_size)
 {
 	assert(device);
Index: uspace/drv/bus/usb/ehci/res.h
===================================================================
--- uspace/drv/bus/usb/ehci/res.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ehci/res.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,7 +38,7 @@
 #include <ddf/driver.h>
 
-int get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
-int enable_interrupts(const ddf_dev_t *);
-int disable_legacy(const ddf_dev_t *, uintptr_t, size_t);
+int get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int enable_interrupts(ddf_dev_t *);
+int disable_legacy(ddf_dev_t *, uintptr_t, size_t);
 
 #endif
Index: uspace/drv/bus/usb/ohci/endpoint_list.c
===================================================================
--- uspace/drv/bus/usb/ohci/endpoint_list.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/endpoint_list.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -65,5 +65,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Set the next list in transfer list chain.
  *
@@ -80,5 +80,5 @@
 	ed_append_ed(instance->list_head, next->list_head);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Add endpoint to the list and queue.
  *
@@ -132,5 +132,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Remove endpoint from the list and queue.
  *
@@ -162,5 +162,5 @@
 		qpos = "NOT FIRST";
 	}
-	assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(ep->ed));
+	assert(ed_next(prev_ed) == addr_to_phys(ep->ed));
 	prev_ed->next = ep->ed->next;
 	/* Make sure ED is updated */
Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -26,4 +26,5 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 /** @addtogroup drvusbohcihc
  * @{
@@ -32,4 +33,5 @@
  * @brief OHCI Host controller driver routines
  */
+
 #include <errno.h>
 #include <str_error.h>
@@ -49,5 +51,5 @@
 static const irq_pio_range_t ohci_pio_ranges[] = {
 	{
-		.base = 0,	/* filled later */
+		.base = 0,
 		.size = sizeof(ohci_regs_t)
 	}
@@ -55,9 +57,28 @@
 
 static const irq_cmd_t ohci_irq_commands[] = {
-	{ .cmd = CMD_PIO_READ_32, .dstarg = 1, .addr = NULL /* filled later */ },
-	{ .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS },
-	{ .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
-	{ .cmd = CMD_PIO_WRITE_A_32, .srcarg = 1, .addr = NULL /* filled later */ },
-	{ .cmd = CMD_ACCEPT },
+	{
+		.cmd = CMD_PIO_READ_32,
+		.dstarg = 1,
+		.addr = NULL
+	},
+	{
+		.cmd = CMD_AND,
+		.srcarg = 1,
+		.dstarg = 2,
+		.value = 0
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.srcarg = 2,
+		.value = 2
+	},
+	{
+		.cmd = CMD_PIO_WRITE_A_32,
+		.srcarg = 1,
+		.addr = NULL
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
 };
 
@@ -68,5 +89,5 @@
 static int interrupt_emulator(hc_t *instance);
 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
-/*----------------------------------------------------------------------------*/
+
 /** Get number of PIO ranges used in IRQ code.
  * @return Number of ranges.
@@ -76,6 +97,5 @@
 	return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);
 }
-/*----------------------------------------------------------------------------*/
-/*----------------------------------------------------------------------------*/
+
 /** Get number of commands used in IRQ code.
  * @return Number of commands.
@@ -85,5 +105,5 @@
 	return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Generate IRQ code.
  * @param[out] ranges PIO ranges buffer.
@@ -112,8 +132,9 @@
 	cmds[0].addr = (void *) &registers->interrupt_status;
 	cmds[3].addr = (void *) &registers->interrupt_status;
+	OHCI_WR(cmds[1].value, OHCI_USED_INTERRUPTS);
 
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Announce OHCI root hub to the DDF
  *
@@ -166,5 +187,5 @@
 
 	ret = usb_device_manager_bind_address(&instance->generic.dev_manager,
-	    instance->rh.address, hub_fun->handle);
+	    instance->rh.address, ddf_fun_get_handle(hub_fun));
 	if (ret != EOK)
 		usb_log_warning("Failed to bind root hub address: %s.\n",
@@ -174,5 +195,5 @@
 #undef CHECK_RET_RELEASE
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize OHCI hc driver structure
  *
@@ -227,5 +248,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
 {
@@ -241,23 +262,24 @@
 	switch (ep->transfer_type) {
 	case USB_TRANSFER_CONTROL:
-		instance->registers->control &= ~C_CLE;
+		OHCI_CLR(instance->registers->control, C_CLE);
 		endpoint_list_add_ep(list, ohci_ep);
-		instance->registers->control_current = 0;
-		instance->registers->control |= C_CLE;
+		OHCI_WR(instance->registers->control_current, 0);
+		OHCI_SET(instance->registers->control, C_CLE);
 		break;
 	case USB_TRANSFER_BULK:
-		instance->registers->control &= ~C_BLE;
+		OHCI_CLR(instance->registers->control, C_BLE);
 		endpoint_list_add_ep(list, ohci_ep);
-		instance->registers->control |= C_BLE;
+		OHCI_WR(instance->registers->bulk_current, 0);
+		OHCI_SET(instance->registers->control, C_BLE);
 		break;
 	case USB_TRANSFER_ISOCHRONOUS:
 	case USB_TRANSFER_INTERRUPT:
-		instance->registers->control &= (~C_PLE & ~C_IE);
+		OHCI_CLR(instance->registers->control, C_PLE | C_IE);
 		endpoint_list_add_ep(list, ohci_ep);
-		instance->registers->control |= C_PLE | C_IE;
-		break;
-	}
-}
-/*----------------------------------------------------------------------------*/
+		OHCI_SET(instance->registers->control, C_PLE | C_IE);
+		break;
+	}
+}
+
 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep)
 {
@@ -273,19 +295,20 @@
 	switch (ep->transfer_type) {
 	case USB_TRANSFER_CONTROL:
-		instance->registers->control &= ~C_CLE;
+		OHCI_CLR(instance->registers->control, C_CLE);
 		endpoint_list_remove_ep(list, ohci_ep);
-		instance->registers->control_current = 0;
-		instance->registers->control |= C_CLE;
+		OHCI_WR(instance->registers->control_current, 0);
+		OHCI_SET(instance->registers->control, C_CLE);
 		break;
 	case USB_TRANSFER_BULK:
-		instance->registers->control &= ~C_BLE;
+		OHCI_CLR(instance->registers->control, C_BLE);
 		endpoint_list_remove_ep(list, ohci_ep);
-		instance->registers->control |= C_BLE;
+		OHCI_WR(instance->registers->bulk_current, 0);
+		OHCI_SET(instance->registers->control, C_BLE);
 		break;
 	case USB_TRANSFER_ISOCHRONOUS:
 	case USB_TRANSFER_INTERRUPT:
-		instance->registers->control &= (~C_PLE & ~C_IE);
+		OHCI_CLR(instance->registers->control, C_PLE | C_IE);
 		endpoint_list_remove_ep(list, ohci_ep);
-		instance->registers->control |= C_PLE | C_IE;
+		OHCI_SET(instance->registers->control, C_PLE | C_IE);
 		break;
 	default:
@@ -293,5 +316,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Add USB transfer to the schedule.
  *
@@ -308,4 +331,5 @@
 	/* Check for root hub communication */
 	if (batch->ep->address == instance->rh.address) {
+		usb_log_debug("OHCI root hub request.\n");
 		rh_request(&instance->rh, batch);
 		return EOK;
@@ -323,8 +347,8 @@
 	{
 	case USB_TRANSFER_CONTROL:
-		instance->registers->command_status |= CS_CLF;
+		OHCI_SET(instance->registers->command_status, CS_CLF);
 		break;
 	case USB_TRANSFER_BULK:
-		instance->registers->command_status |= CS_BLF;
+		OHCI_SET(instance->registers->command_status, CS_BLF);
 		break;
 	default:
@@ -334,5 +358,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Interrupt handling routine
  *
@@ -342,4 +366,5 @@
 void hc_interrupt(hc_t *instance, uint32_t status)
 {
+	status = OHCI_RD(status);
 	assert(instance);
 	if ((status & ~I_SF) == 0) /* ignore sof status */
@@ -352,8 +377,8 @@
 		fibril_mutex_lock(&instance->guard);
 		usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
-		    instance->registers->hcca,
+		    OHCI_RD(instance->registers->hcca),
 		    (void *) addr_to_phys(instance->hcca));
 		usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
-		    instance->registers->periodic_current);
+		    OHCI_RD(instance->registers->periodic_current));
 
 		link_t *current = list_first(&instance->pending_batches);
@@ -379,5 +404,5 @@
 
 }
-/*----------------------------------------------------------------------------*/
+
 /** Check status register regularly
  *
@@ -397,5 +422,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Turn off any (BIOS)driver that might be in control of the device.
  *
@@ -410,5 +435,5 @@
 
 	usb_log_debug("Requesting OHCI control.\n");
-	if (instance->registers->revision & R_LEGACY_FLAG) {
+	if (OHCI_RD(instance->registers->revision) & R_LEGACY_FLAG) {
 		/* Turn off legacy emulation, it should be enough to zero
 		 * the lowest bit, but it caused problems. Thus clear all
@@ -419,18 +444,18 @@
 		(uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
 		usb_log_debug("OHCI legacy register %p: %x.\n",
-		    ohci_emulation_reg, *ohci_emulation_reg);
+		    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
 		/* Zero everything but A20State */
-		*ohci_emulation_reg &= 0x100;
+		OHCI_CLR(*ohci_emulation_reg, ~0x100);
 		usb_log_debug(
 		    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
-		    ohci_emulation_reg, *ohci_emulation_reg);
+		    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
 	}
 
 	/* Interrupt routing enabled => smm driver is active */
-	if (instance->registers->control & C_IR) {
+	if (OHCI_RD(instance->registers->control) & C_IR) {
 		usb_log_debug("SMM driver: request ownership change.\n");
-		instance->registers->command_status |= CS_OCR;
+		OHCI_SET(instance->registers->command_status, CS_OCR);
 		/* Hope that SMM actually knows its stuff or we can hang here */
-		while (instance->registers->control & C_IR) {
+		while (OHCI_RD(instance->registers->control & C_IR)) {
 			async_usleep(1000);
 		}
@@ -449,5 +474,5 @@
 			return;
 		}
-		/* HC is suspended assert resume for 20ms, */
+		/* HC is suspended assert resume for 20ms */
 		C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
 		async_usleep(20000);
@@ -461,5 +486,5 @@
 	async_usleep(50000);
 }
-/*----------------------------------------------------------------------------*/
+
 /** OHCI hw initialization routine.
  *
@@ -473,5 +498,5 @@
 
 	/* Save contents of fm_interval register */
-	const uint32_t fm_interval = instance->registers->fm_interval;
+	const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval);
 	usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
 
@@ -479,6 +504,6 @@
 	usb_log_debug2("HC reset.\n");
 	size_t time = 0;
-	instance->registers->command_status = CS_HCR;
-	while (instance->registers->command_status & CS_HCR) {
+	OHCI_WR(instance->registers->command_status, CS_HCR);
+	while (OHCI_RD(instance->registers->command_status) & CS_HCR) {
 		async_usleep(10);
 		time += 10;
@@ -487,23 +512,23 @@
 
 	/* Restore fm_interval */
-	instance->registers->fm_interval = fm_interval;
-	assert((instance->registers->command_status & CS_HCR) == 0);
+	OHCI_WR(instance->registers->fm_interval, fm_interval);
+	assert((OHCI_RD(instance->registers->command_status) & CS_HCR) == 0);
 
 	/* hc is now in suspend state */
 	usb_log_debug2("HC should be in suspend state(%x).\n",
-	    instance->registers->control);
+	    OHCI_RD(instance->registers->control));
 
 	/* Use HCCA */
-	instance->registers->hcca = addr_to_phys(instance->hcca);
+	OHCI_WR(instance->registers->hcca, addr_to_phys(instance->hcca));
 
 	/* Use queues */
-	instance->registers->bulk_head =
-	    instance->lists[USB_TRANSFER_BULK].list_head_pa;
+	OHCI_WR(instance->registers->bulk_head,
+	    instance->lists[USB_TRANSFER_BULK].list_head_pa);
 	usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
 	    instance->lists[USB_TRANSFER_BULK].list_head,
 	    instance->lists[USB_TRANSFER_BULK].list_head_pa);
 
-	instance->registers->control_head =
-	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
+	OHCI_WR(instance->registers->control_head,
+	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
 	usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
 	    instance->lists[USB_TRANSFER_CONTROL].list_head,
@@ -511,26 +536,27 @@
 
 	/* Enable queues */
-	instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
-	usb_log_debug2("All queues enabled(%x).\n",
-	    instance->registers->control);
+	OHCI_SET(instance->registers->control, (C_PLE | C_IE | C_CLE | C_BLE));
+	usb_log_debug("Queues enabled(%x).\n",
+	    OHCI_RD(instance->registers->control));
 
 	/* Enable interrupts */
-	instance->registers->interrupt_enable = OHCI_USED_INTERRUPTS;
-	usb_log_debug2("Enabled interrupts: %x.\n",
-	    instance->registers->interrupt_enable);
-	instance->registers->interrupt_enable = I_MI;
+	OHCI_WR(instance->registers->interrupt_enable, OHCI_USED_INTERRUPTS);
+	usb_log_debug("Enabled interrupts: %x.\n",
+	    OHCI_RD(instance->registers->interrupt_enable));
+	OHCI_WR(instance->registers->interrupt_enable, I_MI);
 
 	/* Set periodic start to 90% */
-	uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
-	instance->registers->periodic_start = (frame_length / 10) * 9;
+	const uint32_t frame_length =
+	    (fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK;
+	OHCI_WR(instance->registers->periodic_start,
+	    ((frame_length / 10) * 9) & PS_MASK << PS_SHIFT);
 	usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
-	    instance->registers->periodic_start,
-	    instance->registers->periodic_start, frame_length);
-
+	    OHCI_RD(instance->registers->periodic_start),
+	    OHCI_RD(instance->registers->periodic_start), frame_length);
 	C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
 	usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
-	    instance->registers->control);
-}
-/*----------------------------------------------------------------------------*/
+	    OHCI_RD(instance->registers->control));
+}
+
 /** Initialize schedule queues
  *
@@ -566,5 +592,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize memory structures used by the OHCI hcd.
  *
@@ -587,10 +613,9 @@
 	if (instance->hcca == NULL)
 		return ENOMEM;
-	bzero(instance->hcca, sizeof(hcca_t));
 	usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
 
-	for (unsigned i = 0; i < 32; ++i) {
-		instance->hcca->int_ep[i] =
-		    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
+	for (unsigned i = 0; i < HCCA_INT_EP_COUNT; ++i) {
+		hcca_set_int_ep(instance->hcca, i,
+		    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
 	}
 	usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
Index: uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -58,5 +58,5 @@
 		/* Mark as dead, used for dummy EDs at the beginning of
 		 * endpoint lists. */
-		instance->status = ED_STATUS_K_FLAG;
+		OHCI_MEM32_WR(instance->status, ED_STATUS_K_FLAG);
 		return;
 	}
@@ -65,27 +65,27 @@
 
 	/* Status: address, endpoint nr, direction mask and max packet size. */
-	instance->status = 0
-	    | ((ep->address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT)
+	OHCI_MEM32_WR(instance->status,
+	    ((ep->address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT)
 	    | ((ep->endpoint & ED_STATUS_EN_MASK) << ED_STATUS_EN_SHIFT)
 	    | ((dir[ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT)
 	    | ((ep->max_packet_size & ED_STATUS_MPS_MASK)
-	        << ED_STATUS_MPS_SHIFT);
+	        << ED_STATUS_MPS_SHIFT));
 
 	/* Low speed flag */
 	if (ep->speed == USB_SPEED_LOW)
-		instance->status |= ED_STATUS_S_FLAG;
+		OHCI_MEM32_SET(instance->status, ED_STATUS_S_FLAG);
 
 	/* Isochronous format flag */
 	if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)
-		instance->status |= ED_STATUS_F_FLAG;
+		OHCI_MEM32_SET(instance->status, ED_STATUS_F_FLAG);
 
 	/* Set TD to the list */
 	const uintptr_t pa = addr_to_phys(td);
-	instance->td_head = pa & ED_TDHEAD_PTR_MASK;
-	instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
+	OHCI_MEM32_WR(instance->td_head, pa & ED_TDHEAD_PTR_MASK);
+	OHCI_MEM32_WR(instance->td_tail, pa & ED_TDTAIL_PTR_MASK);
 
 	/* Set toggle bit */
 	if (ep->toggle)
-		instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
+		OHCI_MEM32_SET(instance->td_head, ED_TDHEAD_TOGGLE_CARRY);
 
 }
Index: uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -44,4 +44,5 @@
 
 #include "completion_codes.h"
+#include "mem_access.h"
 
 /**
@@ -116,6 +117,12 @@
 {
 	assert(instance);
-	return (instance->td_head & ED_TDHEAD_HALTED_FLAG)
-	    || (instance->status & ED_STATUS_K_FLAG);
+	return (OHCI_MEM32_RD(instance->td_head) & ED_TDHEAD_HALTED_FLAG)
+	    || (OHCI_MEM32_RD(instance->status) & ED_STATUS_K_FLAG);
+}
+
+static inline void ed_clear_halt(ed_t *instance)
+{
+	assert(instance);
+	OHCI_MEM32_CLR(instance->td_head, ED_TDHEAD_HALTED_FLAG);
 }
 
@@ -128,6 +135,6 @@
 {
 	assert(instance);
-	return (instance->td_head & ED_TDHEAD_PTR_MASK)
-	    != (instance->td_tail & ED_TDTAIL_PTR_MASK);
+	return (OHCI_MEM32_RD(instance->td_head) & ED_TDHEAD_PTR_MASK)
+	    != (OHCI_MEM32_RD(instance->td_tail) & ED_TDTAIL_PTR_MASK);
 }
 
@@ -141,5 +148,17 @@
 	assert(instance);
 	const uintptr_t pa = addr_to_phys(td);
-	instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
+	OHCI_MEM32_WR(instance->td_tail, pa & ED_TDTAIL_PTR_MASK);
+}
+
+static inline uint32_t ed_tail_td(const ed_t *instance)
+{
+	assert(instance);
+	return OHCI_MEM32_RD(instance->td_tail) & ED_TDTAIL_PTR_MASK;
+}
+
+static inline uint32_t ed_head_td(const ed_t *instance)
+{
+	assert(instance);
+	return OHCI_MEM32_RD(instance->td_head) & ED_TDHEAD_PTR_MASK;
 }
 
@@ -155,5 +174,11 @@
 	const uint32_t pa = addr_to_phys(next);
 	assert((pa & ED_NEXT_PTR_MASK) << ED_NEXT_PTR_SHIFT == pa);
-	instance->next = pa;
+	OHCI_MEM32_WR(instance->next, pa);
+}
+
+static inline uint32_t ed_next(const ed_t *instance)
+{
+	assert(instance);
+	return OHCI_MEM32_RD(instance->next) & ED_NEXT_PTR_MASK;
 }
 
@@ -166,5 +191,5 @@
 {
 	assert(instance);
-	return (instance->td_head & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0;
+	return (OHCI_MEM32_RD(instance->td_head) & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0;
 }
 
@@ -178,9 +203,9 @@
 	assert(instance);
 	if (toggle) {
-		instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
+		OHCI_MEM32_SET(instance->td_head, ED_TDHEAD_TOGGLE_CARRY);
 	} else {
 		/* Clear halted flag when reseting toggle TODO: Why? */
-		instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY;
-		instance->td_head &= ~ED_TDHEAD_HALTED_FLAG;
+		OHCI_MEM32_CLR(instance->td_head, ED_TDHEAD_TOGGLE_CARRY);
+		OHCI_MEM32_CLR(instance->td_head, ED_TDHEAD_HALTED_FLAG);
 	}
 }
Index: uspace/drv/bus/usb/ohci/hw_struct/hcca.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/hcca.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/hw_struct/hcca.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,19 +38,49 @@
 #include <malloc.h>
 
+#include "mem_access.h"
+
+#define HCCA_INT_EP_COUNT  32
+
 /** Host controller communication area.
  * Shared memory used for communication between the controller and the driver.
  */
 typedef struct hcca {
-	uint32_t int_ep[32];
+	/** Interrupt endpoints */
+	uint32_t int_ep[HCCA_INT_EP_COUNT];
+	/** Frame number. */
 	uint16_t frame_number;
 	uint16_t pad1;
+	/** Pointer to the last completed TD. (useless) */
 	uint32_t done_head;
+	/** Padding to make the size 256B */
 	uint32_t reserved[30];
 } hcca_t;
 
-static inline void * hcca_get(void)
+/** Allocate properly aligned structure.
+ *
+ * The returned structure is zeroed upon allocation.
+ *
+ * @return Usable HCCA memory structure.
+ */
+static inline hcca_t * hcca_get(void)
 {
 	assert(sizeof(hcca_t) == 256);
-	return memalign(256, sizeof(hcca_t));
+	hcca_t *hcca = memalign(256, sizeof(hcca_t));
+	if (hcca)
+		bzero(hcca, sizeof(hcca_t));
+	return hcca;
+}
+
+/** Set HCCA interrupt endpoint pointer table entry.
+ * @param hcca HCCA memory structure.
+ * @param index table index.
+ * @param pa Physical address.
+ */
+static inline void hcca_set_int_ep(hcca_t *hcca, unsigned index, uintptr_t pa)
+{
+	assert(hcca);
+	assert(index < HCCA_INT_EP_COUNT);
+	OHCI_MEM32_WR(hcca->int_ep[index], pa);
+
 }
 #endif
Index: uspace/drv/bus/usb/ohci/hw_struct/mem_access.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/mem_access.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/bus/usb/ohci/hw_struct/mem_access.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,49 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HW_MEM_ACCESS_H
+#define DRV_OHCI_HW_MEM_ACCESS_H
+
+#include <byteorder.h>
+
+#define OHCI_MEM32_WR(reg, val) reg = host2uint32_t_le(val)
+#define OHCI_MEM32_RD(reg) uint32_t_le2host(reg)
+#define OHCI_MEM32_SET(reg, val) reg |= host2uint32_t_le(val)
+#define OHCI_MEM32_CLR(reg, val) reg &= host2uint32_t_le(~val)
+
+#endif
+
+/*
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,4 +33,6 @@
  */
 #include <usb/usb.h>
+#include <mem.h>
+#include "../utils/malloc32.h"
 #include "transfer_descriptor.h"
 
@@ -58,26 +60,26 @@
 	bzero(instance, sizeof(td_t));
 	/* Set PID and Error code */
-	instance->status = 0
-	    | ((dir[direction] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
-	    | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT);
+	OHCI_MEM32_WR(instance->status,
+	    ((dir[direction] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
+	    | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT));
 
 	if (toggle == 0 || toggle == 1) {
 		/* Set explicit toggle bit */
-		instance->status |= TD_STATUS_T_USE_TD_FLAG;
-		instance->status |= toggle ? TD_STATUS_T_FLAG : 0;
+		OHCI_MEM32_SET(instance->status, TD_STATUS_T_USE_TD_FLAG);
+		OHCI_MEM32_SET(instance->status, toggle ? TD_STATUS_T_FLAG : 0);
 	}
 
 	/* Alow less data on input. */
 	if (dir == USB_DIRECTION_IN) {
-		instance->status |= TD_STATUS_ROUND_FLAG;
+		OHCI_MEM32_SET(instance->status, TD_STATUS_ROUND_FLAG);
 	}
 
 	if (buffer != NULL) {
 		assert(size != 0);
-		instance->cbp = addr_to_phys(buffer);
-		instance->be = addr_to_phys(buffer + size - 1);
+		OHCI_MEM32_WR(instance->cbp, addr_to_phys(buffer));
+		OHCI_MEM32_WR(instance->be, addr_to_phys(buffer + size - 1));
 	}
 
-	instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK;
+	OHCI_MEM32_WR(instance->next, addr_to_phys(next) & TD_NEXT_PTR_MASK);
 
 }
Index: uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,5 +38,5 @@
 #include <stdint.h>
 
-#include "../utils/malloc32.h"
+#include "mem_access.h"
 #include "completion_codes.h"
 
@@ -100,6 +100,6 @@
 {
 	assert(instance);
-	const int cc =
-	    (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
+	const int cc =(OHCI_MEM32_RD(instance->status)
+	    >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
 	/* This value is changed on transfer completion,
 	 * either to CC_NOERROR or and error code.
@@ -119,6 +119,6 @@
 {
 	assert(instance);
-	const int cc =
-	    (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
+	const int cc = (OHCI_MEM32_RD(instance->status)
+	    >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
 	return cc_to_rc(cc);
 }
@@ -136,5 +136,5 @@
 		return 0;
 	/* Buffer end points to the last byte of transfer buffer, so add 1 */
-	return instance->be - instance->cbp + 1;
+	return OHCI_MEM32_RD(instance->be) - OHCI_MEM32_RD(instance->cbp) + 1;
 }
 #endif
Index: uspace/drv/bus/usb/ohci/main.c
===================================================================
--- uspace/drv/bus/usb/ohci/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -59,18 +59,18 @@
 		return ret;
 	}
-	usb_log_info("Controlling new OHCI device '%s'.\n", device->name);
+	usb_log_info("Controlling new OHCI device '%s'.\n", ddf_dev_get_name(device));
 
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static driver_ops_t ohci_driver_ops = {
 	.dev_add = ohci_dev_add,
 };
-/*----------------------------------------------------------------------------*/
+
 static driver_t ohci_driver = {
 	.name = NAME,
 	.driver_ops = &ohci_driver_ops
 };
-/*----------------------------------------------------------------------------*/
+
 /** Initializes global driver structures (NONE).
  *
@@ -83,5 +83,5 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	log_init(NAME);
 	return ddf_driver_main(&ohci_driver);
 }
Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,4 +33,8 @@
  * @brief OHCI driver
  */
+
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 #include <errno.h>
 #include <str_error.h>
@@ -52,8 +56,7 @@
 } ohci_t;
 
-static inline ohci_t * dev_to_ohci(ddf_dev_t *dev)
-{
-	assert(dev);
-	return dev->driver_data;
+static inline ohci_t *dev_to_ohci(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
 }
 /** IRQ handling callback, identifies device
@@ -75,5 +78,5 @@
 	hc_interrupt(&ohci->hc, status);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Get USB address assigned to root hub.
  *
@@ -87,10 +90,10 @@
 
 	if (address != NULL) {
-		*address = dev_to_ohci(fun->dev)->hc.rh.address;
+		*address = dev_to_ohci(ddf_fun_get_dev(fun))->hc.rh.address;
 	}
 
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Gets handle of the respective hc (this device, hc function).
  *
@@ -103,12 +106,12 @@
 {
 	assert(fun);
-	ddf_fun_t *hc_fun = dev_to_ohci(fun->dev)->hc_fun;
+	ddf_fun_t *hc_fun = dev_to_ohci(ddf_fun_get_dev(fun))->hc_fun;
 	assert(hc_fun);
 
 	if (handle != NULL)
-		*handle = hc_fun->handle;
+		*handle = ddf_fun_get_handle(hc_fun);
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Root hub USB interface */
 static usb_iface_t usb_iface = {
@@ -116,15 +119,15 @@
 	.get_my_address = rh_get_my_address,
 };
-/*----------------------------------------------------------------------------*/
+
 /** Standard USB HC options (HC interface) */
 static ddf_dev_ops_t hc_ops = {
 	.interfaces[USBHC_DEV_IFACE] = &hcd_iface,
 };
-/*----------------------------------------------------------------------------*/
+
 /** Standard USB RH options (RH interface) */
 static ddf_dev_ops_t rh_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface,
 };
-/*----------------------------------------------------------------------------*/
+
 /** Initialize hc and rh ddf structures and their respective drivers.
  *
@@ -152,9 +155,7 @@
 if (ret != EOK) { \
 	if (instance->hc_fun) { \
-		instance->hc_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->hc_fun); \
 	} \
 	if (instance->rh_fun) { \
-		instance->rh_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->rh_fun); \
 	} \
@@ -167,6 +168,6 @@
 	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed to create OHCI HC function: %s.\n", str_error(ret));
-	instance->hc_fun->ops = &hc_ops;
-	instance->hc_fun->driver_data = &instance->hc;
+	ddf_fun_set_ops(instance->hc_fun, &hc_ops);
+	ddf_fun_data_implant(instance->hc_fun, &instance->hc);
 
 	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh");
@@ -174,5 +175,5 @@
 	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed to create OHCI RH function: %s.\n", str_error(ret));
-	instance->rh_fun->ops = &rh_ops;
+	ddf_fun_set_ops(instance->rh_fun, &rh_ops);
 
 	uintptr_t reg_base = 0;
@@ -183,5 +184,5 @@
 	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed to get register memory addresses for %" PRIun ": %s.\n",
-	    device->handle, str_error(ret));
+	    ddf_dev_get_handle(device), str_error(ret));
 	usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
 	    (void *) reg_base, reg_size, irq);
Index: uspace/drv/bus/usb/ohci/ohci_batch.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_batch.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/ohci_batch.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -44,5 +44,5 @@
 
 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t);
-/*----------------------------------------------------------------------------*/
+
 /** Safely destructs ohci_transfer_batch_t structure
  *
@@ -67,5 +67,5 @@
 	free(ohci_batch);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Finishes usb_transfer_batch and destroys the structure.
  *
@@ -80,5 +80,5 @@
 	ohci_transfer_batch_dispose(ohci_batch);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Allocate memory and initialize internal data structure.
  *
@@ -158,5 +158,5 @@
 #undef CHECK_NULL_DISPOSE_RET
 }
-/*----------------------------------------------------------------------------*/
+
 /** Check batch TDs' status.
  *
@@ -199,20 +199,21 @@
 		    ohci_batch->tds[i]->next, ohci_batch->tds[i]->be);
 
-		/* If the TD got all its data through, it will report 0 bytes
-		 * remain, the sole exception is INPUT with data rounding flag
-		 * (short), i.e. every INPUT. Nice thing is that short packets
-		 * will correctly report remaining data, thus making
-		 * this computation correct (short packets need to be produced
-		 * by the last TD)
-		 * NOTE: This also works for CONTROL transfer as
-		 * the first TD will return 0 remain.
-		 * NOTE: Short packets don't break the assumption that
-		 * we leave the very last(unused) TD behind.
-		 */
-		ohci_batch->usb_batch->transfered_size
-		    -= td_remain_size(ohci_batch->tds[i]);
-
 		ohci_batch->usb_batch->error = td_error(ohci_batch->tds[i]);
-		if (ohci_batch->usb_batch->error != EOK) {
+		if (ohci_batch->usb_batch->error == EOK) {
+			/* If the TD got all its data through, it will report
+			 * 0 bytes remain, the sole exception is INPUT with
+			 * data rounding flag (short), i.e. every INPUT.
+			 * Nice thing is that short packets will correctly
+			 * report remaining data, thus making this computation
+			 * correct (short packets need to be produced by the
+			 * last TD)
+			 * NOTE: This also works for CONTROL transfer as
+			 * the first TD will return 0 remain.
+			 * NOTE: Short packets don't break the assumption that
+			 * we leave the very last(unused) TD behind.
+			 */
+			ohci_batch->usb_batch->transfered_size
+			    -= td_remain_size(ohci_batch->tds[i]);
+		} else {
 			usb_log_debug("Batch %p found error TD(%zu):%08x.\n",
 			    ohci_batch->usb_batch, i,
@@ -231,14 +232,13 @@
 
 			/* Check TD assumption */
-			const uint32_t pa =
-			    addr_to_phys(ohci_batch->tds[leave_td]);
-			assert((ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK)
-			    == pa);
-
+			assert(ed_head_td(ohci_batch->ed) ==
+			    addr_to_phys(ohci_batch->tds[leave_td]));
+
+			/* Set tail to the same TD */
 			ed_set_tail_td(ohci_batch->ed,
 			    ohci_batch->tds[leave_td]);
 
 			/* Clear possible ED HALT */
-			ohci_batch->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
+			ed_clear_halt(ohci_batch->ed);
 			break;
 		}
@@ -253,11 +253,10 @@
 
 	/* Make sure that we are leaving the right TD behind */
-	const uint32_t pa = addr_to_phys(ohci_ep->td);
-	assert(pa == (ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK));
-	assert(pa == (ohci_batch->ed->td_tail & ED_TDTAIL_PTR_MASK));
+	assert(addr_to_phys(ohci_ep->td) == ed_head_td(ohci_batch->ed));
+	assert(addr_to_phys(ohci_ep->td) == ed_tail_td(ohci_batch->ed));
 
 	return true;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Starts execution of the TD list
  *
@@ -269,5 +268,5 @@
 	ed_set_tail_td(ohci_batch->ed, ohci_batch->tds[ohci_batch->td_count]);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Prepare generic control transfer
  *
@@ -345,5 +344,5 @@
 	    USB_TRANSFER_BATCH_ARGS(*ohci_batch->usb_batch));
 }
-/*----------------------------------------------------------------------------*/
+
 /** Prepare generic data transfer
  *
@@ -392,5 +391,5 @@
 	    USB_TRANSFER_BATCH_ARGS(*ohci_batch->usb_batch));
 }
-/*----------------------------------------------------------------------------*/
+
 /** Transfer setup table. */
 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t) =
Index: uspace/drv/bus/usb/ohci/ohci_batch.h
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_batch.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/ohci_batch.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -63,5 +63,5 @@
 void ohci_transfer_batch_commit(const ohci_transfer_batch_t *batch);
 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch);
-/*----------------------------------------------------------------------------*/
+
 static inline ohci_transfer_batch_t *ohci_transfer_batch_from_link(link_t *l)
 {
Index: uspace/drv/bus/usb/ohci/ohci_endpoint.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_endpoint.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/ohci_endpoint.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -48,5 +48,5 @@
 	ed_toggle_set(instance->ed, toggle);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback to get value of toggle bit.
  *
@@ -61,5 +61,5 @@
 	return ed_toggle_get(instance->ed);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Creates new hcd endpoint representation.
  *
@@ -93,5 +93,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Disposes hcd endpoint structure
  *
Index: uspace/drv/bus/usb/ohci/ohci_regs.h
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_regs.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/ohci_regs.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,4 +35,11 @@
 #define DRV_OHCI_OHCI_REGS_H
 #include <sys/types.h>
+#include <byteorder.h>
+
+#define OHCI_WR(reg, val) reg = host2uint32_t_le(val)
+#define OHCI_RD(reg) uint32_t_le2host(reg)
+#define OHCI_SET(reg, val) reg |= host2uint32_t_le(val)
+#define OHCI_CLR(reg, val) reg &= host2uint32_t_le(~val)
+
 
 #define LEGACY_REGS_OFFSET 0x100
@@ -42,14 +49,14 @@
 	const ioport32_t revision;
 #define R_REVISION_MASK (0x3f)
-#define R_REVISION_SHIFT (0)
 #define R_LEGACY_FLAG   (0x80)
 
 	ioport32_t control;
-#define C_CBSR_MASK (0x3) /* Control-bulk service ratio */
+/* Control-bulk service ratio */
 #define C_CBSR_1_1  (0x0)
 #define C_CBSR_1_2  (0x1)
 #define C_CBSR_1_3  (0x2)
 #define C_CBSR_1_4  (0x3)
-#define C_CBSR_SHIFT (0)
+#define C_CBSR_MASK (0x3)
+#define C_CBSR_SHIFT 0
 
 #define C_PLE (1 << 2)   /* Periodic list enable */
@@ -58,22 +65,20 @@
 #define C_BLE (1 << 5)   /* Bulk list enable */
 
-#define C_HCFS_MASK        (0x3) /* Host controller functional state */
+/* Host controller functional state */
 #define C_HCFS_RESET       (0x0)
 #define C_HCFS_RESUME      (0x1)
 #define C_HCFS_OPERATIONAL (0x2)
 #define C_HCFS_SUSPEND     (0x3)
-#define C_HCFS_SHIFT       (6)
-
-#define C_HCFS_GET(reg) \
-	((reg >> C_HCFS_SHIFT) & C_HCFS_MASK)
-#define C_HCFS_SET(reg, hcfs_state) \
+#define C_HCFS_GET(reg) ((OHCI_RD(reg) >> 6) & 0x3)
+#define C_HCFS_SET(reg, value) \
 do { \
-	reg = (reg & ~(C_HCFS_MASK << C_HCFS_SHIFT)) \
-	    | ((hcfs_state & C_HCFS_MASK) << C_HCFS_SHIFT); \
+	uint32_t r = OHCI_RD(reg); \
+	r &= ~(0x3 << 6); \
+	r |= (value & 0x3) << 6; \
+	OHCI_WR(reg, r); \
 } while (0)
 
-
-#define C_IR  (1 << 8)   /* Interrupt routing, make sure it's 0 */
-#define C_RWC (1 << 9)   /* Remote wakeup connected, host specific */
+#define C_IR  (1 << 8)  /* Interrupt routing, make sure it's 0 */
+#define C_RWC (1 << 9)  /* Remote wakeup connected, host specific */
 #define C_RWE (1 << 10)  /* Remote wakeup enable */
 
@@ -83,6 +88,8 @@
 #define CS_BLF (1 << 2)   /* Bulk list filled */
 #define CS_OCR (1 << 3)   /* Ownership change request */
+#if 0
 #define CS_SOC_MASK (0x3) /* Scheduling overrun count */
 #define CS_SOC_SHIFT (16)
+#endif
 
 	/** Interupt enable/disable/status,
@@ -101,5 +108,5 @@
 #define I_RHSC (1 << 6)   /* Root hub status change */
 #define I_OC   (1 << 30)  /* Ownership change */
-#define I_MI   (1 << 31)  /* Master interrupt (all/any interrupts) */
+#define I_MI   (1 << 31)  /* Master interrupt (any/all) */
 
 	/** HCCA pointer (see hw_struct hcca.h) */
@@ -145,5 +152,6 @@
 	/** Remaining bit time in frame to start periodic transfers */
 	ioport32_t periodic_start;
-#define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */
+#define PS_MASK 0x3fff
+#define PS_SHIFT 0
 
 	/** Threshold for starting LS transaction */
@@ -153,46 +161,54 @@
 	/** The first root hub control register */
 	ioport32_t rh_desc_a;
-#define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */
-#define RHDA_NDS_SHIFT (0)
-#define RHDA_PSM_FLAG  (1 << 8)  /* Power switching mode: 0-global, 1-per port*/
-#define RHDA_NPS_FLAG  (1 << 9)  /* No power switch: 1-power on, 0-use PSM*/
-#define RHDA_DT_FLAG   (1 << 10) /* 1-Compound device, must be 0 */
-#define RHDA_OCPM_FLAG (1 << 11) /* Over-current mode: 0-global, 1-per port */
-#define RHDA_NOCP_FLAG (1 << 12) /* OC control: 0-use OCPM, 1-OC off */
-#define RHDA_POTPGT_MASK (0xff)  /* Power on to power good time */
-#define RHDA_POTPGT_SHIFT (24)
+/** Number of downstream ports, max 15 */
+#define RHDA_NDS_MASK  (0xff)
+/** Power switching mode: 0-global, 1-per port*/
+#define RHDA_PSM_FLAG  (1 << 8)
+/** No power switch: 1-power on, 0-use PSM*/
+#define RHDA_NPS_FLAG  (1 << 9)
+/** 1-Compound device, must be 0 */
+#define RHDA_DT_FLAG   (1 << 10)
+/** Over-current mode: 0-global, 1-per port */
+#define RHDA_OCPM_FLAG (1 << 11)
+/** OC control: 0-use OCPM, 1-OC off */
+#define RHDA_NOCP_FLAG (1 << 12)
+/** Power on to power good time */
+#define RHDA_POTPGT_SHIFT   24
 
 	/** The other root hub control register */
 	ioport32_t rh_desc_b;
-#define RHDB_DR_MASK (0xffff) /* Device removable mask */
-#define RHDB_DR_SHIFT (0)
-#define RHDB_PCC_MASK (0xffff) /* Power control mask */
-#define RHDB_PCC_SHIFT (16)
-
-/* Port device removable status */
-#define RHDB_DR_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)
-/* Port power control status: 1-per port power control, 0-global power switch */
-#define RHDB_PPC_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)
+/** Device removable mask */
+#define RHDB_DR_SHIFT   0
+#define RHDB_DR_MASK    0xffff
+/** Power control mask */
+#define RHDB_PCC_MASK (0xffff)
+#define RHDB_PCC_SHIFT 16
 
 	/** Root hub status register */
 	ioport32_t rh_status;
-#define RHS_LPS_FLAG  (1 <<  0)/* read: 0,
-                                * write: 0-no effect,
-                                *        1-turn off port power for ports
-                                *        specified in PPCM(RHDB), or all ports,
-                                *        if power is set globally */
+/* read: 0,
+ * write: 0-no effect,
+ *        1-turn off port power for ports
+ *        specified in PPCM(RHDB), or all ports,
+ *        if power is set globally */
+#define RHS_LPS_FLAG  (1 <<  0)
 #define RHS_CLEAR_GLOBAL_POWER RHS_LPS_FLAG /* synonym for the above */
-#define RHS_OCI_FLAG  (1 <<  1)/* Over-current indicator, if per-port: 0 */
-#define RHS_DRWE_FLAG (1 << 15)/* read: 0-connect status change does not wake HC
-                                *       1-connect status change wakes HC
-                                * write: 1-set DRWE, 0-no effect */
+/** Over-current indicator, if per-port: 0 */
+#define RHS_OCI_FLAG  (1 <<  1)
+
+/* read: 0-connect status change does not wake HC
+ *       1-connect status change wakes HC
+ * write: 1-set DRWE, 0-no effect */
+#define RHS_DRWE_FLAG (1 << 15)
 #define RHS_SET_DRWE RHS_DRWE_FLAG
-#define RHS_LPSC_FLAG (1 << 16)/* read: 0,
-                                * write: 0-no effect
-                                *        1-turn on port power for ports
-                                *        specified in PPCM(RHDB), or all ports,
-                                *        if power is set globally */
+/* read: 0,
+ * write: 0-no effect
+ *        1-turn on port power for ports
+ *        specified in PPCM(RHDB), or all ports,
+ *        if power is set globally */
+#define RHS_LPSC_FLAG (1 << 16)
 #define RHS_SET_GLOBAL_POWER RHS_LPSC_FLAG /* synonym for the above */
-#define RHS_OCIC_FLAG (1 << 17)/* Over-current indicator change   */
+/** Over-current change indicator*/
+#define RHS_OCIC_FLAG (1 << 17)
 #define RHS_CLEAR_DRWE (1 << 31)
 
@@ -200,32 +216,33 @@
 	ioport32_t rh_port_status[];
 #define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,
-                                * w: 1-clear port enable, 0-nothing */
+                                               * w: 1-clear port enable, 0-N/S*/
 #define RHPS_CLEAR_PORT_ENABLE RHPS_CCS_FLAG
 #define RHPS_PES_FLAG (1 << 1) /* r: port enable status
-                                * w: 1-set port enable, 0-nothing */
+                                              * w: 1-set port enable, 0-N/S */
 #define RHPS_SET_PORT_ENABLE RHPS_PES_FLAG
 #define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status
-                                * w: 1-set port suspend, 0-nothing */
+                                               * w: 1-set port suspend, 0-N/S */
 #define RHPS_SET_PORT_SUSPEND RHPS_PSS_FLAG
-#define RHPS_POCI_FLAG (1 << 3) /* r: port over-current (if reports are per-port
-                                 * w: 1-clear port suspend (start resume
-                                 *      if suspened)
-                                 *    0-nothing */
+#define RHPS_POCI_FLAG (1 << 3) /* r: port over-current
+                                                * (if reports are per-port
+                                                * w: 1-clear port suspend
+						*  (start resume if suspened)
+                                                *    0-nothing */
 #define RHPS_CLEAR_PORT_SUSPEND RHPS_POCI_FLAG
 #define RHPS_PRS_FLAG (1 << 4) /* r: port reset status
-                                * w: 1-set port reset, 0-nothing */
+                                               * w: 1-set port reset, 0-N/S */
 #define RHPS_SET_PORT_RESET RHPS_PRS_FLAG
 #define RHPS_PPS_FLAG (1 << 8) /* r: port power status
-                                * w: 1-set port power, 0-nothing */
+                                              * w: 1-set port power, 0-N/S */
 #define RHPS_SET_PORT_POWER RHPS_PPS_FLAG
 #define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached
-                                 * w: 1-clear port power, 0-nothing */
+                                                * w: 1-clear port power, 0-N/S*/
 #define RHPS_CLEAR_PORT_POWER RHPS_LSDA_FLAG
-#define RHPS_CSC_FLAG  (1 << 16) /* connect status change Write-Clean */
+#define RHPS_CSC_FLAG  (1 << 16) /* connect status change WC */
 #define RHPS_PESC_FLAG (1 << 17) /* port enable status change WC */
 #define RHPS_PSSC_FLAG (1 << 18) /* port suspend status change WC */
 #define RHPS_OCIC_FLAG (1 << 19) /* port over-current change WC */
 #define RHPS_PRSC_FLAG (1 << 20) /* port reset status change WC */
-#define RHPS_CHANGE_WC_MASK 0x1f0000
+#define RHPS_CHANGE_WC_MASK (0x1f0000)
 } __attribute__((packed)) ohci_regs_t;
 #endif
Index: uspace/drv/bus/usb/ohci/res.c
===================================================================
--- uspace/drv/bus/usb/ohci/res.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/res.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -53,5 +53,5 @@
  * @return Error code.
  */
-int get_my_registers(const ddf_dev_t *dev,
+int get_my_registers(ddf_dev_t *dev,
     uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
 {
@@ -59,6 +59,6 @@
 
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
@@ -94,9 +94,9 @@
  * @return Error code.
  */
-int enable_interrupts(const ddf_dev_t *device)
+int enable_interrupts(ddf_dev_t *device)
 {
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
-	    IPC_FLAG_BLOCKING);
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
Index: uspace/drv/bus/usb/ohci/res.h
===================================================================
--- uspace/drv/bus/usb/ohci/res.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/res.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,6 +37,6 @@
 #include <ddf/driver.h>
 
-int get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
-int enable_interrupts(const ddf_dev_t *);
+int get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int enable_interrupts(ddf_dev_t *);
 
 #endif
Index: uspace/drv/bus/usb/ohci/root_hub.c
===================================================================
--- uspace/drv/bus/usb/ohci/root_hub.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/root_hub.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,17 +33,19 @@
  */
 #include <assert.h>
+#include <byteorder.h>
 #include <errno.h>
 #include <str_error.h>
 #include <fibril_synch.h>
 
+#include <usb/usb.h>
 #include <usb/debug.h>
 #include <usb/dev/request.h>
 #include <usb/classes/hub.h>
 
-#include "root_hub.h"
 #include <usb/classes/classes.h>
 #include <usb/classes/hub.h>
 #include <usb/dev/driver.h>
 #include "ohci_regs.h"
+#include "root_hub.h"
 
 /**
@@ -122,4 +124,6 @@
 {
 	assert(request);
+	usb_log_debug("Sending interrupt vector(%zu) %hhx:%hhx.\n",
+	    size, ((uint8_t*)&mask)[0], ((uint8_t*)&mask)[1]);
 	usb_transfer_batch_finish_error(request, &mask, size, EOK);
 	usb_transfer_batch_destroy(request);
@@ -150,6 +154,6 @@
 
 	instance->registers = regs;
-	instance->port_count =
-	    (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
+	instance->port_count = OHCI_RD(regs->rh_desc_a) & RHDA_NDS_MASK;
+	usb_log_debug2("rh_desc_a: %x.\n", OHCI_RD(regs->rh_desc_a));
 	if (instance->port_count > 15) {
 		usb_log_warning("OHCI specification does not allow more than 15"
@@ -163,35 +167,39 @@
 
 #if defined OHCI_POWER_SWITCH_no
+	usb_log_debug("OHCI rh: Set power mode to no power switching.\n");
 	/* Set port power mode to no power-switching. (always on) */
-	instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
+	OHCI_SET(regs->rh_desc_a, RHDA_NPS_FLAG);
 
 	/* Set to no over-current reporting */
-	instance->registers->rh_desc_a |= RHDA_NOCP_FLAG;
+	OHCI_SET(regs->rh_desc_a, RHDA_NOCP_FLAG);
 
 #elif defined OHCI_POWER_SWITCH_ganged
-	/* Set port power mode to no ganged power-switching. */
-	instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
-	instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG;
-	instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
+	usb_log_debug("OHCI rh: Set power mode to ganged power switching.\n");
+	/* Set port power mode to ganged power-switching. */
+	OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG);
+	OHCI_CLR(regs->rh_desc_a, RHDA_PSM_FLAG);
+
+	/* Turn off power (hub driver will turn this back on)*/
+	OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER);
 
 	/* Set to global over-current */
-	instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
-	instance->registers->rh_desc_a &= ~RHDA_OCPM_FLAG;
+	OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG);
+	OHCI_CLR(regs->rh_desc_a, RHDA_OCPM_FLAG);
 #else
-	/* Set port power mode to no per port power-switching. */
-	instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
-	instance->registers->rh_desc_a |= RHDA_PSM_FLAG;
+	usb_log_debug("OHCI rh: Set power mode to per-port power switching.\n");
+	/* Set port power mode to per port power-switching. */
+	OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG);
+	OHCI_SET(regs->rh_desc_a, RHDA_PSM_FLAG);
 
 	/* Control all ports by global switch and turn them off */
-	instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT);
-	instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
+	OHCI_CLR(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT);
+	OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER);
 
 	/* Return control to per port state */
-	instance->registers->rh_desc_b |=
-		((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT;
+	OHCI_SET(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT);
 
 	/* Set per port over-current */
-	instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
-	instance->registers->rh_desc_a |= RHDA_OCPM_FLAG;
+	OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG);
+	OHCI_SET(regs->rh_desc_a, RHDA_OCPM_FLAG);
 #endif
 
@@ -202,5 +210,5 @@
 	    instance->port_count);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process root hub request.
@@ -226,7 +234,7 @@
 		fibril_mutex_lock(&instance->guard);
 		assert(instance->unfinished_interrupt_transfer == NULL);
-		uint16_t mask = create_interrupt_mask(instance);
+		const uint16_t mask = create_interrupt_mask(instance);
 		if (mask == 0) {
-			usb_log_debug("No changes...\n");
+			usb_log_debug("No changes(%hx)...\n", mask);
 			instance->unfinished_interrupt_transfer = request;
 		} else {
@@ -243,5 +251,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process interrupt on a hub device.
@@ -257,5 +265,5 @@
 	if (instance->unfinished_interrupt_transfer) {
 		usb_log_debug("Finalizing interrupt transfer\n");
-		uint16_t mask = create_interrupt_mask(instance);
+		const uint16_t mask = create_interrupt_mask(instance);
 		interrupt_request(instance->unfinished_interrupt_transfer,
 		    mask, instance->interrupt_mask_size);
@@ -264,5 +272,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Create hub descriptor.
@@ -282,6 +290,6 @@
 	instance->hub_descriptor_size = size;
 
-	uint32_t hub_desc = instance->registers->rh_desc_a;
-	uint32_t port_desc = instance->registers->rh_desc_b;
+	const uint32_t hub_desc = OHCI_RD(instance->registers->rh_desc_a);
+	const uint32_t port_desc = OHCI_RD(instance->registers->rh_desc_b);
 
 	/* bDescLength */
@@ -305,21 +313,19 @@
 	instance->descriptors.hub[4] = 0;
 	/* bPwrOn2PwrGood */
-	instance->descriptors.hub[5] =
-	    (hub_desc >> RHDA_POTPGT_SHIFT) & RHDA_POTPGT_MASK;
+	instance->descriptors.hub[5] = hub_desc >> RHDA_POTPGT_SHIFT;
 	/* bHubContrCurrent, root hubs don't need no power. */
 	instance->descriptors.hub[6] = 0;
 
 	/* Device Removable and some legacy 1.0 stuff*/
-	instance->descriptors.hub[7] =
-	    (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK & 0xff;
+	instance->descriptors.hub[7] = (port_desc >> RHDB_DR_SHIFT) & 0xff;
 	instance->descriptors.hub[8] = 0xff;
 	if (instance->interrupt_mask_size == 2) {
 		instance->descriptors.hub[8] =
-		    (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK >> 8;
+		    (port_desc >> RHDB_DR_SHIFT) >> 8;
 		instance->descriptors.hub[9]  = 0xff;
 		instance->descriptors.hub[10] = 0xff;
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize hub descriptors.
  *
@@ -341,11 +347,11 @@
 	    instance->interrupt_mask_size;
 
-	instance->descriptors.configuration.total_length =
+	instance->descriptors.configuration.total_length = uint16_host2usb(
 	    sizeof(usb_standard_configuration_descriptor_t) +
 	    sizeof(usb_standard_endpoint_descriptor_t) +
 	    sizeof(usb_standard_interface_descriptor_t) +
-	    instance->hub_descriptor_size;
-}
-/*----------------------------------------------------------------------------*/
+	    instance->hub_descriptor_size);
+}
+
 /**
  * Create bitmap of changes to answer status interrupt.
@@ -364,19 +370,19 @@
 
 	/* Only local power source change and over-current change can happen */
-	if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
+	if (OHCI_RD(instance->registers->rh_status)
+	    & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
 		mask |= 1;
 	}
 	for (size_t port = 1; port <= instance->port_count; ++port) {
 		/* Write-clean bits are those that indicate change */
-		if (RHPS_CHANGE_WC_MASK
-		    & instance->registers->rh_port_status[port - 1]) {
-
+		if (OHCI_RD(instance->registers->rh_port_status[port - 1])
+		    & RHPS_CHANGE_WC_MASK) {
 			mask |= (1 << port);
 		}
 	}
-	/* USB is little endian */
-	return host2uint32_t_le(mask);
-}
-/*----------------------------------------------------------------------------*/
+	usb_log_debug2("OHCI root hub interrupt mask: %hx.\n", mask);
+	return uint16_host2usb(mask);
+}
+
 /**
  * Create answer to status request.
@@ -396,4 +402,6 @@
 	usb_device_request_setup_packet_t *request_packet =
 	    (usb_device_request_setup_packet_t*)request->setup_buffer;
+
+	const uint16_t index = uint16_usb2host(request_packet->index);
 
 	switch (request_packet->request_type)
@@ -406,7 +414,8 @@
 			TRANSFER_END(request, EOVERFLOW);
 		} else {
-			uint32_t data = instance->registers->rh_status &
-			    (RHS_LPS_FLAG | RHS_LPSC_FLAG
-			        | RHS_OCI_FLAG | RHS_OCIC_FLAG);
+			const uint32_t data =
+			    OHCI_RD(instance->registers->rh_status) &
+			        (RHS_LPS_FLAG | RHS_LPSC_FLAG
+			            | RHS_OCI_FLAG | RHS_OCIC_FLAG);
 			TRANSFER_END_DATA(request, &data, sizeof(data));
 		}
@@ -420,10 +429,11 @@
 			TRANSFER_END(request, EOVERFLOW);
 		} else {
-			unsigned port = request_packet->index;
+			const unsigned port = index;
 			if (port < 1 || port > instance->port_count)
 				TRANSFER_END(request, EINVAL);
-
-			uint32_t data =
-			    instance->registers->rh_port_status[port - 1];
+			/* Register format matches the format of port status
+			 * field */
+			const uint32_t data = uint32_host2usb(OHCI_RD(
+			    instance->registers->rh_port_status[port - 1]));
 			TRANSFER_END_DATA(request, &data, sizeof(data));
 		}
@@ -434,5 +444,5 @@
 			TRANSFER_END(request, EOVERFLOW);
 		} else {
-			uint16_t data =
+			const uint16_t data =
 			    uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED);
 			TRANSFER_END_DATA(request, &data, sizeof(data));
@@ -441,10 +451,10 @@
 	case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE):
 		/* Hubs are allowed to have only one interface */
-		if (request_packet->index != 0)
+		if (index != 0)
 			TRANSFER_END(request, EINVAL);
 		/* Fall through, as the answer will be the same: 0x0000 */
 	case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT):
 		/* Endpoint 0 (default control) and 1 (interrupt) */
-		if (request_packet->index >= 2)
+		if (index >= 2)
 			TRANSFER_END(request, EINVAL);
 
@@ -455,5 +465,5 @@
 		} else {
 			/* Endpoints are OK. (We don't halt) */
-			uint16_t data = 0;
+			const uint16_t data = 0;
 			TRANSFER_END_DATA(request, &data, sizeof(data));
 		}
@@ -465,5 +475,5 @@
 
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Create answer to a descriptor request.
@@ -482,6 +492,8 @@
 	usb_device_request_setup_packet_t *setup_request =
 	    (usb_device_request_setup_packet_t *) request->setup_buffer;
-	uint16_t setup_request_value = setup_request->value_high;
-	switch (setup_request_value)
+	/* "The wValue field specifies the descriptor type in the high byte
+	 * and the descriptor index in the low byte (refer to Table 9-5)." */
+	const int desc_type = uint16_usb2host(setup_request->value) >> 8;
+	switch (desc_type)
 	{
 	case USB_DESCTYPE_HUB:
@@ -530,5 +542,5 @@
 		    setup_request->value,
 		    setup_request->request_type, setup_request->request,
-		    setup_request_value, setup_request->index,
+		    desc_type, setup_request->index,
 		    setup_request->length);
 		TRANSFER_END(request, EINVAL);
@@ -537,5 +549,5 @@
 	TRANSFER_END(request, ENOTSUP);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * process feature-enabling request on hub
@@ -554,21 +566,27 @@
 		return EINVAL;
 
-	switch (feature)
-	{
-	case USB_HUB_FEATURE_PORT_POWER:   //8
-		/* No power switching */
-		if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
-			return EOK;
-		/* Ganged power switching */
-		if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
-			instance->registers->rh_status = RHS_SET_GLOBAL_POWER;
-			return EOK;
+	switch (feature) {
+	case USB_HUB_FEATURE_PORT_POWER:   /*8*/
+		{
+			const uint32_t rhda =
+			    OHCI_RD(instance->registers->rh_desc_a);
+			/* No power switching */
+			if (rhda & RHDA_NPS_FLAG)
+				return EOK;
+			/* Ganged power switching, one port powers all */
+			if (!(rhda & RHDA_PSM_FLAG)) {
+				OHCI_WR(instance->registers->rh_status,
+				    RHS_SET_GLOBAL_POWER);
+				return EOK;
+			}
 		}
-	case USB_HUB_FEATURE_PORT_ENABLE:  //1
-	case USB_HUB_FEATURE_PORT_SUSPEND: //2
-	case USB_HUB_FEATURE_PORT_RESET:   //4
-		/* Nice thing is that these shifts correspond to the position
-		 * of control bits in register */
-		instance->registers->rh_port_status[port - 1] = (1 << feature);
+			/* Fall through */
+	case USB_HUB_FEATURE_PORT_ENABLE:  /*1*/
+	case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/
+	case USB_HUB_FEATURE_PORT_RESET:   /*4*/
+		usb_log_debug2("Setting port POWER, ENABLE, SUSPEND or RESET "
+		    "on port %"PRIu16".\n", port);
+		OHCI_WR(instance->registers->rh_port_status[port - 1],
+		    1 << feature);
 		return EOK;
 	default:
@@ -576,5 +594,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process feature clear request.
@@ -596,35 +614,42 @@
 	switch (feature)
 	{
-	case USB_HUB_FEATURE_PORT_POWER:          //8
-		/* No power switching */
-		if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
-			return ENOTSUP;
-		/* Ganged power switching */
-		if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
-			instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
+	case USB_HUB_FEATURE_PORT_POWER:          /*8*/
+		{
+			const uint32_t rhda =
+			    OHCI_RD(instance->registers->rh_desc_a);
+			/* No power switching */
+			if (rhda & RHDA_NPS_FLAG)
+				return ENOTSUP;
+			/* Ganged power switching, one port powers all */
+			if (!(rhda & RHDA_PSM_FLAG)) {
+				OHCI_WR(instance->registers->rh_status,
+				    RHS_CLEAR_GLOBAL_POWER);
+				return EOK;
+			}
+			OHCI_WR(instance->registers->rh_port_status[port - 1],
+			    RHPS_CLEAR_PORT_POWER);
 			return EOK;
 		}
-		instance->registers->rh_port_status[port - 1] =
-			RHPS_CLEAR_PORT_POWER;
+
+	case USB_HUB_FEATURE_PORT_ENABLE:         /*1*/
+		OHCI_WR(instance->registers->rh_port_status[port - 1],
+		    RHPS_CLEAR_PORT_ENABLE);
 		return EOK;
 
-	case USB_HUB_FEATURE_PORT_ENABLE:         //1
-		instance->registers->rh_port_status[port - 1] =
-			RHPS_CLEAR_PORT_ENABLE;
+	case USB_HUB_FEATURE_PORT_SUSPEND:        /*2*/
+		OHCI_WR(instance->registers->rh_port_status[port - 1],
+		    RHPS_CLEAR_PORT_SUSPEND);
 		return EOK;
 
-	case USB_HUB_FEATURE_PORT_SUSPEND:        //2
-		instance->registers->rh_port_status[port - 1] =
-			RHPS_CLEAR_PORT_SUSPEND;
-		return EOK;
-
-	case USB_HUB_FEATURE_C_PORT_CONNECTION:   //16
-	case USB_HUB_FEATURE_C_PORT_ENABLE:       //17
-	case USB_HUB_FEATURE_C_PORT_SUSPEND:      //18
-	case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: //19
-	case USB_HUB_FEATURE_C_PORT_RESET:        //20
-		/* Nice thing is that these shifts correspond to the position
-		 * of control bits in register */
-		instance->registers->rh_port_status[port - 1] = (1 << feature);
+	case USB_HUB_FEATURE_C_PORT_CONNECTION:   /*16*/
+	case USB_HUB_FEATURE_C_PORT_ENABLE:       /*17*/
+	case USB_HUB_FEATURE_C_PORT_SUSPEND:      /*18*/
+	case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: /*19*/
+	case USB_HUB_FEATURE_C_PORT_RESET:        /*20*/
+		usb_log_debug2("Clearing port C_CONNECTION, C_ENABLE, "
+		    "C_SUSPEND, C_OC or C_RESET on port %"PRIu16".\n", port);
+		/* Bit offsets correspond to the feature number */
+		OHCI_WR(instance->registers->rh_port_status[port - 1],
+		    1 << feature);
 		return EOK;
 
@@ -633,5 +658,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * process one of requests that do not request nor carry additional data
@@ -654,5 +679,5 @@
 	case USB_HUB_REQ_TYPE_SET_PORT_FEATURE:
 		usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
-		int ret = set_feature_port(instance,
+		const int ret = set_feature_port(instance,
 		    setup_request->value, setup_request->index);
 		TRANSFER_END(request, ret);
@@ -671,5 +696,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * process one of requests that do not request nor carry additional data
@@ -693,5 +718,5 @@
 	case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE:
 		usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n");
-		int ret = clear_feature_port(instance,
+		const int ret = clear_feature_port(instance,
 		    setup_request->value, setup_request->index);
 		TRANSFER_END(request, ret);
@@ -706,6 +731,7 @@
 		 * as root hubs do not support local power status feature.
 		 * (OHCI pg. 127) */
-		if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
-			instance->registers->rh_status = RHS_OCIC_FLAG;
+		if (uint16_usb2host(setup_request->value)
+		    == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
+			OHCI_WR(instance->registers->rh_status, RHS_OCIC_FLAG);
 			TRANSFER_END(request, EOK);
 		}
@@ -717,5 +743,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process hub control request.
@@ -771,5 +797,5 @@
 		if (request->buffer_size == 0)
 			TRANSFER_END(request, EOVERFLOW);
-		uint8_t config = 1;
+		const uint8_t config = 1;
 		TRANSFER_END_DATA(request, &config, sizeof(config));
 
@@ -790,10 +816,10 @@
 			TRANSFER_END(request, EINVAL);
 
-		instance->address = setup_request->value;
+		instance->address = uint16_usb2host(setup_request->value);
 		TRANSFER_END(request, EOK);
 
 	case USB_DEVREQ_SET_CONFIGURATION:
 		usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n",
-		    setup_request->value);
+		    uint16_usb2host(setup_request->value));
 		/* We have only one configuration, it's number is 1 */
 		if (uint16_usb2host(setup_request->value) != 1)
Index: uspace/drv/bus/usb/ohci/utils/malloc32.h
===================================================================
--- uspace/drv/bus/usb/ohci/utils/malloc32.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/ohci/utils/malloc32.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -63,5 +63,5 @@
 	return result;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Physical mallocator simulator
  *
@@ -71,5 +71,5 @@
 static inline void * malloc32(size_t size)
 	{ return memalign(OHCI_ALIGN, size); }
-/*----------------------------------------------------------------------------*/
+
 /** Physical mallocator simulator
  *
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -50,5 +50,5 @@
 static const irq_pio_range_t uhci_irq_pio_ranges[] = {
 	{
-		.base = 0,	/* filled later */
+		.base = 0,
 		.size = sizeof(uhci_regs_t)
 	}
@@ -56,10 +56,28 @@
 
 static const irq_cmd_t uhci_irq_commands[] = {
-	{ .cmd = CMD_PIO_READ_16, .dstarg = 1, .addr = NULL/*filled later*/},
-	{ .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2,
-	  .value = UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS },
-	{ .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
-	{ .cmd = CMD_PIO_WRITE_A_16, .srcarg = 1, .addr = NULL/*filled later*/},
-	{ .cmd = CMD_ACCEPT },
+	{
+		.cmd = CMD_PIO_READ_16,
+		.dstarg = 1,
+		.addr = NULL
+	},
+	{
+		.cmd = CMD_AND,
+		.srcarg = 1,
+		.dstarg = 2,
+		.value = UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.srcarg = 2,
+		.value = 2
+	},
+	{
+		.cmd = CMD_PIO_WRITE_A_16,
+		.srcarg = 1,
+		.addr = NULL
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
 };
 
@@ -72,5 +90,5 @@
 static int hc_debug_checker(void *arg);
 
-/*----------------------------------------------------------------------------*/
+
 /** Get number of PIO ranges used in IRQ code.
  * @return Number of ranges.
@@ -80,5 +98,5 @@
 	return sizeof(uhci_irq_pio_ranges) / sizeof(irq_pio_range_t);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Get number of commands used in IRQ code.
  * @return Number of commands.
@@ -88,5 +106,5 @@
 	return sizeof(uhci_irq_commands) / sizeof(irq_cmd_t);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Generate IRQ code.
  * @param[out] ranges PIO ranges buffer.
@@ -118,5 +136,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Take action based on the interrupt cause.
  *
@@ -175,5 +193,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize UHCI hc driver structure
  *
@@ -235,5 +253,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize UHCI hc hw resources.
  *
@@ -277,5 +295,5 @@
 	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize UHCI hc memory structures.
  *
@@ -319,5 +337,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize UHCI hc transfer lists.
  *
@@ -381,5 +399,5 @@
 #undef CHECK_RET_CLEAR_RETURN
 }
-/*----------------------------------------------------------------------------*/
+
 /** Schedule batch for execution.
  *
@@ -409,5 +427,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Polling function, emulates interrupts.
  *
@@ -432,5 +450,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Debug function, checks consistency of memory structures.
  *
Index: uspace/drv/bus/usb/uhci/hw_struct/queue_head.h
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/queue_head.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhci/hw_struct/queue_head.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,5 +47,5 @@
 	volatile link_pointer_t element;
 } __attribute__((packed)) qh_t;
-/*----------------------------------------------------------------------------*/
+
 /** Initialize queue head structure
  *
@@ -61,5 +61,5 @@
 	instance->next = LINK_POINTER_TERM;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Set queue head next pointer
  *
@@ -81,5 +81,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Set queue head element pointer
  *
Index: uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -107,5 +107,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Convert TD status into standard error code
  *
@@ -145,5 +145,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Print values in status field (dw1) in a human readable way.
  *
Index: uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -100,5 +100,5 @@
 
 void td_print_status(const td_t *instance);
-/*----------------------------------------------------------------------------*/
+
 /** Helper function for parsing actual size out of TD.
  *
@@ -113,5 +113,5 @@
 	return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Check whether less than max data were received on SPD marked transfer.
  *
@@ -129,5 +129,5 @@
 	    (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Helper function for parsing value of toggle bit.
  *
@@ -140,5 +140,5 @@
 	return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Helper function for parsing value of active bit
  *
@@ -151,5 +151,5 @@
 	return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Helper function for setting IOC bit.
  *
@@ -161,5 +161,5 @@
 	instance->status |= TD_STATUS_IOC_FLAG;
 }
-/*----------------------------------------------------------------------------*/
+
 #endif
 /**
Index: uspace/drv/bus/usb/uhci/main.c
===================================================================
--- uspace/drv/bus/usb/uhci/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhci/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -44,14 +44,14 @@
 
 static int uhci_dev_add(ddf_dev_t *device);
-/*----------------------------------------------------------------------------*/
+
 static driver_ops_t uhci_driver_ops = {
 	.dev_add = uhci_dev_add,
 };
-/*----------------------------------------------------------------------------*/
+
 static driver_t uhci_driver = {
 	.name = NAME,
 	.driver_ops = &uhci_driver_ops
 };
-/*----------------------------------------------------------------------------*/
+
 /** Initialize a new ddf driver instance for uhci hc and hub.
  *
@@ -70,10 +70,10 @@
 	} else {
 		usb_log_info("Controlling new UHCI device '%s'.\n",
-		    device->name);
+		    ddf_dev_get_name(device));
 	}
 
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize global driver structures (NONE).
  *
@@ -87,5 +87,5 @@
 {
 	printf(NAME ": HelenOS UHCI driver.\n");
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	log_init(NAME);
 
 	return ddf_driver_main(&uhci_driver);
Index: uspace/drv/bus/usb/uhci/res.c
===================================================================
--- uspace/drv/bus/usb/uhci/res.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhci/res.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -51,5 +51,5 @@
  * @return Error code.
  */
-int get_my_registers(const ddf_dev_t *dev,
+int get_my_registers(ddf_dev_t *dev,
     uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no)
 {
@@ -57,6 +57,6 @@
 
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
@@ -92,9 +92,9 @@
  * @return Error code.
  */
-int enable_interrupts(const ddf_dev_t *device)
+int enable_interrupts(ddf_dev_t *device)
 {
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
-	    IPC_FLAG_BLOCKING);
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
@@ -111,10 +111,10 @@
  * @return Error code.
  */
-int disable_legacy(const ddf_dev_t *device)
+int disable_legacy(ddf_dev_t *device)
 {
 	assert(device);
 
 	async_sess_t *parent_sess = devman_parent_device_connect(
-	    EXCHANGE_SERIALIZE, device->handle, IPC_FLAG_BLOCKING);
+	    EXCHANGE_SERIALIZE, ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
Index: uspace/drv/bus/usb/uhci/res.h
===================================================================
--- uspace/drv/bus/usb/uhci/res.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhci/res.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,7 +38,7 @@
 #include <ddf/driver.h>
 
-int get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
-int enable_interrupts(const ddf_dev_t *);
-int disable_legacy(const ddf_dev_t *);
+int get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int enable_interrupts(ddf_dev_t *);
+int disable_legacy(ddf_dev_t *);
 
 #endif
Index: uspace/drv/bus/usb/uhci/transfer_list.c
===================================================================
--- uspace/drv/bus/usb/uhci/transfer_list.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhci/transfer_list.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,5 +42,5 @@
 static void transfer_list_remove_batch(
     transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch);
-/*----------------------------------------------------------------------------*/
+
 /** Initialize transfer list structures.
  *
@@ -69,5 +69,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Dispose transfer list structures.
  *
@@ -97,5 +97,5 @@
 	qh_set_next_qh(instance->queue_head, next->queue_head);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Add transfer batch to the list and queue.
  *
@@ -144,5 +144,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Add completed batches to the provided list.
  *
@@ -171,5 +171,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Walk the list and finish all batches with EINTR.
  *
@@ -188,5 +188,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Remove a transfer batch from the list and queue.
  *
Index: uspace/drv/bus/usb/uhci/uhci.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,4 +33,8 @@
  * @brief UHCI driver
  */
+
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 #include <errno.h>
 #include <str_error.h>
@@ -60,10 +64,9 @@
 } uhci_t;
 
-static inline uhci_t * dev_to_uhci(const ddf_dev_t *dev)
-{
-	assert(dev);
-	return dev->driver_data;
-}
-/*----------------------------------------------------------------------------*/
+static inline uhci_t *dev_to_uhci(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
+}
+
 /** IRQ handling callback, forward status from call to diver structure.
  *
@@ -83,10 +86,10 @@
 	hc_interrupt(&uhci->hc, status);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Operations supported by the HC driver */
 static ddf_dev_ops_t hc_ops = {
 	.interfaces[USBHC_DEV_IFACE] = &hcd_iface, /* see iface.h/c */
 };
-/*----------------------------------------------------------------------------*/
+
 /** Gets handle of the respective hc.
  *
@@ -97,18 +100,17 @@
 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
 {
-	assert(fun);
-	ddf_fun_t *hc_fun = dev_to_uhci(fun->dev)->hc_fun;
+	ddf_fun_t *hc_fun = dev_to_uhci(ddf_fun_get_dev(fun))->hc_fun;
 	assert(hc_fun);
 
 	if (handle != NULL)
-		*handle = hc_fun->handle;
+		*handle = ddf_fun_get_handle(hc_fun);
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** USB interface implementation used by RH */
 static usb_iface_t usb_iface = {
 	.get_hc_handle = usb_iface_get_hc_handle,
 };
-/*----------------------------------------------------------------------------*/
+
 /** Get root hub hw resources (I/O registers).
  *
@@ -118,10 +120,9 @@
 static hw_resource_list_t *get_resource_list(ddf_fun_t *fun)
 {
-	assert(fun);
-	rh_t *rh = fun->driver_data;
+	rh_t *rh = ddf_fun_data_get(fun);
 	assert(rh);
 	return &rh->resource_list;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Interface to provide the root hub driver with hw info */
 static hw_res_ops_t hw_res_iface = {
@@ -129,5 +130,5 @@
 	.enable_interrupt = NULL,
 };
-/*----------------------------------------------------------------------------*/
+
 /** RH function support for uhci_rhd */
 static ddf_dev_ops_t rh_ops = {
@@ -135,5 +136,5 @@
 	.interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
 };
-/*----------------------------------------------------------------------------*/
+
 /** Initialize hc and rh DDF structures and their respective drivers.
  *
@@ -160,8 +161,6 @@
 if (ret != EOK) { \
 	if (instance->hc_fun) \
-		instance->hc_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->hc_fun); \
 	if (instance->rh_fun) {\
-		instance->rh_fun->driver_data = NULL; \
 		ddf_fun_destroy(instance->rh_fun); \
 	} \
@@ -174,12 +173,12 @@
 	int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
 	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n");
-	instance->hc_fun->ops = &hc_ops;
-	instance->hc_fun->driver_data = &instance->hc.generic;
+	ddf_fun_set_ops(instance->hc_fun, &hc_ops);
+	ddf_fun_data_implant(instance->hc_fun, &instance->hc.generic);
 
 	instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh");
 	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
 	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n");
-	instance->rh_fun->ops = &rh_ops;
-	instance->rh_fun->driver_data = &instance->rh;
+	ddf_fun_set_ops(instance->rh_fun, &rh_ops);
+	ddf_fun_data_implant(instance->rh_fun, &instance->rh);
 
 	uintptr_t reg_base = 0;
@@ -190,5 +189,5 @@
 	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed to get I/O addresses for %" PRIun ": %s.\n",
-	    device->handle, str_error(ret));
+	    ddf_dev_get_handle(device), str_error(ret));
 	usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n",
 	    (void *) reg_base, reg_size, irq);
Index: uspace/drv/bus/usb/uhci/uhci_batch.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci_batch.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhci/uhci_batch.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -58,5 +58,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Finishes usb_transfer_batch and destroys the structure.
  *
@@ -71,8 +71,8 @@
 	uhci_transfer_batch_dispose(uhci_batch);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Transfer batch setup table. */
 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t);
-/*----------------------------------------------------------------------------*/
+
 /** Allocate memory and initialize internal data structure.
  *
@@ -143,5 +143,5 @@
 	return uhci_batch;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Check batch TDs for activity.
  *
@@ -196,5 +196,5 @@
 	return true;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Direction to pid conversion table */
 static const usb_packet_id direction_pids[] = {
@@ -202,5 +202,5 @@
 	[USB_DIRECTION_OUT] = USB_PID_OUT,
 };
-/*----------------------------------------------------------------------------*/
+
 /** Prepare generic data transfer
  *
@@ -259,5 +259,5 @@
 	    USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch));
 }
-/*----------------------------------------------------------------------------*/
+
 /** Prepare generic control transfer
  *
@@ -331,5 +331,5 @@
 	    uhci_batch->tds[td].status);
 }
-/*----------------------------------------------------------------------------*/
+
 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t) =
 {
Index: uspace/drv/bus/usb/uhci/uhci_batch.h
===================================================================
--- uspace/drv/bus/usb/uhci/uhci_batch.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhci/uhci_batch.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -76,5 +76,5 @@
 	    uhci_batch->td_count * sizeof(td_t);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Get offset to data buffer accessible to the HC hw.
  * @param uhci_batch UHCI batch structure.
@@ -89,5 +89,5 @@
 	    uhci_batch->usb_batch->setup_size;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Aborts the batch.
  * Sets error to EINTR and size off transferd data to 0, before finishing the
@@ -103,5 +103,5 @@
 	uhci_transfer_batch_finish_dispose(uhci_batch);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Linked list conversion wrapper.
  * @param l Linked list link.
Index: uspace/drv/bus/usb/uhci/utils/malloc32.h
===================================================================
--- uspace/drv/bus/usb/uhci/utils/malloc32.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhci/utils/malloc32.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,10 +35,11 @@
 #define DRV_UHCI_UTILS_MALLOC32_H
 
+#include <as.h>
 #include <assert.h>
-#include <unistd.h>
+#include <ddi.h>
 #include <errno.h>
 #include <malloc.h>
 #include <mem.h>
-#include <as.h>
+#include <unistd.h>
 
 #define UHCI_STRCUTURES_ALIGNMENT 16
@@ -63,5 +64,5 @@
 	return result;
 }
-/*----------------------------------------------------------------------------*/
+
 /** DMA malloc simulator
  *
@@ -85,5 +86,5 @@
 	return memalign(alignment, size);
 }
-/*----------------------------------------------------------------------------*/
+
 /** DMA malloc simulator
  *
@@ -92,5 +93,5 @@
 static inline void free32(void *addr)
 	{ free(addr); }
-/*----------------------------------------------------------------------------*/
+
 /** Create 4KB page mapping
  *
@@ -99,16 +100,13 @@
 static inline void * get_page(void)
 {
-	void *address = as_area_create(AS_AREA_ANY, UHCI_REQUIRED_PAGE_SIZE,
-	    AS_AREA_READ | AS_AREA_WRITE);
-	if (address == AS_MAP_FAILED)
-		return NULL;
-	
-	return address;
+	void *address, *phys;
+	const int ret = dmamem_map_anonymous(UHCI_REQUIRED_PAGE_SIZE,
+	    AS_AREA_READ | AS_AREA_WRITE, 0, &phys, &address);
+	return ret == EOK ? address : NULL;
 }
-/*----------------------------------------------------------------------------*/
+
 static inline void return_page(void *page)
 {
-	if (page)
-		as_area_destroy(page);
+	dmamem_unmap_anonymous(page);
 }
 
Index: uspace/drv/bus/usb/uhcirh/main.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhcirh/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -48,5 +48,5 @@
 #define NAME "uhcirh"
 
-static int hc_get_my_registers(const ddf_dev_t *dev,
+static int hc_get_my_registers(ddf_dev_t *dev,
     uintptr_t *io_reg_address, size_t *io_reg_size);
 
@@ -73,5 +73,5 @@
 {
 	printf(NAME ": HelenOS UHCI root hub driver.\n");
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	log_init(NAME);
 	return ddf_driver_main(&uhci_rh_driver);
 }
@@ -88,5 +88,5 @@
 
 	usb_log_debug2("uhci_rh_dev_add(handle=%" PRIun ")\n",
-	    device->handle);
+	    ddf_dev_get_handle(device));
 
 	uintptr_t io_regs = 0;
@@ -98,6 +98,4 @@
 if (ret != EOK) { \
 	usb_log_error(message); \
-	if (rh) \
-		free(rh); \
 	return ret; \
 } else (void)0
@@ -109,5 +107,5 @@
 	    (void *) io_regs, io_size);
 
-	rh = malloc(sizeof(uhci_root_hub_t));
+	rh = ddf_dev_data_alloc(device, sizeof(uhci_root_hub_t));
 	ret = (rh == NULL) ? ENOMEM : EOK;
 	CHECK_RET_FREE_RH_RETURN(ret,
@@ -119,7 +117,6 @@
 	    ret, str_error(ret));
 
-	device->driver_data = rh;
 	usb_log_info("Controlling root hub '%s' (%" PRIun ").\n",
-	    device->name, device->handle);
+	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
 	return EOK;
 }
@@ -133,11 +130,9 @@
  */
 int hc_get_my_registers(
-    const ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size)
+    ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size)
 {
-	assert(dev);
-
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
 	if (!parent_sess)
 		return ENOMEM;
Index: uspace/drv/bus/usb/uhcirh/port.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/port.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhcirh/port.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -63,5 +63,5 @@
 	return pio_read_16(port->address);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Register writing helper function.
  *
@@ -75,5 +75,5 @@
 	pio_write_16(port->address, val);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize UHCI root hub port instance.
  *
@@ -127,5 +127,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Cleanup UHCI root hub port instance.
  *
@@ -141,5 +141,5 @@
 	return;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Periodically checks port status and reports new devices.
  *
@@ -210,5 +210,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback for enabling port during adding a new device.
  *
@@ -247,5 +247,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize and report connected device.
  *
@@ -279,8 +279,8 @@
 	usb_log_info("%s: New device, address %d (handle %" PRIun ").\n",
 	    port->id_string, port->attached_device.address,
-	    port->attached_device.fun->handle);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
+	    ddf_fun_get_handle(port->attached_device.fun));
+	return EOK;
+}
+
 /** Remove device.
  *
@@ -324,5 +324,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Enable or disable root hub port.
  *
@@ -358,5 +358,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Print the port status value in a human friendly way
  *
Index: uspace/drv/bus/usb/uhcirh/root_hub.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/root_hub.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/uhcirh/root_hub.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -79,5 +79,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Cleanup UHCI root hub instance.
  *
@@ -92,5 +92,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * @}
Index: uspace/drv/bus/usb/usbflbk/main.c
===================================================================
--- uspace/drv/bus/usb/usbflbk/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbflbk/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -69,5 +69,5 @@
 	    " (node `%s', handle %" PRIun ").\n",
 	    dev->interface_no < 0 ? "device" : "interface",
-	    dev->ddf_dev->name, fun_name, dev->ddf_dev->handle);
+	    ddf_dev_get_name(dev->ddf_dev), fun_name, ddf_dev_get_handle(dev->ddf_dev));
 
 	return EOK;
@@ -85,5 +85,5 @@
 	const int ret = ddf_fun_unbind(ctl_fun);
 	if (ret != EOK) {
-		usb_log_error("Failed to unbind %s.\n", ctl_fun->name);
+		usb_log_error("Failed to unbind %s.\n", ddf_fun_get_name(ctl_fun));
 		return ret;
 	}
@@ -110,5 +110,5 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	log_init(NAME);
 
 	return usb_driver_main(&usbfallback_driver);
Index: uspace/drv/bus/usb/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,4 +35,7 @@
  */
 
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 #include <usb/debug.h>
 #include <usb/classes/classes.h>
@@ -46,5 +49,5 @@
 #include "usbhid.h"
 
-/*----------------------------------------------------------------------------*/
+
 
 const usb_endpoint_description_t usb_hid_generic_poll_endpoint_description = {
@@ -60,5 +63,5 @@
 const char *HID_GENERIC_CLASS_NAME = "hid";
 
-/*----------------------------------------------------------------------------*/
+
 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun);
 static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer,
@@ -68,5 +71,5 @@
 static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc,
     size_t size, size_t *actual_size);
-/*----------------------------------------------------------------------------*/
+
 static usbhid_iface_t usb_generic_iface = {
 	.get_event = usb_generic_hid_get_event,
@@ -75,20 +78,26 @@
 	.get_report_descriptor = usb_generic_get_report_descriptor
 };
-/*----------------------------------------------------------------------------*/
+
 static ddf_dev_ops_t usb_generic_hid_ops = {
 	.interfaces[USBHID_DEV_IFACE] = &usb_generic_iface,
 	.open = usb_generic_hid_client_connected
 };
-/*----------------------------------------------------------------------------*/
+
+/** Return hid_dev_t * for generic HID function node.
+ *
+ * For the generic HID subdriver the 'hid' function has usb_hid_gen_fun_t
+ * as soft state. Through that we can get to the usb_hid_dev_t.
+ */
+static usb_hid_dev_t *fun_hid_dev(ddf_fun_t *fun)
+{
+	return ((usb_hid_gen_fun_t *)ddf_fun_data_get(fun))->hid_dev;
+}
+
 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)
 {
 	usb_log_debug2("Generic HID: Get event length (fun: %p, "
-	    "fun->driver_data: %p.\n", fun, fun->driver_data);
-
-	if (fun == NULL || fun->driver_data == NULL) {
-		return 0;
-	}
-
-	const usb_hid_dev_t *hid_dev = fun->driver_data;
+	    "fun->driver_data: %p.\n", fun, ddf_fun_data_get(fun));
+
+	const usb_hid_dev_t *hid_dev = fun_hid_dev(fun);
 
 	usb_log_debug2("hid_dev: %p, Max input report size (%zu).\n",
@@ -97,5 +106,5 @@
 	return hid_dev->max_input_report_size;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer,
     size_t size, size_t *act_size, int *event_nr, unsigned int flags)
@@ -103,11 +112,10 @@
 	usb_log_debug2("Generic HID: Get event.\n");
 
-	if (fun == NULL || fun->driver_data == NULL || buffer == NULL
-	    || act_size == NULL || event_nr == NULL) {
+	if (buffer == NULL || act_size == NULL || event_nr == NULL) {
 		usb_log_debug("No function");
 		return EINVAL;
 	}
 
-	const usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	const usb_hid_dev_t *hid_dev = fun_hid_dev(fun);
 
 	if (hid_dev->input_report_size > size) {
@@ -127,15 +135,10 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun)
 {
 	usb_log_debug("Generic HID: Get report descriptor length.\n");
 
-	if (fun == NULL || fun->driver_data == NULL) {
-		usb_log_debug("No function");
-		return EINVAL;
-	}
-
-	const usb_hid_dev_t *hid_dev = fun->driver_data;
+	const usb_hid_dev_t *hid_dev = fun_hid_dev(fun);
 
 	usb_log_debug2("hid_dev->report_desc_size = %zu\n",
@@ -144,5 +147,5 @@
 	return hid_dev->report_desc_size;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc,
     size_t size, size_t *actual_size)
@@ -150,10 +153,5 @@
 	usb_log_debug2("Generic HID: Get report descriptor.\n");
 
-	if (fun == NULL || fun->driver_data == NULL) {
-		usb_log_debug("No function");
-		return EINVAL;
-	}
-
-	const usb_hid_dev_t *hid_dev = fun->driver_data;
+	const usb_hid_dev_t *hid_dev = fun_hid_dev(fun);
 
 	if (hid_dev->report_desc_size > size) {
@@ -166,5 +164,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_generic_hid_client_connected(ddf_fun_t *fun)
 {
@@ -172,5 +170,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_generic_hid_deinit(usb_hid_dev_t *hid_dev, void *data)
 {
@@ -183,13 +181,12 @@
 		return;
 	}
-	usb_log_debug2("%s unbound.\n", fun->name);
-	/* We did not allocate this, so leave this alone
-	 * the device would take care of it */
-	fun->driver_data = NULL;
+	usb_log_debug2("%s unbound.\n", ddf_fun_get_name(fun));
 	ddf_fun_destroy(fun);
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data)
 {
+	usb_hid_gen_fun_t *hid_fun;
+
 	if (hid_dev == NULL) {
 		return EINVAL;
@@ -205,8 +202,8 @@
 	}
 
-	/* This is nasty, both device and this function have the same
-	 * driver data, thus destruction causes to double free */
-	fun->driver_data = hid_dev;
-	fun->ops = &usb_generic_hid_ops;
+	/* Create softstate */
+	hid_fun = ddf_fun_data_alloc(fun, sizeof(usb_hid_gen_fun_t));
+	hid_fun->hid_dev = hid_dev;
+	ddf_fun_set_ops(fun, &usb_generic_hid_ops);
 
 	int rc = ddf_fun_bind(fun);
@@ -214,15 +211,15 @@
 		usb_log_error("Could not bind DDF function: %s.\n",
 		    str_error(rc));
-		fun->driver_data = NULL;
 		ddf_fun_destroy(fun);
 		return rc;
 	}
 
-	usb_log_debug("HID function created. Handle: %" PRIun "\n", fun->handle);
+	usb_log_debug("HID function created. Handle: %" PRIun "\n",
+	    ddf_fun_get_handle(fun));
 	*data = fun;
 
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, void *data)
 {
Index: uspace/drv/bus/usb/usbhid/generic/hiddev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/generic/hiddev.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/generic/hiddev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,5 +47,8 @@
 const char *HID_GENERIC_CLASS_NAME;
 
-/*----------------------------------------------------------------------------*/
+/** The USB HID generic 'hid' function softstate */
+typedef struct {
+	struct usb_hid_dev *hid_dev;
+} usb_hid_gen_fun_t;
 
 int usb_generic_hid_init(struct usb_hid_dev *hid_dev, void **data);
Index: uspace/drv/bus/usb/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -34,4 +34,7 @@
  * USB HID keyboard device structure and API.
  */
+
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
 
 #include <errno.h>
@@ -71,5 +74,7 @@
 #include "../usbhid.h"
 
-/*----------------------------------------------------------------------------*/
+static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
+static ddf_dev_ops_t kbdops = { .default_handler = default_connection_handler };
+
 
 static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
@@ -86,5 +91,5 @@
 static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;
 
-/*----------------------------------------------------------------------------*/
+
 /** Keyboard polling endpoint description for boot protocol class. */
 const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
@@ -101,5 +106,5 @@
 
 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
-/*----------------------------------------------------------------------------*/
+
 static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[] = {
 	0x05, 0x01,  /* Usage Page (Generic Desktop), */
@@ -136,5 +141,5 @@
 	0xC0         /* End Collection */
 };
-/*----------------------------------------------------------------------------*/
+
 typedef enum usb_kbd_flags {
 	USB_KBD_STATUS_UNINITIALIZED = 0,
@@ -142,7 +147,7 @@
 	USB_KBD_STATUS_TO_DESTROY = -1
 } usb_kbd_flags;
-/*----------------------------------------------------------------------------*/
+
 /* IPC method handler                                                         */
-/*----------------------------------------------------------------------------*/
+
 /**
  * Default handler for IPC methods not handled by DDF.
@@ -160,12 +165,6 @@
     ipc_callid_t icallid, ipc_call_t *icall)
 {
-	if (fun == NULL || fun->driver_data == NULL) {
-		usb_log_error("%s: Missing parameter.\n", __FUNCTION__);
-		async_answer_0(icallid, EINVAL);
-		return;
-	}
-
 	const sysarg_t method = IPC_GET_IMETHOD(*icall);
-	usb_kbd_t *kbd_dev = fun->driver_data;
+	usb_kbd_t *kbd_dev = ddf_fun_data_get(fun);
 
 	switch (method) {
@@ -187,6 +186,6 @@
 			break;
 		}
-		if (kbd_dev->console_sess == NULL) {
-			kbd_dev->console_sess = sess;
+		if (kbd_dev->client_sess == NULL) {
+			kbd_dev->client_sess = sess;
 			usb_log_debug("%s: OK\n", __FUNCTION__);
 			async_answer_0(icallid, EOK);
@@ -206,7 +205,7 @@
 
 }
-/*----------------------------------------------------------------------------*/
+
 /* Key processing functions                                                   */
-/*----------------------------------------------------------------------------*/
+
 /**
  * Handles turning of LED lights on and off.
@@ -281,5 +280,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Send key event.
  *
@@ -292,5 +291,5 @@
 {
 	usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
-	if (kbd_dev->console_sess == NULL) {
+	if (kbd_dev->client_sess == NULL) {
 		usb_log_warning(
 		    "Connection to console not ready, key discarded.\n");
@@ -298,5 +297,5 @@
 	}
 
-	async_exch_t *exch = async_exchange_begin(kbd_dev->console_sess);
+	async_exch_t *exch = async_exchange_begin(kbd_dev->client_sess);
 	if (exch != NULL) {
 		async_msg_2(exch, KBDEV_EVENT, type, key);
@@ -306,5 +305,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 static inline int usb_kbd_is_lock(unsigned int key_code)
 {
@@ -313,5 +312,5 @@
 	    || key_code == KC_CAPS_LOCK);
 }
-/*----------------------------------------------------------------------------*/
+
 static size_t find_in_array_int32(int32_t val, int32_t *arr, size_t arr_size)
 {
@@ -324,5 +323,5 @@
 	return (size_t) -1;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Checks if some keys were pressed or released and generates key events.
@@ -407,7 +406,7 @@
 	usb_log_debug2("Stored keys %s.\n", key_buffer);
 }
-/*----------------------------------------------------------------------------*/
+
 /* General kbd functions                                                      */
-/*----------------------------------------------------------------------------*/
+
 /**
  * Processes data received from the device in form of report.
@@ -479,7 +478,7 @@
 	usb_kbd_check_key_changes(hid_dev, kbd_dev);
 }
-/*----------------------------------------------------------------------------*/
+
 /* HID/KBD structure manipulation                                             */
-/*----------------------------------------------------------------------------*/
+
 static int usb_kbd_create_function(usb_kbd_t *kbd_dev)
 {
@@ -499,6 +498,6 @@
 	/* Store the initialized HID device and HID ops
 	 * to the DDF function. */
-	fun->ops = &kbd_dev->ops;
-	fun->driver_data = kbd_dev;
+	ddf_fun_set_ops(fun, &kbdops);
+	ddf_fun_data_implant(fun, kbd_dev);
 
 	int rc = ddf_fun_bind(fun);
@@ -506,5 +505,4 @@
 		usb_log_error("Could not bind DDF function: %s.\n",
 		    str_error(rc));
-		fun->driver_data = NULL; /* We did not allocate this. */
 		ddf_fun_destroy(fun);
 		return rc;
@@ -512,5 +510,5 @@
 
 	usb_log_debug("%s function created. Handle: %" PRIun "\n",
-	    HID_KBD_FUN_NAME, fun->handle);
+	    HID_KBD_FUN_NAME, ddf_fun_get_handle(fun));
 
 	usb_log_debug("Adding DDF function to category %s...\n",
@@ -522,10 +520,9 @@
 		    HID_KBD_CLASS_NAME, str_error(rc));
 		if (ddf_fun_unbind(fun) == EOK) {
-			fun->driver_data = NULL; /* We did not allocate this. */
 			ddf_fun_destroy(fun);
 		} else {
 			usb_log_error(
 			    "Failed to unbind `%s', will not destroy.\n",
-			    fun->name);
+			    ddf_fun_get_name(fun));
 		}
 		return rc;
@@ -535,7 +532,7 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /* API functions                                                              */
-/*----------------------------------------------------------------------------*/
+
 /**
  * Initialization of the USB/HID keyboard structure.
@@ -576,5 +573,4 @@
 	fibril_mutex_initialize(&kbd_dev->repeat_mtx);
 	kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
-	kbd_dev->ops.default_handler = default_connection_handler;
 
 	/* Store link to HID device */
@@ -700,5 +696,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data)
 {
@@ -714,15 +710,15 @@
 	return true;
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
 {
 	return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
 {
 	return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Properly destroys the USB/HID keyboard structure.
@@ -737,6 +733,6 @@
 
 	/* Hangup session to the console. */
-	if (kbd_dev->console_sess)
-		async_hangup(kbd_dev->console_sess);
+	if (kbd_dev->client_sess)
+		async_hangup(kbd_dev->client_sess);
 
 	//assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
@@ -756,14 +752,13 @@
 		if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
 			usb_log_warning("Failed to unbind %s.\n",
-			    kbd_dev->fun->name);
+			    ddf_fun_get_name(kbd_dev->fun));
 		} else {
-			usb_log_debug2("%s unbound.\n", kbd_dev->fun->name);
-			kbd_dev->fun->driver_data = NULL;
+			usb_log_debug2("%s unbound.\n",
+			    ddf_fun_get_name(kbd_dev->fun));
 			ddf_fun_destroy(kbd_dev->fun);
 		}
 	}
-	free(kbd_dev);
-}
-/*----------------------------------------------------------------------------*/
+}
+
 void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
 {
@@ -778,5 +773,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
 {
Index: uspace/drv/bus/usb/usbhid/kbd/kbddev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbddev.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/kbd/kbddev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -50,5 +50,5 @@
 struct usb_hid_dev;
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * USB/HID keyboard device type.
@@ -82,9 +82,6 @@
 	unsigned lock_keys;
 
-	/** IPC session to the console device (for sending key events). */
-	async_sess_t *console_sess;
-
-	/** @todo What is this actually? */
-	ddf_dev_ops_t ops;
+	/** IPC session to client (for sending key events). */
+	async_sess_t *client_sess;
 
 	/** Information for auto-repeat of keys. */
@@ -116,5 +113,5 @@
 } usb_kbd_t;
 
-/*----------------------------------------------------------------------------*/
+
 
 extern const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description;
@@ -123,5 +120,5 @@
 const char *HID_KBD_CLASS_NAME;
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_kbd_init(struct usb_hid_dev *hid_dev, void **data);
Index: uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -105,5 +105,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Main routine to be executed by a fibril for handling auto-repeat.
@@ -132,5 +132,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Start repeating particular key.
@@ -149,5 +149,5 @@
 	fibril_mutex_unlock(&kbd->repeat_mtx);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Stop repeating particular key.
Index: uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,5 +42,5 @@
 struct usb_kbd_t;
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Structure for keeping information needed for auto-repeat of keys.
@@ -57,5 +57,5 @@
 } usb_kbd_repeat_t;
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_kbd_repeat_fibril(void *arg);
Index: uspace/drv/bus/usb/usbhid/main.c
===================================================================
--- uspace/drv/bus/usb/usbhid/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -103,5 +103,5 @@
 	if (rc != EOK) {
 		usb_log_error("Failed to start polling fibril for `%s'.\n",
-		    dev->ddf_dev->name);
+		    ddf_dev_get_name(dev->ddf_dev));
 		usb_hid_deinit(hid_dev);
 		return rc;
@@ -109,9 +109,10 @@
 	hid_dev->running = true;
 
-	usb_log_info("HID device `%s' ready to use.\n", dev->ddf_dev->name);
+	usb_log_info("HID device `%s' ready to use.\n",
+	    ddf_dev_get_name(dev->ddf_dev));
 
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Callback for a device about to be removed from the driver.
@@ -126,5 +127,5 @@
 	return ENOTSUP;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Callback for removing a device from the driver.
@@ -149,8 +150,8 @@
 
 	usb_hid_deinit(hid_dev);
-	usb_log_debug2("%s destruction complete.\n", dev->ddf_dev->name);
+	usb_log_debug2("%s destruction complete.\n", ddf_dev_get_name(dev->ddf_dev));
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** USB generic driver callbacks */
 static const usb_driver_ops_t usb_hid_driver_ops = {
@@ -159,5 +160,5 @@
 	.device_gone = usb_hid_device_gone,
 };
-/*----------------------------------------------------------------------------*/
+
 /** The driver itself. */
 static const usb_driver_t usb_hid_driver = {
@@ -166,10 +167,10 @@
         .endpoints = usb_hid_endpoints
 };
-/*----------------------------------------------------------------------------*/
+
 int main(int argc, char *argv[])
 {
 	printf(NAME ": HelenOS USB HID driver.\n");
 
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	log_init(NAME);
 
 	return usb_driver_main(&usb_hid_driver);
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,4 +35,7 @@
  */
 
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 #include <usb/debug.h>
 #include <usb/classes/classes.h>
@@ -54,5 +57,8 @@
 #define NAME "mouse"
 
-/*----------------------------------------------------------------------------*/
+static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
+
+static ddf_dev_ops_t ops = { .default_handler = default_connection_handler };
+
 
 const usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
@@ -71,5 +77,5 @@
 static const uint8_t IDLE_RATE = 0;
 
-/*----------------------------------------------------------------------------*/
+
 static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[] = {
 	0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
@@ -101,5 +107,5 @@
 };
 
-/*----------------------------------------------------------------------------*/
+
 
 /** Default handler for IPC methods not handled by DDF.
@@ -112,5 +118,5 @@
     ipc_callid_t icallid, ipc_call_t *icall)
 {
-	usb_mouse_t *mouse_dev = fun->driver_data;
+	usb_mouse_t *mouse_dev = ddf_fun_data_get(fun);
 
 	if (mouse_dev == NULL) {
@@ -120,5 +126,5 @@
 	}
 
-	usb_log_debug("%s: fun->name: %s\n", __FUNCTION__, fun->name);
+	usb_log_debug("%s: fun->name: %s\n", __FUNCTION__, ddf_fun_get_name(fun));
 	usb_log_debug("%s: mouse_sess: %p\n",
 	    __FUNCTION__, mouse_dev->mouse_sess);
@@ -130,9 +136,9 @@
 			mouse_dev->mouse_sess = sess;
 			usb_log_debug("Console session to %s set ok (%p).\n",
-			    fun->name, sess);
+			    ddf_fun_get_name(fun), sess);
 			async_answer_0(icallid, EOK);
 		} else {
 			usb_log_error("Console session to %s already set.\n",
-			    fun->name);
+			    ddf_fun_get_name(fun));
 			async_answer_0(icallid, ELIMIT);
 			async_hangup(sess);
@@ -143,5 +149,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 static int get_mouse_axis_move_value(uint8_t rid, usb_hid_report_t *report,
     int32_t usage)
@@ -221,20 +227,10 @@
 		assert(index < mouse_dev->buttons_count);
 
-		if (mouse_dev->buttons[index] == 0 && field->value != 0) {
+		if (mouse_dev->buttons[index] != field->value) {
 			async_exch_t *exch =
 			    async_exchange_begin(mouse_dev->mouse_sess);
 			if (exch != NULL) {
 				async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
-				    field->usage, 1);
-				async_exchange_end(exch);
-				mouse_dev->buttons[index] = field->value;
-			}
-
-		} else if (mouse_dev->buttons[index] != 0 && field->value == 0) {
-			async_exch_t *exch =
-			    async_exchange_begin(mouse_dev->mouse_sess);
-			if (exch != NULL) {
-				async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
-				    field->usage, 0);
+				    field->usage, (field->value != 0) ? 1 : 0);
 				async_exchange_end(exch);
 				mouse_dev->buttons[index] = field->value;
@@ -252,16 +248,15 @@
 	return true;
 }
-/*----------------------------------------------------------------------------*/
+
 #define FUN_UNBIND_DESTROY(fun) \
 if (fun) { \
 	if (ddf_fun_unbind((fun)) == EOK) { \
-		(fun)->driver_data = NULL; \
 		ddf_fun_destroy((fun)); \
 	} else { \
 		usb_log_error("Could not unbind function `%s', it " \
-		    "will not be destroyed.\n", (fun)->name); \
+		    "will not be destroyed.\n", ddf_fun_get_name(fun)); \
 	} \
 } else (void)0
-/*----------------------------------------------------------------------------*/
+
 static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse)
 {
@@ -279,12 +274,11 @@
 	}
 
-	fun->ops = &mouse->ops;
-	fun->driver_data = mouse;
+	ddf_fun_set_ops(fun, &ops);
+	ddf_fun_data_implant(fun, mouse);
 
 	int rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
 		usb_log_error("Could not bind DDF function `%s': %s.\n",
-		    fun->name, str_error(rc));
-		fun->driver_data = NULL;
+		    ddf_fun_get_name(fun), str_error(rc));
 		ddf_fun_destroy(fun);
 		return rc;
@@ -292,5 +286,5 @@
 
 	usb_log_debug("Adding DDF function `%s' to category %s...\n",
-	    fun->name, HID_MOUSE_CATEGORY);
+	    ddf_fun_get_name(fun), HID_MOUSE_CATEGORY);
 	rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
 	if (rc != EOK) {
@@ -302,5 +296,4 @@
 	}
 	mouse->mouse_fun = fun;
-
 	return EOK;
 }
@@ -345,5 +338,5 @@
 	return highest_button;
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
 {
@@ -379,7 +372,4 @@
 	}
 
-	// set handler for incoming calls
-	mouse_dev->ops.default_handler = default_connection_handler;
-
 	// TODO: how to know if the device supports the request???
 	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
@@ -398,5 +388,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data)
 {
@@ -411,5 +401,5 @@
 	return usb_mouse_process_report(hid_dev, mouse_dev);
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data)
 {
@@ -430,7 +420,6 @@
 
 	free(mouse_dev->buttons);
-	free(mouse_dev);
-}
-/*----------------------------------------------------------------------------*/
+}
+
 int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
 {
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,9 +42,9 @@
 struct usb_hid_dev;
 
-/*----------------------------------------------------------------------------*/
+
 
 /** Container for USB mouse device. */
 typedef struct {
-	/** IPC session to console (consumer). */
+	/** IPC session to consumer. */
 	async_sess_t *mouse_sess;
 
@@ -53,10 +53,9 @@
 	size_t buttons_count;
 
-	ddf_dev_ops_t ops;
 	/* DDF mouse function */
 	ddf_fun_t *mouse_fun;
 } usb_mouse_t;
 
-/*----------------------------------------------------------------------------*/
+
 
 extern const usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description;
@@ -65,5 +64,5 @@
 const char *HID_MOUSE_CATEGORY;
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_mouse_init(struct usb_hid_dev *hid_dev, void **data);
@@ -75,5 +74,5 @@
 int usb_mouse_set_boot_protocol(struct usb_hid_dev *hid_dev);
 
-/*----------------------------------------------------------------------------*/
+
 
 #endif // USB_HID_MOUSEDEV_H_
Index: uspace/drv/bus/usb/usbhid/multimedia/multimedia.c
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -54,5 +54,5 @@
 #define NAME  "multimedia-keys"
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Logitech UltraX device type.
@@ -70,5 +70,5 @@
 
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Default handler for IPC methods not handled by DDF.
@@ -86,10 +86,6 @@
 {
 	usb_log_debug(NAME " default_connection_handler()\n");
-	if (fun == NULL || fun->driver_data == NULL) {
-		async_answer_0(icallid, EINVAL);
-		return;
-	}
-
-	usb_multimedia_t *multim_dev = fun->driver_data;
+
+	usb_multimedia_t *multim_dev = ddf_fun_data_get(fun);
 
 	async_sess_t *sess =
@@ -106,9 +102,9 @@
 		async_answer_0(icallid, EINVAL);
 }
-/*----------------------------------------------------------------------------*/
+
 static ddf_dev_ops_t multimedia_ops = {
 	.default_handler = default_connection_handler
 };
-/*----------------------------------------------------------------------------*/
+
 /**
  * Processes key events.
@@ -155,5 +151,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
 {
@@ -172,5 +168,5 @@
 	}
 
-	fun->ops = &multimedia_ops;
+	ddf_fun_set_ops(fun, &multimedia_ops);
 
 	usb_multimedia_t *multim_dev =
@@ -194,5 +190,5 @@
 
 	usb_log_debug(NAME " function created (handle: %" PRIun ").\n",
-	    fun->handle);
+	    ddf_fun_get_handle(fun));
 
 	rc = ddf_fun_add_to_category(fun, "keyboard");
@@ -203,5 +199,5 @@
 		if (ddf_fun_unbind(fun) != EOK) {
 			usb_log_error("Failed to unbind %s, won't destroy.\n",
-			    fun->name);
+			    ddf_fun_get_name(fun));
 		} else {
 			ddf_fun_destroy(fun);
@@ -216,37 +212,34 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data)
 {
 	ddf_fun_t *fun = data;
-	if (fun != NULL && fun->driver_data != NULL) {
-		usb_multimedia_t *multim_dev = fun->driver_data;
-		/* Hangup session to the console */
-		if (multim_dev->console_sess)
-			async_hangup(multim_dev->console_sess);
-		if (ddf_fun_unbind(fun) != EOK) {
-			usb_log_error("Failed to unbind %s, won't destroy.\n",
-			    fun->name);
-		} else {
-			usb_log_debug2("%s unbound.\n", fun->name);
-			/* This frees multim_dev too as it was stored in
-			 * fun->data */
-			ddf_fun_destroy(fun);
-		}
+
+	usb_multimedia_t *multim_dev = ddf_fun_data_get(fun);
+
+	/* Hangup session to the console */
+	if (multim_dev->console_sess)
+		async_hangup(multim_dev->console_sess);
+	if (ddf_fun_unbind(fun) != EOK) {
+		usb_log_error("Failed to unbind %s, won't destroy.\n",
+		    ddf_fun_get_name(fun));
 	} else {
-		usb_log_error(
-		    "Failed to deinit multimedia subdriver, data missing.\n");
-	}
-}
-/*----------------------------------------------------------------------------*/
+		usb_log_debug2("%s unbound.\n", ddf_fun_get_name(fun));
+		/* This frees multim_dev too as it was stored in
+		 * fun->data */
+		ddf_fun_destroy(fun);
+	}
+}
+
 bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data)
 {
 	// TODO: checks
 	ddf_fun_t *fun = data;
-	if (hid_dev == NULL || fun == NULL || fun->driver_data == NULL) {
+	if (hid_dev == NULL) {
 		return false;
 	}
 
-	usb_multimedia_t *multim_dev = fun->driver_data;
+	usb_multimedia_t *multim_dev = ddf_fun_data_get(fun);
 
 	usb_hid_report_path_t *path = usb_hid_report_path();
Index: uspace/drv/bus/usb/usbhid/multimedia/multimedia.h
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/multimedia.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/multimedia/multimedia.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,5 +41,5 @@
 struct usb_hid_dev;
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data);
@@ -49,5 +49,5 @@
 bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data);
 
-/*----------------------------------------------------------------------------*/
+
 
 #endif // USB_HID_MULTIMEDIA_H_
Index: uspace/drv/bus/usb/usbhid/subdrivers.h
===================================================================
--- uspace/drv/bus/usb/usbhid/subdrivers.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/subdrivers.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,5 +40,5 @@
 #include "kbd/kbddev.h"
 
-/*----------------------------------------------------------------------------*/
+
 
 typedef struct usb_hid_subdriver_usage {
@@ -47,5 +47,5 @@
 } usb_hid_subdriver_usage_t;
 
-/*----------------------------------------------------------------------------*/
+
 
 /** Structure representing the mapping between device requirements and the 
@@ -81,10 +81,10 @@
 } usb_hid_subdriver_mapping_t;
 
-/*----------------------------------------------------------------------------*/
+
 
 extern const usb_hid_subdriver_mapping_t usb_hid_subdrivers[];
 extern const size_t USB_HID_MAX_SUBDRIVERS;
 
-/*----------------------------------------------------------------------------*/
+
 
 #endif /* USB_HID_SUBDRIVERS_H_ */
Index: uspace/drv/bus/usb/usbhid/usbhid.c
===================================================================
--- uspace/drv/bus/usb/usbhid/usbhid.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/usbhid.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -58,5 +58,5 @@
 	NULL
 };
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
 {
@@ -74,5 +74,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
 {
@@ -90,5 +90,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
 {
@@ -110,5 +110,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static bool usb_hid_ids_match(const usb_hid_dev_t *hid_dev,
     const usb_hid_subdriver_mapping_t *mapping)
@@ -122,5 +122,5 @@
 	    == mapping->product_id);
 }
-/*----------------------------------------------------------------------------*/
+
 static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
     const usb_hid_subdriver_mapping_t *mapping)
@@ -178,5 +178,5 @@
 	return matches;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
     const usb_hid_subdriver_t **subdrivers, unsigned count)
@@ -211,5 +211,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
 {
@@ -263,5 +263,5 @@
 	return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, const usb_device_t *dev)
 {
@@ -290,5 +290,5 @@
 	return ENOTSUP;
 }
-/*----------------------------------------------------------------------------*/
+
 static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
 {
@@ -322,5 +322,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /*
  * This functions initializes required structures from the device's descriptors
@@ -458,5 +458,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     size_t buffer_size, void *arg)
@@ -500,5 +500,5 @@
 	return cont;
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg)
 {
@@ -517,15 +517,15 @@
 	hid_dev->running = false;
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_hid_new_report(usb_hid_dev_t *hid_dev)
 {
 	++hid_dev->report_nr;
 }
-/*----------------------------------------------------------------------------*/
+
 int usb_hid_report_number(const usb_hid_dev_t *hid_dev)
 {
 	return hid_dev->report_nr;
 }
-/*----------------------------------------------------------------------------*/
+
 void usb_hid_deinit(usb_hid_dev_t *hid_dev)
 {
Index: uspace/drv/bus/usb/usbhid/usbhid.h
===================================================================
--- uspace/drv/bus/usb/usbhid/usbhid.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhid/usbhid.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -95,5 +95,5 @@
 };
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Structure for holding general HID device data.
@@ -132,5 +132,5 @@
 };
 
-/*----------------------------------------------------------------------------*/
+
 
 enum {
@@ -143,5 +143,5 @@
 extern const usb_endpoint_description_t *usb_hid_endpoints[];
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev);
Index: uspace/drv/bus/usb/usbhub/main.c
===================================================================
--- uspace/drv/bus/usb/usbhub/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhub/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -79,5 +79,5 @@
 {
 	printf(NAME ": HelenOS USB hub driver.\n");
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	log_init(NAME);
 
 	return usb_driver_main(&usb_hub_driver);
Index: uspace/drv/bus/usb/usbhub/port.c
===================================================================
--- uspace/drv/bus/usb/usbhub/port.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhub/port.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -70,5 +70,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Clear feature on hub port.
@@ -92,5 +92,5 @@
 	    sizeof(clear_request), NULL, 0);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Set feature on hub port.
@@ -114,5 +114,5 @@
 	    sizeof(clear_request), NULL, 0);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Mark reset process as failed due to external reasons
@@ -129,5 +129,5 @@
 	fibril_mutex_unlock(&port->mutex);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process interrupts on given port
@@ -245,5 +245,5 @@
 	    port->port_number, status);
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * routine called when a device on port has been removed
@@ -299,5 +299,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process port reset change
@@ -335,5 +335,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Retrieve port status.
  *
@@ -352,5 +352,5 @@
 		.request = USB_HUB_REQUEST_GET_STATUS,
 		.value = 0,
-		.index = port->port_number,
+		.index = uint16_host2usb(port->port_number),
 		.length = sizeof(usb_port_status_t),
 	};
@@ -375,5 +375,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback for enabling a specific port.
  *
@@ -407,5 +407,5 @@
 	return port->reset_okay ? EOK : ESTALL;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Fibril for adding a new device.
  *
@@ -436,6 +436,7 @@
 		usb_log_info("Detected new device on `%s' (port %zu), "
 		    "address %d (handle %" PRIun ").\n",
-		    data->hub->usb_device->ddf_dev->name,
-		    data->port->port_number, new_address, child_fun->handle);
+		    ddf_dev_get_name(data->hub->usb_device->ddf_dev),
+		    data->port->port_number, new_address,
+		    ddf_fun_get_handle(child_fun));
 	} else {
 		usb_log_error("Failed registering device on port %zu: %s.\n",
@@ -454,5 +455,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Start device adding when connection change is detected.
  *
Index: uspace/drv/bus/usb/usbhub/status.h
===================================================================
--- uspace/drv/bus/usb/usbhub/status.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhub/status.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,6 +42,7 @@
  * should not be accessed directly, use supplied getter/setter methods.
  *
- * For more information refer to table 11-15 in
- * "Universal Serial Bus Specification Revision 1.1"
+ * For more information refer to tables 11-15 and 11-16 in
+ * "Universal Serial Bus Specification Revision 1.1" pages 274 and 277
+ * (290 and 293 in pdf)
  *
  */
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -160,10 +160,10 @@
 	hub_dev->running = true;
 	usb_log_info("Controlling hub '%s' (%zu ports).\n",
-	    hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);
+	    ddf_dev_get_name(hub_dev->usb_device->ddf_dev), hub_dev->port_count);
 
 	usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Turn off power to all ports.
@@ -176,5 +176,5 @@
 	return ENOTSUP;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Remove all attached devices
@@ -219,5 +219,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback for polling hub for changes.
  *
@@ -256,5 +256,5 @@
 	return true;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Load hub-specific information into hub_dev structure and process if needed
@@ -331,5 +331,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Set configuration of and USB device
@@ -378,5 +378,5 @@
 	return opResult;
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process hub over current change
@@ -416,5 +416,5 @@
 
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * Process hub interrupts.
@@ -485,5 +485,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /**
  * callback called from hub polling fibril when the fibril terminates
Index: uspace/drv/bus/usb/usbmast/main.c
===================================================================
--- uspace/drv/bus/usb/usbmast/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbmast/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,5 +37,5 @@
 #include <as.h>
 #include <async.h>
-#include <ipc/bd.h>
+#include <bd_srv.h>
 #include <macros.h>
 #include <usb/dev/driver.h>
@@ -82,4 +82,25 @@
     void *arg);
 
+static int usbmast_bd_open(bd_srvs_t *, bd_srv_t *);
+static int usbmast_bd_close(bd_srv_t *);
+static int usbmast_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
+static int usbmast_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
+static int usbmast_bd_get_block_size(bd_srv_t *, size_t *);
+static int usbmast_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
+
+static bd_ops_t usbmast_bd_ops = {
+	.open = usbmast_bd_open,
+	.close = usbmast_bd_close,
+	.read_blocks = usbmast_bd_read_blocks,
+	.write_blocks = usbmast_bd_write_blocks,
+	.get_block_size = usbmast_bd_get_block_size,
+	.get_num_blocks = usbmast_bd_get_num_blocks
+};
+
+static usbmast_fun_t *bd_srv_usbmast(bd_srv_t *bd)
+{
+	return (usbmast_fun_t *) bd->srvs->sarg;
+}
+
 /** Callback when a device is removed from the system.
  *
@@ -139,5 +160,5 @@
 	mdev->usb_dev = dev;
 
-	usb_log_info("Initializing mass storage `%s'.\n", dev->ddf_dev->name);
+	usb_log_info("Initializing mass storage `%s'.\n", ddf_dev_get_name(dev->ddf_dev));
 	usb_log_debug("Bulk in endpoint: %d [%zuB].\n",
 	    dev->pipes[BULK_IN_EP].pipe.endpoint_no,
@@ -219,6 +240,10 @@
 	mfun->lun = lun;
 
+	bd_srvs_init(&mfun->bds);
+	mfun->bds.ops = &usbmast_bd_ops;
+	mfun->bds.sarg = mfun;
+
 	/* Set up a connection handler. */
-	fun->conn_handler = usbmast_bd_connection;
+	ddf_fun_set_conn_handler(fun, usbmast_bd_connection);
 
 	usb_log_debug("Inquire...\n");
@@ -227,5 +252,5 @@
 	if (rc != EOK) {
 		usb_log_warning("Failed to inquire device `%s': %s.\n",
-		    mdev->ddf_dev->name, str_error(rc));
+		    ddf_dev_get_name(mdev->ddf_dev), str_error(rc));
 		rc = EIO;
 		goto error;
@@ -234,5 +259,5 @@
 	usb_log_info("Mass storage `%s' LUN %u: " \
 	    "%s by %s rev. %s is %s (%s).\n",
-	    mdev->ddf_dev->name,
+	    ddf_dev_get_name(mdev->ddf_dev),
 	    lun,
 	    inquiry.product,
@@ -247,5 +272,5 @@
 	if (rc != EOK) {
 		usb_log_warning("Failed to read capacity, device `%s': %s.\n",
-		    mdev->ddf_dev->name, str_error(rc));
+		    ddf_dev_get_name(mdev->ddf_dev), str_error(rc));
 		rc = EIO;
 		goto error;
@@ -284,64 +309,61 @@
 {
 	usbmast_fun_t *mfun;
-	void *comm_buf = NULL;
-	size_t comm_size;
-	ipc_callid_t callid;
-	ipc_call_t call;
-	unsigned int flags;
-	sysarg_t method;
-	uint64_t ba;
-	size_t cnt;
-	int retval;
-
-	async_answer_0(iid, EOK);
-
-	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-	
-	(void) async_share_out_finalize(callid, &comm_buf);
-	if (comm_buf == AS_MAP_FAILED) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-	
-	mfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
-
-	while (true) {
-		callid = async_get_call(&call);
-		method = IPC_GET_IMETHOD(call);
-
-		if (!method) {
-			/* The other side hung up. */
-			async_answer_0(callid, EOK);
-			return;
-		}
-
-		switch (method) {
-		case BD_GET_BLOCK_SIZE:
-			async_answer_1(callid, EOK, mfun->block_size);
-			break;
-		case BD_GET_NUM_BLOCKS:
-			async_answer_2(callid, EOK, LOWER32(mfun->nblocks),
-			    UPPER32(mfun->nblocks));
-			break;
-		case BD_READ_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			retval = usbmast_read(mfun, ba, cnt, comm_buf);
-			async_answer_0(callid, retval);
-			break;
-		case BD_WRITE_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			retval = usbmast_write(mfun, ba, cnt, comm_buf);
-			async_answer_0(callid, retval);
-			break;
-		default:
-			async_answer_0(callid, EINVAL);
-		}
-	}
-}
+
+	mfun = (usbmast_fun_t *) ddf_fun_data_get((ddf_fun_t *)arg);
+	bd_conn(iid, icall, &mfun->bds);
+}
+
+/** Open device. */
+static int usbmast_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
+{
+	return EOK;
+}
+
+/** Close device. */
+static int usbmast_bd_close(bd_srv_t *bd)
+{
+	return EOK;
+}
+
+/** Read blocks from the device. */
+static int usbmast_bd_read_blocks(bd_srv_t *bd, uint64_t ba, size_t cnt, void *buf,
+    size_t size)
+{
+	usbmast_fun_t *mfun = bd_srv_usbmast(bd);
+
+	if (size < cnt * mfun->block_size)
+		return EINVAL;
+
+	return usbmast_read(mfun, ba, cnt, buf);
+}
+
+/** Write blocks to the device. */
+static int usbmast_bd_write_blocks(bd_srv_t *bd, uint64_t ba, size_t cnt,
+    const void *buf, size_t size)
+{
+	usbmast_fun_t *mfun = bd_srv_usbmast(bd);
+
+	if (size < cnt * mfun->block_size)
+		return EINVAL;
+
+	return usbmast_write(mfun, ba, cnt, buf);
+}
+
+/** Get device block size. */
+static int usbmast_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
+{
+	usbmast_fun_t *mfun = bd_srv_usbmast(bd);
+	*rsize = mfun->block_size;
+	return EOK;
+}
+
+/** Get number of blocks on device. */
+static int usbmast_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
+{
+	usbmast_fun_t *mfun = bd_srv_usbmast(bd);
+	*rnb = mfun->nblocks;
+	return EOK;
+}
+
 
 /** USB mass storage driver ops. */
@@ -361,5 +383,5 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	log_init(NAME);
 
 	return usb_driver_main(&usbmast_driver);
Index: uspace/drv/bus/usb/usbmast/scsi_ms.c
===================================================================
--- uspace/drv/bus/usb/usbmast/scsi_ms.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbmast/scsi_ms.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -88,5 +88,5 @@
 		if (rc != EOK) {
 			usb_log_error("Inquiry transport failed, device %s: %s.\n",
-			   mfun->mdev->ddf_dev->name, str_error(rc));
+			   ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
 			return rc;
 		}
@@ -96,5 +96,5 @@
 
 		usb_log_error("SCSI command failed, device %s.\n",
-		    mfun->mdev->ddf_dev->name);
+		    ddf_dev_get_name(mfun->mdev->ddf_dev));
 
 		rc = usbmast_request_sense(mfun, &sense_buf, sizeof(sense_buf));
@@ -147,5 +147,5 @@
 	if (rc != EOK) {
 		usb_log_error("Inquiry transport failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
+		   ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
 		return rc;
 	}
@@ -153,5 +153,5 @@
 	if (cmd.status != CMDS_GOOD) {
 		usb_log_error("Inquiry command failed, device %s.\n",
-		   mfun->mdev->ddf_dev->name);
+		   ddf_dev_get_name(mfun->mdev->ddf_dev));
 		return EIO;
 	}
@@ -215,5 +215,5 @@
         if (rc != EOK || cmd.status != CMDS_GOOD) {
 		usb_log_error("Request Sense failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
+		   ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
 		return rc;
 	}
@@ -257,5 +257,5 @@
         if (rc != EOK) {
 		usb_log_error("Read Capacity (10) transport failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
+		   ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
 		return rc;
 	}
@@ -263,5 +263,5 @@
 	if (cmd.status != CMDS_GOOD) {
 		usb_log_error("Read Capacity (10) command failed, device %s.\n",
-		   mfun->mdev->ddf_dev->name);
+		   ddf_dev_get_name(mfun->mdev->ddf_dev));
 		return EIO;
 	}
@@ -314,5 +314,5 @@
         if (rc != EOK) {
 		usb_log_error("Read (10) transport failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
+		   ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
 		return rc;
 	}
@@ -320,5 +320,5 @@
 	if (cmd.status != CMDS_GOOD) {
 		usb_log_error("Read (10) command failed, device %s.\n",
-		   mfun->mdev->ddf_dev->name);
+		   ddf_dev_get_name(mfun->mdev->ddf_dev));
 		return EIO;
 	}
@@ -370,5 +370,5 @@
         if (rc != EOK) {
 		usb_log_error("Write (10) transport failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
+		   ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));
 		return rc;
 	}
@@ -376,5 +376,5 @@
 	if (cmd.status != CMDS_GOOD) {
 		usb_log_error("Write (10) command failed, device %s.\n",
-		   mfun->mdev->ddf_dev->name);
+		   ddf_dev_get_name(mfun->mdev->ddf_dev));
 		return EIO;
 	}
Index: uspace/drv/bus/usb/usbmast/usbmast.h
===================================================================
--- uspace/drv/bus/usb/usbmast/usbmast.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbmast/usbmast.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,4 +37,5 @@
 #define USBMAST_H_
 
+#include <bd_srv.h>
 #include <sys/types.h>
 #include <usb/usb.h>
@@ -68,4 +69,6 @@
 	/** Block size in bytes */
 	size_t block_size;
+	/** Block device service structure */
+	bd_srvs_t bds;
 } usbmast_fun_t;
 
Index: uspace/drv/bus/usb/usbmid/explore.c
===================================================================
--- uspace/drv/bus/usb/usbmid/explore.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbmid/explore.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -172,5 +172,5 @@
 		return false;
 	}
-	usb_mid->ctl_fun->ops = &mid_device_ops;
+	ddf_fun_set_ops(usb_mid->ctl_fun, &mid_device_ops);
 
 	/* Bind control function. */
Index: uspace/drv/bus/usb/usbmid/main.c
===================================================================
--- uspace/drv/bus/usb/usbmid/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbmid/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -51,5 +51,5 @@
 static int usbmid_device_add(usb_device_t *dev)
 {
-	usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name);
+	usb_log_info("Taking care of new MID `%s'.\n", ddf_dev_get_name(dev->ddf_dev));
 
 	const bool accept = usbmid_explore_device(dev);
@@ -61,5 +61,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback when a MID device is about to be removed from the host.
  *
@@ -115,5 +115,5 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback when a MID device was removed from the host.
  *
@@ -127,5 +127,5 @@
 	assert(usb_mid);
 
-	usb_log_info("USB MID gone: `%s'.\n", dev->ddf_dev->name);
+	usb_log_info("USB MID gone: `%s'.\n", ddf_dev_get_name(dev->ddf_dev));
 
 	/* Remove ctl function */
@@ -180,5 +180,5 @@
 	printf(NAME ": USB multi interface device driver.\n");
 
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	log_init(NAME);
 
 	return usb_driver_main(&mid_driver);
Index: uspace/drv/bus/usb/usbmid/usbmid.c
===================================================================
--- uspace/drv/bus/usb/usbmid/usbmid.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/usbmid/usbmid.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -30,4 +30,8 @@
  * @{
  */
+
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 /**
  * @file
@@ -47,7 +51,5 @@
 static int usb_iface_get_interface_impl(ddf_fun_t *fun, int *iface_no)
 {
-	assert(fun);
-
-	usbmid_interface_t *iface = fun->driver_data;
+	usbmid_interface_t *iface = ddf_fun_data_get(fun);
 	assert(iface);
 
@@ -123,10 +125,24 @@
 	}
 
+	match_id_list_t match_ids;
+	init_match_ids(&match_ids);
+
 	rc = usb_device_create_match_ids_from_interface(device_descriptor,
-	    interface_descriptor, &child->match_ids);
+	    interface_descriptor, &match_ids);
 	if (rc != EOK) {
 		ddf_fun_destroy(child);
 		return rc;
 	}
+
+	list_foreach(match_ids.ids, link) {
+		match_id_t *match_id = list_get_instance(link, match_id_t, link);
+		rc = ddf_fun_add_match_id(child, match_id->id, match_id->score);
+		if (rc != EOK) {
+			clean_match_ids(&match_ids);
+			ddf_fun_destroy(child);
+			return rc;
+		}
+	}
+	clean_match_ids(&match_ids);
 
 	rc = ddf_fun_bind(child);
@@ -138,6 +154,6 @@
 
 	iface->fun = child;
-	child->driver_data = iface;
-	child->ops = &child_device_ops;
+	ddf_fun_data_implant(child, iface);
+	ddf_fun_set_ops(child, &child_device_ops);
 
 	return EOK;
Index: uspace/drv/bus/usb/vhc/Makefile
===================================================================
--- uspace/drv/bus/usb/vhc/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/vhc/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -32,6 +32,6 @@
 	$(LIBUSBDEV_PREFIX)/libusbdev.a \
 	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSBVIRT_PREFIX)/libusbvirt.a \
 	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBUSBVIRT_PREFIX)/libusbvirt.a \
 	$(LIBDRV_PREFIX)/libdrv.a
 
Index: uspace/drv/bus/usb/vhc/conndev.c
===================================================================
--- uspace/drv/bus/usb/vhc/conndev.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/vhc/conndev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -94,5 +94,5 @@
     ipc_call_t *icall)
 {
-	vhc_data_t *vhc = fun->dev->driver_data;
+	vhc_data_t *vhc = ddf_dev_data_get(ddf_fun_get_dev(fun));
 	
 	async_sess_t *callback =
@@ -125,5 +125,5 @@
 void on_client_close(ddf_fun_t *fun)
 {
-	vhc_data_t *vhc = fun->dev->driver_data;
+	vhc_data_t *vhc = ddf_dev_data_get(ddf_fun_get_dev(fun));
 
 	if (plugged_device_handle != 0) {
Index: uspace/drv/bus/usb/vhc/connhost.c
===================================================================
--- uspace/drv/bus/usb/vhc/connhost.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/vhc/connhost.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,5 +42,5 @@
 
 #define GET_VHC_DATA(fun) \
-	((vhc_data_t *)fun->dev->driver_data)
+	((vhc_data_t *)ddf_dev_data_get(ddf_fun_get_dev(fun)))
 #define VHC_DATA(vhc, fun) \
 	vhc_data_t *vhc = GET_VHC_DATA(fun); assert(vhc->magic == 0xdeadbeef)
@@ -483,5 +483,5 @@
 	VHC_DATA(vhc, root_hub_fun);
 
-	*handle = vhc->hc_fun->handle;
+	*handle = ddf_fun_get_handle(vhc->hc_fun);
 
 	return EOK;
@@ -492,5 +492,5 @@
 	VHC_DATA(vhc, root_hub_fun);
 
-	devman_handle_t handle = root_hub_fun->handle;
+	devman_handle_t handle = ddf_fun_get_handle(root_hub_fun);
 
 	usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
Index: uspace/drv/bus/usb/vhc/hub.c
===================================================================
--- uspace/drv/bus/usb/vhc/hub.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/vhc/hub.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -100,5 +100,6 @@
 	async_sess_t *sess;
 	do {
-		sess = devman_device_connect(EXCHANGE_SERIALIZE, hc_dev->handle, 0);
+		sess = devman_device_connect(EXCHANGE_SERIALIZE,
+		    ddf_fun_get_handle(hc_dev), 0);
 	} while (!sess);
 	async_hangup(sess);
@@ -107,5 +108,5 @@
 
 	usb_hc_connection_t hc_conn;
-	usb_hc_connection_initialize(&hc_conn, hc_dev->handle);
+	usb_hc_connection_initialize(&hc_conn, ddf_fun_get_handle(hc_dev));
 
 	rc = usb_hc_connection_open(&hc_conn);
@@ -113,5 +114,5 @@
 
 	ddf_fun_t *hub_dev;
-	rc = usb_hc_new_device_wrapper(hc_dev->dev, &hc_conn, USB_SPEED_FULL,
+	rc = usb_hc_new_device_wrapper(ddf_fun_get_dev(hc_dev), &hc_conn, USB_SPEED_FULL,
 	    pretend_port_rest, NULL, NULL, &rh_ops, hc_dev, &hub_dev);
 	if (rc != EOK) {
@@ -123,5 +124,5 @@
 
 	usb_log_info("Created root hub function (handle %zu).\n",
-	    (size_t) hub_dev->handle);
+	    (size_t) ddf_fun_get_handle(hub_dev));
 
 	return 0;
Index: uspace/drv/bus/usb/vhc/main.c
===================================================================
--- uspace/drv/bus/usb/vhc/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/bus/usb/vhc/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -67,5 +67,5 @@
 	}
 
-	vhc_data_t *data = malloc(sizeof(vhc_data_t));
+	vhc_data_t *data = ddf_dev_data_alloc(dev, sizeof(vhc_data_t));
 	if (data == NULL) {
 		usb_log_fatal("Failed to allocate memory.\n");
@@ -89,11 +89,9 @@
 	}
 
-	hc->ops = &vhc_ops;
+	ddf_fun_set_ops(hc, &vhc_ops);
 	list_initialize(&data->devices);
 	fibril_mutex_initialize(&data->guard);
 	data->hub = &virtual_hub_device;
 	data->hc_fun = hc;
-
-	dev->driver_data = data;
 
 	rc = ddf_fun_bind(hc);
@@ -116,7 +114,5 @@
 
 	usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n",
-	    (size_t) dev->handle, (size_t) hc->handle);
-
-
+	    (size_t) ddf_dev_get_handle(dev), (size_t) ddf_fun_get_handle(hc));
 
 	rc = vhc_virtdev_plug_hub(data, data->hub, NULL);
@@ -142,5 +138,5 @@
 int main(int argc, char * argv[])
 {	
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	log_init(NAME);
 
 	printf(NAME ": virtual USB host controller driver.\n");
Index: uspace/drv/char/i8042/i8042.c
===================================================================
--- uspace/drv/char/i8042/i8042.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/char/i8042/i8042.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -39,5 +39,4 @@
  */
 
-#include <devman.h>
 #include <device/hw_res.h>
 #include <ddi.h>
@@ -120,5 +119,5 @@
 	},
 	{
-		.cmd = CMD_BTEST,
+		.cmd = CMD_AND,
 		.value = i8042_OUTPUT_FULL,
 		.srcarg = 1,
@@ -140,4 +139,10 @@
 };
 
+/** Get i8042 soft state from device node. */
+static i8042_t *dev_i8042(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
+}
+
 /** Wait until it is safe to write to the device. */
 static void wait_ready(i8042_t *dev)
@@ -159,8 +164,5 @@
     ipc_call_t *call)
 {
-	if ((!dev) || (!dev->driver_data))
-		return;
-	
-	i8042_t *controller = dev->driver_data;
+	i8042_t *controller = dev_i8042(dev);
 	
 	const uint8_t status = IPC_GET_ARG1(*call);
@@ -188,40 +190,49 @@
     int irq_mouse, ddf_dev_t *ddf_dev)
 {
-	assert(ddf_dev);
-	assert(dev);
-	
-	if (reg_size < sizeof(i8042_regs_t))
-		return EINVAL;
-	
-	if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0)
-		return -1;
+	const size_t range_count = sizeof(i8042_ranges) /
+	    sizeof(irq_pio_range_t);
+	irq_pio_range_t ranges[range_count];
+	const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
+	irq_cmd_t cmds[cmd_count];
+
+	int rc;
+	bool kbd_bound = false;
+	bool aux_bound = false;
+
+	dev->kbd_fun = NULL;
+	dev->aux_fun = NULL;
+	
+	if (reg_size < sizeof(i8042_regs_t)) {
+		rc = EINVAL;
+		goto error;
+	}
+	
+	if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0) {
+		rc = EIO;
+		goto error;
+	}
 	
 	dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
-	if (!dev->kbd_fun)
-		return ENOMEM;
-	
-	int ret = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
-	if (ret != EOK) {
-		ddf_fun_destroy(dev->kbd_fun);
-		return ret;
-	}
+	if (dev->kbd_fun == NULL) {
+		rc = ENOMEM;
+		goto error;
+	};
+	
+	rc = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
+	if (rc != EOK)
+		goto error;
 	
 	dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
-	if (!dev->aux_fun) {
-		ddf_fun_destroy(dev->kbd_fun);
-		return ENOMEM;
-	}
-	
-	ret = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
-	if (ret != EOK) {
-		ddf_fun_destroy(dev->kbd_fun);
-		ddf_fun_destroy(dev->aux_fun);
-		return ret;
-	}
-	
-	dev->kbd_fun->ops = &ops;
-	dev->aux_fun->ops = &ops;
-	dev->kbd_fun->driver_data = dev;
-	dev->aux_fun->driver_data = dev;
+	if (dev->aux_fun == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+	
+	rc = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
+	if (rc != EOK)
+		goto error;
+	
+	ddf_fun_set_ops(dev->kbd_fun, &ops);
+	ddf_fun_set_ops(dev->aux_fun, &ops);
 	
 	buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
@@ -229,11 +240,19 @@
 	fibril_mutex_initialize(&dev->write_guard);
 	
-	ret = ddf_fun_bind(dev->kbd_fun);
-	CHECK_RET_DESTROY(ret, "Failed to bind keyboard function: %s.",
-	    str_error(ret));
-	
-	ret = ddf_fun_bind(dev->aux_fun);
-	CHECK_RET_DESTROY(ret, "Failed to bind mouse function: %s.",
-	    str_error(ret));
+	rc = ddf_fun_bind(dev->kbd_fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to bind keyboard function: %s.",
+		    ddf_fun_get_name(dev->kbd_fun));
+		goto error;
+	}
+	kbd_bound = true;
+	
+	rc = ddf_fun_bind(dev->aux_fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to bind aux function: %s.",
+		    ddf_fun_get_name(dev->aux_fun));
+		goto error;
+	}
+	aux_bound = true;
 	
 	/* Disable kbd and aux */
@@ -247,12 +266,7 @@
 		(void) pio_read_8(&dev->regs->data);
 
-	const size_t range_count = sizeof(i8042_ranges) /
-	    sizeof(irq_pio_range_t);
-	irq_pio_range_t ranges[range_count];
 	memcpy(ranges, i8042_ranges, sizeof(i8042_ranges));
 	ranges[0].base = (uintptr_t) regs;
 
-	const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
-	irq_cmd_t cmds[cmd_count];
 	memcpy(cmds, i8042_cmds, sizeof(i8042_cmds));
 	cmds[0].addr = (void *) &(((i8042_regs_t *) regs)->status);
@@ -266,25 +280,31 @@
 	};
 	
-	ret = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
+	rc = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
 	    &irq_code);
-	CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for kbd: %s.",
-	    str_error(ret));
-	
-	ret = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler,
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed set handler for kbd: %s.",
+		    ddf_dev_get_name(ddf_dev));
+		goto error;
+	}
+	
+	rc = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler,
 	    &irq_code);
-	CHECK_RET_UNBIND_DESTROY(ret, "Failed set handler for mouse: %s.",
-	    str_error(ret));
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed set handler for mouse: %s.",
+		    ddf_dev_get_name(ddf_dev));
+		goto error;
+	}
 	
 	/* Enable interrupts */
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, ddf_dev->handle,
-	    IPC_FLAG_BLOCKING);
-	ret = parent_sess ? EOK : ENOMEM;
-	CHECK_RET_UNBIND_DESTROY(ret, "Failed to create parent connection.");
+	async_sess_t *parent_sess = ddf_dev_parent_sess_get(ddf_dev);
+	assert(parent_sess != NULL);
 	
 	const bool enabled = hw_res_enable_interrupt(parent_sess);
-	async_hangup(parent_sess);
-	ret = enabled ? EOK : EIO;
-	CHECK_RET_UNBIND_DESTROY(ret, "Failed to enable interrupts: %s.");
+	if (!enabled) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to enable interrupts: %s.",
+		    ddf_dev_get_name(ddf_dev));
+		rc = EIO;
+		goto error;
+	}
 	
 	/* Enable port interrupts. */
@@ -296,4 +316,15 @@
 	
 	return EOK;
+error:
+	if (kbd_bound)
+		ddf_fun_unbind(dev->kbd_fun);
+	if (aux_bound)
+		ddf_fun_unbind(dev->aux_fun);
+	if (dev->kbd_fun != NULL)
+		ddf_fun_destroy(dev->kbd_fun);
+	if (dev->aux_fun != NULL)
+		ddf_fun_destroy(dev->aux_fun);
+
+	return rc;
 }
 
@@ -315,8 +346,5 @@
 static int i8042_write(ddf_fun_t *fun, char *buffer, size_t size)
 {
-	assert(fun);
-	assert(fun->driver_data);
-	
-	i8042_t *controller = fun->driver_data;
+	i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
 	fibril_mutex_lock(&controller->write_guard);
 	
@@ -347,8 +375,5 @@
 static int i8042_read(ddf_fun_t *fun, char *data, size_t size)
 {
-	assert(fun);
-	assert(fun->driver_data);
-	
-	i8042_t *controller = fun->driver_data;
+	i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
 	buffer_t *buffer = (fun == controller->aux_fun) ?
 	    &controller->aux_buffer : &controller->kbd_buffer;
Index: uspace/drv/char/i8042/main.c
===================================================================
--- uspace/drv/char/i8042/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/char/i8042/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,5 +37,4 @@
 #include <libarch/inttypes.h>
 #include <ddf/driver.h>
-#include <devman.h>
 #include <device/hw_res_parsed.h>
 #include <errno.h>
@@ -64,13 +63,12 @@
  *
  */
-static int get_my_registers(const ddf_dev_t *dev, uintptr_t *io_reg_address,
+static int get_my_registers(ddf_dev_t *dev, uintptr_t *io_reg_address,
     size_t *io_reg_size, int *kbd_irq, int *mouse_irq)
 {
 	assert(dev);
 	
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
+	async_sess_t *parent_sess = ddf_dev_parent_sess_create(
+	    dev, EXCHANGE_SERIALIZE);
+	if (parent_sess == NULL)
 		return ENOMEM;
 	
@@ -78,5 +76,4 @@
 	hw_res_list_parsed_init(&hw_resources);
 	const int ret = hw_res_get_list_parsed(parent_sess, &hw_resources, 0);
-	async_hangup(parent_sess);
 	if (ret != EOK)
 		return ret;
@@ -136,5 +133,5 @@
 	
 	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
-	    device->name, device->handle);
+	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
 	return EOK;
 }
@@ -154,5 +151,5 @@
 {
 	printf("%s: HelenOS PS/2 driver.\n", NAME);
-	ddf_log_init(NAME, LVL_NOTE);
+	ddf_log_init(NAME);
 	return ddf_driver_main(&i8042_driver);
 }
Index: uspace/drv/char/ns8250/cyclic_buffer.h
===================================================================
--- uspace/drv/char/ns8250/cyclic_buffer.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/char/ns8250/cyclic_buffer.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,5 +36,5 @@
 #define CYCLIC_BUFFER_H_
 
-#define BUF_LEN 256
+#define BUF_LEN 4096
 
 typedef struct cyclic_buffer {
Index: uspace/drv/char/ns8250/ns8250.c
===================================================================
--- uspace/drv/char/ns8250/ns8250.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/char/ns8250/ns8250.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -58,7 +58,5 @@
 #include <ops/char_dev.h>
 
-#include <devman.h>
 #include <ns.h>
-#include <ipc/devman.h>
 #include <ipc/services.h>
 #include <ipc/irc.h>
@@ -82,4 +80,6 @@
 /** Interrupt ID Register definition. */
 #define	NS8250_IID_ACTIVE	(1 << 0)
+#define NS8250_IID_CAUSE_MASK 0x0e
+#define NS8250_IID_CAUSE_RXSTATUS 0x06
 
 /** FIFO Control Register definition. */
@@ -125,10 +125,4 @@
 #define	NS8250_MSR_SIGNALS	(NS8250_MSR_CTS | NS8250_MSR_DSR \
     | NS8250_MSR_RI | NS8250_MSR_DCD)
-
-/** Obtain soft-state structure from function node */
-#define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data))
-
-/** Obtain soft-state structure from device node */
-#define NS8250_FROM_DEV(dnode) ((ns8250_t *) ((dnode)->driver_data))
 
 /** The number of bits of one data unit send by the serial port. */
@@ -179,8 +173,22 @@
 	/** The fibril mutex for synchronizing the access to the device. */
 	fibril_mutex_t mutex;
+	/** Indicates that some data has become available */
+	fibril_condvar_t input_buffer_available;
 	/** True if device is removed. */
 	bool removed;
 } ns8250_t;
 
+/** Obtain soft-state structure from device node */
+static ns8250_t *dev_ns8250(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
+}
+
+/** Obtain soft-state structure from function node */
+static ns8250_t *fun_ns8250(ddf_fun_t *fun)
+{
+	return dev_ns8250(ddf_fun_get_dev(fun));
+}
+
 /** Find out if there is some incomming data available on the serial port.
  *
@@ -237,8 +245,12 @@
 static int ns8250_read(ddf_fun_t *fun, char *buf, size_t count)
 {
-	ns8250_t *ns = NS8250(fun);
-	int ret = EOK;
+	ns8250_t *ns = fun_ns8250(fun);
+	int ret = 0;
+	
+	if (count == 0) return 0;
 	
 	fibril_mutex_lock(&ns->mutex);
+	while (buf_is_empty(&ns->input_buffer))
+		fibril_condvar_wait(&ns->input_buffer_available, &ns->mutex);
 	while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) {
 		buf[ret] = (char)buf_pop_front(&ns->input_buffer);
@@ -271,5 +283,5 @@
 static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count)
 {
-	ns8250_t *ns = NS8250(fun);
+	ns8250_t *ns = fun_ns8250(fun);
 	size_t idx;
 	
@@ -309,8 +321,4 @@
 static void ns8250_dev_cleanup(ns8250_t *ns)
 {
-	if (ns->dev->parent_sess) {
-		async_hangup(ns->dev->parent_sess);
-		ns->dev->parent_sess = NULL;
-	}
 }
 
@@ -322,5 +330,5 @@
 static bool ns8250_pio_enable(ns8250_t *ns)
 {
-	ddf_msg(LVL_DEBUG, "ns8250_pio_enable %s", ns->dev->name);
+	ddf_msg(LVL_DEBUG, "ns8250_pio_enable %s", ddf_dev_get_name(ns->dev));
 	
 	/* Gain control over port's registers. */
@@ -328,5 +336,5 @@
 	    (void **) &ns->port)) {
 		ddf_msg(LVL_ERROR, "Cannot map the port %#" PRIx32
-		    " for device %s.", ns->io_addr, ns->dev->name);
+		    " for device %s.", ns->io_addr, ddf_dev_get_name(ns->dev));
 		return false;
 	}
@@ -344,5 +352,5 @@
 static bool ns8250_dev_probe(ns8250_t *ns)
 {
-	ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ns->dev->name);
+	ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ddf_dev_get_name(ns->dev));
 	
 	bool res = true;
@@ -364,5 +372,5 @@
 	if (!res) {
 		ddf_msg(LVL_DEBUG, "Device %s is not present.",
-		    ns->dev->name);
+		    ddf_dev_get_name(ns->dev));
 	}
 	
@@ -377,7 +385,8 @@
 static int ns8250_dev_initialize(ns8250_t *ns)
 {
-	ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ns->dev->name);
-	
+	async_sess_t *parent_sess;
 	int ret = EOK;
+	
+	ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ddf_dev_get_name(ns->dev));
 	
 	hw_resource_list_t hw_resources;
@@ -385,9 +394,8 @@
 	
 	/* Connect to the parent's driver. */
-	ns->dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-	    ns->dev->handle, IPC_FLAG_BLOCKING);
-	if (!ns->dev->parent_sess) {
+	parent_sess = ddf_dev_parent_sess_create(ns->dev, EXCHANGE_SERIALIZE);
+	if (parent_sess == NULL) {
 		ddf_msg(LVL_ERROR, "Failed to connect to parent driver of "
-		    "device %s.", ns->dev->name);
+		    "device %s.", ddf_dev_get_name(ns->dev));
 		ret = ENOENT;
 		goto failed;
@@ -395,8 +403,8 @@
 	
 	/* Get hw resources. */
-	ret = hw_res_get_resource_list(ns->dev->parent_sess, &hw_resources);
+	ret = hw_res_get_resource_list(parent_sess, &hw_resources);
 	if (ret != EOK) {
 		ddf_msg(LVL_ERROR, "Failed to get HW resources for device "
-		    "%s.", ns->dev->name);
+		    "%s.", ddf_dev_get_name(ns->dev));
 		goto failed;
 	}
@@ -414,5 +422,5 @@
 			irq = true;
 			ddf_msg(LVL_NOTE, "Device %s was asigned irq = 0x%x.",
-			    ns->dev->name, ns->irq);
+			    ddf_dev_get_name(ns->dev), ns->irq);
 			break;
 			
@@ -421,5 +429,5 @@
 			if (res->res.io_range.size < REG_COUNT) {
 				ddf_msg(LVL_ERROR, "I/O range assigned to "
-				    "device %s is too small.", ns->dev->name);
+				    "device %s is too small.", ddf_dev_get_name(ns->dev));
 				ret = ELIMIT;
 				goto failed;
@@ -427,5 +435,5 @@
 			ioport = true;
 			ddf_msg(LVL_NOTE, "Device %s was asigned I/O address = "
-			    "0x%x.", ns->dev->name, ns->io_addr);
+			    "0x%x.", ddf_dev_get_name(ns->dev), ns->io_addr);
     			break;
 			
@@ -437,5 +445,5 @@
 	if (!irq || !ioport) {
 		ddf_msg(LVL_ERROR, "Missing HW resource(s) for device %s.",
-		    ns->dev->name);
+		    ddf_dev_get_name(ns->dev));
 		ret = ENOENT;
 		goto failed;
@@ -460,5 +468,5 @@
 {
 	/* Interrupt when data received. */
-	pio_write_8(&regs->ier, NS8250_IER_RXREADY);
+	pio_write_8(&regs->ier, NS8250_IER_RXREADY | NS8250_IER_RXSTATUS);
 	pio_write_8(&regs->mcr, NS8250_MCR_DTR | NS8250_MCR_RTS 
 	    | NS8250_MCR_OUT2);
@@ -499,4 +507,7 @@
 	async_exchange_end(exch);
 
+	/* Read LSR to clear possible previous LSR interrupt */
+	pio_read_8(&ns->regs->lsr);
+
 	/* Enable interrupt on the serial port. */
 	ns8250_port_interrupts_enable(ns->regs);
@@ -602,4 +613,7 @@
 	*parity = ((val >> NS8250_LCR_PARITY) & 7);
 	
+	/* Silence warnings */
+	*word_length = 0;
+
 	switch (val & 3) {
 	case WORD_LENGTH_5:
@@ -695,8 +709,11 @@
 	/* 8 bits, no parity, two stop bits. */
 	ns8250_port_set_com_props(ns->regs, SERIAL_NO_PARITY, 8, 2);
-	/* Enable FIFO, clear them, with 14-byte threshold. */
+	/*
+	 * Enable FIFO, clear them, with 4-byte threshold for greater
+	 * reliability.
+	 */
 	pio_write_8(&ns->regs->iid, NS8250_FCR_FIFOENABLE
-	    | NS8250_FCR_RXFIFORESET | NS8250_FCR_TXFIFORESET 
-	    | NS8250_FCR_RXTRIGGERLOW | NS8250_FCR_RXTRIGGERHI);
+	    | NS8250_FCR_RXFIFORESET | NS8250_FCR_TXFIFORESET
+	    | NS8250_FCR_RXTRIGGERLOW);
 	/*
 	 * RTS/DSR set (Request to Send and Data Terminal Ready lines enabled),
@@ -731,7 +748,6 @@
 	bool cont = true;
 	
+	fibril_mutex_lock(&ns->mutex);
 	while (cont) {
-		fibril_mutex_lock(&ns->mutex);
-		
 		cont = ns8250_received(regs);
 		if (cont) {
@@ -739,24 +755,28 @@
 			
 			if (ns->client_connected) {
+				bool buf_was_empty = buf_is_empty(&ns->input_buffer);
 				if (!buf_push_back(&ns->input_buffer, val)) {
 					ddf_msg(LVL_WARN, "Buffer overflow on "
-					    "%s.", ns->dev->name);
+					    "%s.", ddf_dev_get_name(ns->dev));
+					break;
 				} else {
 					ddf_msg(LVL_DEBUG2, "Character %c saved "
 					    "to the buffer of %s.",
-					    val, ns->dev->name);
+					    val, ddf_dev_get_name(ns->dev));
+					if (buf_was_empty)
+						fibril_condvar_broadcast(&ns->input_buffer_available);
 				}
 			}
 		}
-		
-		fibril_mutex_unlock(&ns->mutex);
-		fibril_yield();
-	}
+	}
+	fibril_mutex_unlock(&ns->mutex);
+	fibril_yield();
 }
 
 /** The interrupt handler.
  *
- * The serial port is initialized to interrupt when some data come, so the
- * interrupt is handled by reading the incomming data.
+ * The serial port is initialized to interrupt when some data come or line
+ * status register changes, so the interrupt is handled by reading the incoming
+ * data and reading the line status register.
  *
  * @param dev		The serial port device.
@@ -765,5 +785,15 @@
     ipc_call_t *icall)
 {
-	ns8250_read_from_device(NS8250_FROM_DEV(dev));
+	ns8250_t *ns = dev_ns8250(dev);
+
+	uint8_t iir = pio_read_8(&ns->regs->iid);
+	if ((iir & NS8250_IID_CAUSE_MASK) == NS8250_IID_CAUSE_RXSTATUS) {
+		uint8_t lsr = pio_read_8(&ns->regs->lsr);
+		if (lsr & NS8250_LSR_OE) {
+			ddf_msg(LVL_WARN, "Overrun error on %s", ddf_dev_get_name(ns->dev));
+		}
+	}
+	
+	ns8250_read_from_device(ns);
 }
 
@@ -801,5 +831,5 @@
 	
 	ddf_msg(LVL_DEBUG, "ns8250_dev_add %s (handle = %d)",
-	    dev->name, (int) dev->handle);
+	    ddf_dev_get_name(dev), (int) ddf_dev_get_handle(dev));
 	
 	/* Allocate soft-state for the device */
@@ -811,4 +841,5 @@
 	
 	fibril_mutex_initialize(&ns->mutex);
+	fibril_condvar_initialize(&ns->input_buffer_available);
 	ns->dev = dev;
 	
@@ -855,5 +886,5 @@
 	
 	/* Set device operations. */
-	fun->ops = &ns8250_dev_ops;
+	ddf_fun_set_ops(fun, &ns8250_dev_ops);
 	rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
@@ -867,5 +898,5 @@
 	
 	ddf_msg(LVL_NOTE, "Device %s successfully initialized.",
-	    dev->name);
+	    ddf_dev_get_name(dev));
 	
 	return EOK;
@@ -880,5 +911,5 @@
 static int ns8250_dev_remove(ddf_dev_t *dev)
 {
-	ns8250_t *ns = NS8250_FROM_DEV(dev);
+	ns8250_t *ns = dev_ns8250(dev);
 	int rc;
 	
@@ -914,5 +945,5 @@
 static int ns8250_open(ddf_fun_t *fun)
 {
-	ns8250_t *ns = NS8250(fun);
+	ns8250_t *ns = fun_ns8250(fun);
 	int res;
 	
@@ -940,5 +971,5 @@
 static void ns8250_close(ddf_fun_t *fun)
 {
-	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
+	ns8250_t *data = fun_ns8250(fun);
 	
 	fibril_mutex_lock(&data->mutex);
@@ -965,5 +996,5 @@
     unsigned int *word_length, unsigned int* stop_bits)
 {
-	ns8250_t *data = (ns8250_t *) dev->driver_data;
+	ns8250_t *data = dev_ns8250(dev);
 	ns8250_regs_t *regs = data->regs;
 	
@@ -996,5 +1027,5 @@
 	    stop_bits);
 	
-	ns8250_t *data = (ns8250_t *) dev->driver_data;
+	ns8250_t *data = dev_ns8250(dev);
 	ns8250_regs_t *regs = data->regs;
 	int ret;
@@ -1025,5 +1056,5 @@
 	switch (method) {
 	case SERIAL_GET_COM_PROPS:
-		ns8250_get_props(fun->dev, &baud_rate, &parity, &word_length,
+		ns8250_get_props(ddf_fun_get_dev(fun), &baud_rate, &parity, &word_length,
 		    &stop_bits);
 		async_answer_4(callid, EOK, baud_rate, parity, word_length,
@@ -1036,5 +1067,5 @@
 		word_length = IPC_GET_ARG3(*call);
 		stop_bits = IPC_GET_ARG4(*call);
-		ret = ns8250_set_props(fun->dev, baud_rate, parity, word_length,
+		ret = ns8250_set_props(ddf_fun_get_dev(fun), baud_rate, parity, word_length,
 		    stop_bits);
 		async_answer_0(callid, ret);
@@ -1053,5 +1084,5 @@
 static void ns8250_init(void)
 {
-	ddf_log_init(NAME, LVL_ERROR);
+	ddf_log_init(NAME);
 	
 	ns8250_dev_ops.open = &ns8250_open;
Index: uspace/drv/char/ps2mouse/main.c
===================================================================
--- uspace/drv/char/ps2mouse/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/char/ps2mouse/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -69,5 +69,5 @@
 {
 	printf(NAME ": HelenOS ps/2 mouse driver.\n");
-	ddf_log_init(NAME, LVL_NOTE);
+	ddf_log_init(NAME);
 	return ddf_driver_main(&mouse_driver);
 }
@@ -98,5 +98,5 @@
 
 	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
-	    device->name, device->handle);
+	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
 	return EOK;
 }
Index: uspace/drv/char/ps2mouse/ps2mouse.c
===================================================================
--- uspace/drv/char/ps2mouse/ps2mouse.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/char/ps2mouse/ps2mouse.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,5 +35,4 @@
 #include <bool.h>
 #include <errno.h>
-#include <devman.h>
 #include <ddf/log.h>
 #include <io/keycode.h>
@@ -76,5 +75,5 @@
 	const ssize_t size = chardev_read(sess, &data, 1); \
 	if (size != 1) { \
-		ddf_msg(LVL_ERROR, "Failed reading byte: %d)", size);\
+		ddf_msg(LVL_ERROR, "Failed reading byte: %zd)", size);\
 		return size < 0 ? size : EIO; \
 	} \
@@ -114,9 +113,6 @@
 int ps2_mouse_init(ps2_mouse_t *mouse, ddf_dev_t *dev)
 {
-	assert(mouse);
-	assert(dev);
 	mouse->client_sess = NULL;
-	mouse->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-	    dev->handle, IPC_FLAG_BLOCKING);
+	mouse->parent_sess = ddf_dev_parent_sess_create(dev, EXCHANGE_SERIALIZE);
 	if (!mouse->parent_sess)
 		return ENOMEM;
@@ -124,14 +120,10 @@
 	mouse->mouse_fun = ddf_fun_create(dev, fun_exposed, "mouse");
 	if (!mouse->mouse_fun) {
-		async_hangup(mouse->parent_sess);
-		return ENOMEM;
-	}
-	mouse->mouse_fun->ops = &mouse_ops;
-	mouse->mouse_fun->driver_data = mouse;
+		return ENOMEM;
+	}
+	ddf_fun_set_ops(mouse->mouse_fun, &mouse_ops);
 
 	int ret = ddf_fun_bind(mouse->mouse_fun);
 	if (ret != EOK) {
-		async_hangup(mouse->parent_sess);
-		mouse->mouse_fun->driver_data = NULL;
 		ddf_fun_destroy(mouse->mouse_fun);
 		return ENOMEM;
@@ -140,7 +132,5 @@
 	ret = ddf_fun_add_to_category(mouse->mouse_fun, "mouse");
 	if (ret != EOK) {
-		async_hangup(mouse->parent_sess);
 		ddf_fun_unbind(mouse->mouse_fun);
-		mouse->mouse_fun->driver_data = NULL;
 		ddf_fun_destroy(mouse->mouse_fun);
 		return ENOMEM;
@@ -161,7 +151,5 @@
 		ddf_msg(LVL_ERROR, "Failed to enable data reporting.");
 		async_exchange_end(exch);
-		async_hangup(mouse->parent_sess);
 		ddf_fun_unbind(mouse->mouse_fun);
-		mouse->mouse_fun->driver_data = NULL;
 		ddf_fun_destroy(mouse->mouse_fun);
 		return EIO;
@@ -173,7 +161,5 @@
 		ddf_msg(LVL_ERROR, "Failed to confirm data reporting: %hhx.",
 		    report);
-		async_hangup(mouse->parent_sess);
 		ddf_fun_unbind(mouse->mouse_fun);
-		mouse->mouse_fun->driver_data = NULL;
 		ddf_fun_destroy(mouse->mouse_fun);
 		return EIO;
@@ -182,7 +168,5 @@
 	mouse->polling_fibril = fibril_create(polling_f, mouse);
 	if (!mouse->polling_fibril) {
-		async_hangup(mouse->parent_sess);
 		ddf_fun_unbind(mouse->mouse_fun);
-		mouse->mouse_fun->driver_data = NULL;
 		ddf_fun_destroy(mouse->mouse_fun);
 		return ENOMEM;
@@ -368,12 +352,6 @@
     ipc_callid_t icallid, ipc_call_t *icall)
 {
-	if (fun == NULL || fun->driver_data == NULL) {
-		ddf_msg(LVL_ERROR, "%s: Missing parameter.", __FUNCTION__);
-		async_answer_0(icallid, EINVAL);
-		return;
-	}
-
 	const sysarg_t method = IPC_GET_IMETHOD(*icall);
-	ps2_mouse_t *mouse = fun->driver_data;
+	ps2_mouse_t *mouse = ddf_dev_data_get(ddf_fun_get_dev(fun));
 
 	switch (method) {
Index: uspace/drv/char/xtkbd/main.c
===================================================================
--- uspace/drv/char/xtkbd/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/char/xtkbd/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -69,5 +69,5 @@
 {
 	printf(NAME ": HelenOS XT keyboard driver.\n");
-	ddf_log_init(NAME, LVL_NOTE);
+	ddf_log_init(NAME);
 	return ddf_driver_main(&kbd_driver);
 }
@@ -98,5 +98,5 @@
 
 	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
-	    device->name, device->handle);
+	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
 	return EOK;
 }
Index: uspace/drv/char/xtkbd/xtkbd.c
===================================================================
--- uspace/drv/char/xtkbd/xtkbd.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/char/xtkbd/xtkbd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -34,5 +34,4 @@
 
 #include <errno.h>
-#include <devman.h>
 #include <ddf/log.h>
 #include <io/keycode.h>
@@ -207,6 +206,5 @@
 	assert(dev);
 	kbd->client_sess = NULL;
-	kbd->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-	    dev->handle, IPC_FLAG_BLOCKING);
+	kbd->parent_sess = ddf_dev_parent_sess_create(dev, EXCHANGE_SERIALIZE);
 	if (!kbd->parent_sess)
 		return ENOMEM;
@@ -214,14 +212,10 @@
 	kbd->kbd_fun = ddf_fun_create(dev, fun_exposed, "kbd");
 	if (!kbd->kbd_fun) {
-		async_hangup(kbd->parent_sess);
-		return ENOMEM;
-	}
-	kbd->kbd_fun->ops = &kbd_ops;
-	kbd->kbd_fun->driver_data = kbd;
+		return ENOMEM;
+	}
+	ddf_fun_set_ops(kbd->kbd_fun, &kbd_ops);
 
 	int ret = ddf_fun_bind(kbd->kbd_fun);
 	if (ret != EOK) {
-		async_hangup(kbd->parent_sess);
-		kbd->kbd_fun->driver_data = NULL;
 		ddf_fun_destroy(kbd->kbd_fun);
 		return ENOMEM;
@@ -230,7 +224,5 @@
 	ret = ddf_fun_add_to_category(kbd->kbd_fun, "keyboard");
 	if (ret != EOK) {
-		async_hangup(kbd->parent_sess);
 		ddf_fun_unbind(kbd->kbd_fun);
-		kbd->kbd_fun->driver_data = NULL;
 		ddf_fun_destroy(kbd->kbd_fun);
 		return ENOMEM;
@@ -239,7 +231,5 @@
 	kbd->polling_fibril = fibril_create(polling, kbd);
 	if (!kbd->polling_fibril) {
-		async_hangup(kbd->parent_sess);
 		ddf_fun_unbind(kbd->kbd_fun);
-		kbd->kbd_fun->driver_data = NULL;
 		ddf_fun_destroy(kbd->kbd_fun);
 		return ENOMEM;
@@ -319,12 +309,6 @@
     ipc_callid_t icallid, ipc_call_t *icall)
 {
-	if (fun == NULL || fun->driver_data == NULL) {
-		ddf_msg(LVL_ERROR, "%s: Missing parameter.", __FUNCTION__);
-		async_answer_0(icallid, EINVAL);
-		return;
-	}
-
 	const sysarg_t method = IPC_GET_IMETHOD(*icall);
-	xt_kbd_t *kbd = fun->driver_data;
+	xt_kbd_t *kbd = ddf_dev_data_get(ddf_fun_get_dev(fun));
 
 	switch (method) {
Index: uspace/drv/fb/kfb/Makefile
===================================================================
--- uspace/drv/fb/kfb/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/fb/kfb/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# Copyright (c) 2011 Petr Koupy
+# 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 = $(LIBDRV_PREFIX)/libdrv.a $(LIBGRAPH_PREFIX)/libgraph.a $(LIBSOFTREND_PREFIX)/libsoftrend.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBGRAPH_PREFIX) -I$(LIBSOFTREND_PREFIX)
+BINARY = kfb
+
+SOURCES = \
+	port.c \
+	kfb.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/fb/kfb/kfb.c
===================================================================
--- uspace/drv/fb/kfb/kfb.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/fb/kfb/kfb.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 kfb
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <loc.h>
+#include <async.h>
+#include <task.h>
+#include <graph.h>
+#include <ops/graph_dev.h>
+#include "port.h"
+#include "kfb.h"
+
+static int kgraph_dev_add(ddf_dev_t *dev)
+{
+	port_init(dev);
+	printf("%s: Accepting connections\n", NAME);
+	return EOK;
+}
+
+static driver_ops_t kgraph_driver_ops = {
+	.dev_add = kgraph_dev_add,
+};
+
+static driver_t kgraph_driver = {
+	.name = NAME,
+	.driver_ops = &kgraph_driver_ops
+};
+
+static graph_dev_ops_t graph_vsl_dev_ops = {
+	.connect = (connect_func) &graph_visualizer_connection
+};
+
+ddf_dev_ops_t graph_vsl_device_ops = {
+	.interfaces[GRAPH_DEV_IFACE] = &graph_vsl_dev_ops
+};
+
+static graph_dev_ops_t graph_rnd_dev_ops = {
+	.connect = (connect_func) &graph_renderer_connection
+};
+
+ddf_dev_ops_t graph_rnd_device_ops = {
+	.interfaces[GRAPH_DEV_IFACE] = &graph_rnd_dev_ops
+};
+
+int main(int argc, char *argv[])
+{
+	printf("%s: HelenOS kernel framebuffer driver\n", NAME);
+	return ddf_driver_main(&kgraph_driver);
+}
+
+/** @}
+ */
Index: uspace/drv/fb/kfb/kfb.h
===================================================================
--- uspace/drv/fb/kfb/kfb.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/fb/kfb/kfb.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 kfb
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef KFB_KFB_H_
+#define KFB_KFB_H_
+
+#include <ddf/driver.h>
+
+#define NAME  "kfb"
+
+extern ddf_dev_ops_t graph_vsl_device_ops;
+extern ddf_dev_ops_t graph_rnd_device_ops;
+
+#endif
+
+/** @}
+ */
Index: uspace/drv/fb/kfb/kfb.ma
===================================================================
--- uspace/drv/fb/kfb/kfb.ma	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/fb/kfb/kfb.ma	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1 @@
+10 virtual&kfb
Index: uspace/drv/fb/kfb/port.c
===================================================================
--- uspace/drv/fb/kfb/port.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/fb/kfb/port.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2006 Jakub Vana
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2008 Martin Decky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 kfb
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <abi/fb/visuals.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include <malloc.h>
+#include <mem.h>
+#include <as.h>
+#include <align.h>
+
+#include <sysinfo.h>
+#include <ddi.h>
+
+#include <adt/list.h>
+
+#include <io/mode.h>
+#include <io/pixelmap.h>
+#include <io/chargrid.h>
+
+#include <pixconv.h>
+
+#include <graph.h>
+
+#include "kfb.h"
+#include "port.h"
+
+#define FB_POS(x, y)  ((y) * kfb.scanline + (x) * kfb.pixel_bytes)
+
+typedef struct {
+	sysarg_t width;
+	sysarg_t height;
+	size_t offset;
+	size_t scanline;
+	visual_t visual;
+	
+	pixel2visual_t pixel2visual;
+	visual2pixel_t visual2pixel;
+	visual_mask_t visual_mask;
+	size_t pixel_bytes;
+	
+	size_t size;
+	uint8_t *addr;
+} kfb_t;
+
+static kfb_t kfb;
+
+static vslmode_list_element_t pixel_mode;
+
+static pixel_t color_table[16] = {
+	[COLOR_BLACK]       = 0x000000,
+	[COLOR_BLUE]        = 0x0000f0,
+	[COLOR_GREEN]       = 0x00f000,
+	[COLOR_CYAN]        = 0x00f0f0,
+	[COLOR_RED]         = 0xf00000,
+	[COLOR_MAGENTA]     = 0xf000f0,
+	[COLOR_YELLOW]      = 0xf0f000,
+	[COLOR_WHITE]       = 0xf0f0f0,
+
+	[COLOR_BLACK + 8]   = 0x000000,
+	[COLOR_BLUE + 8]    = 0x0000ff,
+	[COLOR_GREEN + 8]   = 0x00ff00,
+	[COLOR_CYAN + 8]    = 0x00ffff,
+	[COLOR_RED + 8]     = 0xff0000,
+	[COLOR_MAGENTA + 8] = 0xff00ff,
+	[COLOR_YELLOW + 8]  = 0xffff00,
+	[COLOR_WHITE + 8]   = 0xffffff,
+};
+
+static inline void attrs_rgb(char_attrs_t attrs, pixel_t *bgcolor, pixel_t *fgcolor)
+{
+	switch (attrs.type) {
+	case CHAR_ATTR_STYLE:
+		switch (attrs.val.style) {
+		case STYLE_NORMAL:
+			*bgcolor = color_table[COLOR_WHITE];
+			*fgcolor = color_table[COLOR_BLACK];
+			break;
+		case STYLE_EMPHASIS:
+			*bgcolor = color_table[COLOR_WHITE];
+			*fgcolor = color_table[COLOR_RED];
+			break;
+		case STYLE_INVERTED:
+			*bgcolor = color_table[COLOR_BLACK];
+			*fgcolor = color_table[COLOR_WHITE];
+			break;
+		case STYLE_SELECTED:
+			*bgcolor = color_table[COLOR_RED];
+			*fgcolor = color_table[COLOR_WHITE];
+			break;
+		}
+		break;
+	case CHAR_ATTR_INDEX:
+		*bgcolor = color_table[(attrs.val.index.bgcolor & 7) |
+		    ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
+		*fgcolor = color_table[(attrs.val.index.fgcolor & 7) |
+		    ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
+		break;
+	case CHAR_ATTR_RGB:
+		*bgcolor = attrs.val.rgb.bgcolor;
+		*fgcolor = attrs.val.rgb.fgcolor;
+		break;
+	}
+}
+
+static int kfb_claim(visualizer_t *vs)
+{
+	return EOK;
+}
+
+static int kfb_yield(visualizer_t *vs)
+{
+	if (vs->mode_set) {
+		vs->ops.handle_damage = NULL;
+	}
+
+	return EOK;
+}
+
+static int kfb_handle_damage_pixels(visualizer_t *vs,
+    sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height,
+    sysarg_t x_offset, sysarg_t y_offset)
+{
+	pixelmap_t *map = &vs->cells;
+
+	if (x_offset == 0 && y_offset == 0) {
+		/* Faster damage routine ignoring offsets. */
+		for (sysarg_t y = y0; y < height + y0; ++y) {
+			for (sysarg_t x = x0; x < width + x0; ++x) {
+				kfb.pixel2visual(kfb.addr + FB_POS(x, y),
+				    *pixelmap_pixel_at(map, x, y));
+			}
+		}
+	} else {
+		for (sysarg_t y = y0; y < height + y0; ++y) {
+			for (sysarg_t x = x0; x < width + x0; ++x) {
+				kfb.pixel2visual(kfb.addr + FB_POS(x, y),
+				    *pixelmap_pixel_at(map,
+				    (x + x_offset) % map->width,
+				    (y + y_offset) % map->height));
+			}
+		}
+	}
+
+	return EOK;
+}
+
+static int kfb_change_mode(visualizer_t *vs, vslmode_t new_mode)
+{
+	vs->ops.handle_damage = kfb_handle_damage_pixels;
+	return EOK;
+}
+
+static int kfb_suspend(visualizer_t *vs)
+{
+	return EOK;
+}
+
+static int kfb_wakeup(visualizer_t *vs)
+{
+	return EOK;
+}
+
+static visualizer_ops_t kfb_ops = {
+	.claim = kfb_claim,
+	.yield = kfb_yield,
+	.change_mode = kfb_change_mode,
+	.handle_damage = NULL,
+	.suspend = kfb_suspend,
+	.wakeup = kfb_wakeup
+};
+
+int port_init(ddf_dev_t *dev)
+{
+	sysarg_t present;
+	int rc = sysinfo_get_value("fb", &present);
+	if (rc != EOK)
+		present = false;
+
+	if (!present)
+		return ENOENT;
+	
+	sysarg_t kind;
+	rc = sysinfo_get_value("fb.kind", &kind);
+	if (rc != EOK)
+		kind = (sysarg_t) -1;
+	
+	if (kind != 1)
+		return EINVAL;
+
+	sysarg_t paddr;
+	rc = sysinfo_get_value("fb.address.physical", &paddr);
+	if (rc != EOK)
+		return rc;
+	
+	sysarg_t offset;
+	rc = sysinfo_get_value("fb.offset", &offset);
+	if (rc != EOK)
+		offset = 0;
+	
+	sysarg_t width;
+	rc = sysinfo_get_value("fb.width", &width);
+	if (rc != EOK)
+		return rc;
+	
+	sysarg_t height;
+	rc = sysinfo_get_value("fb.height", &height);
+	if (rc != EOK)
+		return rc;
+	
+	sysarg_t scanline;
+	rc = sysinfo_get_value("fb.scanline", &scanline);
+	if (rc != EOK)
+		return rc;
+	
+	sysarg_t visual;
+	rc = sysinfo_get_value("fb.visual", &visual);
+	if (rc != EOK)
+		return rc;
+	
+	kfb.width = width;
+	kfb.height = height;
+	kfb.offset = offset;
+	kfb.scanline = scanline;
+	kfb.visual = visual;
+
+	switch (visual) {
+	case VISUAL_INDIRECT_8:
+		kfb.pixel2visual = pixel2bgr_323;
+		kfb.visual2pixel = bgr_323_2pixel;
+		kfb.visual_mask = visual_mask_323;
+		kfb.pixel_bytes = 1;
+		break;
+	case VISUAL_RGB_5_5_5_LE:
+		kfb.pixel2visual = pixel2rgb_555_le;
+		kfb.visual2pixel = rgb_555_le_2pixel;
+		kfb.visual_mask = visual_mask_555;
+		kfb.pixel_bytes = 2;
+		break;
+	case VISUAL_RGB_5_5_5_BE:
+		kfb.pixel2visual = pixel2rgb_555_be;
+		kfb.visual2pixel = rgb_555_be_2pixel;
+		kfb.visual_mask = visual_mask_555;
+		kfb.pixel_bytes = 2;
+		break;
+	case VISUAL_RGB_5_6_5_LE:
+		kfb.pixel2visual = pixel2rgb_565_le;
+		kfb.visual2pixel = rgb_565_le_2pixel;
+		kfb.visual_mask = visual_mask_565;
+		kfb.pixel_bytes = 2;
+		break;
+	case VISUAL_RGB_5_6_5_BE:
+		kfb.pixel2visual = pixel2rgb_565_be;
+		kfb.visual2pixel = rgb_565_be_2pixel;
+		kfb.visual_mask = visual_mask_565;
+		kfb.pixel_bytes = 2;
+		break;
+	case VISUAL_RGB_8_8_8:
+		kfb.pixel2visual = pixel2rgb_888;
+		kfb.visual2pixel = rgb_888_2pixel;
+		kfb.visual_mask = visual_mask_888;
+		kfb.pixel_bytes = 3;
+		break;
+	case VISUAL_BGR_8_8_8:
+		kfb.pixel2visual = pixel2bgr_888;
+		kfb.visual2pixel = bgr_888_2pixel;
+		kfb.visual_mask = visual_mask_888;
+		kfb.pixel_bytes = 3;
+		break;
+	case VISUAL_RGB_8_8_8_0:
+		kfb.pixel2visual = pixel2rgb_8880;
+		kfb.visual2pixel = rgb_8880_2pixel;
+		kfb.visual_mask = visual_mask_8880;
+		kfb.pixel_bytes = 4;
+		break;
+	case VISUAL_RGB_0_8_8_8:
+		kfb.pixel2visual = pixel2rgb_0888;
+		kfb.visual2pixel = rgb_0888_2pixel;
+		kfb.visual_mask = visual_mask_0888;
+		kfb.pixel_bytes = 4;
+		break;
+	case VISUAL_BGR_0_8_8_8:
+		kfb.pixel2visual = pixel2bgr_0888;
+		kfb.visual2pixel = bgr_0888_2pixel;
+		kfb.visual_mask = visual_mask_0888;
+		kfb.pixel_bytes = 4;
+		break;
+	case VISUAL_BGR_8_8_8_0:
+		kfb.pixel2visual = pixel2bgr_8880;
+		kfb.visual2pixel = bgr_8880_2pixel;
+		kfb.visual_mask = visual_mask_8880;
+		kfb.pixel_bytes = 4;
+		break;
+	default:
+		return EINVAL;
+	}
+	
+	kfb.size = scanline * height;
+	rc = physmem_map((void *) paddr + offset,
+	    ALIGN_UP(kfb.size, PAGE_SIZE) >> PAGE_WIDTH,
+	    AS_AREA_READ | AS_AREA_WRITE, (void *) &kfb.addr);
+	if (rc != EOK)
+		return rc;
+	
+	ddf_fun_t *fun_vs = ddf_fun_create(dev, fun_exposed, "vsl0");
+	if (fun_vs == NULL) {
+		as_area_destroy(kfb.addr);
+		return ENOMEM;
+	}
+	ddf_fun_set_ops(fun_vs, &graph_vsl_device_ops);
+
+	visualizer_t *vs = ddf_fun_data_alloc(fun_vs, sizeof(visualizer_t));
+	if (vs == NULL) {
+		as_area_destroy(kfb.addr);
+		return ENOMEM;
+	}
+	graph_init_visualizer(vs);
+
+	pixel_mode.mode.index = 0;
+	pixel_mode.mode.version = 0;
+	pixel_mode.mode.refresh_rate = 0;
+	pixel_mode.mode.screen_aspect.width = width;
+	pixel_mode.mode.screen_aspect.height = height;
+	pixel_mode.mode.screen_width = width;
+	pixel_mode.mode.screen_height = height;
+	pixel_mode.mode.cell_aspect.width = 1;
+	pixel_mode.mode.cell_aspect.height = 1;
+	pixel_mode.mode.cell_visual.pixel_visual = visual;
+
+	link_initialize(&pixel_mode.link);
+	list_append(&pixel_mode.link, &vs->modes);
+
+	vs->def_mode_idx = 0;
+
+	vs->ops = kfb_ops;
+	vs->dev_ctx = NULL;
+
+	rc = ddf_fun_bind(fun_vs);
+	if (rc != EOK) {
+		list_remove(&pixel_mode.link);
+		ddf_fun_destroy(fun_vs);
+		as_area_destroy(kfb.addr);
+		return rc;
+	}
+
+	vs->reg_svc_handle = ddf_fun_get_handle(fun_vs);
+	ddf_fun_add_to_category(fun_vs, "visualizer");
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/drv/fb/kfb/port.h
===================================================================
--- uspace/drv/fb/kfb/port.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/fb/kfb/port.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,46 @@
+/*
+ * 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 kgraph
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef KFB_PORT_H_
+#define KFB_PORT_H_
+
+#include <ddf/driver.h>
+
+extern int port_init(ddf_dev_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/drv/infrastructure/root/root.c
===================================================================
--- uspace/drv/infrastructure/root/root.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/infrastructure/root/root.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -204,5 +204,5 @@
 {
 	ddf_msg(LVL_DEBUG, "root_dev_add, device handle=%" PRIun,
-	    dev->handle);
+	    ddf_dev_get_handle(dev));
 
 	/*
@@ -237,5 +237,5 @@
 	printf(NAME ": HelenOS root device driver\n");
 
-	ddf_log_init(NAME, LVL_ERROR);
+	ddf_log_init(NAME);
 	return ddf_driver_main(&root_driver);
 }
Index: uspace/drv/infrastructure/rootmac/rootmac.c
===================================================================
--- uspace/drv/infrastructure/rootmac/rootmac.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/infrastructure/rootmac/rootmac.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -44,18 +44,24 @@
 #define NAME  "rootmac"
 
-/** Obtain function soft-state from DDF function node */
-#define ROOTMAC_FUN(fnode) \
-	((rootmac_fun_t *) (fnode)->driver_data)
-
 typedef struct {
 	hw_resource_list_t hw_resources;
 } rootmac_fun_t;
 
-static hw_resource_t pci_conf_regs = {
-	.type = IO_RANGE,
-	.res.io_range = {
-		.address = 0xCF8,
-		.size = 8,
-		.endianness = LITTLE_ENDIAN
+static hw_resource_t pci_conf_regs[] = {
+	{
+		.type = IO_RANGE,
+		.res.io_range = {
+			.address = 0xfec00000,
+			.size = 4,
+			.endianness = LITTLE_ENDIAN
+		}
+	},
+	{
+		.type = IO_RANGE,
+		.res.io_range = {
+			.address = 0xfee00000,
+			.size = 4,
+			.endianness = LITTLE_ENDIAN
+		}
 	}
 };
@@ -63,6 +69,6 @@
 static rootmac_fun_t pci_data = {
 	.hw_resources = {
-		1,
-		&pci_conf_regs
+		2,
+		pci_conf_regs
 	}
 };
@@ -70,11 +76,17 @@
 static ddf_dev_ops_t rootmac_fun_ops;
 
+/** Obtain function soft-state from DDF function node */
+static rootmac_fun_t *rootmac_fun(ddf_fun_t *fnode)
+{
+	return ddf_fun_data_get(fnode);
+}
+
 static bool rootmac_add_fun(ddf_dev_t *dev, const char *name,
-    const char *str_match_id, rootmac_fun_t *fun)
+    const char *str_match_id, rootmac_fun_t *fun_proto)
 {
 	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
 	
 	ddf_fun_t *fnode = NULL;
-	match_id_t *match_id = NULL;
+	int rc;
 	
 	/* Create new device. */
@@ -83,17 +95,14 @@
 		goto failure;
 	
-	fnode->driver_data = fun;
+	rootmac_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(rootmac_fun_t));
+	*fun = *fun_proto;
 	
-	/* Initialize match id list */
-	match_id = create_match_id();
-	if (match_id == NULL)
+	/* Add match ID */
+	rc = ddf_fun_add_match_id(fnode, str_match_id, 100);
+	if (rc != EOK)
 		goto failure;
 	
-	match_id->id = str_match_id;
-	match_id->score = 100;
-	add_match_id(&fnode->match_ids, match_id);
-	
 	/* Set provided operations to the device. */
-	fnode->ops = &rootmac_fun_ops;
+	ddf_fun_set_ops(fnode, &rootmac_fun_ops);
 	
 	/* Register function. */
@@ -106,7 +115,4 @@
 	
 failure:
-	if (match_id != NULL)
-		match_id->id = NULL;
-	
 	if (fnode != NULL)
 		ddf_fun_destroy(fnode);
@@ -127,7 +133,12 @@
 static int rootmac_dev_add(ddf_dev_t *dev)
 {
+#if 0
 	/* Register functions */
-	if (!rootmac_add_fun(dev, "pci0", "pangea_pci", &pci_data))
+	if (!rootmac_add_fun(dev, "pci0", "intel_pci", &pci_data))
 		ddf_msg(LVL_ERROR, "Failed to add functions for Mac platform.");
+#else
+	(void)pci_data;
+	(void)rootmac_add_fun;
+#endif
 	
 	return EOK;
@@ -147,5 +158,5 @@
 static hw_resource_list_t *rootmac_get_resources(ddf_fun_t *fnode)
 {
-	rootmac_fun_t *fun = ROOTMAC_FUN(fnode);
+	rootmac_fun_t *fun = rootmac_fun(fnode);
 	assert(fun != NULL);
 	
@@ -168,5 +179,5 @@
 {
 	printf("%s: HelenOS Mac platform driver\n", NAME);
-	ddf_log_init(NAME, LVL_ERROR);
+	ddf_log_init(NAME);
 	rootmac_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
 	return ddf_driver_main(&rootmac_driver);
Index: uspace/drv/infrastructure/rootpc/rootpc.c
===================================================================
--- uspace/drv/infrastructure/rootpc/rootpc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/infrastructure/rootpc/rootpc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -54,7 +54,4 @@
 #define NAME "rootpc"
 
-/** Obtain function soft-state from DDF function node */
-#define ROOTPC_FUN(fnode) ((rootpc_fun_t *) (fnode)->driver_data)
-
 typedef struct rootpc_fun {
 	hw_resource_list_t hw_resources;
@@ -75,10 +72,20 @@
 };
 
-static hw_resource_t pci_conf_regs = {
-	.type = IO_RANGE,
-	.res.io_range = {
-		.address = 0xCF8,
-		.size = 8,
-		.endianness = LITTLE_ENDIAN
+static hw_resource_t pci_conf_regs[] = {
+	{
+		.type = IO_RANGE,
+		.res.io_range = {
+			.address = 0xCF8,
+			.size = 4,
+			.endianness = LITTLE_ENDIAN
+		}
+	},
+	{
+		.type = IO_RANGE,
+		.res.io_range = {
+			.address = 0xCFC,
+			.size = 4,
+			.endianness = LITTLE_ENDIAN
+		}
 	}
 };
@@ -86,12 +93,18 @@
 static rootpc_fun_t pci_data = {
 	.hw_resources = {
-		1,
-		&pci_conf_regs
-	}
-};
+		sizeof(pci_conf_regs)/sizeof(pci_conf_regs[0]),
+		pci_conf_regs
+	}
+};
+
+/** Obtain function soft-state from DDF function node */
+static rootpc_fun_t *rootpc_fun(ddf_fun_t *fnode)
+{
+	return ddf_fun_data_get(fnode);
+}
 
 static hw_resource_list_t *rootpc_get_resources(ddf_fun_t *fnode)
 {
-	rootpc_fun_t *fun = ROOTPC_FUN(fnode);
+	rootpc_fun_t *fun = rootpc_fun(fnode);
 	
 	assert(fun != NULL);
@@ -116,10 +129,10 @@
 static bool
 rootpc_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id,
-    rootpc_fun_t *fun)
+    rootpc_fun_t *fun_proto)
 {
 	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
 	
 	ddf_fun_t *fnode = NULL;
-	match_id_t *match_id = NULL;
+	int rc;
 	
 	/* Create new device. */
@@ -128,17 +141,14 @@
 		goto failure;
 	
-	fnode->driver_data = fun;
-	
-	/* Initialize match id list */
-	match_id = create_match_id();
-	if (match_id == NULL)
+	rootpc_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(rootpc_fun_t));
+	*fun = *fun_proto;
+	
+	/* Add match ID */
+	rc = ddf_fun_add_match_id(fnode, str_match_id, 100);
+	if (rc != EOK)
 		goto failure;
 	
-	match_id->id = str_match_id;
-	match_id->score = 100;
-	add_match_id(&fnode->match_ids, match_id);
-	
 	/* Set provided operations to the device. */
-	fnode->ops = &rootpc_fun_ops;
+	ddf_fun_set_ops(fnode, &rootpc_fun_ops);
 	
 	/* Register function. */
@@ -151,7 +161,4 @@
 	
 failure:
-	if (match_id != NULL)
-		match_id->id = NULL;
-	
 	if (fnode != NULL)
 		ddf_fun_destroy(fnode);
@@ -176,5 +183,5 @@
 {
 	ddf_msg(LVL_DEBUG, "rootpc_dev_add, device handle = %d",
-	    (int)dev->handle);
+	    (int)ddf_dev_get_handle(dev));
 	
 	/* Register functions. */
@@ -188,5 +195,5 @@
 static void root_pc_init(void)
 {
-	ddf_log_init(NAME, LVL_ERROR);
+	ddf_log_init(NAME);
 	rootpc_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
 }
Index: uspace/drv/infrastructure/rootvirt/devices.def
===================================================================
--- uspace/drv/infrastructure/rootvirt/devices.def	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/infrastructure/rootvirt/devices.def	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -4,4 +4,10 @@
  * Unless the list is empty, the last item shall be followed by a comma.
  */
+
+/* Kernel framebuffer */
+{
+    .name = "kfb",
+    .match_id = "virtual&kfb"
+},
 
 #ifdef CONFIG_TEST_DRIVERS
Index: uspace/drv/infrastructure/rootvirt/rootvirt.c
===================================================================
--- uspace/drv/infrastructure/rootvirt/rootvirt.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/infrastructure/rootvirt/rootvirt.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -151,5 +151,5 @@
 {
 	int rc;
-	const char *name = rvfun->fun->name;
+	const char *name = ddf_fun_get_name(rvfun->fun);
 
 	ddf_msg(LVL_DEBUG, "rootvirt_fun_remove('%s')", name);
@@ -183,5 +183,5 @@
 	}
 
-	ddf_msg(LVL_DEBUG, "dev_add(handle=%d)", (int)dev->handle);
+	ddf_msg(LVL_DEBUG, "dev_add(handle=%d)", (int)ddf_dev_get_handle(dev));
 
 	rootvirt = ddf_dev_data_alloc(dev, sizeof(rootvirt_t));
@@ -207,5 +207,5 @@
 static int rootvirt_dev_remove(ddf_dev_t *dev)
 {
-	rootvirt_t *rootvirt = (rootvirt_t *)dev->driver_data;
+	rootvirt_t *rootvirt = (rootvirt_t *)ddf_dev_data_get(dev);
 	int rc;
 
@@ -240,5 +240,5 @@
 	printf(NAME ": HelenOS virtual devices root driver\n");
 
-	ddf_log_init(NAME, LVL_ERROR);
+	ddf_log_init(NAME);
 	return ddf_driver_main(&rootvirt_driver);
 }
Index: uspace/drv/nic/e1k/e1k.c
===================================================================
--- uspace/drv/nic/e1k/e1k.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/nic/e1k/e1k.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -32,4 +32,7 @@
  *
  */
+
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
 
 #include <assert.h>
@@ -71,11 +74,19 @@
 	((e1000_t *) nic_get_specific(nic))
 
-/** device_t* -> nic_driver_data_t* cast */
+/** ddf_fun_t * -> nic_driver_data_t* cast */
+#define NIC_DATA_FUN(fun) \
+	((nic_t *) ddf_fun_data_get(fun))
+
+/** ddf_dev_t * -> nic_driver_data_t* cast */
 #define NIC_DATA_DEV(dev) \
-	((nic_t *) ((dev)->driver_data))
-
-/** device_t* -> e1000_t* cast */
+	((nic_t *) ddf_dev_data_get(dev))
+
+/** ddf_dev_t * -> e1000_t* cast */
 #define DRIVER_DATA_DEV(dev) \
 	(DRIVER_DATA_NIC(NIC_DATA_DEV(dev)))
+
+/** ddf_fun_t * -> e1000_t* cast */
+#define DRIVER_DATA_FUN(fun) \
+	(DRIVER_DATA_NIC(NIC_DATA_FUN(fun)))
 
 /** Cast pointer to uint64_t
@@ -305,11 +316,7 @@
  *
  */
-static int e1000_get_cable_state(ddf_fun_t *dev, nic_cable_state_t *state)
-{
-	assert(dev);
-	assert(DRIVER_DATA_DEV(dev));
-	assert(state);
-	
-	e1000_t *e1000 = DRIVER_DATA_DEV(dev);
+static int e1000_get_cable_state(ddf_fun_t *fun, nic_cable_state_t *state)
+{
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	if (E1000_REG_READ(e1000, E1000_STATUS) & (STATUS_LU))
 		*state = NIC_CS_PLUGGED;
@@ -328,8 +335,8 @@
  *
  */
-static int e1000_get_operation_mode(ddf_fun_t *dev, int *speed,
+static int e1000_get_operation_mode(ddf_fun_t *fun, int *speed,
     nic_channel_mode_t *duplex, nic_role_t *role)
 {
-	e1000_t *e1000 = DRIVER_DATA_DEV(dev);
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	uint32_t status = E1000_REG_READ(e1000, E1000_STATUS);
 	
@@ -376,5 +383,5 @@
  *
  */
-static int e1000_set_operation_mode(ddf_fun_t *dev, int speed,
+static int e1000_set_operation_mode(ddf_fun_t *fun, int speed,
     nic_channel_mode_t duplex, nic_role_t role)
 {
@@ -385,5 +392,5 @@
 		return EINVAL;
 	
-	e1000_t *e1000 = DRIVER_DATA_DEV(dev);
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	
 	fibril_mutex_lock(&e1000->ctrl_lock);
@@ -424,7 +431,7 @@
  *
  */
-static int e1000_autoneg_enable(ddf_fun_t *dev, uint32_t advertisement)
-{
-	e1000_t *e1000 = DRIVER_DATA_DEV(dev);
+static int e1000_autoneg_enable(ddf_fun_t *fun, uint32_t advertisement)
+{
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	
 	fibril_mutex_lock(&e1000->ctrl_lock);
@@ -452,7 +459,7 @@
  *
  */
-static int e1000_autoneg_disable(ddf_fun_t *dev)
-{
-	e1000_t *e1000 = DRIVER_DATA_DEV(dev);
+static int e1000_autoneg_disable(ddf_fun_t *fun)
+{
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	
 	fibril_mutex_lock(&e1000->ctrl_lock);
@@ -491,7 +498,7 @@
  *
  */
-static int e1000_defective_get_mode(ddf_fun_t *device, uint32_t *mode)
-{
-	e1000_t *e1000 = DRIVER_DATA_DEV(device);
+static int e1000_defective_get_mode(ddf_fun_t *fun, uint32_t *mode)
+{
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	
 	*mode = 0;
@@ -512,7 +519,7 @@
  *
  */
-static int e1000_defective_set_mode(ddf_fun_t *device, uint32_t mode)
-{
-	e1000_t *e1000 = DRIVER_DATA_DEV(device);
+static int e1000_defective_set_mode(ddf_fun_t *fun, uint32_t mode)
+{
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	int rc = EOK;
 	
@@ -1038,5 +1045,5 @@
  *
  */
-static int e1000_vlan_set_tag(ddf_fun_t *device, uint16_t tag, bool add,
+static int e1000_vlan_set_tag(ddf_fun_t *fun, uint16_t tag, bool add,
     bool strip)
 {
@@ -1052,5 +1059,5 @@
 		return ENOTSUP;
 	
-	e1000_t *e1000 = DRIVER_DATA_DEV(device);
+	e1000_t *e1000 = DRIVER_DATA_FUN(fun);
 	
 	e1000->vlan_tag = tag;
@@ -1855,7 +1862,4 @@
 static e1000_t *e1000_create_dev_data(ddf_dev_t *dev)
 {
-	assert(dev);
-	assert(!dev->driver_data);
-	
 	nic_t *nic = nic_create_and_bind(dev);
 	if (!nic)
@@ -1896,5 +1900,5 @@
 	assert(dev);
 	
-	if (dev->driver_data != NULL)
+	if (ddf_dev_data_get(dev) != NULL)
 		nic_unbind_and_destroy(dev);
 }
@@ -1910,9 +1914,4 @@
 	
 	e1000_delete_dev_data(dev);
-	
-	if (dev->parent_sess != NULL) {
-		async_hangup(dev->parent_sess);
-		dev->parent_sess = NULL;
-	}
 }
 
@@ -1931,8 +1930,4 @@
     const hw_res_list_parsed_t *hw_resources)
 {
-	assert(dev != NULL);
-	assert(hw_resources != NULL);
-	assert(dev->driver_data != NULL);
-	
 	e1000_t *e1000 = DRIVER_DATA_DEV(dev);
 	
@@ -2003,5 +1998,5 @@
 	
 	uint16_t device_id;
-	rc = pci_config_space_read_16(dev->parent_sess, PCI_DEVICE_ID,
+	rc = pci_config_space_read_16(ddf_dev_parent_sess_get(dev), PCI_DEVICE_ID,
 	    &device_id);
 	if (rc != EOK) {
@@ -2121,5 +2116,5 @@
 	
 	/* Device initialization */
-	nic_t *nic = dev->driver_data;
+	nic_t *nic = ddf_dev_data_get(dev);
 	e1000_t *e1000 = DRIVER_DATA_NIC(nic);
 	
@@ -2147,6 +2142,6 @@
 		goto err_tx_structure;
 	nic_set_ddf_fun(nic, fun);
-	fun->ops = &e1000_dev_ops;
-	fun->driver_data = nic;
+	ddf_fun_set_ops(fun, &e1000_dev_ops);
+	ddf_fun_data_implant(fun, nic);
 	
 	rc = e1000_register_int_handler(nic);
@@ -2278,7 +2273,7 @@
  * @return Negative error code otherwise
  */
-static int e1000_set_addr(ddf_fun_t *dev, const nic_address_t *addr)
-{
-	nic_t *nic = NIC_DATA_DEV(dev);
+static int e1000_set_addr(ddf_fun_t *fun, const nic_address_t *addr)
+{
+	nic_t *nic = NIC_DATA_FUN(fun);
 	e1000_t *e1000 = DRIVER_DATA_NIC(nic);
 	
@@ -2386,5 +2381,5 @@
 	    &e1000_nic_iface);
 	
-	ddf_log_init(NAME, LVL_ERROR);
+	ddf_log_init(NAME);
 	ddf_msg(LVL_NOTE, "HelenOS E1000 driver started");
 	return ddf_driver_main(&e1000_driver);
Index: uspace/drv/nic/ne2k/dp8390.c
===================================================================
--- uspace/drv/nic/ne2k/dp8390.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/nic/ne2k/dp8390.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -201,5 +201,5 @@
 	/* Check if the DP8390 is really there */
 	uint8_t val = pio_read_8(ne2k->port + DP_CR);
-	if ((val & (CR_STP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT))
+	if ((val & (CR_STP | CR_TXP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT))
 		return EXDEV;
 	
Index: uspace/drv/nic/ne2k/ne2k.c
===================================================================
--- uspace/drv/nic/ne2k/ne2k.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/nic/ne2k/ne2k.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,4 +38,7 @@
  */
 
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 #include <stdio.h>
 #include <errno.h>
@@ -61,5 +64,5 @@
 #define IRQ_GET_TSR(call)  ((int) IPC_GET_ARG3(call))
 
-#define DRIVER_DATA(dev) ((nic_t *) ((dev)->driver_data))
+#define DRIVER_DATA(dev) ((nic_t *) ddf_dev_data_get(dev))
 #define NE2K(device) ((ne2k_t *) nic_get_specific(DRIVER_DATA(device)))
 
@@ -83,5 +86,5 @@
 	{
 		/* Mask supported interrupt causes */
-		.cmd = CMD_BTEST,
+		.cmd = CMD_AND,
 		.value = (ISR_PRX | ISR_PTX | ISR_RXE | ISR_TXE | ISR_OVW |
 		    ISR_CNT | ISR_RDC),
@@ -169,5 +172,5 @@
 static void ne2k_dev_cleanup(ddf_dev_t *dev)
 {
-	if (dev->driver_data != NULL) {
+	if (ddf_dev_data_get(dev) != NULL) {
 		ne2k_t *ne2k = NE2K(dev);
 		if (ne2k) {
@@ -177,8 +180,4 @@
 		nic_unbind_and_destroy(dev);
 	}
-	if (dev->parent_sess != NULL) {
-		async_hangup(dev->parent_sess);
-		dev->parent_sess = NULL;
-	}
 }
 
@@ -279,5 +278,5 @@
 static int ne2k_set_address(ddf_fun_t *fun, const nic_address_t *address)
 {
-	nic_t *nic_data = DRIVER_DATA(fun);
+	nic_t *nic_data = DRIVER_DATA(ddf_fun_get_dev(fun));
 	int rc = nic_report_address(nic_data, address);
 	if (rc != EOK) {
@@ -410,6 +409,6 @@
 	}
 	nic_set_ddf_fun(nic_data, fun);
-	fun->ops = &ne2k_dev_ops;
-	fun->driver_data = nic_data;
+	ddf_fun_set_ops(fun, &ne2k_dev_ops);
+	ddf_fun_data_implant(fun, nic_data);
 	
 	rc = ddf_fun_bind(fun);
Index: uspace/drv/nic/rtl8139/driver.c
===================================================================
--- uspace/drv/nic/rtl8139/driver.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/nic/rtl8139/driver.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -27,4 +27,7 @@
  */
 
+/* XXX Fix this */
+#define _DDF_DATA_IMPLANT
+
 #include <assert.h>
 #include <errno.h>
@@ -212,13 +215,12 @@
 	rtl8139_regs_lock(rtl8139->io_port);
 
+	async_sess_t *pci_sess =
+		ddf_dev_parent_sess_get(nic_get_ddf_dev(rtl8139->nic_data));
+
 	if (bit_val) {
-		async_sess_t *pci_sess =
-			nic_get_ddf_dev(rtl8139->nic_data)->parent_sess;
 		uint8_t pmen;
 		pci_config_space_read_8(pci_sess, 0x55, &pmen);
 		pci_config_space_write_8(pci_sess, 0x55, pmen | 1 | (1 << 7));
 	} else {
-		async_sess_t *pci_sess =
-			nic_get_ddf_dev(rtl8139->nic_data)->parent_sess;
 		uint8_t pmen;
 		pci_config_space_read_8(pci_sess, 0x55, &pmen);
@@ -618,6 +620,6 @@
 		/* Check if the header is valid, otherwise we are lost in the buffer */
 		if (size == 0 || size > RTL8139_FRAME_MAX_LENGTH) {
-			ddf_msg(LVL_ERROR, "Receiver error -> receiver reset (size: %4"PRIu16", "
-			    "header 0x%4"PRIx16". Offset: %zu)", size, frame_header, 
+			ddf_msg(LVL_ERROR, "Receiver error -> receiver reset (size: %4" PRIu16 ", "
+			    "header 0x%4" PRIx16 ". Offset: %d)", size, frame_header,
 			    rx_offset);
 			goto rx_err;
@@ -1052,11 +1054,6 @@
 	assert(dev);
 
-	if (dev->driver_data)
+	if (ddf_dev_data_get(dev))
 		nic_unbind_and_destroy(dev);
-
-	if (dev->parent_sess != NULL) {
-		async_hangup(dev->parent_sess);
-		dev->parent_sess = NULL;
-	}
 }
 
@@ -1080,22 +1077,22 @@
 
 	if (hw_resources->irqs.count != 1) {
-		ddf_msg(LVL_ERROR, "%s device: unexpected irq count", dev->name);
+		ddf_msg(LVL_ERROR, "%s device: unexpected irq count", ddf_dev_get_name(dev));
 		return EINVAL;
 	};
 	if (hw_resources->io_ranges.count != 1) {
-		ddf_msg(LVL_ERROR, "%s device: unexpected io ranges count", dev->name);
+		ddf_msg(LVL_ERROR, "%s device: unexpected io ranges count", ddf_dev_get_name(dev));
 		return EINVAL;
 	}
 
 	rtl8139->irq = hw_resources->irqs.irqs[0];
-	ddf_msg(LVL_DEBUG, "%s device: irq 0x%x assigned", dev->name, rtl8139->irq);
+	ddf_msg(LVL_DEBUG, "%s device: irq 0x%x assigned", ddf_dev_get_name(dev), rtl8139->irq);
 
 	rtl8139->io_addr = IOADDR_TO_PTR(hw_resources->io_ranges.ranges[0].address);
 	if (hw_resources->io_ranges.ranges[0].size < RTL8139_IO_SIZE) {
 		ddf_msg(LVL_ERROR, "i/o range assigned to the device "
-		    "%s is too small.", dev->name);
+		    "%s is too small.", ddf_dev_get_name(dev));
 		return EINVAL;
 	}
-	ddf_msg(LVL_DEBUG, "%s device: i/o addr %p assigned.", dev->name, rtl8139->io_addr);
+	ddf_msg(LVL_DEBUG, "%s device: i/o addr %p assigned.", ddf_dev_get_name(dev), rtl8139->io_addr);
 
 	return EOK;
@@ -1165,5 +1162,5 @@
 
 	/* Allocate buffer for receiver */
-	ddf_msg(LVL_DEBUG, "Allocating receiver buffer of the size %zu bytes",
+	ddf_msg(LVL_DEBUG, "Allocating receiver buffer of the size %d bytes",
 	    RxBUF_TOT_LENGTH);
 
@@ -1192,5 +1189,5 @@
 static int rtl8139_device_initialize(ddf_dev_t *dev)
 {
-	ddf_msg(LVL_DEBUG, "rtl8139_dev_initialize %s", dev->name);
+	ddf_msg(LVL_DEBUG, "rtl8139_dev_initialize %s", ddf_dev_get_name(dev));
 
 	int ret = EOK;
@@ -1201,5 +1198,5 @@
 	rtl8139_t *rtl8139 = rtl8139_create_dev_data(dev);
 	if (rtl8139 == NULL) {
-		ddf_msg(LVL_ERROR, "Not enough memory for initializing %s.", dev->name);
+		ddf_msg(LVL_ERROR, "Not enough memory for initializing %s.", ddf_dev_get_name(dev));
 		return ENOMEM;
 	}
@@ -1246,5 +1243,5 @@
 static int rtl8139_pio_enable(ddf_dev_t *dev)
 {
-	ddf_msg(LVL_DEBUG, NAME ": rtl8139_pio_enable %s", dev->name);
+	ddf_msg(LVL_DEBUG, NAME ": rtl8139_pio_enable %s", ddf_dev_get_name(dev));
 
 	rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_dev(dev));
@@ -1252,6 +1249,6 @@
 	/* Gain control over port's registers. */
 	if (pio_enable(rtl8139->io_addr, RTL8139_IO_SIZE, &rtl8139->io_port)) {
-		ddf_msg(LVL_ERROR, "Cannot gain the port %lx for device %s.", rtl8139->io_addr,
-		    dev->name);
+		ddf_msg(LVL_ERROR, "Cannot gain the port %p for device %s.", rtl8139->io_addr,
+		    ddf_dev_get_name(dev));
 		return EADDRNOTAVAIL;
 	}
@@ -1299,5 +1296,6 @@
 
 	assert(dev);
-	ddf_msg(LVL_NOTE, "RTL8139_dev_add %s (handle = %d)", dev->name, dev->handle);
+	ddf_msg(LVL_NOTE, "RTL8139_dev_add %s (handle = %zu)",
+	    ddf_dev_get_name(dev), ddf_dev_get_handle(dev));
 
 	/* Init device structure for rtl8139 */
@@ -1330,5 +1328,5 @@
 	rc = nic_connect_to_services(nic_data);
 	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed to connect to services", rc);
+		ddf_msg(LVL_ERROR, "Failed to connect to services (%d)", rc);
 		goto err_irq;
 	}
@@ -1340,6 +1338,6 @@
 	}
 	nic_set_ddf_fun(nic_data, fun);
-	fun->ops = &rtl8139_dev_ops;
-	fun->driver_data = nic_data;
+	ddf_fun_set_ops(fun, &rtl8139_dev_ops);
+	ddf_fun_data_implant(fun, nic_data);
 
 	rc = ddf_fun_bind(fun);
@@ -1355,5 +1353,5 @@
 
 	ddf_msg(LVL_NOTE, "The %s device has been successfully initialized.",
-	    dev->name);
+	    ddf_dev_get_name(dev));
 
 	return EOK;
@@ -2141,7 +2139,8 @@
 		pio_write_32(rtl8139->io_port + TCTR, 0);
 
-		ddf_msg(LVL_DEBUG, "Periodic mode. Interrupt mask %"PRIx16", poll.full_skips %"
-		    PRIu32", last timer %"PRIu32".", rtl8139->int_mask, 
-		    rtl8139->poll_timer.full_skips, rtl8139->poll_timer.last_val);
+		ddf_msg(LVL_DEBUG, "Periodic mode. Interrupt mask %" PRIx16 ", "
+		    "poll.full_skips %zu, last timer %" PRIu32,
+		    rtl8139->int_mask, rtl8139->poll_timer.full_skips,
+		    rtl8139->poll_timer.last_val);
 		break;
 	default:
@@ -2188,5 +2187,5 @@
 		&rtl8139_driver_ops, &rtl8139_dev_ops, &rtl8139_nic_iface);
 
-	ddf_log_init(NAME, LVL_ERROR);
+	ddf_log_init(NAME);
 	ddf_msg(LVL_NOTE, "HelenOS RTL8139 driver started");
 	return ddf_driver_main(&rtl8139_driver);
Index: uspace/drv/test/test1/test1.c
===================================================================
--- uspace/drv/test/test1/test1.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/test/test1/test1.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -145,13 +145,16 @@
 	ddf_fun_t *fun_a;
 	test1_t *test1;
-	int rc;
-
+	const char *dev_name;
+	int rc;
+
+	dev_name = ddf_dev_get_name(dev);
 	ddf_msg(LVL_DEBUG, "dev_add(name=\"%s\", handle=%d)",
-	    dev->name, (int) dev->handle);
+	    dev_name, (int) ddf_dev_get_handle(dev));
 
 	test1 = ddf_dev_data_alloc(dev, sizeof(test1_t));
 	if (test1 == NULL) {
 		ddf_msg(LVL_ERROR, "Failed allocating soft state.\n");
-		return ENOMEM;
+		rc = ENOMEM;
+		goto error;
 	}
 
@@ -159,5 +162,6 @@
 	if (fun_a == NULL) {
 		ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
-		return ENOMEM;
+		rc = ENOMEM;
+		goto error;
 	}
 
@@ -168,13 +172,13 @@
 		ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
 		ddf_fun_destroy(fun_a);
-		return rc;
+		goto error;
 	}
 
 	ddf_fun_add_to_category(fun_a, "virtual");
 
-	if (str_cmp(dev->name, "null") == 0) {
-		fun_a->ops = &char_device_ops;
+	if (str_cmp(dev_name, "null") == 0) {
+		ddf_fun_set_ops(fun_a,  &char_device_ops);
 		ddf_fun_add_to_category(fun_a, "virt-null");
-	} else if (str_cmp(dev->name, "test1") == 0) {
+	} else if (str_cmp(dev_name, "test1") == 0) {
 		(void) register_fun_verbose(dev,
 		    "cloning myself ;-)", "clone",
@@ -183,5 +187,5 @@
 		    "cloning myself twice ;-)", "clone",
 		    "virtual&test1", 10, EEXISTS, NULL);
-	} else if (str_cmp(dev->name, "clone") == 0) {
+	} else if (str_cmp(dev_name, "clone") == 0) {
 		(void) register_fun_verbose(dev,
 		    "run by the same task", "child",
@@ -189,7 +193,8 @@
 	}
 
-	ddf_msg(LVL_DEBUG, "Device `%s' accepted.", dev->name);
-
-	return EOK;
+	ddf_msg(LVL_DEBUG, "Device `%s' accepted.", dev_name);
+	return EOK;
+error:
+	return rc;
 }
 
@@ -232,5 +237,5 @@
 static int test1_dev_remove(ddf_dev_t *dev)
 {
-	test1_t *test1 = (test1_t *)dev->driver_data;
+	test1_t *test1 = (test1_t *)ddf_dev_data_get(dev);
 	int rc;
 
@@ -260,5 +265,5 @@
 static int test1_dev_gone(ddf_dev_t *dev)
 {
-	test1_t *test1 = (test1_t *)dev->driver_data;
+	test1_t *test1 = (test1_t *)ddf_dev_data_get(dev);
 	int rc;
 
@@ -301,5 +306,5 @@
 {
 	printf(NAME ": HelenOS test1 virtual device driver\n");
-	ddf_log_init(NAME, LVL_ERROR);
+	ddf_log_init(NAME);
 	return ddf_driver_main(&test1_driver);
 }
Index: uspace/drv/test/test2/test2.c
===================================================================
--- uspace/drv/test/test2/test2.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/test/test2/test2.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -196,7 +196,8 @@
 {
 	test2_t *test2;
+	const char *dev_name = ddf_dev_get_name(dev);
 
 	ddf_msg(LVL_DEBUG, "test2_dev_add(name=\"%s\", handle=%d)",
-	    dev->name, (int) dev->handle);
+	    dev_name, (int) ddf_dev_get_handle(dev));
 
 	test2 = ddf_dev_data_alloc(dev, sizeof(test2_t));
@@ -208,5 +209,5 @@
 	test2->dev = dev;
 
-	if (str_cmp(dev->name, "child") != 0) {
+	if (str_cmp(dev_name, "child") != 0) {
 		fid_t postpone = fibril_create(plug_unplug, test2);
 		if (postpone == 0) {
@@ -225,5 +226,5 @@
 static int test2_dev_remove(ddf_dev_t *dev)
 {
-	test2_t *test2 = (test2_t *)dev->driver_data;
+	test2_t *test2 = (test2_t *)ddf_dev_data_get(dev);
 	int rc;
 
@@ -259,5 +260,5 @@
 static int test2_dev_gone(ddf_dev_t *dev)
 {
-	test2_t *test2 = (test2_t *)dev->driver_data;
+	test2_t *test2 = (test2_t *)ddf_dev_data_get(dev);
 	int rc;
 
@@ -307,5 +308,5 @@
 {
 	printf(NAME ": HelenOS test2 virtual device driver\n");
-	ddf_log_init(NAME, LVL_NOTE);
+	ddf_log_init(NAME);
 	return ddf_driver_main(&test2_driver);
 }
Index: uspace/drv/test/test3/test3.c
===================================================================
--- uspace/drv/test/test3/test3.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/drv/test/test3/test3.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -133,5 +133,5 @@
 
 	ddf_msg(LVL_DEBUG, "dev_add(name=\"%s\", handle=%d)",
-	    dev->name, (int) dev->handle);
+	    ddf_dev_get_name(dev), (int) ddf_dev_get_handle(dev));
 
 	test3 = ddf_dev_data_alloc(dev, sizeof(test3_t));
@@ -155,5 +155,5 @@
 static int test3_dev_remove(ddf_dev_t *dev)
 {
-	test3_t *test3 = (test3_t *)dev->driver_data;
+	test3_t *test3 = (test3_t *)ddf_dev_data_get(dev);
 	char *fun_name;
 	int rc;
@@ -193,5 +193,5 @@
 {
 	printf(NAME ": HelenOS test3 virtual device driver\n");
-	ddf_log_init(NAME, LVL_ERROR);
+	ddf_log_init(NAME);
 	return ddf_driver_main(&test3_driver);
 }
Index: uspace/drv/time/cmos-rtc/Makefile
===================================================================
--- uspace/drv/time/cmos-rtc/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/time/cmos-rtc/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2012 Maurizio Lombardi
+# 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 = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = cmos-rtc
+
+SOURCES = \
+	cmos-rtc.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/time/cmos-rtc/cmos-regs.h
===================================================================
--- uspace/drv/time/cmos-rtc/cmos-regs.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/time/cmos-rtc/cmos-regs.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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.
+ */
+
+#ifndef _CMOS_RTC_H_
+#define _CMOS_RTC_H_
+
+#define RTC_SEC           0x00
+#define RTC_MIN           0x02
+#define RTC_HOUR          0x04
+#define RTC_DAY           0x07
+#define RTC_MON           0x08
+#define RTC_YEAR          0x09
+
+#define RTC_STATUS_B      0x0B
+#define RTC_B_24H         0x02 /* 24h mode */
+#define RTC_B_BCD         0x04 /* BCD mode */
+#define RTC_B_INH         0x80 /* Inhibit updates */
+
+#define RTC_STATUS_D      0x0D
+#define RTC_D_BATTERY_OK  0x80 /* Battery status */
+
+#define RTC_STATUS_A      0x0A
+#define RTC_A_UPDATE      0x80 /* Update in progress */
+#define RTC_A_CLK_STOP    0x70 /* Stop the clock */
+
+#endif
+
Index: uspace/drv/time/cmos-rtc/cmos-rtc.c
===================================================================
--- uspace/drv/time/cmos-rtc/cmos-rtc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/time/cmos-rtc/cmos-rtc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,775 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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.
+ */
+
+/**
+ * @defgroup CMOS RTC driver.
+ * @brief HelenOS RTC driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <errno.h>
+#include <ddi.h>
+#include <as.h>
+#include <sysinfo.h>
+#include <libarch/ddi.h>
+#include <libarch/barrier.h>
+#include <stdio.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <ops/clock_dev.h>
+#include <ops/battery_dev.h>
+#include <fibril_synch.h>
+#include <device/hw_res.h>
+#include <macros.h>
+#include <time.h>
+
+#include "cmos-regs.h"
+
+#define NAME "cmos-rtc"
+
+#define REG_COUNT 2
+
+#define REG_SEL_PORT(port)  (port)
+#define REG_RW_PORT(port)   ((port) + 1)
+
+typedef struct rtc {
+	/** DDF device node */
+	ddf_dev_t *dev;
+	/** DDF function node */
+	ddf_fun_t *fun;
+	/** The fibril mutex for synchronizing the access to the device */
+	fibril_mutex_t mutex;
+	/** The base I/O address of the device registers */
+	ioport8_t *io_addr;
+	/** The I/O port used to access the CMOS registers */
+	ioport8_t *port;
+	/** true if device is removed */
+	bool removed;
+	/** number of connected clients */
+	int clients_connected;
+	/** time at which the system booted */
+	time_t boottime;
+} rtc_t;
+
+static rtc_t *dev_rtc(ddf_dev_t *dev);
+static rtc_t *fun_rtc(ddf_fun_t *fun);
+static int
+rtc_battery_status_get(ddf_fun_t *fun, battery_status_t *status);
+static int  rtc_time_get(ddf_fun_t *fun, struct tm *t);
+static int  rtc_time_set(ddf_fun_t *fun, struct tm *t);
+static int  rtc_dev_add(ddf_dev_t *dev);
+static int  rtc_dev_initialize(rtc_t *rtc);
+static bool rtc_pio_enable(rtc_t *rtc);
+static void rtc_dev_cleanup(rtc_t *rtc);
+static int  rtc_open(ddf_fun_t *fun);
+static void rtc_close(ddf_fun_t *fun);
+static bool rtc_update_in_progress(rtc_t *rtc);
+static int  rtc_register_read(rtc_t *rtc, int reg);
+static unsigned bcd2bin(unsigned bcd);
+static unsigned bin2bcd(unsigned binary);
+static int rtc_dev_remove(ddf_dev_t *dev);
+static void rtc_register_write(rtc_t *rtc, int reg, int data);
+static time_t uptime_get(void);
+static bool is_battery_ok(rtc_t *rtc);
+static int  rtc_fun_online(ddf_fun_t *fun);
+static int  rtc_fun_offline(ddf_fun_t *fun);
+
+static ddf_dev_ops_t rtc_dev_ops;
+
+/** The RTC device driver's standard operations */
+static driver_ops_t rtc_ops = {
+	.dev_add = rtc_dev_add,
+	.dev_remove = rtc_dev_remove,
+	.fun_online = rtc_fun_online,
+	.fun_offline = rtc_fun_offline,
+};
+
+/** The RTC device driver structure */
+static driver_t rtc_driver = {
+	.name = NAME,
+	.driver_ops = &rtc_ops,
+};
+
+/** Clock interface */
+static clock_dev_ops_t rtc_clock_dev_ops = {
+	.time_get = rtc_time_get,
+	.time_set = rtc_time_set,
+};
+
+/** Battery powered device interface */
+static battery_dev_ops_t rtc_battery_dev_ops = {
+	.battery_status_get = rtc_battery_status_get,
+	.battery_charge_level_get = NULL,
+};
+
+/** Obtain soft state structure from device node */
+static rtc_t *
+dev_rtc(ddf_dev_t *dev)
+{
+	return ddf_dev_data_get(dev);
+}
+
+/** Obtain soft state structure from function node */
+static rtc_t *
+fun_rtc(ddf_fun_t *fun)
+{
+	return dev_rtc(ddf_fun_get_dev(fun));
+}
+
+/** Initialize the RTC driver */
+static void
+rtc_init(void)
+{
+	ddf_log_init(NAME);
+
+	rtc_dev_ops.open = rtc_open;
+	rtc_dev_ops.close = rtc_close;
+
+	rtc_dev_ops.interfaces[CLOCK_DEV_IFACE] = &rtc_clock_dev_ops;
+	rtc_dev_ops.interfaces[BATTERY_DEV_IFACE] = &rtc_battery_dev_ops;
+	rtc_dev_ops.default_handler = NULL;
+}
+
+/** Clean up the RTC soft state
+ *
+ * @param rtc  The RTC device
+ */
+static void
+rtc_dev_cleanup(rtc_t *rtc)
+{
+}
+
+/** Enable the I/O ports of the device
+ *
+ * @param rtc  The real time clock device
+ *
+ * @return  true in case of success, false otherwise
+ */
+static bool
+rtc_pio_enable(rtc_t *rtc)
+{
+	if (pio_enable((void *) rtc->io_addr, REG_COUNT,
+	    (void **) &rtc->port)) {
+
+		ddf_msg(LVL_ERROR, "Cannot map the port %lx"
+		    " for device %s", (long unsigned int)rtc->io_addr,
+		    ddf_dev_get_name(rtc->dev));
+		return false;
+	}
+
+	return true;
+}
+
+/** Initialize the RTC device
+ *
+ * @param rtc  Pointer to the RTC device
+ *
+ * @return  EOK on success or a negative error code
+ */ 
+static int
+rtc_dev_initialize(rtc_t *rtc)
+{
+	int rc;
+	size_t i;
+	hw_resource_t *res;
+	bool ioport = false;
+	async_sess_t *parent_sess;
+
+	ddf_msg(LVL_DEBUG, "rtc_dev_initialize %s", ddf_dev_get_name(rtc->dev));
+
+	rtc->boottime = 0;
+	rtc->clients_connected = 0;
+
+	hw_resource_list_t hw_resources;
+	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
+
+	/* Connect to the parent's driver */
+
+	parent_sess = ddf_dev_parent_sess_create(rtc->dev, EXCHANGE_SERIALIZE);
+	if (!parent_sess) {
+		ddf_msg(LVL_ERROR, "Failed to connect to parent driver\
+		    of device %s.", ddf_dev_get_name(rtc->dev));
+		rc = ENOENT;
+		goto error;
+	}
+
+	/* Get the HW resources */
+	rc = hw_res_get_resource_list(parent_sess, &hw_resources);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to get HW resources\
+		    for device %s", ddf_dev_get_name(rtc->dev));
+		goto error;
+	}
+
+	for (i = 0; i < hw_resources.count; ++i) {
+		res = &hw_resources.resources[i];
+
+		if (res->res.io_range.size < REG_COUNT) {
+			ddf_msg(LVL_ERROR, "I/O range assigned to \
+			    device %s is too small",
+			    ddf_dev_get_name(rtc->dev));
+			rc = ELIMIT;
+			continue;
+		}
+
+		rtc->io_addr = (ioport8_t *) (long) res->res.io_range.address;
+		ioport = true;
+		ddf_msg(LVL_NOTE, "Device %s was assigned I/O address "
+		    "0x%lx", ddf_dev_get_name(rtc->dev),
+		    (unsigned long int) rtc->io_addr);
+		rc = EOK;
+		break;
+	}
+
+	if (rc != EOK)
+		goto error;
+
+	if (!ioport) {
+		/* No I/O address assigned to this device */
+		ddf_msg(LVL_ERROR, "Missing HW resource for device %s",
+		    ddf_dev_get_name(rtc->dev));
+		rc = ENOENT;
+		goto error;
+	}
+
+	hw_res_clean_resource_list(&hw_resources);
+
+	return EOK;
+
+error:
+	rtc_dev_cleanup(rtc);
+	hw_res_clean_resource_list(&hw_resources);
+
+	return rc;
+}
+
+/** Read a register from the CMOS memory
+ *
+ * @param rtc    The rtc device
+ * @param reg    The index of the register to read
+ *
+ * @return       The value of the register
+ */
+static int
+rtc_register_read(rtc_t *rtc, int reg)
+{
+	pio_write_8(REG_SEL_PORT(rtc->port), reg);
+	return pio_read_8(REG_RW_PORT(rtc->port));
+}
+
+/** Write a register to the CMOS memory
+ *
+ * @param rtc    The rtc device
+ * @param reg    The index of the register to write
+ * @param data   The data to write
+ */
+static void
+rtc_register_write(rtc_t *rtc, int reg, int data)
+{
+	pio_write_8(REG_SEL_PORT(rtc->port), reg);
+	pio_write_8(REG_RW_PORT(rtc->port), data);
+}
+
+/** Check if an update is in progress
+ *
+ * @param rtc  The rtc device
+ *
+ * @return  true if an update is in progress, false otherwise
+ */
+static bool
+rtc_update_in_progress(rtc_t *rtc)
+{
+	return rtc_register_read(rtc, RTC_STATUS_A) & RTC_A_UPDATE;
+}
+
+/** Read the current time from the CMOS
+ *
+ * @param fun  The RTC function
+ * @param t    Pointer to the time variable
+ *
+ * @return  EOK on success or a negative error code
+ */
+static int
+rtc_time_get(ddf_fun_t *fun, struct tm *t)
+{
+	bool bcd_mode;
+	bool pm_mode = false;
+	rtc_t *rtc = fun_rtc(fun);
+
+	fibril_mutex_lock(&rtc->mutex);
+
+	if (rtc->boottime != 0) {
+		/* There is no need to read the current time from the
+		 * device because it has already been cached.
+		 */
+
+		time_t cur_time = rtc->boottime + uptime_get();
+
+		fibril_mutex_unlock(&rtc->mutex);
+
+		return time_local2tm(cur_time, t);
+	}
+
+	/* Check if the RTC battery is OK */
+	if (!is_battery_ok(rtc)) {
+		fibril_mutex_unlock(&rtc->mutex);
+		return EIO;
+	}
+
+	/* now read the registers */
+	do {
+		/* Suspend until the update process has finished */
+		while (rtc_update_in_progress(rtc));
+
+		t->tm_sec  = rtc_register_read(rtc, RTC_SEC);
+		t->tm_min  = rtc_register_read(rtc, RTC_MIN);
+		t->tm_hour = rtc_register_read(rtc, RTC_HOUR);
+		t->tm_mday = rtc_register_read(rtc, RTC_DAY);
+		t->tm_mon  = rtc_register_read(rtc, RTC_MON);
+		t->tm_year = rtc_register_read(rtc, RTC_YEAR);
+
+		/* Now check if it is stable */
+	} while(t->tm_sec  != rtc_register_read(rtc, RTC_SEC) ||
+	    t->tm_min  != rtc_register_read(rtc, RTC_MIN) ||
+	    t->tm_mday != rtc_register_read(rtc, RTC_DAY) ||
+	    t->tm_mon  != rtc_register_read(rtc, RTC_MON) ||
+	    t->tm_year != rtc_register_read(rtc, RTC_YEAR));
+
+	/* Check if the RTC is working in 12h mode */
+	bool _12h_mode = !(rtc_register_read(rtc, RTC_STATUS_B) &
+	    RTC_B_24H);
+
+	if (_12h_mode) {
+		/* The RTC is working in 12h mode, check if it is AM or PM */
+		if (t->tm_hour & 0x80) {
+			/* PM flag is active, it must be cleared */
+			t->tm_hour &= ~0x80;
+			pm_mode = true;
+		}
+	}
+
+	/* Check if the RTC is working in BCD mode */
+	bcd_mode = !(rtc_register_read(rtc, RTC_STATUS_B) & RTC_B_BCD);
+
+	if (bcd_mode) {
+		t->tm_sec  = bcd2bin(t->tm_sec);
+		t->tm_min  = bcd2bin(t->tm_min);
+		t->tm_hour = bcd2bin(t->tm_hour);
+		t->tm_mday = bcd2bin(t->tm_mday);
+		t->tm_mon  = bcd2bin(t->tm_mon);
+		t->tm_year = bcd2bin(t->tm_year);
+	}
+
+	if (_12h_mode) {
+		/* Convert to 24h mode */
+		if (pm_mode) {
+			if (t->tm_hour < 12)
+				t->tm_hour += 12;
+		} else if (t->tm_hour == 12)
+			t->tm_hour = 0;
+	}
+
+	/* Count the months starting from 0, not from 1 */
+	t->tm_mon--;
+
+	if (t->tm_year < 100) {
+		/* tm_year is the number of years since 1900 but the
+		 * RTC epoch is 2000.
+		 */
+		t->tm_year += 100;
+	}
+
+	/* Try to normalize the content of the tm structure */
+	time_t r = mktime(t);
+	int result;
+
+	if (r < 0)
+		result = EINVAL;
+	else {
+		rtc->boottime = r - uptime_get();
+		result = EOK;
+	}
+
+	fibril_mutex_unlock(&rtc->mutex);
+
+	return result;
+}
+
+/** Set the time in the RTC
+ *
+ * @param fun  The RTC function
+ * @param t    The time value to set
+ *
+ * @return  EOK or a negative error code
+ */
+static int
+rtc_time_set(ddf_fun_t *fun, struct tm *t)
+{
+	bool bcd_mode;
+	time_t norm_time;
+	time_t uptime;
+	int  reg_b;
+	int  reg_a;
+	int  epoch;
+	rtc_t *rtc = fun_rtc(fun);
+
+	/* Try to normalize the content of the tm structure */
+	if ((norm_time = mktime(t)) < 0)
+		return EINVAL;
+
+	uptime = uptime_get();
+	if (norm_time <= uptime) {
+		/* This is not acceptable */
+		return EINVAL;
+	}
+
+	fibril_mutex_lock(&rtc->mutex);
+
+	if (!is_battery_ok(rtc)) {
+		fibril_mutex_unlock(&rtc->mutex);
+		return EIO;
+	}
+
+	/* boottime must be recomputed */
+	rtc->boottime = 0;
+
+	/* Detect the RTC epoch */
+	if (rtc_register_read(rtc, RTC_YEAR) < 100)
+		epoch = 2000;
+	else
+		epoch = 1900;
+
+	if (epoch == 2000 && t->tm_year < 100) {
+		/* Can't set a year before the epoch */
+		fibril_mutex_unlock(&rtc->mutex);
+		return EINVAL;
+	}
+
+	t->tm_mon++; /* counts from 1, not from 0 */
+
+	reg_b = rtc_register_read(rtc, RTC_STATUS_B);
+
+	if (!(reg_b & RTC_B_24H)) {
+		/* Force 24h mode of operation */
+		reg_b |= RTC_B_24H;
+		rtc_register_write(rtc, RTC_STATUS_B, reg_b);
+	}
+
+	if (epoch == 2000) {
+		/* The RTC epoch is year 2000  but the tm_year
+		 * field counts years since 1900.
+		 */
+		t->tm_year -= 100;
+	}
+
+	/* Check if the rtc is working in bcd mode */
+	bcd_mode = !(reg_b & RTC_B_BCD);
+	if (bcd_mode) {
+		/* Convert the tm struct fields in BCD mode */
+		t->tm_sec  = bin2bcd(t->tm_sec);
+		t->tm_min  = bin2bcd(t->tm_min);
+		t->tm_hour = bin2bcd(t->tm_hour);
+		t->tm_mday = bin2bcd(t->tm_mday);
+		t->tm_mon  = bin2bcd(t->tm_mon);
+		t->tm_year = bin2bcd(t->tm_year);
+	}
+
+	/* Inhibit updates */
+	rtc_register_write(rtc, RTC_STATUS_B, reg_b | RTC_B_INH);
+
+	/* Write current time to RTC */
+	rtc_register_write(rtc, RTC_SEC, t->tm_sec);
+	rtc_register_write(rtc, RTC_MIN, t->tm_min);
+	rtc_register_write(rtc, RTC_HOUR, t->tm_hour);
+	rtc_register_write(rtc, RTC_DAY, t->tm_mday);
+	rtc_register_write(rtc, RTC_MON, t->tm_mon);
+	rtc_register_write(rtc, RTC_YEAR, t->tm_year);
+
+	/* Stop the clock */
+	reg_a = rtc_register_read(rtc, RTC_STATUS_A);
+	rtc_register_write(rtc, RTC_STATUS_A, RTC_A_CLK_STOP | reg_a);
+	
+	/* Enable updates */
+	rtc_register_write(rtc, RTC_STATUS_B, reg_b);
+	rtc_register_write(rtc, RTC_STATUS_A, reg_a);
+
+	fibril_mutex_unlock(&rtc->mutex);
+
+	return EOK;
+}
+
+/** Get the status of the real time clock battery
+ *
+ * @param fun    The RTC function
+ * @param status The status of the battery
+ *
+ * @return       EOK on success or a negative error code
+ */
+static int
+rtc_battery_status_get(ddf_fun_t *fun, battery_status_t *status)
+{
+	rtc_t *rtc = fun_rtc(fun);
+
+	fibril_mutex_lock(&rtc->mutex);
+	const bool batt_ok = is_battery_ok(rtc);
+	fibril_mutex_unlock(&rtc->mutex);
+
+	*status = batt_ok ? BATTERY_OK : BATTERY_LOW;
+
+	return EOK;
+}
+
+/** Check if the battery is working properly or not.
+ *  The caller already holds the rtc->mutex lock.
+ *
+ *  @param rtc   The RTC instance.
+ *
+ *  @return      true if the battery is ok, false otherwise.
+ */
+static bool
+is_battery_ok(rtc_t *rtc)
+{
+	return rtc_register_read(rtc, RTC_STATUS_D) & RTC_D_BATTERY_OK;
+}
+
+/** The dev_add callback of the rtc driver
+ *
+ * @param dev  The RTC device
+ *
+ * @return  EOK on success or a negative error code
+ */
+static int
+rtc_dev_add(ddf_dev_t *dev)
+{
+	rtc_t *rtc;
+	ddf_fun_t *fun = NULL;
+	int rc;
+	bool need_cleanup = false;
+
+	ddf_msg(LVL_DEBUG, "rtc_dev_add %s (handle = %d)",
+	    ddf_dev_get_name(dev), (int) ddf_dev_get_handle(dev));
+
+	rtc = ddf_dev_data_alloc(dev, sizeof(rtc_t));
+	if (!rtc)
+		return ENOMEM;
+
+	rtc->dev = dev;
+	fibril_mutex_initialize(&rtc->mutex);
+
+	rc = rtc_dev_initialize(rtc);
+	if (rc != EOK)
+		goto error;
+
+	need_cleanup = true;
+
+	if (!rtc_pio_enable(rtc)) {
+		rc = EADDRNOTAVAIL;
+		goto error;
+	}
+
+	fun = ddf_fun_create(dev, fun_exposed, "a");
+	if (!fun) {
+		ddf_msg(LVL_ERROR, "Failed creating function");
+		rc = ENOENT;
+		goto error;
+	}
+
+	ddf_fun_set_ops(fun, &rtc_dev_ops);
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function");
+		goto error;
+	}
+
+	rtc->fun = fun;
+
+	ddf_fun_add_to_category(fun, "clock");
+
+	ddf_msg(LVL_NOTE, "Device %s successfully initialized",
+	    ddf_dev_get_name(dev));
+
+	return rc;
+
+error:
+	if (fun)
+		ddf_fun_destroy(fun);
+	if (need_cleanup)
+		rtc_dev_cleanup(rtc);
+	return rc;
+}
+
+/** The dev_remove callback for the rtc driver
+ *
+ * @param dev   The RTC device
+ *
+ * @return      EOK on success or a negative error code
+ */
+static int
+rtc_dev_remove(ddf_dev_t *dev)
+{
+	rtc_t *rtc = dev_rtc(dev);
+	int rc;
+
+	fibril_mutex_lock(&rtc->mutex);
+	if (rtc->clients_connected > 0) {
+		fibril_mutex_unlock(&rtc->mutex);
+		return EBUSY;
+	}
+
+	rtc->removed = true;
+	fibril_mutex_unlock(&rtc->mutex);
+
+	rc = rtc_fun_offline(rtc->fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to offline function");
+		return rc;
+	}
+
+	rc = ddf_fun_unbind(rtc->fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to unbind function");
+		return rc;
+	}
+
+	ddf_fun_destroy(rtc->fun);
+	rtc_dev_cleanup(rtc);
+
+	return rc;
+}
+
+/** Open the device
+ *
+ * @param fun   The function node
+ *
+ * @return  EOK on success or a negative error code
+ */
+static int
+rtc_open(ddf_fun_t *fun)
+{
+	int rc;
+	rtc_t *rtc = fun_rtc(fun);
+
+	fibril_mutex_lock(&rtc->mutex);
+
+	if (rtc->removed)
+		rc = ENXIO;
+	else {
+		rc = EOK;
+		rtc->clients_connected++;
+	}
+
+	fibril_mutex_unlock(&rtc->mutex);
+	return rc;
+}
+
+/** Close the device
+ *
+ * @param fun  The function node
+ */
+static void
+rtc_close(ddf_fun_t *fun)
+{
+	rtc_t *rtc = fun_rtc(fun);
+
+	fibril_mutex_lock(&rtc->mutex);
+
+	rtc->clients_connected--;
+	assert(rtc->clients_connected >= 0);
+
+	fibril_mutex_unlock(&rtc->mutex);
+}
+
+/** Convert from BCD mode to binary mode
+ *
+ * @param bcd   The number in BCD format to convert
+ *
+ * @return      The converted value
+ */
+static unsigned 
+bcd2bin(unsigned bcd)
+{
+	return ((bcd & 0xF0) >> 1) + ((bcd & 0xF0) >> 3) + (bcd & 0xf);
+}
+
+/** Convert from binary mode to BCD mode
+ *
+ * @param bcd   The number in binary mode to convert
+ *
+ * @return      The converted value
+ */
+static unsigned
+bin2bcd(unsigned binary)
+{
+	return ((binary / 10) << 4) + (binary % 10);
+}
+
+static time_t
+uptime_get(void)
+{
+	struct timeval tv;
+
+	getuptime(&tv);
+
+	return tv.tv_sec;
+}
+
+static int
+rtc_fun_online(ddf_fun_t *fun)
+{
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "rtc_fun_online()");
+
+	rc = ddf_fun_online(fun);
+	if (rc == EOK)
+		ddf_fun_add_to_category(fun, "clock");
+
+	return rc;
+}
+
+static int
+rtc_fun_offline(ddf_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "rtc_fun_offline()");
+	return ddf_fun_offline(fun);
+}
+
+int
+main(int argc, char **argv)
+{
+	printf(NAME ": HelenOS RTC driver\n");
+	rtc_init();
+	return ddf_driver_main(&rtc_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/time/cmos-rtc/cmos-rtc.ma
===================================================================
--- uspace/drv/time/cmos-rtc/cmos-rtc.ma	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/drv/time/cmos-rtc/cmos-rtc.ma	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1 @@
+100 isa/cmos-rtc
Index: uspace/lib/bithenge/Makefile
===================================================================
--- uspace/lib/bithenge/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2012 Sean Bartell
+# 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 = ../..
+LIBRARY = libbithenge
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -D__HELENOS__ -Iinclude
+
+SOURCES = \
+	src/helenos/block.c \
+	src/blob.c \
+	src/compound.c \
+	src/expression.c \
+	src/file.c \
+	src/print.c \
+	src/script.c \
+	src/sequence.c \
+	src/source.c \
+	src/transform.c \
+	src/tree.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/bithenge/Makefile.linux
===================================================================
--- uspace/lib/bithenge/Makefile.linux	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/Makefile.linux	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,65 @@
+#
+# Copyright (c) 2012 Sean Bartell
+# 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.
+#
+
+CFLAGS += -fexec-charset=UTF-8 -finput-charset=UTF-8 -std=gnu99 -pipe
+CFLAGS += -Wall -Wextra -Werror -Wno-clobbered -Wno-unused-parameter -Wmissing-prototypes -Werror-implicit-function-declaration -Wwrite-strings
+CFLAGS += -ftrapv
+CFLAGS += -g
+CFLAGS += -Iinclude
+
+LIBRARY = libbithenge.a
+
+SOURCES = \
+	src/blob.c \
+	src/compound.c \
+	src/expression.c \
+	src/file.c \
+	src/print.c \
+	src/script.c \
+	src/sequence.c \
+	src/source.c \
+	src/transform.c \
+	src/tree.c
+
+ifdef COVERAGE
+	CFLAGS += -fprofile-arcs -ftest-coverage
+endif
+
+ifdef FAILURE
+	CFLAGS += -DBITHENGE_FAILURE_ENABLE=1
+	SOURCES += src/failure.c
+endif
+
+OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
+
+$(LIBRARY): $(OBJECTS)
+	$(AR) rcs $@ $^
+
+clean:
+	find . -name '*.o' -follow -exec rm \{\} \;
+	rm -f $(LIBRARY)
Index: uspace/lib/bithenge/include/bithenge/blob.h
===================================================================
--- uspace/lib/bithenge/include/bithenge/blob.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/include/bithenge/blob.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Raw binary blobs.
+ */
+
+#ifndef BITHENGE_BLOB_H_
+#define BITHENGE_BLOB_H_
+
+#include <sys/types.h>
+#include <errno.h>
+#include "tree.h"
+
+/** A blob of raw binary data.
+ * @implements bithenge_node_t */
+typedef struct {
+	/** @privatesection */
+	struct bithenge_node_t base;
+} bithenge_blob_t;
+
+/** Operations providing random access to binary data.
+ * @todo Should these be thread-safe? */
+typedef struct bithenge_random_access_blob_ops_t {
+	/** @copydoc bithenge_blob_t::bithenge_blob_size */
+	int (*size)(bithenge_blob_t *self, aoff64_t *size);
+	/** @copydoc bithenge_blob_t::bithenge_blob_read */
+	int (*read)(bithenge_blob_t *self, aoff64_t offset, char *buffer,
+	    aoff64_t *size);
+	/** @copydoc bithenge_blob_t::bithenge_blob_read_bits */
+	int (*read_bits)(bithenge_blob_t *self, aoff64_t offset, char *buffer,
+	    aoff64_t *size, bool little_endian);
+	/** Destroy the blob.
+	 * @param blob The blob. */
+	void (*destroy)(bithenge_blob_t *self);
+} bithenge_random_access_blob_ops_t;
+
+/** A blob built from an object that supports only sequential reading.
+ * @implements bithenge_blob_t */
+typedef struct {
+	/** @privatesection */
+	/** The base random-access blob. */
+	bithenge_blob_t base;
+	/** Operations providing sequential access. */
+	const struct bithenge_sequential_blob_ops_t *ops;
+	/** Buffer containing all data read. */
+	char *buffer;
+	/** Size of buffer. */
+	aoff64_t buffer_size;
+	/** Amount of data actually in buffer. */
+	aoff64_t data_size;
+} bithenge_sequential_blob_t;
+
+/** Operations providing sequential access to binary data.
+ * @memberof bithenge_sequential_blob_t */
+typedef struct bithenge_sequential_blob_ops_t {
+
+	/** Get the total size of the blob. If the total size cannot be
+	 * determined easily, this field may be null or return an error,
+	 * forcing the entire blob to be read to determine its size.
+	 *
+	 * @memberof bithenge_blob_t
+	 * @param self The blob.
+	 * @param[out] size Total size of the blob.
+	 * @return EOK on success or an error code from errno.h.
+	 */
+	int (*size)(bithenge_sequential_blob_t *self, aoff64_t *size);
+
+	/** Read the next part of the blob. If the requested data extends
+	 * beyond the end of the blob, the data up until the end of the blob
+	 * will be read.
+	 *
+	 * @param self The blob.
+	 * @param[out] buffer Buffer to read into. If an error occurs, the contents are
+	 * undefined.
+	 * @param[in,out] size Number of bytes to read; may be 0. If not enough
+	 * data is left in the blob, the actual number of bytes read should be
+	 * stored here. If an error occurs, the contents are undefined.
+	 * @return EOK on success or an error code from errno.h.
+	 */
+	int (*read)(bithenge_sequential_blob_t *self, char *buffer,
+	    aoff64_t *size);
+
+	/** Destroy the blob.
+	 * @param self The blob. */
+	void (*destroy)(bithenge_sequential_blob_t *self);
+} bithenge_sequential_blob_ops_t;
+
+/** Get the total size of the blob.
+ *
+ * @memberof bithenge_blob_t
+ * @param self The blob.
+ * @param[out] size Total size of the blob.
+ * @return EOK on success or an error code from errno.h.
+ */
+static inline int bithenge_blob_size(bithenge_blob_t *self, aoff64_t *size)
+{
+	assert(self);
+	assert(self->base.blob_ops);
+	return self->base.blob_ops->size(self, size);
+}
+
+/** Read part of the blob. If the requested data extends beyond the end of the
+ * blob, the data up until the end of the blob will be read. If the offset is
+ * beyond the end of the blob, even if the size is zero, an error will be
+ * returned.
+ *
+ * @memberof bithenge_blob_t
+ * @param self The blob.
+ * @param offset Byte offset within the blob.
+ * @param[out] buffer Buffer to read into. If an error occurs, the contents are
+ * undefined.
+ * @param[in,out] size Number of bytes to read; may be 0. If the requested
+ * range extends beyond the end of the blob, the actual number of bytes read
+ * should be stored here. If an error occurs, the contents are undefined.
+ * @return EOK on success or an error code from errno.h.
+ */
+static inline int bithenge_blob_read(bithenge_blob_t *self, aoff64_t offset,
+    char *buffer, aoff64_t *size)
+{
+	assert(self);
+	assert(self->base.blob_ops);
+	if (!self->base.blob_ops->read)
+		return EINVAL;
+	return self->base.blob_ops->read(self, offset, buffer, size);
+}
+
+/** Read part of the bit blob. If the requested data extends beyond the end of
+ * the blob, the data up until the end of the blob will be read. If the offset
+ * is beyond the end of the blob, even if the size is zero, an error will be
+ * returned.
+ *
+ * @memberof bithenge_blob_t
+ * @param self The blob.
+ * @param offset Byte offset within the blob.
+ * @param[out] buffer Buffer to read into. If an error occurs, the contents are
+ * undefined.
+ * @param[in,out] size Number of bytes to read; may be 0. If the requested
+ * range extends beyond the end of the blob, the actual number of bytes read
+ * should be stored here. If an error occurs, the contents are undefined.
+ * @param little_endian If true, bytes will be filled starting at the least
+ * significant bit; otherwise, they will be filled starting at the most
+ * significant bit.
+ * @return EOK on success or an error code from errno.h.
+ */
+static inline int bithenge_blob_read_bits(bithenge_blob_t *self,
+    aoff64_t offset, char *buffer, aoff64_t *size, bool little_endian)
+{
+	assert(self);
+	assert(self->base.blob_ops);
+	if (!self->base.blob_ops->read_bits)
+		return EINVAL;
+	return self->base.blob_ops->read_bits(self, offset, buffer, size,
+	    little_endian);
+}
+
+/** Check whether the blob is empty.
+ *
+ * @memberof bithenge_blob_t
+ * @param self The blob.
+ * @param[out] out Holds whether the blob is empty.
+ * @return EOK on success or an error code from errno.h. */
+static inline int bithenge_blob_empty(bithenge_blob_t *self, bool *out)
+{
+	assert(self);
+	assert(self->base.blob_ops);
+	aoff64_t size;
+	int rc = bithenge_blob_size(self, &size);
+	*out = size == 0;
+	return rc;
+}
+
+/** Cast a blob node to a generic node.
+ * @memberof bithenge_blob_t
+ * @param blob The blob to cast.
+ * @return The blob node as a generic node. */
+static inline bithenge_node_t *bithenge_blob_as_node(bithenge_blob_t *blob)
+{
+	return &blob->base;
+}
+
+/** Cast a generic node to a blob node.
+ * @memberof bithenge_blob_t
+ * @param node The node to cast, which must be a blob node.
+ * @return The generic node as a blob node. */
+static inline bithenge_blob_t *bithenge_node_as_blob(bithenge_node_t *node)
+{
+	assert(node->type == BITHENGE_NODE_BLOB);
+	return (bithenge_blob_t *)node;
+}
+
+/** Increment a blob's reference count.
+ * @param blob The blob to reference. */
+static inline void bithenge_blob_inc_ref(bithenge_blob_t *blob)
+{
+	bithenge_node_inc_ref(bithenge_blob_as_node(blob));
+}
+
+/** Decrement a blob's reference count.
+ * @param blob The blob to dereference, or NULL. */
+static inline void bithenge_blob_dec_ref(bithenge_blob_t *blob)
+{
+	if (blob)
+		bithenge_node_dec_ref(bithenge_blob_as_node(blob));
+}
+
+/** @memberof bithenge_blob_t */
+int bithenge_init_random_access_blob(bithenge_blob_t *,
+    const bithenge_random_access_blob_ops_t *);
+/** @memberof bithenge_sequential_blob_t */
+int bithenge_init_sequential_blob(bithenge_sequential_blob_t *,
+    const bithenge_sequential_blob_ops_t *);
+/** @memberof bithenge_blob_t */
+int bithenge_new_blob_from_data(bithenge_node_t **, const void *, size_t);
+/** @memberof bithenge_blob_t */
+int bithenge_new_blob_from_buffer(bithenge_node_t **, const void *, size_t,
+    bool);
+int bithenge_new_offset_blob(bithenge_node_t **, bithenge_blob_t *, aoff64_t);
+int bithenge_new_subblob(bithenge_node_t **, bithenge_blob_t *, aoff64_t,
+    aoff64_t);
+/** @memberof bithenge_blob_t */
+int bithenge_blob_equal(bool *, bithenge_blob_t *, bithenge_blob_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/bithenge/include/bithenge/compound.h
===================================================================
--- uspace/lib/bithenge/include/bithenge/compound.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/include/bithenge/compound.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Compound transforms.
+ */
+
+#ifndef BITHENGE_COMPOUND_H_
+#define BITHENGE_COMPOUND_H_
+
+#include "expression.h"
+#include "transform.h"
+
+int bithenge_new_composed_transform(bithenge_transform_t **,
+    bithenge_transform_t **, size_t);
+int bithenge_if_transform(bithenge_transform_t **, bithenge_expression_t *,
+    bithenge_transform_t *, bithenge_transform_t *);
+int bithenge_partial_transform(bithenge_transform_t **,
+    bithenge_transform_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/bithenge/include/bithenge/expression.h
===================================================================
--- uspace/lib/bithenge/include/bithenge/expression.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/include/bithenge/expression.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Expressions.
+ */
+
+#ifndef BITHENGE_EXPRESSION_H_
+#define BITHENGE_EXPRESSION_H_
+
+#include "blob.h"
+#include "transform.h"
+#include "tree.h"
+
+/** An expression that calculates a value given a scope. */
+typedef struct {
+	/** @privatesection */
+	const struct bithenge_expression_ops *ops;
+	unsigned int refs;
+} bithenge_expression_t;
+
+/** Operations provided by an expression. */
+typedef struct bithenge_expression_ops {
+	/** @copydoc bithenge_expression_t::bithenge_expression_evaluate */
+	int (*evaluate)(bithenge_expression_t *self, bithenge_scope_t *scope,
+	    bithenge_node_t **out);
+	/** Destroy the expression.
+	 * @param self The expression. */
+	void (*destroy)(bithenge_expression_t *self);
+} bithenge_expression_ops_t;
+
+/** Increment an expression's reference count.
+ * @param self The expression to reference. */
+static inline void bithenge_expression_inc_ref(bithenge_expression_t *self)
+{
+	assert(self);
+	self->refs++;
+}
+
+/** Decrement an expression's reference count and free it if appropriate.
+ * @param self The expression to dereference, or NULL. */
+static inline void bithenge_expression_dec_ref(bithenge_expression_t *self)
+{
+	if (!self)
+		return;
+	assert(self->ops);
+	assert(self->refs > 0);
+	if (--self->refs == 0)
+		self->ops->destroy(self);
+}
+
+/** Evaluate an expression. Takes ownership of nothing.
+ * @memberof bithenge_expression_t
+ * @param self The expression.
+ * @param scope The scope.
+ * @param[out] out Where the output tree will be stored.
+ * @return EOK on success or an error code from errno.h. */
+static inline int bithenge_expression_evaluate(bithenge_expression_t *self,
+    bithenge_scope_t *scope, bithenge_node_t **out)
+{
+	assert(self);
+	assert(self->ops);
+	return self->ops->evaluate(self, scope, out);
+}
+
+/** The binary operators supported by @a bithenge_binary_expression(). */
+typedef enum {
+	BITHENGE_EXPRESSION_INVALID_BINARY_OP,
+
+	BITHENGE_EXPRESSION_ADD,
+	BITHENGE_EXPRESSION_SUBTRACT,
+	BITHENGE_EXPRESSION_MULTIPLY,
+	BITHENGE_EXPRESSION_INTEGER_DIVIDE,
+	BITHENGE_EXPRESSION_MODULO,
+
+	BITHENGE_EXPRESSION_LESS_THAN,
+	BITHENGE_EXPRESSION_GREATER_THAN,
+	BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL,
+	BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL,
+	BITHENGE_EXPRESSION_EQUALS,
+	BITHENGE_EXPRESSION_NOT_EQUALS,
+
+	BITHENGE_EXPRESSION_AND,
+	BITHENGE_EXPRESSION_OR,
+
+	BITHENGE_EXPRESSION_MEMBER,
+	BITHENGE_EXPRESSION_CONCAT,
+} bithenge_binary_op_t;
+
+int bithenge_init_expression(bithenge_expression_t *,
+    const bithenge_expression_ops_t *);
+int bithenge_binary_expression(bithenge_expression_t **, bithenge_binary_op_t,
+    bithenge_expression_t *, bithenge_expression_t *);
+int bithenge_in_node_expression(bithenge_expression_t **);
+int bithenge_current_node_expression(bithenge_expression_t **);
+int bithenge_param_expression(bithenge_expression_t **, int);
+int bithenge_const_expression(bithenge_expression_t **, bithenge_node_t *);
+int bithenge_scope_member_expression(bithenge_expression_t **,
+    bithenge_node_t *);
+int bithenge_subblob_expression(bithenge_expression_t **,
+    bithenge_expression_t *, bithenge_expression_t *, bithenge_expression_t *,
+    bool);
+int bithenge_param_wrapper(bithenge_transform_t **, bithenge_transform_t *,
+    bithenge_expression_t **);
+int bithenge_expression_transform(bithenge_transform_t **,
+    bithenge_expression_t *);
+int bithenge_inputless_transform(bithenge_transform_t **,
+    bithenge_expression_t *);
+
+int bithenge_concat_blob(bithenge_node_t **, bithenge_blob_t *,
+    bithenge_blob_t *);
+int bithenge_concat_blob_lazy(bithenge_node_t **, bithenge_blob_t *,
+    bithenge_expression_t *, bithenge_scope_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/bithenge/include/bithenge/file.h
===================================================================
--- uspace/lib/bithenge/include/bithenge/file.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/include/bithenge/file.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Access files as blobs.
+ */
+
+#ifndef BITHENGE_FILE_H_
+#define BITHENGE_FILE_H_
+
+#include <stdio.h>
+#include "blob.h"
+
+int bithenge_new_file_blob(bithenge_node_t **, const char *);
+int bithenge_new_file_blob_from_fd(bithenge_node_t **, int);
+int bithenge_new_file_blob_from_file(bithenge_node_t **, FILE *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/bithenge/include/bithenge/os.h
===================================================================
--- uspace/lib/bithenge/include/bithenge/os.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/include/bithenge/os.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * Copyright (c) 2012 Vojtech Horky
+ * 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.
+ */
+
+#ifndef BITHENGE_OS_H_
+#define BITHENGE_OS_H_
+
+
+#ifdef __HELENOS__
+typedef int64_t bithenge_int_t;
+#define BITHENGE_PRId PRId64
+
+#else
+/* Assuming GNU/Linux system. */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#define BITHENGE_PRId PRIdMAX
+typedef intmax_t bithenge_int_t;
+typedef uint64_t aoff64_t;
+#define EOK 0
+
+#endif
+
+#endif
Index: uspace/lib/bithenge/include/bithenge/print.h
===================================================================
--- uspace/lib/bithenge/include/bithenge/print.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/include/bithenge/print.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Write a tree as JSON or other text formats.
+ */
+
+#ifndef BITHENGE_PRINT_H_
+#define BITHENGE_PRINT_H_
+
+#include "tree.h"
+
+/** Specifies the format to be used when printing. */
+typedef enum {
+	/** Print a Python value. Note that internal nodes will be represented
+	 * as unordered dictionaries. */
+	BITHENGE_PRINT_PYTHON,
+	/** Print JSON. Due to the limitations of JSON, type information may be
+	 * lost. */
+	BITHENGE_PRINT_JSON,
+} bithenge_print_type_t;
+
+int bithenge_print_node(bithenge_print_type_t, bithenge_node_t *);
+int bithenge_print_node_to_string(char **, size_t *, bithenge_print_type_t,
+    bithenge_node_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/bithenge/include/bithenge/script.h
===================================================================
--- uspace/lib/bithenge/include/bithenge/script.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/include/bithenge/script.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Script parsing.
+ */
+
+#ifndef BITHENGE_SCRIPT_H_
+#define BITHENGE_SCRIPT_H_
+
+#include "transform.h"
+
+int bithenge_parse_script(const char *, bithenge_transform_t **);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/bithenge/include/bithenge/sequence.h
===================================================================
--- uspace/lib/bithenge/include/bithenge/sequence.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/include/bithenge/sequence.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Sequence transforms.
+ */
+
+#ifndef BITHENGE_SEQUENCE_H_
+#define BITHENGE_SEQUENCE_H_
+
+#include "transform.h"
+
+int bithenge_new_struct(bithenge_transform_t **,
+    bithenge_named_transform_t *);
+int bithenge_repeat_transform(bithenge_transform_t **, bithenge_transform_t *,
+    bithenge_expression_t *);
+int bithenge_do_while_transform(bithenge_transform_t **,
+    bithenge_transform_t *, bithenge_expression_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/bithenge/include/bithenge/source.h
===================================================================
--- uspace/lib/bithenge/include/bithenge/source.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/include/bithenge/source.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Provide various external sources of data.
+ */
+
+#ifndef BITHENGE_SOURCE_H_
+#define BITHENGE_SOURCE_H_
+
+#include "tree.h"
+
+int bithenge_node_from_source(bithenge_node_t **, const char *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/bithenge/include/bithenge/transform.h
===================================================================
--- uspace/lib/bithenge/include/bithenge/transform.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/include/bithenge/transform.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Transforms.
+ */
+
+#ifndef BITHENGE_TRANSFORM_H_
+#define BITHENGE_TRANSFORM_H_
+
+#include "blob.h"
+#include "tree.h"
+
+/** A transform that creates a new tree from an old tree. */
+typedef struct {
+	/** @privatesection */
+	const struct bithenge_transform_ops *ops;
+	unsigned int refs;
+	int num_params;
+} bithenge_transform_t;
+
+/** Context and parameters used when applying transforms. */
+typedef struct bithenge_scope {
+	/** @privatesection */
+	unsigned int refs;
+	struct bithenge_scope *outer;
+	char *error;
+	bool barrier;
+	int num_params;
+	bithenge_node_t **params;
+	bithenge_node_t *current_node;
+	bithenge_node_t *in_node;
+} bithenge_scope_t;
+
+/** Increment a scope's reference count.
+ * @memberof bithenge_scope_t
+ * @param self The scope to reference. */
+static inline void bithenge_scope_inc_ref(bithenge_scope_t *self)
+{
+	assert(self);
+	self->refs++;
+}
+
+/** Operations that may be provided by a transform. All transforms must provide
+ * apply and/or prefix_apply. To be used in struct transforms and repeat
+ * transforms, transforms must provide prefix_length and/or prefix_apply. */
+typedef struct bithenge_transform_ops {
+	/** @copydoc bithenge_transform_t::bithenge_transform_apply */
+	int (*apply)(bithenge_transform_t *self, bithenge_scope_t *scope,
+	    bithenge_node_t *in, bithenge_node_t **out);
+	/** @copydoc bithenge_transform_t::bithenge_transform_prefix_length */
+	int (*prefix_length)(bithenge_transform_t *self,
+	    bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out);
+	/** @copydoc bithenge_transform_t::bithenge_transform_prefix_apply */
+	int (*prefix_apply)(bithenge_transform_t *self,
+	    bithenge_scope_t *scope, bithenge_blob_t *blob,
+	    bithenge_node_t **out_node, aoff64_t *out_size);
+	/** Destroy the transform.
+	 * @param self The transform. */
+	void (*destroy)(bithenge_transform_t *self);
+} bithenge_transform_ops_t;
+
+/** Get the number of parameters required by a transform. This number is used
+ * by the parser and param-wrapper. Takes ownership of nothing.
+ * @param self The transform.
+ * @return The number of parameters required. */
+static inline int bithenge_transform_num_params(bithenge_transform_t *self)
+{
+	assert(self);
+	return self->num_params;
+}
+
+/** Increment a transform's reference count.
+ * @param self The transform to reference. */
+static inline void bithenge_transform_inc_ref(bithenge_transform_t *self)
+{
+	assert(self);
+	self->refs++;
+}
+
+/** Decrement a transform's reference count and free it if appropriate.
+ * @param self The transform to dereference, or NULL. */
+static inline void bithenge_transform_dec_ref(bithenge_transform_t *self)
+{
+	if (!self)
+		return;
+	assert(self->ops);
+	assert(self->refs > 0);
+	if (--self->refs == 0)
+		self->ops->destroy(self);
+}
+
+/** A transform with a name. */
+typedef struct {
+	/** The transform's name. */
+	const char *name;
+	/** The transform. */
+	bithenge_transform_t *transform;
+} bithenge_named_transform_t;
+
+/** Transform that decodes an 8-bit unsigned integer */
+extern bithenge_transform_t bithenge_uint8_transform;
+/** Transform that decodes a 16-bit little-endian unsigned integer */
+extern bithenge_transform_t bithenge_uint16le_transform;
+/** Transform that decodes a 16-bit big-endian unsigned integer */
+extern bithenge_transform_t bithenge_uint16be_transform;
+/** Transform that decodes a 32-bit little-endian unsigned integer */
+extern bithenge_transform_t bithenge_uint32le_transform;
+/** Transform that decodes a 32-bit big-endian unsigned integer */
+extern bithenge_transform_t bithenge_uint32be_transform;
+/** Transform that decodes a 64-bit little-endian unsigned integer */
+extern bithenge_transform_t bithenge_uint64le_transform;
+/** Transform that decodes a 64-bit big-endian unsigned integer */
+extern bithenge_transform_t bithenge_uint64be_transform;
+
+/** @cond */
+extern bithenge_transform_t bithenge_ascii_transform;
+extern bithenge_transform_t bithenge_bit_transform;
+extern bithenge_transform_t bithenge_bits_be_transform;
+extern bithenge_transform_t bithenge_bits_le_transform;
+extern bithenge_transform_t bithenge_invalid_transform;
+extern bithenge_transform_t bithenge_known_length_transform;
+extern bithenge_transform_t bithenge_nonzero_boolean_transform;
+extern bithenge_transform_t bithenge_uint_le_transform;
+extern bithenge_transform_t bithenge_uint_be_transform;
+extern bithenge_transform_t bithenge_zero_terminated_transform;
+extern bithenge_named_transform_t *bithenge_primitive_transforms;
+/** @endcond */
+
+/** @memberof bithenge_transform_t */
+int bithenge_init_transform(bithenge_transform_t *,
+    const bithenge_transform_ops_t *, int);
+/** @memberof bithenge_transform_t */
+int bithenge_transform_apply(bithenge_transform_t *, bithenge_scope_t *,
+    bithenge_node_t *, bithenge_node_t **);
+/** @memberof bithenge_transform_t */
+int bithenge_transform_prefix_length(bithenge_transform_t *,
+    bithenge_scope_t *, bithenge_blob_t *, aoff64_t *);
+/** @memberof bithenge_transform_t */
+int bithenge_transform_prefix_apply(bithenge_transform_t *, bithenge_scope_t *,
+    bithenge_blob_t *, bithenge_node_t **, aoff64_t *);
+int bithenge_new_barrier_transform(bithenge_transform_t **, int);
+int bithenge_barrier_transform_set_subtransform(bithenge_transform_t *,
+    bithenge_transform_t *);
+
+/** @memberof bithenge_scope_t */
+int bithenge_scope_new(bithenge_scope_t **, bithenge_scope_t *);
+/** @memberof bithenge_scope_t */
+void bithenge_scope_dec_ref(bithenge_scope_t *);
+/** @memberof bithenge_scope_t */
+bithenge_scope_t *bithenge_scope_outer(bithenge_scope_t *);
+/** @memberof bithenge_scope_t */
+const char *bithenge_scope_get_error(bithenge_scope_t *);
+/** @memberof bithenge_scope_t */
+int bithenge_scope_error(bithenge_scope_t *, const char *, ...);
+/** @memberof bithenge_scope_t */
+bithenge_node_t *bithenge_scope_get_current_node(bithenge_scope_t *);
+/** @memberof bithenge_scope_t */
+void bithenge_scope_set_current_node(bithenge_scope_t *, bithenge_node_t *);
+/** @memberof bithenge_scope_t */
+bithenge_node_t *bithenge_scope_in_node(bithenge_scope_t *);
+/** @memberof bithenge_scope_t */
+void bithenge_scope_set_in_node(bithenge_scope_t *, bithenge_node_t *);
+/** @memberof bithenge_scope_t */
+void bithenge_scope_set_barrier(bithenge_scope_t *);
+/** @memberof bithenge_scope_t */
+bool bithenge_scope_is_barrier(bithenge_scope_t *);
+/** @memberof bithenge_scope_t */
+int bithenge_scope_alloc_params(bithenge_scope_t *, int);
+/** @memberof bithenge_scope_t */
+int bithenge_scope_set_param(bithenge_scope_t *, int, bithenge_node_t *);
+/** @memberof bithenge_scope_t */
+int bithenge_scope_get_param(bithenge_scope_t *, int, bithenge_node_t **);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/bithenge/include/bithenge/tree.h
===================================================================
--- uspace/lib/bithenge/include/bithenge/tree.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/include/bithenge/tree.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Trees and nodes.
+ */
+
+#ifndef BITHENGE_TREE_H_
+#define BITHENGE_TREE_H_
+
+#include <assert.h>
+#include <sys/types.h>
+#include "os.h"
+
+/** Indicates the type of a tree node. */
+typedef enum {
+	/** An internal node with labelled edges to other nodes. */
+	BITHENGE_NODE_INTERNAL = 1,
+	/** A leaf node holding a boolean value. */
+	BITHENGE_NODE_BOOLEAN,
+	/** A leaf node holding an integer. */
+	BITHENGE_NODE_INTEGER,
+	/** A leaf node holding a string. */
+	BITHENGE_NODE_STRING,
+	/** A leaf node holding a binary blob. */
+	BITHENGE_NODE_BLOB,
+} bithenge_node_type_t;
+
+/** A tree node. It can have any of the types in @a bithenge_node_type_t. */
+typedef struct bithenge_node_t {
+	/** @privatesection */
+	bithenge_node_type_t type;
+	unsigned int refs;
+	union {
+		/** @privatesection */
+		const struct bithenge_internal_node_ops_t *internal_ops;
+		bool boolean_value;
+		bithenge_int_t integer_value;
+		struct {
+			/** @privatesection */
+			const char *ptr;
+			bool needs_free;
+		} string_value;
+		const struct bithenge_random_access_blob_ops_t *blob_ops;
+	};
+} bithenge_node_t;
+
+/** A callback function used to iterate over a node's children. It takes
+ * ownership of a reference to both the key and the value.
+ * @memberof bithenge_node_t
+ * @param key The key.
+ * @param value The value.
+ * @param data Data provided to @a bithenge_node_t::bithenge_node_for_each.
+ * @return EOK on success or an error code from errno.h. */
+typedef int (*bithenge_for_each_func_t)(bithenge_node_t *key, bithenge_node_t *value, void *data);
+
+/** Operations providing access to an internal node. */
+typedef struct bithenge_internal_node_ops_t {
+	/** @copydoc bithenge_node_t::bithenge_node_for_each */
+	int (*for_each)(bithenge_node_t *self, bithenge_for_each_func_t func, void *data);
+	/** @copydoc bithenge_node_t::bithenge_node_get */
+	int (*get)(bithenge_node_t *self, bithenge_node_t *key,
+	    bithenge_node_t **out);
+	/** Destroys the internal node.
+	 * @param self The node to destroy. */
+	void (*destroy)(bithenge_node_t *self);
+} bithenge_internal_node_ops_t;
+
+/** Find the type of a node.
+ * @memberof bithenge_node_t
+ * @param node The node.
+ * @return The type of the node. */
+static inline bithenge_node_type_t bithenge_node_type(const bithenge_node_t *node)
+{
+	return node->type;
+}
+
+/** Increment a node's reference count.
+ * @memberof bithenge_node_t
+ * @param node The node to reference. */
+static inline void bithenge_node_inc_ref(bithenge_node_t *node)
+{
+	assert(node);
+	node->refs++;
+}
+
+/** @memberof bithenge_node_t */
+void bithenge_node_dec_ref(bithenge_node_t *node);
+
+/** Iterate over a node's children.
+ * @memberof bithenge_node_t
+ * @param self The internal node to iterate over.
+ * @param func The callback function.
+ * @param data Data to provide to the callback function.
+ * @return EOK on success or an error code from errno.h. */
+static inline int bithenge_node_for_each(bithenge_node_t *self,
+    bithenge_for_each_func_t func, void *data)
+{
+	assert(self->type == BITHENGE_NODE_INTERNAL);
+	return self->internal_ops->for_each(self, func, data);
+}
+
+/** @memberof bithenge_node_t */
+int bithenge_node_get(bithenge_node_t *, bithenge_node_t *,
+    bithenge_node_t **);
+
+/** Get the value of a boolean node.
+ * @memberof bithenge_node_t
+ * @param self The boolean node.
+ * @return The node's value. */
+static inline bool bithenge_boolean_node_value(bithenge_node_t *self)
+{
+	assert(self->type == BITHENGE_NODE_BOOLEAN);
+	return self->boolean_value;
+}
+
+/** Get the value of an integer node.
+ * @memberof bithenge_node_t
+ * @param self The integer node.
+ * @return The node's value. */
+static inline bithenge_int_t bithenge_integer_node_value(bithenge_node_t *self)
+{
+	assert(self->type == BITHENGE_NODE_INTEGER);
+	return self->integer_value;
+}
+
+/** Get the value of an string node.
+ * @memberof bithenge_node_t
+ * @param self The string node.
+ * @return The node's value. */
+static inline const char *bithenge_string_node_value(bithenge_node_t *self)
+{
+	assert(self->type == BITHENGE_NODE_STRING);
+	return self->string_value.ptr;
+}
+
+/** @memberof bithenge_node_t */
+int bithenge_init_internal_node(bithenge_node_t *,
+    const bithenge_internal_node_ops_t *);
+/** @memberof bithenge_node_t */
+int bithenge_new_empty_internal_node(bithenge_node_t **);
+/** @memberof bithenge_node_t */
+int bithenge_new_simple_internal_node(bithenge_node_t **, bithenge_node_t **,
+    bithenge_int_t, bool needs_free);
+/** @memberof bithenge_node_t */
+int bithenge_new_boolean_node(bithenge_node_t **, bool);
+/** @memberof bithenge_node_t */
+int bithenge_new_integer_node(bithenge_node_t **, bithenge_int_t);
+/** @memberof bithenge_node_t */
+int bithenge_new_string_node(bithenge_node_t **, const char *, bool);
+/** @memberof bithenge_node_t */
+int bithenge_node_equal(bool *, bithenge_node_t *, bithenge_node_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/bithenge/src/blob.c
===================================================================
--- uspace/lib/bithenge/src/blob.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/blob.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,490 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Raw binary blobs.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "common.h"
+#include <bithenge/blob.h>
+#include <bithenge/tree.h>
+
+/** Initialize a random access blob.
+ * @memberof bithenge_blob_t
+ * @param[out] blob The blob to initialize.
+ * @param[in] ops Operations providing random access support. This pointer must
+ * be valid until the blob is destroyed.
+ * @return EOK on success or an error code from errno.h.
+ */
+int bithenge_init_random_access_blob(bithenge_blob_t *blob,
+    const bithenge_random_access_blob_ops_t *ops)
+{
+	assert(blob);
+	assert(ops);
+	assert(ops->destroy);
+	assert(ops->read || ops->read_bits);
+	assert(ops->size);
+
+	if (bithenge_should_fail())
+		return ENOMEM;
+
+	blob->base.type = BITHENGE_NODE_BLOB;
+	blob->base.refs = 1;
+	blob->base.blob_ops = ops;
+	return EOK;
+}
+
+static int sequential_buffer(bithenge_sequential_blob_t *blob, aoff64_t end)
+{
+	bool need_realloc = false;
+	while (end > blob->buffer_size) {
+		blob->buffer_size = max(4096, 2 * blob->buffer_size);
+		need_realloc = true;
+	}
+	if (need_realloc) {
+		char *buffer = realloc(blob->buffer, blob->buffer_size);
+		if (!buffer)
+			return ENOMEM;
+		blob->buffer = buffer;
+	}
+	aoff64_t size = end - blob->data_size;
+	int rc = blob->ops->read(blob, blob->buffer + blob->data_size, &size);
+	if (rc != EOK)
+		return rc;
+	blob->data_size += size;
+	return EOK;
+}
+
+static inline bithenge_sequential_blob_t *blob_as_sequential(
+    bithenge_blob_t *base)
+{
+	return (bithenge_sequential_blob_t *)base;
+}
+
+static inline bithenge_blob_t *sequential_as_blob(
+    bithenge_sequential_blob_t *blob)
+{
+	return &blob->base;
+}
+
+static int sequential_size(bithenge_blob_t *base, aoff64_t *size)
+{
+	bithenge_sequential_blob_t *blob = blob_as_sequential(base);
+	int rc;
+	if (blob->ops->size) {
+		rc = blob->ops->size(blob, size);
+		if (rc == EOK)
+			return EOK;
+	}
+	rc = sequential_buffer(blob, blob->buffer_size);
+	if (rc != EOK)
+		return rc;
+	while (blob->data_size == blob->buffer_size) {
+		rc = sequential_buffer(blob, 2 * blob->buffer_size);
+		if (rc != EOK)
+			return rc;
+	}
+	*size = blob->data_size;
+	return EOK;
+}
+
+static int sequential_read(bithenge_blob_t *base, aoff64_t offset,
+    char *buffer, aoff64_t *size)
+{
+	bithenge_sequential_blob_t *blob = blob_as_sequential(base);
+	aoff64_t end = offset + *size;
+	if (end > blob->data_size) {
+		int rc = sequential_buffer(blob, end);
+		if (rc != EOK)
+			return rc;
+	}
+	if (offset > blob->data_size)
+		return EINVAL;
+	*size = min(*size, blob->data_size - end);
+	memcpy(buffer, blob->buffer + offset, *size);
+	return EOK;
+}
+
+static void sequential_destroy(bithenge_blob_t *base)
+{
+	bithenge_sequential_blob_t *blob = blob_as_sequential(base);
+	free(blob->buffer);
+	blob->ops->destroy(blob);
+}
+
+static const bithenge_random_access_blob_ops_t sequential_ops = {
+	.size = sequential_size,
+	.read = sequential_read,
+	.destroy = sequential_destroy,
+};
+
+/** Initialize a sequential blob.
+ * @memberof bithenge_sequential_blob_t
+ * @param[out] blob The blob to initialize.
+ * @param[in] ops Operations providing sequential access support. This pointer
+ * must be valid until the blob is destroyed.
+ * @return EOK on success or an error code from errno.h.
+ */
+int bithenge_init_sequential_blob(bithenge_sequential_blob_t *blob,
+    const bithenge_sequential_blob_ops_t *ops)
+{
+	assert(blob);
+	assert(ops);
+	assert(ops->destroy);
+	assert(ops->read);
+	// ops->size is optional
+
+	int rc = bithenge_init_random_access_blob(sequential_as_blob(blob),
+	    &sequential_ops);
+	if (rc != EOK)
+		return rc;
+	blob->ops = ops;
+	blob->buffer = NULL; // realloc(NULL, ...) works like malloc
+	blob->buffer_size = 0;
+	blob->data_size = 0;
+	return EOK;
+}
+
+typedef struct {
+	bithenge_blob_t base;
+	const char *buffer;
+	size_t size;
+	bool needs_free;
+} memory_blob_t;
+
+static inline memory_blob_t *blob_as_memory(bithenge_blob_t *base)
+{
+	return (memory_blob_t *)base;
+}
+
+static inline bithenge_blob_t *memory_as_blob(memory_blob_t *blob)
+{
+	return &blob->base;
+}
+
+static int memory_size(bithenge_blob_t *base, aoff64_t *size)
+{
+	memory_blob_t *blob = blob_as_memory(base);
+	if (bithenge_should_fail())
+		return EIO;
+	*size = blob->size;
+	return EOK;
+}
+
+static int memory_read(bithenge_blob_t *base, aoff64_t offset, char *buffer,
+    aoff64_t *size)
+{
+	memory_blob_t *blob = blob_as_memory(base);
+	if (offset > blob->size)
+		return ELIMIT;
+	*size = min(*size, blob->size - offset);
+	memcpy(buffer, blob->buffer + offset, *size);
+	return EOK;
+}
+
+static void memory_destroy(bithenge_blob_t *base)
+{
+	memory_blob_t *blob = blob_as_memory(base);
+	if (blob->needs_free)
+		free((void *)blob->buffer);
+	free(blob);
+}
+
+static const bithenge_random_access_blob_ops_t memory_ops = {
+	.size = memory_size,
+	.read = memory_read,
+	.destroy = memory_destroy,
+};
+
+/** Create a blob node from a buffer. The buffer must exist as long as the blob
+ * does. The blob must be freed with @a bithenge_node_t::bithenge_node_destroy
+ * after it is used.
+ * @memberof bithenge_blob_t
+ * @param[out] out Stores the created blob node.
+ * @param[in] buffer The buffer, which must not be changed until the blob is
+ * destroyed.
+ * @param len The length of the data.
+ * @param needs_free If true, the buffer will be freed with free() if this
+ * function fails or the blob is destroyed.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_blob_from_buffer(bithenge_node_t **out, const void *buffer,
+    size_t len, bool needs_free)
+{
+	int rc;
+	assert(buffer || !len);
+
+	memory_blob_t *blob = malloc(sizeof(*blob));
+	if (!blob) {
+		rc = ENOMEM;
+		goto error;
+	}
+	rc = bithenge_init_random_access_blob(memory_as_blob(blob),
+	    &memory_ops);
+	if (rc != EOK)
+		goto error;
+	blob->buffer = buffer;
+	blob->size = len;
+	blob->needs_free = needs_free;
+	*out = bithenge_blob_as_node(memory_as_blob(blob));
+	return EOK;
+	
+error:
+	if (needs_free)
+		free((void *)buffer);
+	free(blob);
+	return rc;
+}
+
+/** Create a blob node from data. Unlike with @a
+ * bithenge_blob_t::bithenge_new_blob_from_buffer, the data is copied into a
+ * new buffer and the original data can be changed after this call. The blob
+ * must be freed with @a bithenge_node_t::bithenge_node_destroy after it is
+ * used.
+ * @memberof bithenge_blob_t
+ * @param[out] out Stores the created blob node.
+ * @param[in] data The data.
+ * @param len The length of the data.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_blob_from_data(bithenge_node_t **out, const void *data,
+    size_t len)
+{
+	char *buffer = malloc(len);
+	if (!buffer)
+		return ENOMEM;
+	memcpy(buffer, data, len);
+
+	return bithenge_new_blob_from_buffer(out, buffer, len, true);
+}
+
+
+
+typedef struct {
+	bithenge_blob_t base;
+	bithenge_blob_t *source;
+	aoff64_t offset;
+	aoff64_t size;
+	bool size_matters;
+} subblob_t;
+
+static inline subblob_t *blob_as_subblob(bithenge_blob_t *base)
+{
+	return (subblob_t *)base;
+}
+
+static inline bithenge_blob_t *subblob_as_blob(subblob_t *blob)
+{
+	return &blob->base;
+}
+
+static int subblob_size(bithenge_blob_t *base, aoff64_t *size)
+{
+	subblob_t *blob = blob_as_subblob(base);
+	if (blob->size_matters) {
+		*size = blob->size;
+		return EOK;
+	} else {
+		int rc = bithenge_blob_size(blob->source, size);
+		*size -= blob->offset;
+		return rc;
+	}
+}
+
+static int subblob_read(bithenge_blob_t *base, aoff64_t offset,
+    char *buffer, aoff64_t *size)
+{
+	subblob_t *blob = blob_as_subblob(base);
+	if (blob->size_matters) {
+		if (offset > blob->size)
+			return EINVAL;
+		*size = min(*size, blob->size - offset);
+	}
+	offset += blob->offset;
+	return bithenge_blob_read(blob->source, offset, buffer, size);
+}
+
+static int subblob_read_bits(bithenge_blob_t *base, aoff64_t offset,
+    char *buffer, aoff64_t *size, bool little_endian)
+{
+	subblob_t *blob = blob_as_subblob(base);
+	if (blob->size_matters) {
+		if (offset > blob->size)
+			return EINVAL;
+		*size = min(*size, blob->size - offset);
+	}
+	offset += blob->offset;
+	return bithenge_blob_read_bits(blob->source, offset, buffer, size,
+	    little_endian);
+}
+
+static void subblob_destroy(bithenge_blob_t *base)
+{
+	subblob_t *blob = blob_as_subblob(base);
+	bithenge_blob_dec_ref(blob->source);
+	free(blob);
+}
+
+static const bithenge_random_access_blob_ops_t subblob_ops = {
+	.size = subblob_size,
+	.read = subblob_read,
+	.read_bits = subblob_read_bits,
+	.destroy = subblob_destroy,
+};
+
+static bool is_subblob(bithenge_blob_t *blob)
+{
+	return blob->base.blob_ops == &subblob_ops;
+}
+
+static int new_subblob(bithenge_node_t **out, bithenge_blob_t *source,
+    aoff64_t offset, aoff64_t size, bool size_matters)
+{
+	assert(out);
+	assert(source);
+	int rc;
+	subblob_t *blob = 0;
+
+	if (is_subblob(source)) {
+		/* We can do some optimizations this way */
+		if (!size_matters)
+			size = 0;
+		subblob_t *source_subblob = blob_as_subblob(source);
+		if (source_subblob->size_matters &&
+		    offset + size > source_subblob->size) {
+			rc = EINVAL;
+			goto error;
+		}
+
+		if (source->base.refs == 1) {
+			source_subblob->offset += offset;
+			source_subblob->size -= offset;
+			if (size_matters) {
+				source_subblob->size_matters = true;
+				source_subblob->size = size;
+			}
+			*out = bithenge_blob_as_node(source);
+			return EOK;
+		}
+
+		if (!size_matters && source_subblob->size_matters) {
+			size_matters = true;
+			size = source_subblob->size - offset;
+		}
+		offset += source_subblob->offset;
+		source = source_subblob->source;
+		bithenge_blob_inc_ref(source);
+		bithenge_blob_dec_ref(subblob_as_blob(source_subblob));
+	}
+
+	blob = malloc(sizeof(*blob));
+	if (!blob) {
+		rc = ENOMEM;
+		goto error;
+	}
+	rc = bithenge_init_random_access_blob(subblob_as_blob(blob),
+	    &subblob_ops);
+	if (rc != EOK)
+		goto error;
+	blob->source = source;
+	blob->offset = offset;
+	blob->size = size;
+	blob->size_matters = size_matters;
+	*out = bithenge_blob_as_node(subblob_as_blob(blob));
+	return EOK;
+
+error:
+	bithenge_blob_dec_ref(source);
+	free(blob);
+	return rc;
+}
+
+/** Create a blob from data offset within another blob. This function takes
+ * ownership of a reference to @a blob.
+ * @param[out] out Stores the created blob node. On error, this is unchanged.
+ * @param[in] source The input blob.
+ * @param offset The offset within the input blob at which the new blob will start.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_offset_blob(bithenge_node_t **out, bithenge_blob_t *source,
+    aoff64_t offset)
+{
+	return new_subblob(out, source, offset, 0, false);
+}
+
+/** Create a blob from part of another blob. This function takes ownership of a
+ * reference to @a blob.
+ * @param[out] out Stores the created blob node. On error, this is unchanged.
+ * @param[in] source The input blob.
+ * @param offset The offset within the input blob at which the new blob will start.
+ * @param size The size of the new blob.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_subblob(bithenge_node_t **out, bithenge_blob_t *source,
+    aoff64_t offset, aoff64_t size)
+{
+	return new_subblob(out, source, offset, size, true);
+}
+
+/** Check whether the contents of two blobs are equal.
+ * @memberof bithenge_blob_t
+ * @param[out] out Holds whether the blobs are equal.
+ * @param a, b Blobs to compare.
+ * @return EOK on success, or an error code from errno.h.
+ */
+int bithenge_blob_equal(bool *out, bithenge_blob_t *a, bithenge_blob_t *b)
+{
+	assert(a);
+	assert(a->base.blob_ops);
+	assert(b);
+	assert(b->base.blob_ops);
+	int rc;
+	char buffer_a[4096], buffer_b[4096];
+	aoff64_t offset = 0, size_a = sizeof(buffer_a), size_b = sizeof(buffer_b);
+	do {
+		rc = bithenge_blob_read(a, offset, buffer_a, &size_a);
+		if (rc != EOK)
+			return rc;
+		rc = bithenge_blob_read(b, offset, buffer_b, &size_b);
+		if (rc != EOK)
+			return rc;
+		if (size_a != size_b || bcmp(buffer_a, buffer_b, size_a)) {
+			*out = false;
+			return EOK;
+		}
+		offset += size_a;
+	} while (size_a == sizeof(buffer_a));
+	*out = true;
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/bithenge/src/common.h
===================================================================
--- uspace/lib/bithenge/src/common.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/common.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * Copyright (c) 2012 Vojtech Horky
+ * 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.
+ */
+
+#ifndef BITHENGE_COMMON_H_
+#define BITHENGE_COMMON_H_
+
+#ifdef __HELENOS__
+#include "helenos/common.h"
+#else
+#include "linux/common.h"
+#endif
+
+#ifdef BITHENGE_FAILURE_ENABLE
+#include "failure.h"
+#else
+static inline int bithenge_should_fail(void)
+{
+	return 0;
+}
+#endif
+
+#endif
Index: uspace/lib/bithenge/src/compound.c
===================================================================
--- uspace/lib/bithenge/src/compound.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/compound.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Compound transforms.
+ */
+
+#include <stdlib.h>
+#include <bithenge/compound.h>
+#include <bithenge/expression.h>
+#include <bithenge/transform.h>
+#include <bithenge/tree.h>
+#include "common.h"
+
+
+
+/***************** compose_transform                         *****************/
+
+typedef struct {
+	bithenge_transform_t base;
+	bithenge_transform_t **xforms;
+	size_t num;
+} compose_transform_t;
+
+static bithenge_transform_t *compose_as_transform(compose_transform_t *xform)
+{
+	return &xform->base;
+}
+
+static compose_transform_t *transform_as_compose(bithenge_transform_t *xform)
+{
+	return (compose_transform_t *)xform;
+}
+
+static int compose_apply(bithenge_transform_t *base, bithenge_scope_t *scope,
+    bithenge_node_t *in, bithenge_node_t **out)
+{
+	int rc;
+	compose_transform_t *self = transform_as_compose(base);
+	bithenge_node_inc_ref(in);
+
+	/* i ranges from (self->num - 1) to 0 inside the loop. */
+	for (size_t i = self->num; i--; ) {
+		bithenge_node_t *tmp;
+		rc = bithenge_transform_apply(self->xforms[i], scope, in,
+		    &tmp);
+		bithenge_node_dec_ref(in);
+		if (rc != EOK)
+			return rc;
+		in = tmp;
+	}
+
+	*out = in;
+	return rc;
+}
+
+static int compose_prefix_length(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out)
+{
+	compose_transform_t *self = transform_as_compose(base);
+	return bithenge_transform_prefix_length(self->xforms[self->num - 1],
+	    scope, blob, out);
+}
+
+static void compose_destroy(bithenge_transform_t *base)
+{
+	compose_transform_t *self = transform_as_compose(base);
+	for (size_t i = 0; i < self->num; i++)
+		bithenge_transform_dec_ref(self->xforms[i]);
+	free(self->xforms);
+	free(self);
+}
+
+static const bithenge_transform_ops_t compose_transform_ops = {
+	.apply = compose_apply,
+	.prefix_length = compose_prefix_length,
+	.destroy = compose_destroy,
+};
+
+/** Create a composition of multiple transforms. When the result is applied to a
+ * node, each transform is applied in turn, with the last transform applied
+ * first. @a xforms may contain any number of transforms or no transforms at
+ * all. This function takes ownership of @a xforms and the references therein.
+ * @param[out] out Holds the result.
+ * @param[in] xforms The transforms to apply.
+ * @param num The number of transforms.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_composed_transform(bithenge_transform_t **out,
+    bithenge_transform_t **xforms, size_t num)
+{
+	if (num == 0) {
+		/* TODO: optimize */
+	} else if (num == 1) {
+		*out = xforms[0];
+		free(xforms);
+		return EOK;
+	}
+
+	int rc;
+	compose_transform_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+	rc = bithenge_init_transform(compose_as_transform(self),
+	    &compose_transform_ops, 0);
+	if (rc != EOK)
+		goto error;
+	self->xforms = xforms;
+	self->num = num;
+	*out = compose_as_transform(self);
+	return EOK;
+error:
+	for (size_t i = 0; i < num; i++)
+		bithenge_transform_dec_ref(xforms[i]);
+	free(xforms);
+	free(self);
+	return rc;
+}
+
+
+
+/***************** if_transform                              *****************/
+
+typedef struct {
+	bithenge_transform_t base;
+	bithenge_expression_t *expr;
+	bithenge_transform_t *true_xform, *false_xform;
+} if_transform_t;
+
+static inline bithenge_transform_t *if_as_transform(if_transform_t *self)
+{
+	return &self->base;
+}
+
+static inline if_transform_t *transform_as_if(bithenge_transform_t *base)
+{
+	return (if_transform_t *)base;
+}
+
+static int if_transform_choose(if_transform_t *self, bithenge_scope_t *scope,
+    bool *out)
+{
+	bithenge_node_t *cond_node;
+	int rc = bithenge_expression_evaluate(self->expr, scope, &cond_node);
+	if (rc != EOK)
+		return rc;
+	if (bithenge_node_type(cond_node) != BITHENGE_NODE_BOOLEAN) {
+		bithenge_node_dec_ref(cond_node);
+		return EINVAL;
+	}
+	*out = bithenge_boolean_node_value(cond_node);
+	bithenge_node_dec_ref(cond_node);
+	return EOK;
+}
+
+static int if_transform_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
+{
+	if_transform_t *self = transform_as_if(base);
+	bool cond;
+	int rc = if_transform_choose(self, scope, &cond);
+	if (rc != EOK)
+		return rc;
+	return bithenge_transform_apply(
+	    cond ? self->true_xform : self->false_xform, scope, in, out);
+}
+
+static int if_transform_prefix_length(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
+{
+	if_transform_t *self = transform_as_if(base);
+	bool cond;
+	int rc = if_transform_choose(self, scope, &cond);
+	if (rc != EOK)
+		return rc;
+	return bithenge_transform_prefix_length(
+	    cond ? self->true_xform : self->false_xform, scope, in, out);
+}
+
+static void if_transform_destroy(bithenge_transform_t *base)
+{
+	if_transform_t *self = transform_as_if(base);
+	bithenge_expression_dec_ref(self->expr);
+	bithenge_transform_dec_ref(self->true_xform);
+	bithenge_transform_dec_ref(self->false_xform);
+	free(self);
+}
+
+static const bithenge_transform_ops_t if_transform_ops = {
+	.apply = if_transform_apply,
+	.prefix_length = if_transform_prefix_length,
+	.destroy = if_transform_destroy,
+};
+
+/** Create a transform that applies either of two transforms depending on a
+ * boolean expression. Takes references to @a expr, @a true_xform, and
+ * @a false_xform.
+ * @param[out] out Holds the new transform.
+ * @param expr The boolean expression to evaluate.
+ * @param true_xform The transform to apply if the expression is true.
+ * @param false_xform The transform to apply if the expression is false.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_if_transform(bithenge_transform_t **out,
+    bithenge_expression_t *expr, bithenge_transform_t *true_xform,
+    bithenge_transform_t *false_xform)
+{
+	int rc;
+	if_transform_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_transform(if_as_transform(self), &if_transform_ops,
+	    0);
+	if (rc != EOK)
+		goto error;
+
+	self->expr = expr;
+	self->true_xform = true_xform;
+	self->false_xform = false_xform;
+	*out = if_as_transform(self);
+	return EOK;
+
+error:
+	free(self);
+	bithenge_expression_dec_ref(expr);
+	bithenge_transform_dec_ref(true_xform);
+	bithenge_transform_dec_ref(false_xform);
+	return rc;
+}
+
+
+
+/***************** partial_transform                         *****************/
+
+typedef struct {
+	bithenge_transform_t base;
+	bithenge_transform_t *xform;
+} partial_transform_t;
+
+static inline bithenge_transform_t *partial_as_transform(
+    partial_transform_t *self)
+{
+	return &self->base;
+}
+
+static inline partial_transform_t *transform_as_partial(
+    bithenge_transform_t *base)
+{
+	return (partial_transform_t *)base;
+}
+
+static int partial_transform_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
+{
+	partial_transform_t *self = transform_as_partial(base);
+	if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
+		return EINVAL;
+	return bithenge_transform_prefix_apply(self->xform, scope,
+	    bithenge_node_as_blob(in), out, NULL);
+}
+
+static void partial_transform_destroy(bithenge_transform_t *base)
+{
+	partial_transform_t *self = transform_as_partial(base);
+	bithenge_transform_dec_ref(self->xform);
+	free(self);
+}
+
+static const bithenge_transform_ops_t partial_transform_ops = {
+	.apply = partial_transform_apply,
+	.destroy = partial_transform_destroy,
+};
+
+/** Create a transform that doesn't require its subtransform to use the whole
+ * input. Takes a reference to @a xform.
+ * @param[out] out Holds the new transform.
+ * @param xform The subtransform to apply.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_partial_transform(bithenge_transform_t **out,
+    bithenge_transform_t *xform)
+{
+	int rc;
+	partial_transform_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_transform(partial_as_transform(self),
+	    &partial_transform_ops, 0);
+	if (rc != EOK)
+		goto error;
+
+	self->xform = xform;
+	*out = partial_as_transform(self);
+	return EOK;
+
+error:
+	free(self);
+	bithenge_transform_dec_ref(xform);
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/bithenge/src/expression.c
===================================================================
--- uspace/lib/bithenge/src/expression.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/expression.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1200 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Expressions.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "common.h"
+#include <bithenge/blob.h>
+#include <bithenge/expression.h>
+#include <bithenge/transform.h>
+#include <bithenge/tree.h>
+
+/** Initialize a new expression.
+ * @param[out] self Expression to initialize.
+ * @param[in] ops Operations provided by the expression.
+ * @return EOK or an error code from errno.h. */
+int bithenge_init_expression(bithenge_expression_t *self,
+    const bithenge_expression_ops_t *ops)
+{
+	assert(ops);
+	assert(ops->evaluate);
+	assert(ops->destroy);
+	if (bithenge_should_fail())
+		return ENOMEM;
+	self->ops = ops;
+	self->refs = 1;
+	return EOK;
+}
+
+static void expression_indestructible(bithenge_expression_t *self)
+{
+	assert(false);
+}
+
+
+
+/***************** binary_expression                         *****************/
+
+typedef struct {
+	bithenge_expression_t base;
+	bithenge_binary_op_t op;
+	bithenge_expression_t *a, *b;
+} binary_expression_t;
+
+static inline binary_expression_t *expression_as_binary(
+    bithenge_expression_t *base)
+{
+	return (binary_expression_t *)base;
+}
+
+static inline bithenge_expression_t *binary_as_expression(
+    binary_expression_t *self)
+{
+	return &self->base;
+}
+
+static int binary_expression_evaluate(bithenge_expression_t *base,
+    bithenge_scope_t *scope, bithenge_node_t **out)
+{
+	int rc;
+	binary_expression_t *self = expression_as_binary(base);
+	bithenge_node_t *a, *b;
+	rc = bithenge_expression_evaluate(self->a, scope, &a);
+	if (rc != EOK)
+		return rc;
+	if (self->op != BITHENGE_EXPRESSION_CONCAT) {
+		rc = bithenge_expression_evaluate(self->b, scope, &b);
+		if (rc != EOK) {
+			bithenge_node_dec_ref(a);
+			return rc;
+		}
+	}
+
+	/* Check types and get values. */
+	/* Assigning 0 only to make the compiler happy. */
+	bithenge_int_t a_int = 0, b_int = 0;
+	bool a_bool = false, b_bool = false, out_bool = false;
+	switch (self->op) {
+	case BITHENGE_EXPRESSION_ADD: /* fallthrough */
+	case BITHENGE_EXPRESSION_SUBTRACT: /* fallthrough */
+	case BITHENGE_EXPRESSION_MULTIPLY: /* fallthrough */
+	case BITHENGE_EXPRESSION_INTEGER_DIVIDE: /* fallthrough */
+	case BITHENGE_EXPRESSION_MODULO: /* fallthrough */
+	case BITHENGE_EXPRESSION_LESS_THAN: /* fallthrough */
+	case BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL: /* fallthrough */
+	case BITHENGE_EXPRESSION_GREATER_THAN: /* fallthrough */
+	case BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL:
+		rc = EINVAL;
+		if (bithenge_node_type(a) != BITHENGE_NODE_INTEGER)
+			goto error;
+		if (bithenge_node_type(b) != BITHENGE_NODE_INTEGER)
+			goto error;
+		a_int = bithenge_integer_node_value(a);
+		b_int = bithenge_integer_node_value(b);
+		break;
+	case BITHENGE_EXPRESSION_AND: /* fallthrough */
+	case BITHENGE_EXPRESSION_OR:
+		rc = EINVAL;
+		if (bithenge_node_type(a) != BITHENGE_NODE_BOOLEAN)
+			goto error;
+		if (bithenge_node_type(b) != BITHENGE_NODE_BOOLEAN)
+			goto error;
+		a_bool = bithenge_boolean_node_value(a);
+		b_bool = bithenge_boolean_node_value(b);
+		break;
+	case BITHENGE_EXPRESSION_CONCAT:
+		if (bithenge_node_type(a) != BITHENGE_NODE_BLOB)
+			goto error;
+		break;
+	default:
+		break;
+	}
+
+	switch (self->op) {
+	case BITHENGE_EXPRESSION_ADD:
+		rc = bithenge_new_integer_node(out, a_int + b_int);
+		break;
+	case BITHENGE_EXPRESSION_SUBTRACT:
+		rc = bithenge_new_integer_node(out, a_int - b_int);
+		break;
+	case BITHENGE_EXPRESSION_MULTIPLY:
+		rc = bithenge_new_integer_node(out, a_int * b_int);
+		break;
+	case BITHENGE_EXPRESSION_INTEGER_DIVIDE:
+		/* Integer division can behave in three major ways when the
+		  operands are signed: truncated, floored, or Euclidean. When
+		 * b > 0, we give the same result as floored and Euclidean;
+		 * otherwise, we currently raise an error. See
+		 * https://en.wikipedia.org/wiki/Modulo_operation and its
+		 * references. */
+		if (b_int <= 0) {
+			rc = EINVAL;
+			break;
+		}
+		rc = bithenge_new_integer_node(out,
+		    (a_int / b_int) + (a_int % b_int < 0 ? -1 : 0));
+		break;
+	case BITHENGE_EXPRESSION_MODULO:
+		/* This is consistent with division; see above. */
+		if (b_int <= 0) {
+			rc = EINVAL;
+			break;
+		}
+		rc = bithenge_new_integer_node(out,
+		    (a_int % b_int) + (a_int % b_int < 0 ? b_int : 0));
+		break;
+	case BITHENGE_EXPRESSION_LESS_THAN:
+		rc = bithenge_new_boolean_node(out, a_int < b_int);
+		break;
+	case BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL:
+		rc = bithenge_new_boolean_node(out, a_int <= b_int);
+		break;
+	case BITHENGE_EXPRESSION_GREATER_THAN:
+		rc = bithenge_new_boolean_node(out, a_int > b_int);
+		break;
+	case BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL:
+		rc = bithenge_new_boolean_node(out, a_int >= b_int);
+		break;
+	case BITHENGE_EXPRESSION_EQUALS:
+		rc = bithenge_node_equal(&out_bool, a, b);
+		if (rc != EOK)
+			break;
+		rc = bithenge_new_boolean_node(out, out_bool);
+		break;
+	case BITHENGE_EXPRESSION_NOT_EQUALS:
+		rc = bithenge_node_equal(&out_bool, a, b);
+		if (rc != EOK)
+			break;
+		rc = bithenge_new_boolean_node(out, !out_bool);
+		break;
+	case BITHENGE_EXPRESSION_AND:
+		rc = bithenge_new_boolean_node(out, a_bool && b_bool);
+		break;
+	case BITHENGE_EXPRESSION_OR:
+		rc = bithenge_new_boolean_node(out, a_bool || b_bool);
+		break;
+	case BITHENGE_EXPRESSION_MEMBER:
+		rc = bithenge_node_get(a, b, out);
+		b = NULL;
+		break;
+	case BITHENGE_EXPRESSION_CONCAT:
+		bithenge_expression_inc_ref(self->b);
+		bithenge_scope_inc_ref(scope);
+		rc = bithenge_concat_blob_lazy(out, bithenge_node_as_blob(a),
+		    self->b, scope);
+		a = NULL;
+		b = NULL;
+		break;
+	case BITHENGE_EXPRESSION_INVALID_BINARY_OP:
+		assert(false);
+		break;
+	}
+
+error:
+	bithenge_node_dec_ref(a);
+	bithenge_node_dec_ref(b);
+	return rc;
+}
+
+static void binary_expression_destroy(bithenge_expression_t *base)
+{
+	binary_expression_t *self = expression_as_binary(base);
+	bithenge_expression_dec_ref(self->a);
+	bithenge_expression_dec_ref(self->b);
+	free(self);
+}
+
+static const bithenge_expression_ops_t binary_expression_ops = {
+	.evaluate = binary_expression_evaluate,
+	.destroy = binary_expression_destroy,
+};
+
+/** Create a binary expression. Takes ownership of @a a and @a b.
+ * @param[out] out Holds the new expression.
+ * @param op The operator to apply.
+ * @param a The first operand.
+ * @param b The second operand.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_binary_expression(bithenge_expression_t **out,
+    bithenge_binary_op_t op, bithenge_expression_t *a,
+    bithenge_expression_t *b)
+{
+	int rc;
+	binary_expression_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_expression(binary_as_expression(self),
+	    &binary_expression_ops);
+	if (rc != EOK)
+		goto error;
+
+	self->op = op;
+	self->a = a;
+	self->b = b;
+	*out = binary_as_expression(self);
+	return EOK;
+
+error:
+	bithenge_expression_dec_ref(a);
+	bithenge_expression_dec_ref(b);
+	free(self);
+	return rc;
+}
+
+
+
+/***************** in_node_expression                        *****************/
+
+static int in_node_evaluate(bithenge_expression_t *self,
+    bithenge_scope_t *scope, bithenge_node_t **out)
+{
+	for (; scope; scope = bithenge_scope_outer(scope)) {
+		*out = bithenge_scope_in_node(scope);
+		if (*out)
+			return EOK;
+	}
+	return EINVAL;
+}
+
+static const bithenge_expression_ops_t in_node_ops = {
+	.evaluate = in_node_evaluate,
+	.destroy = expression_indestructible,
+};
+
+static bithenge_expression_t in_node_expression = {
+	&in_node_ops, 1
+};
+
+/** Create an expression that gets the current input node.
+ * @param[out] out Holds the new expression.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_in_node_expression(bithenge_expression_t **out)
+{
+	if (bithenge_should_fail())
+		return ENOMEM;
+	bithenge_expression_inc_ref(&in_node_expression);
+	*out = &in_node_expression;
+	return EOK;
+}
+
+
+
+/***************** current_node_expression                   *****************/
+
+static int current_node_evaluate(bithenge_expression_t *self,
+    bithenge_scope_t *scope, bithenge_node_t **out)
+{
+	*out = bithenge_scope_get_current_node(scope);
+	if (!*out)
+		return EINVAL;
+	return EOK;
+}
+
+static const bithenge_expression_ops_t current_node_ops = {
+	.evaluate = current_node_evaluate,
+	.destroy = expression_indestructible,
+};
+
+static bithenge_expression_t current_node_expression = {
+	&current_node_ops, 1
+};
+
+/** Create an expression that gets the current node being created.
+ * @param[out] out Holds the new expression.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_current_node_expression(bithenge_expression_t **out)
+{
+	bithenge_expression_inc_ref(&current_node_expression);
+	*out = &current_node_expression;
+	return EOK;
+}
+
+
+
+/***************** param_expression                          *****************/
+
+typedef struct {
+	bithenge_expression_t base;
+	int index;
+} param_expression_t;
+
+static inline param_expression_t *expression_as_param(
+    bithenge_expression_t *base)
+{
+	return (param_expression_t *)base;
+}
+
+static inline bithenge_expression_t *param_as_expression(
+    param_expression_t *self)
+{
+	return &self->base;
+}
+
+static int param_expression_evaluate(bithenge_expression_t *base,
+    bithenge_scope_t *scope, bithenge_node_t **out)
+{
+	param_expression_t *self = expression_as_param(base);
+	return bithenge_scope_get_param(scope, self->index, out);
+}
+
+static void param_expression_destroy(bithenge_expression_t *base)
+{
+	param_expression_t *self = expression_as_param(base);
+	free(self);
+}
+
+static const bithenge_expression_ops_t param_expression_ops = {
+	.evaluate = param_expression_evaluate,
+	.destroy = param_expression_destroy,
+};
+
+/** Create an expression that returns a parameter.
+ * @param[out] out Holds the created expression.
+ * @param index The index of the parameter to get.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_param_expression(bithenge_expression_t **out, int index)
+{
+	int rc;
+	param_expression_t *self = malloc(sizeof(*self));
+	if (!self)
+		return ENOMEM;
+
+	rc = bithenge_init_expression(param_as_expression(self),
+	    &param_expression_ops);
+	if (rc != EOK) {
+		free(self);
+		return rc;
+	}
+
+	self->index = index;
+	*out = param_as_expression(self);
+	return EOK;
+}
+
+
+
+/***************** const_expression                          *****************/
+
+typedef struct {
+	bithenge_expression_t base;
+	bithenge_node_t *node;
+} const_expression_t;
+
+static inline const_expression_t *expression_as_const(
+    bithenge_expression_t *base)
+{
+	return (const_expression_t *)base;
+}
+
+static inline bithenge_expression_t *const_as_expression(
+    const_expression_t *self)
+{
+	return &self->base;
+}
+
+static int const_expression_evaluate(bithenge_expression_t *base,
+    bithenge_scope_t *scope, bithenge_node_t **out)
+{
+	const_expression_t *self = expression_as_const(base);
+	bithenge_node_inc_ref(self->node);
+	*out = self->node;
+	return EOK;
+}
+
+static void const_expression_destroy(bithenge_expression_t *base)
+{
+	const_expression_t *self = expression_as_const(base);
+	bithenge_node_dec_ref(self->node);
+	free(self);
+}
+
+static const bithenge_expression_ops_t const_expression_ops = {
+	.evaluate = const_expression_evaluate,
+	.destroy = const_expression_destroy,
+};
+
+/** Create an expression that returns a constant. Takes a reference to @a node.
+ * @param[out] out Holds the created expression.
+ * @param node The constant.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_const_expression(bithenge_expression_t **out,
+    bithenge_node_t *node)
+{
+	int rc;
+	const_expression_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_expression(const_as_expression(self),
+	    &const_expression_ops);
+	if (rc != EOK)
+		goto error;
+
+	self->node = node;
+	*out = const_as_expression(self);
+	return EOK;
+
+error:
+	free(self);
+	bithenge_node_dec_ref(node);
+	return rc;
+}
+
+
+
+/***************** scope_member_expression                   *****************/
+
+typedef struct {
+	bithenge_expression_t base;
+	bithenge_node_t *key;
+} scope_member_expression_t;
+
+static scope_member_expression_t *expression_as_scope_member(
+    bithenge_expression_t *base)
+{
+	return (scope_member_expression_t *)base;
+}
+
+static bithenge_expression_t *scope_member_as_expression(
+    scope_member_expression_t *expr)
+{
+	return &expr->base;
+}
+
+static int scope_member_expression_evaluate(bithenge_expression_t *base, 
+    bithenge_scope_t *scope, bithenge_node_t **out)
+{
+	scope_member_expression_t *self = expression_as_scope_member(base);
+	for (; scope && !bithenge_scope_is_barrier(scope);
+	    scope = bithenge_scope_outer(scope)) {
+		bithenge_node_t *cur = bithenge_scope_get_current_node(scope);
+		if (!cur)
+			continue;
+		bithenge_node_inc_ref(self->key);
+		int rc = bithenge_node_get(cur, self->key, out);
+		bithenge_node_dec_ref(cur);
+		if (rc != ENOENT) /* EOK or error */
+			return rc;
+	}
+	return bithenge_scope_error(scope, "No scope member %t", self->key);
+}
+
+static void scope_member_expression_destroy(bithenge_expression_t *base)
+{
+	scope_member_expression_t *self = expression_as_scope_member(base);
+	bithenge_node_dec_ref(self->key);
+	free(self);
+}
+
+static const bithenge_expression_ops_t scope_member_expression_ops = {
+	.evaluate = scope_member_expression_evaluate,
+	.destroy = scope_member_expression_destroy,
+};
+
+/** Create an expression that gets a member from one of the current nodes being
+ * created. It searches from the current scope outwards, stopping at barrier
+ * scopes.
+ * @param[out] out Holds the new expression.
+ * @param key The key to search for in nodes being created.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_scope_member_expression(bithenge_expression_t **out,
+    bithenge_node_t *key)
+{
+	int rc;
+	scope_member_expression_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_expression(scope_member_as_expression(self),
+	    &scope_member_expression_ops);
+	if (rc != EOK)
+		goto error;
+
+	self->key = key;
+	*out = scope_member_as_expression(self);
+	return EOK;
+
+error:
+	bithenge_node_dec_ref(key);
+	free(self);
+	return rc;
+}
+
+
+
+/***************** subblob_expression                        *****************/
+
+typedef struct {
+	bithenge_expression_t base;
+	bithenge_expression_t *blob, *start, *limit;
+	bool absolute_limit;
+} subblob_expression_t;
+
+static subblob_expression_t *expression_as_subblob(bithenge_expression_t *base)
+{
+	return (subblob_expression_t *)base;
+}
+
+static bithenge_expression_t *subblob_as_expression(subblob_expression_t *expr)
+{
+	return &expr->base;
+}
+
+static int subblob_expression_evaluate(bithenge_expression_t *base, 
+    bithenge_scope_t *scope, bithenge_node_t **out)
+{
+	subblob_expression_t *self = expression_as_subblob(base);
+	bithenge_node_t *start_node;
+	int rc = bithenge_expression_evaluate(self->start, scope, &start_node);
+	if (rc != EOK)
+		return rc;
+	if (bithenge_node_type(start_node) != BITHENGE_NODE_INTEGER) {
+		bithenge_node_dec_ref(start_node);
+		return EINVAL;
+	}
+	bithenge_int_t start = bithenge_integer_node_value(start_node);
+	bithenge_node_dec_ref(start_node);
+
+	bithenge_int_t limit = -1;
+	if (self->limit) {
+		bithenge_node_t *limit_node;
+		rc = bithenge_expression_evaluate(self->limit, scope,
+		    &limit_node);
+		if (rc != EOK)
+			return rc;
+		if (bithenge_node_type(limit_node) != BITHENGE_NODE_INTEGER) {
+			bithenge_node_dec_ref(limit_node);
+			return EINVAL;
+		}
+		limit = bithenge_integer_node_value(limit_node);
+		bithenge_node_dec_ref(limit_node);
+		if (self->absolute_limit)
+			limit -= start;
+	}
+
+	if (start < 0 || (self->limit && limit < 0))
+		return EINVAL;
+
+	bithenge_node_t *blob;
+	rc = bithenge_expression_evaluate(self->blob, scope, &blob);
+	if (rc != EOK)
+		return rc;
+	if (bithenge_node_type(blob) != BITHENGE_NODE_BLOB) {
+		bithenge_node_dec_ref(blob);
+		return EINVAL;
+	}
+
+	if (self->limit)
+		return bithenge_new_subblob(out, bithenge_node_as_blob(blob),
+		    start, limit);
+	else
+		return bithenge_new_offset_blob(out,
+		    bithenge_node_as_blob(blob), start);
+}
+
+static void subblob_expression_destroy(bithenge_expression_t *base)
+{
+	subblob_expression_t *self = expression_as_subblob(base);
+	bithenge_expression_dec_ref(self->blob);
+	bithenge_expression_dec_ref(self->start);
+	bithenge_expression_dec_ref(self->limit);
+	free(self);
+}
+
+static const bithenge_expression_ops_t subblob_expression_ops = {
+	.evaluate = subblob_expression_evaluate,
+	.destroy = subblob_expression_destroy,
+};
+
+/** Create an expression that gets a subblob. Takes references to @a blob,
+ * @a start, and @a limit.
+ * @param[out] out Holds the new expression.
+ * @param blob Calculates the blob.
+ * @param start Calculates the start offset within the blob.
+ * @param limit Calculates the limit. Can be NULL, in which case an offset blob
+ * is returned.
+ * @param absolute_limit If true, the limit is an absolute offset; otherwise,
+ * it is relative to the start.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_subblob_expression(bithenge_expression_t **out,
+    bithenge_expression_t *blob, bithenge_expression_t *start,
+    bithenge_expression_t *limit, bool absolute_limit)
+{
+	int rc;
+	subblob_expression_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_expression(subblob_as_expression(self),
+	    &subblob_expression_ops);
+	if (rc != EOK)
+		goto error;
+
+	self->blob = blob;
+	self->start = start;
+	self->limit = limit;
+	self->absolute_limit = absolute_limit;
+	*out = subblob_as_expression(self);
+	return EOK;
+
+error:
+	bithenge_expression_dec_ref(blob);
+	bithenge_expression_dec_ref(start);
+	bithenge_expression_dec_ref(limit);
+	free(self);
+	return rc;
+}
+
+/***************** param_wrapper                             *****************/
+
+typedef struct {
+	bithenge_transform_t base;
+	bithenge_transform_t *transform;
+	bithenge_expression_t **params;
+} param_wrapper_t;
+
+static inline bithenge_transform_t *param_wrapper_as_transform(
+    param_wrapper_t *self)
+{
+	return &self->base;
+}
+
+static inline param_wrapper_t *transform_as_param_wrapper(
+    bithenge_transform_t *base)
+{
+	return (param_wrapper_t *)base;
+}
+
+static int param_wrapper_fill_scope(param_wrapper_t *self, bithenge_scope_t
+    *inner, bithenge_scope_t *outer)
+{
+	int rc;
+	int num_params = bithenge_transform_num_params(self->transform);
+	rc = bithenge_scope_alloc_params(inner, num_params);
+	if (rc != EOK)
+		return rc;
+	for (int i = 0; i < num_params; i++) {
+		bithenge_node_t *node;
+		rc = bithenge_expression_evaluate(self->params[i], outer,
+		    &node);
+		if (rc != EOK)
+			return rc;
+		rc = bithenge_scope_set_param(inner, i, node);
+		if (rc != EOK)
+			return rc;
+	}
+	return EOK;
+}
+
+static int param_wrapper_apply(bithenge_transform_t *base,
+    bithenge_scope_t *outer, bithenge_node_t *in, bithenge_node_t **out)
+{
+	param_wrapper_t *self = transform_as_param_wrapper(base);
+	bithenge_scope_t *inner;
+	int rc = bithenge_scope_new(&inner, outer);
+	if (rc != EOK)
+		return rc;
+	rc = param_wrapper_fill_scope(self, inner, outer);
+	if (rc != EOK)
+		goto error;
+
+	rc = bithenge_transform_apply(self->transform, inner, in, out);
+	in = NULL;
+
+error:
+	bithenge_scope_dec_ref(inner);
+	return rc;
+}
+
+static int param_wrapper_prefix_length(bithenge_transform_t *base,
+    bithenge_scope_t *outer, bithenge_blob_t *in, aoff64_t *out)
+{
+	param_wrapper_t *self = transform_as_param_wrapper(base);
+	bithenge_scope_t *inner;
+	int rc = bithenge_scope_new(&inner, outer);
+	if (rc != EOK)
+		return rc;
+	rc = param_wrapper_fill_scope(self, inner, outer);
+	if (rc != EOK)
+		goto error;
+
+	rc = bithenge_transform_prefix_length(self->transform, inner, in, out);
+	in = NULL;
+
+error:
+	bithenge_scope_dec_ref(inner);
+	return rc;
+}
+
+static int param_wrapper_prefix_apply(bithenge_transform_t *base,
+    bithenge_scope_t *outer, bithenge_blob_t *in, bithenge_node_t **out_node,
+    aoff64_t *out_length)
+{
+	param_wrapper_t *self = transform_as_param_wrapper(base);
+	bithenge_scope_t *inner;
+	int rc = bithenge_scope_new(&inner, outer);
+	if (rc != EOK)
+		return rc;
+	rc = param_wrapper_fill_scope(self, inner, outer);
+	if (rc != EOK)
+		goto error;
+
+	rc = bithenge_transform_prefix_apply(self->transform, inner, in,
+	    out_node, out_length);
+
+error:
+	bithenge_scope_dec_ref(inner);
+	return rc;
+}
+
+static void param_wrapper_destroy(bithenge_transform_t *base)
+{
+	param_wrapper_t *self = transform_as_param_wrapper(base);
+	int num_params = bithenge_transform_num_params(self->transform);
+	bithenge_transform_dec_ref(self->transform);
+	for (int i = 0; i < num_params; i++)
+		bithenge_expression_dec_ref(self->params[i]);
+	free(self->params);
+	free(self);
+}
+
+static const bithenge_transform_ops_t param_wrapper_ops = {
+	.apply = param_wrapper_apply,
+	.prefix_length = param_wrapper_prefix_length,
+	.prefix_apply = param_wrapper_prefix_apply,
+	.destroy = param_wrapper_destroy,
+};
+
+/** Create a transform that calculates parameters for another transform. Takes
+ * ownership of @a transform, @a params, and each element of @a params. The
+ * number of parameters must be correct.
+ * @param[out] out Holds the new transform.
+ * @param transform The transform for which parameters are calculated.
+ * @param params The expressions used to calculate the parameters.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_param_wrapper(bithenge_transform_t **out,
+    bithenge_transform_t *transform, bithenge_expression_t **params)
+{
+	int rc;
+	int num_params = bithenge_transform_num_params(transform);
+	param_wrapper_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_transform(param_wrapper_as_transform(self),
+	    &param_wrapper_ops, 0);
+	if (rc != EOK)
+		goto error;
+
+	self->transform = transform;
+	self->params = params;
+	*out = param_wrapper_as_transform(self);
+	return EOK;
+
+error:
+	free(self);
+	for (int i = 0; i < num_params; i++)
+		bithenge_expression_dec_ref(params[i]);
+	free(params);
+	bithenge_transform_dec_ref(transform);
+	return rc;
+}
+
+
+
+/***************** expression_transform           *****************/
+
+/* Also used by inputless_transform. */
+typedef struct {
+	bithenge_transform_t base;
+	bithenge_expression_t *expr;
+} expression_transform_t;
+
+static inline bithenge_transform_t *expression_as_transform(
+    expression_transform_t *self)
+{
+	return &self->base;
+}
+
+static inline expression_transform_t *transform_as_expression(
+    bithenge_transform_t *base)
+{
+	return (expression_transform_t *)base;
+}
+
+static int expression_transform_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
+{
+	expression_transform_t *self = transform_as_expression(base);
+	bithenge_scope_t *inner;
+	int rc = bithenge_scope_new(&inner, scope);
+	if (rc != EOK)
+		return rc;
+	bithenge_scope_set_in_node(inner, in);
+	rc = bithenge_expression_evaluate(self->expr, inner, out);
+	bithenge_scope_dec_ref(inner);
+	return rc;
+}
+
+/* Also used by inputless_transform. */
+static void expression_transform_destroy(bithenge_transform_t *base)
+{
+	expression_transform_t *self = transform_as_expression(base);
+	bithenge_expression_dec_ref(self->expr);
+	free(self);
+}
+
+static const bithenge_transform_ops_t expression_transform_ops = {
+	.apply = expression_transform_apply,
+	.destroy = expression_transform_destroy,
+};
+
+/** Create a transform that evaluates an expression on the input node. Takes a
+ * reference to the expression.
+ * @param[out] out Holds the new transform.
+ * @param expr The expression to evaluate.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_expression_transform(bithenge_transform_t ** out,
+    bithenge_expression_t *expr)
+{
+	int rc;
+	expression_transform_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_transform(expression_as_transform(self),
+	    &expression_transform_ops, 0);
+	if (rc != EOK)
+		goto error;
+
+	self->expr = expr;
+	*out = expression_as_transform(self);
+	return EOK;
+
+error:
+	free(self);
+	bithenge_expression_dec_ref(expr);
+	return rc;
+}
+
+
+
+/***************** inputless_transform            *****************/
+
+static int inputless_transform_prefix_length(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
+{
+	*out = 0;
+	return EOK;
+}
+
+static int inputless_transform_prefix_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *in, bithenge_node_t **out_node,
+    aoff64_t *out_size)
+{
+	expression_transform_t *self = transform_as_expression(base);
+	if (out_size)
+		*out_size = 0;
+	return bithenge_expression_evaluate(self->expr, scope, out_node);
+}
+
+static const bithenge_transform_ops_t inputless_transform_ops = {
+	.prefix_length = inputless_transform_prefix_length,
+	.prefix_apply = inputless_transform_prefix_apply,
+	.destroy = expression_transform_destroy,
+};
+
+/** Create a transform that takes an empty blob and produces the result of an
+ * expression. Takes a reference to the expression.
+ * @param[out] out Holds the new transform.
+ * @param expr The expression to evaluate.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_inputless_transform(bithenge_transform_t ** out,
+    bithenge_expression_t *expr)
+{
+	int rc;
+	expression_transform_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_transform(expression_as_transform(self),
+	    &inputless_transform_ops, 0);
+	if (rc != EOK)
+		goto error;
+
+	self->expr = expr;
+	*out = expression_as_transform(self);
+	return EOK;
+
+error:
+	free(self);
+	bithenge_expression_dec_ref(expr);
+	return rc;
+}
+
+
+
+/***************** concat_blob                    *****************/
+
+typedef struct {
+	bithenge_blob_t base;
+	bithenge_blob_t *a, *b;
+	aoff64_t a_size;
+	bithenge_expression_t *b_expr;
+	bithenge_scope_t *scope;
+} concat_blob_t;
+
+static inline concat_blob_t *blob_as_concat(bithenge_blob_t *base)
+{
+	return (concat_blob_t *)base;
+}
+
+static inline bithenge_blob_t *concat_as_blob(concat_blob_t *blob)
+{
+	return &blob->base;
+}
+
+static int concat_blob_evaluate_b(concat_blob_t *self)
+{
+	if (self->b)
+		return EOK;
+	bithenge_node_t *b_node;
+	int rc = bithenge_expression_evaluate(self->b_expr, self->scope,
+	    &b_node);
+	if (rc != EOK)
+		return rc;
+	if (bithenge_node_type(b_node) != BITHENGE_NODE_BLOB) {
+		bithenge_node_dec_ref(b_node);
+		return bithenge_scope_error(self->scope,
+		    "Concatenation arguments must be blobs");
+	}
+	self->b = bithenge_node_as_blob(b_node);
+	bithenge_expression_dec_ref(self->b_expr);
+	bithenge_scope_dec_ref(self->scope);
+	self->b_expr = NULL;
+	self->scope = NULL;
+	return EOK;
+}
+
+static int concat_blob_size(bithenge_blob_t *base, aoff64_t *size)
+{
+	concat_blob_t *self = blob_as_concat(base);
+	int rc = concat_blob_evaluate_b(self);
+	if (rc != EOK)
+		return rc;
+	rc = bithenge_blob_size(self->b, size);
+	*size += self->a_size;
+	return rc;
+}
+
+static int concat_blob_read(bithenge_blob_t *base, aoff64_t offset,
+    char *buffer, aoff64_t *size)
+{
+	int rc;
+	concat_blob_t *self = blob_as_concat(base);
+
+	aoff64_t a_size = 0, b_size = 0;
+	if (offset < self->a_size) {
+		a_size = *size;
+		rc = bithenge_blob_read(self->a, offset, buffer, &a_size);
+		if (rc != EOK)
+			return rc;
+	}
+	if (offset + *size > self->a_size) {
+		rc = concat_blob_evaluate_b(self);
+		if (rc != EOK)
+			return rc;
+		b_size = *size - a_size;
+		rc = bithenge_blob_read(self->b,
+		    offset + a_size - self->a_size, buffer + a_size, &b_size);
+		if (rc != EOK)
+			return rc;
+	}
+	assert(a_size + b_size <= *size);
+	*size = a_size + b_size;
+	return EOK;
+}
+
+static int concat_blob_read_bits(bithenge_blob_t *base, aoff64_t offset,
+    char *buffer, aoff64_t *size, bool little_endian)
+{
+	int rc;
+	concat_blob_t *self = blob_as_concat(base);
+
+	aoff64_t a_size = 0, b_size = 0;
+	if (offset < self->a_size) {
+		a_size = *size;
+		rc = bithenge_blob_read_bits(self->a, offset, buffer, &a_size,
+		    little_endian);
+		if (rc != EOK)
+			return rc;
+	}
+	if (offset + *size > self->a_size) {
+		rc = concat_blob_evaluate_b(self);
+		if (rc != EOK)
+			return rc;
+		b_size = *size - a_size;
+		assert(a_size % 8 == 0); /* TODO: don't require this */
+		rc = bithenge_blob_read_bits(self->b,
+		    offset + a_size - self->a_size, buffer + a_size / 8,
+		    &b_size, little_endian);
+		if (rc != EOK)
+			return rc;
+	}
+	assert(a_size + b_size <= *size);
+	*size = a_size + b_size;
+	return EOK;
+}
+
+static void concat_blob_destroy(bithenge_blob_t *base)
+{
+	concat_blob_t *self = blob_as_concat(base);
+	bithenge_blob_dec_ref(self->a);
+	bithenge_blob_dec_ref(self->b);
+	bithenge_expression_dec_ref(self->b_expr);
+	bithenge_scope_dec_ref(self->scope);
+	free(self);
+}
+
+static const bithenge_random_access_blob_ops_t concat_blob_ops = {
+	.size = concat_blob_size,
+	.read = concat_blob_read,
+	.read_bits = concat_blob_read_bits,
+	.destroy = concat_blob_destroy,
+};
+
+/** Create a concatenated blob. Takes references to @a a and @a b.
+ * @param[out] out Holds the new blob.
+ * @param a The first blob.
+ * @param b The second blob.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_concat_blob(bithenge_node_t **out, bithenge_blob_t *a,
+    bithenge_blob_t *b)
+{
+	assert(out);
+	assert(a);
+	assert(b);
+	int rc;
+	concat_blob_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_blob_size(a, &self->a_size);
+	if (rc != EOK)
+		goto error;
+
+	rc = bithenge_init_random_access_blob(concat_as_blob(self),
+	    &concat_blob_ops);
+	if (rc != EOK)
+		goto error;
+	self->a = a;
+	self->b = b;
+	self->b_expr = NULL;
+	self->scope = NULL;
+	*out = bithenge_blob_as_node(concat_as_blob(self));
+	return EOK;
+
+error:
+	bithenge_blob_dec_ref(a);
+	bithenge_blob_dec_ref(b);
+	free(self);
+	return rc;
+}
+
+/** Create a lazy concatenated blob. Takes references to @a a, @a b_expr, and
+ * @a scope.
+ * @param[out] out Holds the new blob.
+ * @param a The first blob.
+ * @param b_expr An expression to calculate the second blob.
+ * @param scope The scope in which @a b_expr should be evaluated.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_concat_blob_lazy(bithenge_node_t **out, bithenge_blob_t *a,
+    bithenge_expression_t *b_expr, bithenge_scope_t *scope)
+{
+	assert(out);
+	assert(a);
+	assert(b_expr);
+	assert(scope);
+	int rc;
+	concat_blob_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_blob_size(a, &self->a_size);
+	if (rc != EOK)
+		goto error;
+
+	rc = bithenge_init_random_access_blob(concat_as_blob(self),
+	    &concat_blob_ops);
+	if (rc != EOK)
+		goto error;
+	self->a = a;
+	self->b = NULL;
+	self->b_expr = b_expr;
+	self->scope = scope;
+	*out = bithenge_blob_as_node(concat_as_blob(self));
+	return EOK;
+
+error:
+	bithenge_blob_dec_ref(a);
+	bithenge_expression_dec_ref(b_expr);
+	bithenge_scope_dec_ref(scope);
+	free(self);
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/bithenge/src/failure.c
===================================================================
--- uspace/lib/bithenge/src/failure.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/failure.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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.
+ */
+
+/** @cond internal */
+/** @addtogroup bithenge
+ * @{
+ */
+/**
+ * @file
+ * Fake system call errors for testing.
+ */
+
+#include <errno.h>
+#include <execinfo.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#define BITHENGE_FAILURE_DECLS_ONLY 1
+#include "failure.h"
+#include "common.h"
+
+/* This file raises fake errors from system calls, to test that Bithenge
+ * handles the errors correctly. It has two primary modes of operation,
+ * depending on an environment variable:
+ *
+ * BITHENGE_FAILURE_INDEX not set: when a system call is made, a child process
+ * returns a fake error from that call. If the child process handles the error
+ * correctly (exit code is 1), the main process continues without errors. If
+ * the child process has a problem, the main process raises the fake error
+ * again and shows all stdout and stderr output. For speed, errors are only
+ * raised when part of the backtrace has not been seen before.
+ *
+ * BITHENGE_FAILURE_INDEX set: the program runs normally until system call
+ * number BITHENGE_FAILURE_INDEX is made; a fake error is returned from this
+ * call. */
+
+static int g_initialized = 0;
+static int g_failure_index = -1;
+static int g_failure_index_selected = -1;
+
+typedef struct backtrace_item {
+	struct backtrace_item *next;
+	void *backtrace_item;
+} backtrace_item_t;
+
+static backtrace_item_t *g_backtrace_items = NULL;
+
+static void atexit_handler(void)
+{
+	while (g_backtrace_items) {
+		backtrace_item_t *first = g_backtrace_items;
+		g_backtrace_items = first->next;
+		free(first);
+	}
+}
+
+static inline void initialize(void)
+{
+	g_initialized = 1;
+	int rc = atexit(atexit_handler);
+	if (rc)
+		exit(127);
+
+	char *sel_str = getenv("BITHENGE_FAILURE_INDEX");
+	if (sel_str)
+		g_failure_index_selected = strtol(sel_str, NULL, 10);
+}
+
+/* Record a hit for a backtrace address and return whether this is the first
+ * hit. */
+static inline int backtrace_item_hit(void *addr)
+{
+	backtrace_item_t **bip;
+	for (bip = &g_backtrace_items; *bip; bip = &(*bip)->next) {
+		backtrace_item_t *bi = *bip;
+		if (bi->backtrace_item == addr) {
+			/* Keep frequently accessed items near the front. */
+			*bip = bi->next;
+			bi->next = g_backtrace_items;
+			g_backtrace_items = bi;
+			return 0;
+		}
+	}
+
+	/* No item found; create one. */
+	backtrace_item_t *i = malloc(sizeof(*i));
+	if (!i)
+		exit(127);
+	i->next = g_backtrace_items;
+	i->backtrace_item = addr;
+	g_backtrace_items = i;
+	return 1;
+}
+
+int bithenge_should_fail(void)
+{
+	g_failure_index++;
+
+	if (!g_initialized)
+		initialize();
+
+	if (g_failure_index_selected != -1) {
+		if (g_failure_index == g_failure_index_selected)
+			return 1; /* breakpoint here */
+		return 0;
+	}
+
+	/* If all backtrace items have been seen already, there's no need to
+	 * try raising an error. */
+	void *trace[256];
+	int size = backtrace(trace, 256);
+	int raise_error = 0;
+	for (int i = 0; i < size; i++) {
+		if (backtrace_item_hit(trace[i]))
+			raise_error = 1;
+	}
+	if (!raise_error)
+		return 0;
+
+	if (!fork()) {
+		/* Child silently fails. */
+		int null = open("/dev/null", O_WRONLY);
+		if (null == -1)
+			exit(127);
+		dup2(null, STDOUT_FILENO);
+		dup2(null, STDERR_FILENO);
+		close(null);
+		return 1;
+	}
+
+	/* Parent checks whether child failed correctly. */
+	int status;
+	wait(&status);
+	if (WIFEXITED(status) && WEXITSTATUS(status) == 1)
+		return 0;
+
+	/* The child had an error! We couldn't easily debug it because it was
+	 * in a separate process with redirected stdout and stderr. Do it again
+	 * without redirecting or forking. */
+	fprintf(stderr, "** Fake error raised here (BITHENGE_FAILURE_INDEX=%d)\n",
+	    g_failure_index);
+	return 1;
+}
+
+void *bithenge_failure_malloc(size_t size)
+{
+	if (bithenge_should_fail())
+		return NULL;
+	return malloc(size);
+}
+
+void *bithenge_failure_realloc(void *ptr, size_t size)
+{
+	if (bithenge_should_fail())
+		return NULL;
+	return realloc(ptr, size);
+}
+
+ssize_t bithenge_failure_read(int fd, void *buf, size_t count)
+{
+	if (bithenge_should_fail()) {
+		errno = EIO;
+		return -1;
+	}
+	return read(fd, buf, count);
+}
+
+off_t bithenge_failure_lseek(int fd, off_t offset, int whither)
+{
+	if (bithenge_should_fail()) {
+		errno = EINVAL;
+		return (off_t) -1;
+	}
+	return lseek(fd, offset, whither);
+}
+
+int bithenge_failure_ferror(FILE *stream)
+{
+	if (bithenge_should_fail())
+		return 1;
+	return ferror(stream);
+}
+
+char *bithenge_failure_str_ndup(const char *s, size_t max_len)
+{
+	if (bithenge_should_fail())
+		return NULL;
+	return str_ndup(s, max_len);
+}
+
+int bithenge_failure_open(const char *pathname, int flags)
+{
+	if (bithenge_should_fail()) {
+		errno = EACCES;
+		return -1;
+	}
+	return open(pathname, flags);
+}
+
+int bithenge_failure_fstat(int fd, struct stat *buf)
+{
+	if (bithenge_should_fail()) {
+		errno = EIO;
+		return -1;
+	}
+	return fstat(fd, buf);
+}
+
+/** @}
+ */
+/** @endcond */
Index: uspace/lib/bithenge/src/failure.h
===================================================================
--- uspace/lib/bithenge/src/failure.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/failure.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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.
+ */
+
+/** @cond internal */
+/** @addtogroup bithenge
+ * @{
+ */
+/**
+ * @file
+ * Fake system call errors for testing.
+ */
+
+#ifndef BITHENGE_FAILURE_H_
+#define BITHENGE_FAILURE_H_
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int bithenge_should_fail(void);
+void *bithenge_failure_malloc(size_t);
+void *bithenge_failure_realloc(void *, size_t);
+ssize_t bithenge_failure_read(int, void *, size_t);
+off_t bithenge_failure_lseek(int, off_t, int);
+int bithenge_failure_ferror(FILE *);
+char *bithenge_failure_str_ndup(const char *, size_t);
+int bithenge_failure_open(const char *, int);
+int bithenge_failure_fstat(int, struct stat *);
+
+#ifndef BITHENGE_FAILURE_DECLS_ONLY
+#define malloc bithenge_failure_malloc
+#define realloc bithenge_failure_realloc
+#define read bithenge_failure_read
+#define lseek bithenge_failure_lseek
+#define ferror bithenge_failure_ferror
+#define str_ndup bithenge_failure_str_ndup
+#define open bithenge_failure_open
+#define fstat bithenge_failure_fstat
+#endif
+
+#endif
+
+/** @}
+ */
+
+/** @endcond */
+
Index: uspace/lib/bithenge/src/file.c
===================================================================
--- uspace/lib/bithenge/src/file.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/file.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Access files as blobs.
+ * @todo Provide more information about the file.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "common.h"
+#include <bithenge/blob.h>
+#include <bithenge/file.h>
+
+typedef struct {
+	bithenge_blob_t base;
+	int fd;
+	aoff64_t size; // needed by file_read()
+	bool needs_close;
+} file_blob_t;
+
+static inline file_blob_t *blob_as_file(bithenge_blob_t *base)
+{
+	return (file_blob_t *)base;
+}
+
+static inline bithenge_blob_t *file_as_blob(file_blob_t *blob)
+{
+	return &blob->base;
+}
+
+static int file_size(bithenge_blob_t *base, aoff64_t *size)
+{
+	file_blob_t *blob = blob_as_file(base);
+	*size = blob->size;
+	return EOK;
+}
+
+static int file_read(bithenge_blob_t *base, aoff64_t offset, char *buffer,
+    aoff64_t *size)
+{
+	file_blob_t *blob = blob_as_file(base);
+	if (offset > blob->size)
+		return ELIMIT;
+	if (lseek(blob->fd, offset, SEEK_SET) < 0)
+		return errno == EINVAL ? EIO : errno;
+
+	ssize_t amount_read;
+	aoff64_t remaining_size = *size;
+	*size = 0;
+	do {
+		amount_read = read(blob->fd, buffer, remaining_size);
+		if (amount_read < 0)
+			return errno;
+		buffer += amount_read;
+		*size += amount_read;
+		remaining_size -= amount_read;
+	} while (remaining_size && amount_read);
+	return EOK;
+}
+
+static void file_destroy(bithenge_blob_t *base)
+{
+	file_blob_t *blob = blob_as_file(base);
+	close(blob->fd);
+	free(blob);
+}
+
+static const bithenge_random_access_blob_ops_t file_ops = {
+	.size = file_size,
+	.read = file_read,
+	.destroy = file_destroy,
+};
+
+static int new_file_blob(bithenge_node_t **out, int fd, bool needs_close)
+{
+	assert(out);
+
+	struct stat stat;
+	int rc = fstat(fd, &stat);
+	if (rc != EOK) {
+		if (needs_close)
+			close(fd);
+		return rc;
+	}
+
+	// Create blob
+	file_blob_t *blob = malloc(sizeof(*blob));
+	if (!blob) {
+		if (needs_close)
+			close(fd);
+		return ENOMEM;
+	}
+	rc = bithenge_init_random_access_blob(file_as_blob(blob), &file_ops);
+	if (rc != EOK) {
+		free(blob);
+		if (needs_close)
+			close(fd);
+		return rc;
+	}
+	blob->fd = fd;
+#ifdef __HELENOS__
+	blob->size = stat.size;
+#else
+	blob->size = stat.st_size;
+#endif
+	blob->needs_close = needs_close;
+	*out = bithenge_blob_as_node(file_as_blob(blob));
+
+	return EOK;
+}
+
+/** Create a blob for a file. The blob must be freed with @a
+ * bithenge_node_t::bithenge_node_destroy after it is used.
+ * @param[out] out Stores the created blob.
+ * @param filename The name of the file.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_file_blob(bithenge_node_t **out, const char *filename)
+{
+	assert(filename);
+
+	int fd = open(filename, O_RDONLY);
+	if (fd < 0)
+		return fd;
+
+	return new_file_blob(out, fd, true);
+}
+
+/** Create a blob for a file descriptor. The blob must be freed with @a
+ * bithenge_node_t::bithenge_node_destroy after it is used.
+ * @param[out] out Stores the created blob.
+ * @param fd The file descriptor.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_file_blob_from_fd(bithenge_node_t **out, int fd)
+{
+	return new_file_blob(out, fd, false);
+}
+
+/** Create a blob for a file pointer. The blob must be freed with @a
+ * bithenge_node_t::bithenge_node_destroy after it is used.
+ * @param[out] out Stores the created blob.
+ * @param file The file pointer.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_file_blob_from_file(bithenge_node_t **out, FILE *file)
+{
+	int fd = fileno(file);
+	if (fd < 0)
+		return errno;
+	return new_file_blob(out, fd, false);
+}
+
+/** @}
+ */
Index: uspace/lib/bithenge/src/helenos/block.c
===================================================================
--- uspace/lib/bithenge/src/helenos/block.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/helenos/block.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Access block devices as blobs.
+ * @todo Provide more information about the block device (block size).
+ */
+
+#include <assert.h>
+#include <block.h>
+#include <errno.h>
+#include <loc.h>
+#include <macros.h>
+#include <stdlib.h>
+#include <bithenge/blob.h>
+#include "block.h"
+
+typedef struct {
+	bithenge_blob_t base;
+	service_id_t service_id;
+	aoff64_t size;
+} block_blob_t;
+
+static inline block_blob_t *blob_as_block(bithenge_blob_t *base)
+{
+	return (block_blob_t *)base;
+}
+
+static inline bithenge_blob_t *block_as_blob(block_blob_t *blob)
+{
+	return &blob->base;
+}
+
+static int block_size(bithenge_blob_t *base, aoff64_t *size)
+{
+	block_blob_t *self = blob_as_block(base);
+	*size = self->size;
+	return EOK;
+}
+
+static int block_read(bithenge_blob_t *base, aoff64_t offset, char *buffer,
+    aoff64_t *size)
+{
+	block_blob_t *self = blob_as_block(base);
+	if (offset > self->size)
+		return ELIMIT;
+	*size = min(*size, self->size - offset);
+	return block_read_bytes_direct(self->service_id, offset, *size, buffer);
+}
+
+static void block_destroy(bithenge_blob_t *base)
+{
+	block_blob_t *self = blob_as_block(base);
+	block_fini(self->service_id);
+	free(self);
+}
+
+static const bithenge_random_access_blob_ops_t block_ops = {
+	.size = block_size,
+	.read = block_read,
+	.destroy = block_destroy,
+};
+
+/** Create a blob for a block device. The blob must be freed with
+ * @a bithenge_node_t::bithenge_node_destroy after it is used.
+ * @param[out] out Stores the created blob.
+ * @param service_id The service ID of the block device.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_block_blob(bithenge_node_t **out, service_id_t service_id)
+{
+	assert(out);
+
+	// Initialize libblock
+	int rc;
+	rc = block_init(EXCHANGE_SERIALIZE, service_id, 2048);
+	if (rc != EOK)
+		return rc;
+
+	// Calculate total device size
+	size_t bsize;
+	aoff64_t nblocks;
+	aoff64_t size;
+	rc = block_get_bsize(service_id, &bsize);
+	if (rc != EOK) {
+		block_fini(service_id);
+		return rc;
+	}
+	rc = block_get_nblocks(service_id, &nblocks);
+	if (rc != EOK) {
+		block_fini(service_id);
+		return rc;
+	}
+	size = bsize * nblocks;
+
+	// Create blob
+	block_blob_t *blob = malloc(sizeof(*blob));
+	if (!blob) {
+		block_fini(service_id);
+		return ENOMEM;
+	}
+	rc = bithenge_init_random_access_blob(block_as_blob(blob),
+	    &block_ops);
+	if (rc != EOK) {
+		free(blob);
+		block_fini(service_id);
+		return rc;
+	}
+	blob->service_id = service_id;
+	blob->size = size;
+	*out = bithenge_blob_as_node(block_as_blob(blob));
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/bithenge/src/helenos/block.h
===================================================================
--- uspace/lib/bithenge/src/helenos/block.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/helenos/block.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Access block devices as blobs.
+ */
+
+#ifndef BITHENGE_BLOCK_H_
+#define BITHENGE_BLOCK_H_
+
+#include <loc.h>
+#include <bithenge/tree.h>
+
+int bithenge_new_block_blob(bithenge_node_t **, service_id_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/bithenge/src/helenos/common.h
===================================================================
--- uspace/lib/bithenge/src/helenos/common.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/helenos/common.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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.
+ */
+
+#ifndef BITHENGE_HELENOS_COMMON_H_
+#define BITHENGE_HELENOS_COMMON_H_
+
+#include <bithenge/os.h>
+#include <bool.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <macros.h>
+#include <mem.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <str.h>
+#include <str_error.h>
+
+#define BITHENGE_PRId PRId64
+
+typedef struct {
+	const char *string;
+	size_t offset;
+	wchar_t ch;
+} string_iterator_t;
+
+static inline string_iterator_t string_iterator(const char *string)
+{
+	string_iterator_t i;
+	i.string = string;
+	i.offset = 0;
+	i.ch = str_decode(i.string, &i.offset, STR_NO_LIMIT);
+	return i;
+}
+
+static inline bool string_iterator_done(const string_iterator_t *i)
+{
+	return i->ch == L'\0';
+}
+
+static inline int string_iterator_next(string_iterator_t *i, wchar_t *out)
+{
+	*out = i->ch;
+	if (*out == U_SPECIAL)
+		return EINVAL;
+	i->ch = str_decode(i->string, &i->offset, STR_NO_LIMIT);
+	return EOK;
+}
+
+static inline void *memchr(const void *s, int c, size_t n)
+{
+	for (size_t i = 0; i < n; i++)
+		if (((char *)s)[i] == c)
+			return (void *)(s + i);
+	return NULL;
+}
+
+static inline int bithenge_parse_int(const char *start, bithenge_int_t *result)
+{
+	const char *real_start = *start == '-' ? start + 1 : start;
+	uint64_t val;
+	int rc = str_uint64_t(real_start, NULL, 10, false, &val);
+	*result = val;
+	if (*start == '-')
+		*result = -*result;
+	return rc;
+}
+
+#endif
Index: uspace/lib/bithenge/src/linux/common.h
===================================================================
--- uspace/lib/bithenge/src/linux/common.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/linux/common.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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.
+ */
+
+#ifndef BITHENGE_LINUX_COMMON_H_
+#define BITHENGE_LINUX_COMMON_H_
+
+#include <endian.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <memory.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#define max(aleph, bet) ((aleph) > (bet) ? (aleph) : (bet))
+#define min(aleph, bet) ((aleph) < (bet) ? (aleph) : (bet))
+
+#define EOK 0
+#define ELIMIT EINVAL
+
+typedef intmax_t bithenge_int_t;
+#define BITHENGE_PRId PRIdMAX
+typedef uint64_t aoff64_t;
+typedef const char *string_iterator_t;
+
+static inline string_iterator_t string_iterator(const char *string)
+{
+	return string;
+}
+
+static inline int string_iterator_next(string_iterator_t *i, wchar_t *out)
+{
+	wint_t rc = btowc(*(*i)++); // TODO
+	*out = (wchar_t) rc;
+	return rc == WEOF ? EILSEQ : EOK;
+}
+
+static inline bool string_iterator_done(const string_iterator_t *i)
+{
+	return !**i;
+}
+
+static inline size_t str_length(const char *string)
+{
+	return strlen(string);
+}
+
+static inline const char *str_chr(const char *string, wchar_t ch)
+{
+	return strchr(string, wctob(ch)); // TODO
+}
+
+static inline int str_cmp(const char *s1, const char *s2)
+{
+	return strcmp(s1, s2);
+}
+
+static inline int str_lcmp(const char *s1, const char *s2, size_t max_len)
+{
+	return strncmp(s1, s2, max_len);
+}
+
+static inline char *str_dup(const char *s)
+{
+	return strdup(s);
+}
+
+static inline char *str_ndup(const char *s, size_t max_len)
+{
+	return strndup(s, max_len);
+}
+
+static inline const char *str_error(int e)
+{
+	return strerror(e);
+}
+
+static inline uint16_t uint16_t_le2host(uint16_t val)
+{
+	return le16toh(val);
+}
+
+static inline uint16_t uint16_t_be2host(uint16_t val)
+{
+	return be16toh(val);
+}
+
+static inline uint32_t uint32_t_le2host(uint32_t val)
+{
+	return le32toh(val);
+}
+
+static inline uint32_t uint32_t_be2host(uint32_t val)
+{
+	return be32toh(val);
+}
+
+static inline uint64_t uint64_t_le2host(uint64_t val)
+{
+	return le64toh(val);
+}
+
+static inline uint64_t uint64_t_be2host(uint64_t val)
+{
+	return be64toh(val);
+}
+
+static inline int bithenge_parse_int(const char *start, bithenge_int_t *result)
+{
+	errno = 0;
+	*result = strtoll(start, NULL, 10);
+	return errno;
+}
+
+#endif
Index: uspace/lib/bithenge/src/print.c
===================================================================
--- uspace/lib/bithenge/src/print.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/print.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Write a tree as JSON or other text formats.
+ * @todo Allow more control over the printing style, and handle printing in
+ * limited space.
+ */
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <bithenge/blob.h>
+#include <bithenge/print.h>
+#include <bithenge/tree.h>
+#include "common.h"
+
+typedef struct {
+	bithenge_print_type_t type;
+	bool first;
+	int depth;
+	char *buffer;
+	size_t buffer_size;
+} state_t;
+
+static void state_printf(state_t *state, const char *format, ...)
+{
+	va_list ap;
+	va_start(ap, format);
+	if (state->buffer) {
+		int rc = vsnprintf(state->buffer, state->buffer_size, format,
+		    ap);
+		if (rc > 0 && (size_t)rc >= state->buffer_size)
+			rc = state->buffer_size - 1;
+		if (rc > 0) {
+			state->buffer += rc;
+			state->buffer_size -= rc;
+		}
+	} else {
+		vprintf(format, ap);
+	}
+	va_end(ap);
+}
+
+static int print_node(state_t *, bithenge_node_t *);
+
+static void newline(state_t *state)
+{
+	state_printf(state, "\n");
+	for (int i = 0; i < state->depth; i++) {
+		state_printf(state, "    ");
+	}
+}
+
+static void increase_depth(state_t *state)
+{
+	state->depth++;
+}
+
+static void decrease_depth(state_t *state)
+{
+	state->depth--;
+}
+
+static int print_internal_func(bithenge_node_t *key, bithenge_node_t *value, void *data)
+{
+	state_t *state = (state_t *)data;
+	int rc = EOK;
+	if (!state->first)
+		state_printf(state, ",");
+	newline(state);
+	state->first = false;
+	bool add_quotes = state->type == BITHENGE_PRINT_JSON
+	    && bithenge_node_type(key) != BITHENGE_NODE_STRING;
+	if (add_quotes)
+		state_printf(state, "\"");
+	rc = print_node(state, key);
+	if (rc != EOK)
+		goto end;
+	if (add_quotes)
+		state_printf(state, "\"");
+	state_printf(state, ": ");
+	rc = print_node(state, value);
+	if (rc != EOK)
+		goto end;
+end:
+	bithenge_node_dec_ref(key);
+	bithenge_node_dec_ref(value);
+	return rc;
+}
+
+static int print_internal(state_t *state, bithenge_node_t *node)
+{
+	int rc;
+	state_printf(state, "{");
+	increase_depth(state);
+	state->first = true;
+	rc = bithenge_node_for_each(node, print_internal_func, state);
+	if (rc != EOK)
+		return rc;
+	decrease_depth(state);
+	if (!state->first)
+		newline(state);
+	state->first = false;
+	state_printf(state, "}");
+	return EOK;
+}
+
+static int print_boolean(state_t *state, bithenge_node_t *node)
+{
+	bool value = bithenge_boolean_node_value(node);
+	switch (state->type) {
+	case BITHENGE_PRINT_PYTHON:
+		state_printf(state, value ? "True" : "False");
+		break;
+	case BITHENGE_PRINT_JSON:
+		state_printf(state, value ? "true" : "false");
+		break;
+	}
+	return EOK;
+}
+
+static int print_integer(state_t *state, bithenge_node_t *node)
+{
+	bithenge_int_t value = bithenge_integer_node_value(node);
+	state_printf(state, "%" BITHENGE_PRId, value);
+	return EOK;
+}
+
+static int print_string(state_t *state, bithenge_node_t *node)
+{
+	const char *value = bithenge_string_node_value(node);
+	state_printf(state, "\"");
+	for (string_iterator_t i = string_iterator(value); !string_iterator_done(&i); ) {
+		wchar_t ch;
+		int rc = string_iterator_next(&i, &ch);
+		if (rc != EOK)
+			return rc;
+		if (ch == '"' || ch == '\\') {
+			state_printf(state, "\\%lc", (wint_t) ch);
+		} else if (ch <= 0x1f) {
+			state_printf(state, "\\u%04x", (unsigned int) ch);
+		} else {
+			state_printf(state, "%lc", (wint_t) ch);
+		}
+	}
+	state_printf(state, "\"");
+	return EOK;
+}
+
+static int print_blob(state_t *state, bithenge_node_t *node)
+{
+	bithenge_blob_t *blob = bithenge_node_as_blob(node);
+	aoff64_t pos = 0;
+	uint8_t buffer[1024];
+	aoff64_t size = sizeof(buffer);
+	int rc;
+	state_printf(state,
+	    state->type == BITHENGE_PRINT_PYTHON ? "b\"" : "\"");
+	do {
+		rc = bithenge_blob_read(blob, pos, (char *)buffer, &size);
+		if (rc != EOK)
+			return rc;
+		for (aoff64_t i = 0; i < size; i++)
+			state_printf(state, "\\x%02x",
+			    (unsigned int)buffer[i]);
+		pos += size;
+	} while (size == sizeof(buffer));
+	state_printf(state, "\"");
+	return EOK;
+}
+
+static int print_node(state_t *state, bithenge_node_t *tree)
+{
+	switch (bithenge_node_type(tree)) {
+	case BITHENGE_NODE_INTERNAL:
+		return print_internal(state, tree);
+	case BITHENGE_NODE_BOOLEAN:
+		return print_boolean(state, tree);
+	case BITHENGE_NODE_INTEGER:
+		return print_integer(state, tree);
+	case BITHENGE_NODE_STRING:
+		return print_string(state, tree);
+	case BITHENGE_NODE_BLOB:
+		return print_blob(state, tree);
+	}
+	return ENOTSUP;
+}
+
+/** Print a tree as text to stdout.
+ * @param type The format to use.
+ * @param tree The root node of the tree to print.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_print_node(bithenge_print_type_t type, bithenge_node_t *tree)
+{
+	state_t state = {type, true, 0, NULL, 0};
+	return print_node(&state, tree);
+}
+
+/** Print a tree as text into a buffer.
+ * @param[in,out] str Holds a pointer to the buffer; changed to point to the
+ * null character.
+ * @param[in,out] size Holds the size of the buffer; changed to hold the
+ * remaining size.
+ * @param type The format to use.
+ * @param tree The root node of the tree to print.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_print_node_to_string(char **str, size_t *size,
+    bithenge_print_type_t type, bithenge_node_t *tree)
+{
+	state_t state = {type, true, 0, *str, *size};
+	int rc = print_node(&state, tree);
+	*str = state.buffer;
+	*size = state.buffer_size;
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/bithenge/src/script.c
===================================================================
--- uspace/lib/bithenge/src/script.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/script.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1340 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Script parsing.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <bithenge/compound.h>
+#include <bithenge/expression.h>
+#include <bithenge/script.h>
+#include <bithenge/sequence.h>
+#include <bithenge/transform.h>
+#include <bithenge/tree.h>
+#include "common.h"
+
+/** @cond internal */
+#define BUFFER_SIZE 4096
+/** @endcond */
+
+/** Tokens with more characters than this may be read incorrectly. */
+static const int MAX_TOKEN_SIZE = 256;
+
+/** @cond internal
+ * Single-character symbols are represented by the character itself. Every
+ * other token uses one of these values: */
+typedef enum {
+	TOKEN_ERROR = -128,
+
+	TOKEN_AND,
+	TOKEN_CONCAT,
+	TOKEN_EQUALS,
+	TOKEN_EOF,
+	TOKEN_GREATER_THAN_OR_EQUAL,
+	TOKEN_IDENTIFIER,
+	TOKEN_INTEGER,
+	TOKEN_INTEGER_DIVIDE,
+	TOKEN_LEFT_ARROW,
+	TOKEN_LESS_THAN_OR_EQUAL,
+	TOKEN_NOT_EQUAL,
+	TOKEN_OR,
+
+	/* Keywords */
+	TOKEN_DO,
+	TOKEN_ELSE,
+	TOKEN_FALSE,
+	TOKEN_IF,
+	TOKEN_IN,
+	TOKEN_PARTIAL,
+	TOKEN_REPEAT,
+	TOKEN_STRUCT,
+	TOKEN_SWITCH,
+	TOKEN_TRANSFORM,
+	TOKEN_TRUE,
+	TOKEN_WHILE,
+} token_type_t;
+/** @endcond */
+
+/** Singly-linked list of named transforms. */
+typedef struct transform_list {
+	char *name;
+	bithenge_transform_t *transform;
+	struct transform_list *next;
+} transform_list_t;
+
+/** State kept by the parser. */
+typedef struct {
+	/** Rather than constantly checking return values, the parser uses this
+	 * to indicate whether an error has occurred. */
+	int error;
+
+	/** The list of named transforms. */
+	transform_list_t *transform_list;
+
+	/** The name of the script file. */
+	const char *filename;
+	/** The script file being read from. */
+	FILE *file;
+	/** The buffer that holds script code. There is always a '\0' after the
+	 * current position to prevent reading too far. */
+	char buffer[BUFFER_SIZE];
+	/** The start position within the buffer of the next unread token. */
+	size_t buffer_pos;
+	/** The start position within the buffer of the current token. */
+	size_t old_buffer_pos;
+	/** The line number of the current token. */
+	int lineno;
+	/** Added to a buffer position to find the column number. */
+	int line_offset;
+
+	/** The type of the current token. */
+	token_type_t token;
+	union {
+		/** The value of a TOKEN_IDENTIFIER token. Unless changed to
+		 * NULL, it will be freed when the next token is read. */
+		char *token_string;
+		/** The value of a TOKEN_INTEGER token. */
+		bithenge_int_t token_int;
+	};
+
+	/** The names of the current transform's parameters. */
+	char **parameter_names;
+	/** The number of parameters. */
+	int num_params;
+	/** @a parse_expression sets this when TOKEN_IN is used. */
+	bool in_node_used;
+} state_t;
+
+/** Free the previous token's data. This must be called before changing
+ * state->token. */
+static void done_with_token(state_t *state)
+{
+	if (state->token == TOKEN_IDENTIFIER)
+		free(state->token_string);
+	state->token = TOKEN_ERROR;
+}
+
+/** Note that an error has occurred if error is not EOK. */
+static void error_errno(state_t *state, int error)
+{
+	// Don't overwrite a previous error.
+	if (state->error == EOK && error != EOK) {
+		done_with_token(state);
+		state->token = TOKEN_ERROR;
+		state->error = error;
+	}
+}
+
+/** Note that a syntax error has occurred and print an error message. */
+static void syntax_error(state_t *state, const char *message)
+{
+	// Printing multiple errors is confusing.
+	if (state->error == EOK) {
+		size_t start_char = state->old_buffer_pos + state->line_offset;
+		size_t end_char = state->buffer_pos + state->line_offset;
+		size_t size = end_char - start_char;
+		fprintf(stderr, "%s:%d:", state->filename, state->lineno);
+		if (size <= 1)
+			fprintf(stderr, "%zd: ", start_char);
+		else
+			fprintf(stderr, "%zd-%zd: ", start_char, end_char - 1);
+		fprintf(stderr, "%s: \"%.*s\"\n", message, (int)size,
+		    state->buffer + state->old_buffer_pos);
+		error_errno(state, EINVAL);
+	}
+}
+
+/** Ensure the buffer contains enough characters to read a token. */
+static void fill_buffer(state_t *state)
+{
+	if (state->buffer_pos + MAX_TOKEN_SIZE < BUFFER_SIZE)
+		return;
+
+	size_t empty_size = state->buffer_pos;
+	size_t used_size = BUFFER_SIZE - 1 - state->buffer_pos;
+	memmove(state->buffer, state->buffer + state->buffer_pos, used_size);
+	state->line_offset += state->buffer_pos;
+	state->buffer_pos = 0;
+
+	size_t read_size = fread(state->buffer + used_size, 1, empty_size,
+	    state->file);
+	if (ferror(state->file))
+		error_errno(state, EIO);
+	state->buffer[used_size + read_size] = '\0';
+}
+
+/** Read the next token. */
+static void next_token(state_t *state)
+{
+	fill_buffer(state);
+	done_with_token(state);
+	state->old_buffer_pos = state->buffer_pos;
+	char ch = state->buffer[state->buffer_pos];
+	if (ch == '\0') {
+		state->token = TOKEN_EOF;
+	} else if (ch == '#') {
+		while (state->buffer[state->buffer_pos] != '\n'
+		    && state->buffer[state->buffer_pos] != '\0') {
+			state->buffer_pos++;
+			fill_buffer(state);
+		}
+		next_token(state);
+		return;
+	} else if (isspace(ch)) {
+		// Will eventually reach the '\0' at the end
+		while (isspace(state->buffer[state->buffer_pos])) {
+			if (state->buffer[state->buffer_pos] == '\n') {
+				state->lineno++;
+				state->line_offset = -state->buffer_pos;
+			}
+			state->buffer_pos++;
+		}
+		next_token(state);
+		return;
+	} else if (isalpha(ch)) {
+		while (isalnum(state->buffer[state->buffer_pos])
+		    || state->buffer[state->buffer_pos] == '_')
+			state->buffer_pos++;
+		char *value = str_ndup(state->buffer + state->old_buffer_pos,
+		    state->buffer_pos - state->old_buffer_pos);
+		if (!value) {
+			error_errno(state, ENOMEM);
+		} else if (!str_cmp(value, "do")) {
+			state->token = TOKEN_DO;
+			free(value);
+		} else if (!str_cmp(value, "else")) {
+			state->token = TOKEN_ELSE;
+			free(value);
+		} else if (!str_cmp(value, "false")) {
+			state->token = TOKEN_FALSE;
+			free(value);
+		} else if (!str_cmp(value, "if")) {
+			state->token = TOKEN_IF;
+			free(value);
+		} else if (!str_cmp(value, "in")) {
+			state->token = TOKEN_IN;
+			free(value);
+		} else if (!str_cmp(value, "partial")) {
+			state->token = TOKEN_PARTIAL;
+			free(value);
+		} else if (!str_cmp(value, "repeat")) {
+			state->token = TOKEN_REPEAT;
+			free(value);
+		} else if (!str_cmp(value, "struct")) {
+			state->token = TOKEN_STRUCT;
+			free(value);
+		} else if (!str_cmp(value, "switch")) {
+			state->token = TOKEN_SWITCH;
+			free(value);
+		} else if (!str_cmp(value, "transform")) {
+			state->token = TOKEN_TRANSFORM;
+			free(value);
+		} else if (!str_cmp(value, "true")) {
+			state->token = TOKEN_TRUE;
+			free(value);
+		} else if (!str_cmp(value, "while")) {
+			state->token = TOKEN_WHILE;
+			free(value);
+		} else {
+			state->token = TOKEN_IDENTIFIER;
+			state->token_string = value;
+		}
+	} else if (isdigit(ch)) {
+		while (isdigit(state->buffer[state->buffer_pos]))
+			state->buffer_pos++;
+		state->token = TOKEN_INTEGER;
+		int rc = bithenge_parse_int(state->buffer +
+		    state->old_buffer_pos, &state->token_int);
+		error_errno(state, rc);
+	} else if (ch == '<') {
+		state->token = ch;
+		state->buffer_pos++;
+		if (state->buffer[state->buffer_pos] == '-') {
+			state->buffer_pos++;
+			state->token = TOKEN_LEFT_ARROW;
+		} else if (state->buffer[state->buffer_pos] == '=') {
+			state->buffer_pos++;
+			state->token = TOKEN_LESS_THAN_OR_EQUAL;
+		}
+	} else if (ch == '>') {
+		state->token = ch;
+		state->buffer_pos++;
+		if (state->buffer[state->buffer_pos] == '=') {
+			state->buffer_pos++;
+			state->token = TOKEN_GREATER_THAN_OR_EQUAL;
+		}
+	} else if (ch == '=') {
+		state->token = ch;
+		state->buffer_pos++;
+		if (state->buffer[state->buffer_pos] == '=') {
+			state->token = TOKEN_EQUALS;
+			state->buffer_pos++;
+		}
+	} else if (ch == '/') {
+		state->token = ch;
+		state->buffer_pos++;
+		if (state->buffer[state->buffer_pos] == '/') {
+			state->token = TOKEN_INTEGER_DIVIDE;
+			state->buffer_pos++;
+		}
+	} else if (ch == '!') {
+		state->token = ch;
+		state->buffer_pos++;
+		if (state->buffer[state->buffer_pos] == '=') {
+			state->token = TOKEN_NOT_EQUAL;
+			state->buffer_pos++;
+		}
+	} else if (ch == '&') {
+		state->token = ch;
+		state->buffer_pos++;
+		if (state->buffer[state->buffer_pos] == '&') {
+			state->token = TOKEN_AND;
+			state->buffer_pos++;
+		}
+	} else if (ch == '|') {
+		state->token = ch;
+		state->buffer_pos++;
+		if (state->buffer[state->buffer_pos] == '|') {
+			state->token = TOKEN_OR;
+			state->buffer_pos++;
+		}
+	} else if (ch == '+') {
+		state->token = ch;
+		state->buffer_pos++;
+		if (state->buffer[state->buffer_pos] == '+') {
+			state->token = TOKEN_CONCAT;
+			state->buffer_pos++;
+		}
+	} else {
+		state->token = ch;
+		state->buffer_pos++;
+	}
+}
+
+/** Allocate memory and handle failure by setting the error in the state. The
+ * caller must check the state for errors before using the return value of this
+ * function. */
+static void *state_malloc(state_t *state, size_t size)
+{
+	if (state->error != EOK)
+		return NULL;
+	void *result = malloc(size);
+	if (result == NULL)
+		error_errno(state, ENOMEM);
+	return result;
+}
+
+/** Reallocate memory and handle failure by setting the error in the state. If
+ * an error occurs, the existing pointer will be returned. */
+static void *state_realloc(state_t *state, void *ptr, size_t size)
+{
+	if (state->error != EOK)
+		return ptr;
+	void *result = realloc(ptr, size);
+	if (result == NULL) {
+		error_errno(state, ENOMEM);
+		return ptr;
+	}
+	return result;
+}
+
+/** Expect and consume a certain token. If the next token is of the wrong type,
+ * an error is caused. */
+static void expect(state_t *state, token_type_t type)
+{
+	if (state->token != type) {
+		syntax_error(state, "unexpected");
+		return;
+	}
+	next_token(state);
+}
+
+/** Expect and consume an identifier token. If the next token is not an
+ * identifier, an error is caused and this function returns null. */
+static char *expect_identifier(state_t *state)
+{
+	if (state->token != TOKEN_IDENTIFIER) {
+		syntax_error(state, "unexpected (identifier expected)");
+		return NULL;
+	}
+	char *val = state->token_string;
+	state->token_string = NULL;
+	next_token(state);
+	return val;
+}
+
+/** Find a transform by name. A reference will be added to the transform.
+ * @return The found transform, or NULL if none was found. */
+static bithenge_transform_t *get_named_transform(state_t *state,
+    const char *name)
+{
+	for (transform_list_t *e = state->transform_list; e; e = e->next) {
+		if (!str_cmp(e->name, name)) {
+			bithenge_transform_inc_ref(e->transform);
+			return e->transform;
+		}
+	}
+	for (int i = 0; bithenge_primitive_transforms[i].name; i++) {
+		if (!str_cmp(bithenge_primitive_transforms[i].name, name)) {
+			bithenge_transform_t *xform =
+			    bithenge_primitive_transforms[i].transform;
+			bithenge_transform_inc_ref(xform);
+			return xform;
+		}
+	}
+	return NULL;
+}
+
+/** Add a named transform. This function takes ownership of the name and a
+ * reference to the transform. If an error has occurred, either may be null. */
+static void add_named_transform(state_t *state, bithenge_transform_t *xform, char *name)
+{
+	transform_list_t *entry = state_malloc(state, sizeof(*entry));
+	if (state->error != EOK) {
+		free(name);
+		bithenge_transform_dec_ref(xform);
+		free(entry);
+		return;
+	}
+	entry->name = name;
+	entry->transform = xform;
+	entry->next = state->transform_list;
+	state->transform_list = entry;
+}
+
+static bithenge_transform_t *parse_transform(state_t *state);
+static bithenge_transform_t *parse_struct(state_t *state);
+static bithenge_expression_t *parse_expression(state_t *state);
+
+
+
+/***************** Expressions                               *****************/
+
+/** @cond internal */
+typedef enum {
+	PRECEDENCE_NONE,
+	PRECEDENCE_AND,
+	PRECEDENCE_EQUALS,
+	PRECEDENCE_COMPARE,
+	PRECEDENCE_ADD,
+	PRECEDENCE_MULTIPLY,
+} precedence_t;
+/** @endcond */
+
+static bithenge_binary_op_t token_as_binary_operator(token_type_t token)
+{
+	switch ((int)token) {
+	case '+':
+		return BITHENGE_EXPRESSION_ADD;
+	case '-':
+		return BITHENGE_EXPRESSION_SUBTRACT;
+	case '*':
+		return BITHENGE_EXPRESSION_MULTIPLY;
+	case TOKEN_INTEGER_DIVIDE:
+		return BITHENGE_EXPRESSION_INTEGER_DIVIDE;
+	case '%':
+		return BITHENGE_EXPRESSION_MODULO;
+	case '<':
+		return BITHENGE_EXPRESSION_LESS_THAN;
+	case TOKEN_LESS_THAN_OR_EQUAL:
+		return BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL;
+	case '>':
+		return BITHENGE_EXPRESSION_GREATER_THAN;
+	case TOKEN_GREATER_THAN_OR_EQUAL:
+		return BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL;
+	case TOKEN_EQUALS:
+		return BITHENGE_EXPRESSION_EQUALS;
+	case TOKEN_NOT_EQUAL:
+		return BITHENGE_EXPRESSION_NOT_EQUALS;
+	case TOKEN_AND:
+		return BITHENGE_EXPRESSION_AND;
+	case TOKEN_OR:
+		return BITHENGE_EXPRESSION_OR;
+	case TOKEN_CONCAT:
+		return BITHENGE_EXPRESSION_CONCAT;
+	default:
+		return BITHENGE_EXPRESSION_INVALID_BINARY_OP;
+	}
+}
+
+static precedence_t binary_operator_precedence(bithenge_binary_op_t op)
+{
+	switch (op) {
+	case BITHENGE_EXPRESSION_ADD: /* fallthrough */
+	case BITHENGE_EXPRESSION_SUBTRACT: /* fallthrough */
+	case BITHENGE_EXPRESSION_CONCAT:
+		return PRECEDENCE_ADD;
+	case BITHENGE_EXPRESSION_MULTIPLY: /* fallthrough */
+	case BITHENGE_EXPRESSION_INTEGER_DIVIDE: /* fallthrough */
+	case BITHENGE_EXPRESSION_MODULO:
+		return PRECEDENCE_MULTIPLY;
+	case BITHENGE_EXPRESSION_LESS_THAN: /* fallthrough */
+	case BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL: /* fallthrough */
+	case BITHENGE_EXPRESSION_GREATER_THAN: /* fallthrough */
+	case BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL:
+		return PRECEDENCE_COMPARE;
+	case BITHENGE_EXPRESSION_EQUALS: /* fallthrough */
+	case BITHENGE_EXPRESSION_NOT_EQUALS:
+		return PRECEDENCE_EQUALS;
+	case BITHENGE_EXPRESSION_AND: /* fallthrough */
+	case BITHENGE_EXPRESSION_OR:
+		return PRECEDENCE_AND;
+	default:
+		assert(false);
+		return PRECEDENCE_NONE;
+	}
+}
+
+static bithenge_expression_t *parse_term(state_t *state)
+{
+	int rc;
+	if (state->token == TOKEN_TRUE || state->token == TOKEN_FALSE) {
+		bool val = state->token == TOKEN_TRUE;
+		next_token(state);
+		bithenge_node_t *node;
+		rc = bithenge_new_boolean_node(&node, val);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+
+		bithenge_expression_t *expr;
+		rc = bithenge_const_expression(&expr, node);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+
+		return expr;
+	} else if (state->token == TOKEN_IN) {
+		next_token(state);
+		state->in_node_used = true;
+		bithenge_expression_t *expr;
+		rc = bithenge_in_node_expression(&expr);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+		return expr;
+	} else if (state->token == TOKEN_INTEGER) {
+		bithenge_int_t val = state->token_int;
+		next_token(state);
+		bithenge_node_t *node;
+		rc = bithenge_new_integer_node(&node, val);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+
+		bithenge_expression_t *expr;
+		rc = bithenge_const_expression(&expr, node);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+
+		return expr;
+	} else if (state->token == TOKEN_IDENTIFIER) {
+		int i;
+		for (i = 0; i < state->num_params; i++)
+			if (!str_cmp(state->parameter_names[i],
+			    state->token_string))
+				break;
+
+		if (i == state->num_params) {
+			syntax_error(state, "unknown identifier");
+			return NULL;
+		}
+
+		next_token(state);
+
+		bithenge_expression_t *expr;
+		rc = bithenge_param_expression(&expr, i);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+		return expr;
+	} else if (state->token == '.') {
+		next_token(state);
+
+		const char *id = expect_identifier(state);
+		bithenge_node_t *key = NULL;
+		bithenge_expression_t *expr = NULL;
+
+		if (state->error == EOK) {
+			rc = bithenge_new_string_node(&key, id, true);
+			id = NULL;
+			error_errno(state, rc);
+		}
+
+		if (state->error == EOK) {
+			rc = bithenge_scope_member_expression(&expr, key);
+			key = NULL;
+			if (rc != EOK)
+				expr = NULL;
+			error_errno(state, rc);
+		}
+
+		if (state->error != EOK) {
+			free((char *)id);
+			bithenge_node_dec_ref(key);
+			bithenge_expression_dec_ref(expr);
+			return NULL;
+		}
+
+		return expr;
+	} else if (state->token == '(') {
+		next_token(state);
+		bithenge_expression_t *expr = parse_expression(state);
+		expect(state, ')');
+		return expr;
+	} else {
+		syntax_error(state, "expression expected");
+		return NULL;
+	}
+}
+
+static bithenge_expression_t *parse_postfix_expression(state_t *state)
+{
+	int rc;
+	bithenge_expression_t *expr = parse_term(state);
+	while (state->error == EOK) {
+		if (state->token == '.') {
+			next_token(state);
+
+			const char *id = expect_identifier(state);
+
+			if (state->error != EOK) {
+				free((char *)id);
+				bithenge_expression_dec_ref(expr);
+				return NULL;
+			}
+
+			bithenge_node_t *key = NULL;
+			rc = bithenge_new_string_node(&key, id, true);
+			if (rc != EOK) {
+				error_errno(state, rc);
+				bithenge_expression_dec_ref(expr);
+				return NULL;
+			}
+
+			bithenge_expression_t *key_expr;
+			rc = bithenge_const_expression(&key_expr, key);
+			if (rc != EOK) {
+				error_errno(state, rc);
+				bithenge_expression_dec_ref(expr);
+				return NULL;
+			}
+
+			rc = bithenge_binary_expression(&expr,
+			    BITHENGE_EXPRESSION_MEMBER, expr, key_expr);
+			if (rc != EOK) {
+				error_errno(state, rc);
+				return NULL;
+			}
+		} else if (state->token == '[') {
+			next_token(state);
+			bithenge_expression_t *start = parse_expression(state);
+			bool absolute_limit = false;
+			if (state->token == ',' || state->token == ':') {
+				absolute_limit = state->token == ':';
+				next_token(state);
+				bithenge_expression_t *limit = NULL;
+				if (!(state->token == ']' && absolute_limit))
+					limit = parse_expression(state);
+				expect(state, ']');
+
+				if (state->error != EOK) {
+					bithenge_expression_dec_ref(expr);
+					bithenge_expression_dec_ref(start);
+					bithenge_expression_dec_ref(limit);
+					return NULL;
+				}
+				rc = bithenge_subblob_expression(&expr, expr, start,
+				    limit, absolute_limit);
+				if (rc != EOK) {
+					error_errno(state, rc);
+					return NULL;
+				}
+			} else if (state->token == ']') {
+				next_token(state);
+
+				if (state->error != EOK) {
+					bithenge_expression_dec_ref(expr);
+					bithenge_expression_dec_ref(start);
+					return NULL;
+				}
+				rc = bithenge_binary_expression(&expr,
+				    BITHENGE_EXPRESSION_MEMBER, expr, start);
+				if (rc != EOK) {
+					error_errno(state, rc);
+					return NULL;
+				}
+			} else {
+				syntax_error(state, "expected ',', ':', or ']'");
+				bithenge_expression_dec_ref(expr);
+				bithenge_expression_dec_ref(start);
+				return NULL;
+			}
+		} else {
+			break;
+		}
+	}
+	return expr;
+}
+
+static bithenge_expression_t *parse_expression_precedence(state_t *state,
+    precedence_t prev_precedence)
+{
+	bithenge_expression_t *expr = parse_postfix_expression(state);
+	while (state->error == EOK) {
+		bithenge_binary_op_t op =
+		    token_as_binary_operator(state->token);
+		if (op == BITHENGE_EXPRESSION_INVALID_BINARY_OP)
+			break;
+		precedence_t precedence = binary_operator_precedence(op);
+		if (precedence <= prev_precedence)
+			break;
+		next_token(state);
+
+		bithenge_expression_t *expr2 =
+		    parse_expression_precedence(state, precedence);
+		if (state->error != EOK) {
+			bithenge_expression_dec_ref(expr2);
+			break;
+		}
+		int rc = bithenge_binary_expression(&expr, op, expr, expr2);
+		if (rc != EOK) {
+			expr = NULL;
+			error_errno(state, rc);
+		}
+	}
+	if (state->error != EOK) {
+		bithenge_expression_dec_ref(expr);
+		expr = NULL;
+	}
+	return expr;
+}
+
+static bithenge_expression_t *parse_expression(state_t *state)
+{
+	return parse_expression_precedence(state, PRECEDENCE_NONE);
+}
+
+
+
+/* state->token must be TOKEN_IDENTIFIER when this is called. */
+static bithenge_transform_t *parse_invocation(state_t *state)
+{
+	bithenge_transform_t *result = get_named_transform(state,
+	    state->token_string);
+	if (!result)
+		syntax_error(state, "transform not found");
+	next_token(state);
+
+	bithenge_expression_t **params = NULL;
+	int num_params = 0;
+	if (state->token == '(') {
+		next_token(state);
+		while (state->error == EOK && state->token != ')') {
+			if (num_params)
+				expect(state, ',');
+			params = state_realloc(state, params,
+			    (num_params + 1)*sizeof(*params));
+			if (state->error != EOK)
+				break;
+			params[num_params] = parse_expression(state);
+			num_params++;
+		}
+		expect(state, ')');
+	}
+
+	/* TODO: show correct error position */
+	if (state->error == EOK
+	    && bithenge_transform_num_params(result) != num_params)
+		syntax_error(state, "incorrect number of parameters before");
+
+	if (state->error != EOK) {
+		while (num_params--)
+			bithenge_expression_dec_ref(params[num_params]);
+		free(params);
+		bithenge_transform_dec_ref(result);
+		return NULL;
+	}
+
+	if (num_params) {
+		int rc = bithenge_param_wrapper(&result, result, params);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			result = NULL;
+		}
+	}
+
+	return result;
+}
+
+/** Create a transform that just produces an empty node.
+ * @param state The parser state.
+ * @return The new transform, or NULL on error. */
+static bithenge_transform_t *make_empty_transform(state_t *state)
+{
+	bithenge_node_t *node;
+	int rc = bithenge_new_empty_internal_node(&node);
+	if (rc != EOK) {
+		error_errno(state, rc);
+		return NULL;
+	}
+
+	bithenge_expression_t *expr;
+	rc = bithenge_const_expression(&expr, node);
+	if (rc != EOK) {
+		error_errno(state, rc);
+		return NULL;
+	}
+
+	bithenge_transform_t *xform;
+	rc = bithenge_inputless_transform(&xform, expr);
+	if (rc != EOK) {
+		error_errno(state, rc);
+		return NULL;
+	}
+
+	return xform;
+}
+
+static bithenge_transform_t *parse_if(state_t *state, bool in_struct)
+{
+	expect(state, TOKEN_IF);
+	expect(state, '(');
+	bithenge_expression_t *expr = parse_expression(state);
+	expect(state, ')');
+	expect(state, '{');
+	bithenge_transform_t *true_xform =
+	    in_struct ? parse_struct(state) : parse_transform(state);
+	expect(state, '}');
+
+	bithenge_transform_t *false_xform = NULL;
+	if (state->token == TOKEN_ELSE) {
+		next_token(state);
+		expect(state, '{');
+		false_xform =
+		    in_struct ? parse_struct(state) : parse_transform(state);
+		expect(state, '}');
+	} else {
+		if (in_struct)
+			false_xform = make_empty_transform(state);
+		else
+			syntax_error(state, "else expected");
+	}
+
+	if (state->error != EOK) {
+		bithenge_expression_dec_ref(expr);
+		bithenge_transform_dec_ref(true_xform);
+		bithenge_transform_dec_ref(false_xform);
+		return NULL;
+	}
+
+	bithenge_transform_t *if_xform;
+	int rc = bithenge_if_transform(&if_xform, expr, true_xform,
+	    false_xform);
+	if (rc != EOK) {
+		error_errno(state, rc);
+		return NULL;
+	}
+	return if_xform;
+}
+
+static bithenge_transform_t *parse_switch(state_t *state, bool in_struct)
+{
+	expect(state, TOKEN_SWITCH);
+	expect(state, '(');
+	bithenge_expression_t *ref_expr = parse_expression(state);
+	expect(state, ')');
+	expect(state, '{');
+	int num = 0;
+	bithenge_expression_t **exprs = NULL;
+	bithenge_transform_t **xforms = NULL;
+	while (state->error == EOK && state->token != '}') {
+		bithenge_expression_t *expr;
+		if (state->token == TOKEN_ELSE) {
+			next_token(state);
+			bithenge_node_t *node;
+			int rc = bithenge_new_boolean_node(&node, true);
+			if (rc != EOK) {
+				error_errno(state, rc);
+				break;
+			}
+			rc = bithenge_const_expression(&expr, node);
+			if (rc != EOK) {
+				error_errno(state, rc);
+				break;
+			}
+		} else {
+			expr = parse_expression(state);
+			if (state->error == EOK) {
+				bithenge_expression_inc_ref(ref_expr);
+				int rc = bithenge_binary_expression(&expr,
+				    BITHENGE_EXPRESSION_EQUALS, ref_expr,
+				    expr);
+				if (rc != EOK) {
+					error_errno(state, rc);
+					break;
+				}
+			}
+		}
+
+		expect(state, ':');
+		bithenge_transform_t *xform;
+		if (in_struct) {
+			expect(state, '{');
+			xform = parse_struct(state);
+			expect(state, '}');
+		} else
+			xform = parse_transform(state);
+		expect(state, ';');
+
+		exprs = state_realloc(state, exprs,
+		    sizeof(*exprs) * (num + 1));
+		xforms = state_realloc(state, xforms,
+		    sizeof(*xforms) * (num + 1));
+		if (state->error != EOK) {
+			bithenge_expression_dec_ref(expr);
+			bithenge_transform_dec_ref(xform);
+			break;
+		}
+
+		exprs[num] = expr;
+		xforms[num] = xform;
+		num++;
+	}
+	bithenge_expression_dec_ref(ref_expr);
+
+	bithenge_transform_t *switch_xform = &bithenge_invalid_transform;
+	bithenge_transform_inc_ref(switch_xform);
+	while (state->error == EOK && num >= 1) {
+		num--;
+		int rc = bithenge_if_transform(&switch_xform, exprs[num],
+		    xforms[num], switch_xform);
+		if (rc != EOK) {
+			switch_xform = NULL;
+			error_errno(state, rc);
+		}
+	}
+
+	while (num >= 1) {
+		num--;
+		bithenge_expression_dec_ref(exprs[num]);
+		bithenge_transform_dec_ref(xforms[num]);
+	}
+	free(exprs);
+	free(xforms);
+
+	expect(state, '}');
+	return switch_xform;
+}
+
+static bithenge_transform_t *parse_repeat(state_t *state)
+{
+	expect(state, TOKEN_REPEAT);
+	bithenge_expression_t *expr = NULL;
+	if (state->token == '(') {
+		next_token(state);
+		expr = parse_expression(state);
+		expect(state, ')');
+	}
+	expect(state, '{');
+	bithenge_transform_t *xform = parse_transform(state);
+	expect(state, '}');
+
+	if (state->error != EOK) {
+		bithenge_expression_dec_ref(expr);
+		bithenge_transform_dec_ref(xform);
+		return NULL;
+	}
+
+	bithenge_transform_t *repeat_xform;
+	int rc = bithenge_repeat_transform(&repeat_xform, xform, expr);
+	if (rc != EOK) {
+		error_errno(state, rc);
+		return NULL;
+	}
+	return repeat_xform;
+}
+
+static bithenge_transform_t *parse_do_while(state_t *state)
+{
+	expect(state, TOKEN_DO);
+	expect(state, '{');
+	bithenge_transform_t *xform = parse_transform(state);
+	expect(state, '}');
+	expect(state, TOKEN_WHILE);
+	expect(state, '(');
+	bithenge_expression_t *expr = parse_expression(state);
+	expect(state, ')');
+
+	if (state->error != EOK) {
+		bithenge_expression_dec_ref(expr);
+		bithenge_transform_dec_ref(xform);
+		return NULL;
+	}
+
+	bithenge_transform_t *do_while_xform;
+	int rc = bithenge_do_while_transform(&do_while_xform, xform, expr);
+	if (rc != EOK) {
+		error_errno(state, rc);
+		return NULL;
+	}
+	return do_while_xform;
+}
+
+static bithenge_transform_t *parse_partial(state_t *state)
+{
+	expect(state, TOKEN_PARTIAL);
+	bithenge_transform_t *offset_xform = NULL;
+	if (state->token == '(') {
+		next_token(state);
+		bithenge_expression_t *offset = parse_expression(state);
+		expect(state, ')');
+
+		bithenge_expression_t *in_expr;
+		int rc = bithenge_in_node_expression(&in_expr);
+		if (rc != EOK)
+			error_errno(state, rc);
+		if (state->error != EOK) {
+			bithenge_expression_dec_ref(offset);
+			return NULL;
+		}
+
+		rc = bithenge_subblob_expression(&offset, in_expr, offset,
+		    NULL, true);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+
+		rc = bithenge_expression_transform(&offset_xform, offset);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+	}
+	expect(state, '{');
+	bithenge_transform_t *xform = parse_transform(state);
+	expect(state, '}');
+	if (state->error != EOK) {
+		bithenge_transform_dec_ref(offset_xform);
+		bithenge_transform_dec_ref(xform);
+		return NULL;
+	}
+
+	int rc = bithenge_partial_transform(&xform, xform);
+	if (rc != EOK) {
+		error_errno(state, rc);
+		bithenge_transform_dec_ref(offset_xform);
+		return NULL;
+	}
+
+	if (offset_xform) {
+		bithenge_transform_t **xforms = malloc(2 * sizeof(*xforms));
+		if (!xforms) {
+			error_errno(state, ENOMEM);
+			bithenge_transform_dec_ref(xform);
+			bithenge_transform_dec_ref(offset_xform);
+			return NULL;
+		}
+		xforms[0] = xform;
+		xforms[1] = offset_xform;
+		rc = bithenge_new_composed_transform(&xform, xforms, 2);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+	}
+
+	return xform;
+}
+
+/* The TOKEN_STRUCT and '{' must already have been skipped. */
+static bithenge_transform_t *parse_struct(state_t *state)
+{
+	size_t num = 0;
+	bithenge_named_transform_t *subxforms;
+	/* We keep an extra space for the {NULL, NULL} terminator. */
+	subxforms = state_malloc(state, sizeof(*subxforms));
+	while (state->error == EOK && state->token != '}') {
+		if (state->token == TOKEN_IF) {
+			subxforms[num].transform = parse_if(state, true);
+			subxforms[num].name = NULL;
+		} else if (state->token == TOKEN_SWITCH) {
+			subxforms[num].transform = parse_switch(state, true);
+			subxforms[num].name = NULL;
+		} else {
+			if (state->token == '.') {
+				next_token(state);
+				subxforms[num].name = expect_identifier(state);
+			} else {
+				subxforms[num].name = NULL;
+			}
+			expect(state, TOKEN_LEFT_ARROW);
+			subxforms[num].transform = parse_transform(state);
+			expect(state, ';');
+		}
+		num++;
+		subxforms = state_realloc(state, subxforms,
+		    (num + 1)*sizeof(*subxforms));
+	}
+
+	if (state->error != EOK) {
+		while (num--) {
+			free((void *)subxforms[num].name);
+			bithenge_transform_dec_ref(subxforms[num].transform);
+		}
+		free(subxforms);
+		return NULL;
+	}
+
+	subxforms[num].name = NULL;
+	subxforms[num].transform = NULL;
+	bithenge_transform_t *result;
+	int rc = bithenge_new_struct(&result, subxforms);
+	if (rc != EOK) {
+		error_errno(state, rc);
+		return NULL;
+	}
+	return result;
+}
+
+/** Parse a transform without composition.
+ * @return The parsed transform, or NULL if an error occurred. */
+static bithenge_transform_t *parse_transform_no_compose(state_t *state)
+{
+	if (state->token == '(') {
+		next_token(state);
+		state->in_node_used = false;
+		bithenge_expression_t *expr = parse_expression(state);
+		expect(state, ')');
+		if (state->error != EOK) {
+			bithenge_expression_dec_ref(expr);
+			return NULL;
+		}
+
+		bithenge_transform_t *xform;
+		int rc;
+		if (state->in_node_used)
+			rc = bithenge_expression_transform(&xform, expr);
+		else
+			rc = bithenge_inputless_transform(&xform, expr);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+		return xform;
+	} else if (state->token == TOKEN_DO) {
+		return parse_do_while(state);
+	} else if (state->token == TOKEN_IDENTIFIER) {
+		return parse_invocation(state);
+	} else if (state->token == TOKEN_IF) {
+		return parse_if(state, false);
+	} else if (state->token == TOKEN_PARTIAL) {
+		return parse_partial(state);
+	} else if (state->token == TOKEN_REPEAT) {
+		return parse_repeat(state);
+	} else if (state->token == TOKEN_STRUCT) {
+		next_token(state);
+		expect(state, '{');
+		bithenge_transform_t *xform = parse_struct(state);
+		expect(state, '}');
+		return xform;
+	} else if (state->token == TOKEN_SWITCH) {
+		return parse_switch(state, false);
+	} else {
+		syntax_error(state, "unexpected (transform expected)");
+		return NULL;
+	}
+}
+
+/** Parse a transform.
+ * @return The parsed transform, or NULL if an error occurred. */
+static bithenge_transform_t *parse_transform(state_t *state)
+{
+	bithenge_transform_t *result = parse_transform_no_compose(state);
+	bithenge_transform_t **xforms = NULL;
+	size_t num = 1;
+	while (state->token == TOKEN_LEFT_ARROW) {
+		expect(state, TOKEN_LEFT_ARROW);
+		xforms = state_realloc(state, xforms,
+		    (num + 1) * sizeof(*xforms));
+		if (state->error != EOK)
+			break;
+		xforms[num++] = parse_transform_no_compose(state);
+	}
+	if (state->error != EOK) {
+		while (xforms && num > 1)
+			bithenge_transform_dec_ref(xforms[--num]);
+		free(xforms);
+		bithenge_transform_dec_ref(result);
+		return NULL;
+	}
+	if (xforms) {
+		xforms[0] = result;
+		int rc = bithenge_new_composed_transform(&result, xforms, num);
+		if (rc != EOK) {
+			error_errno(state, rc);
+			return NULL;
+		}
+	}
+	return result;
+}
+
+/** Parse a definition. */
+static void parse_definition(state_t *state)
+{
+	expect(state, TOKEN_TRANSFORM);
+	char *name = expect_identifier(state);
+
+	if (state->token == '(') {
+		next_token(state);
+		while (state->error == EOK && state->token != ')') {
+			if (state->num_params)
+				expect(state, ',');
+			state->parameter_names = state_realloc(state,
+			    state->parameter_names,
+			    (state->num_params + 1)*sizeof(*state->parameter_names));
+			if (state->error != EOK)
+				break;
+			state->parameter_names[state->num_params++] =
+			    expect_identifier(state);
+		}
+		expect(state, ')');
+	}
+
+	bithenge_transform_t *barrier = NULL;
+	if (state->error == EOK) {
+		int rc = bithenge_new_barrier_transform(&barrier,
+		    state->num_params);
+		if (rc != EOK) {
+			barrier = NULL;
+			error_errno(state, rc);
+		}
+	}
+
+	add_named_transform(state, barrier, name);
+
+	expect(state, '=');
+	bithenge_transform_t *xform = parse_transform(state);
+	expect(state, ';');
+
+	if (state->error == EOK) {
+		int rc = bithenge_barrier_transform_set_subtransform(barrier,
+		    xform);
+		xform = NULL;
+		if (rc != EOK)
+			error_errno(state, rc);
+	}
+
+	if (state->error != EOK)
+		bithenge_transform_dec_ref(xform);
+
+	for (int i = 0; i < state->num_params; i++)
+		free(state->parameter_names[i]);
+	free(state->parameter_names);
+	state->parameter_names = NULL;
+	state->num_params = 0;
+}
+
+/** Initialize the state. */
+static void state_init(state_t *state, const char *filename)
+{
+	state->error = EOK;
+	state->transform_list = NULL;
+	state->parameter_names = NULL;
+	state->num_params = 0;
+	state->token = TOKEN_ERROR;
+	state->old_buffer_pos = state->buffer_pos = BUFFER_SIZE - 1;
+	state->lineno = 1;
+	state->line_offset = (int)-state->buffer_pos + 1;
+	state->filename = filename;
+	state->file = fopen(filename, "r");
+	if (!state->file) {
+		error_errno(state, errno);
+	} else {
+		next_token(state);
+	}
+}
+
+/** Destroy the state. */
+static void state_destroy(state_t *state)
+{
+	done_with_token(state);
+	state->token = TOKEN_ERROR;
+	if (state->file)
+		fclose(state->file);
+	transform_list_t *entry = state->transform_list;
+	while (entry) {
+		transform_list_t *next = entry->next;
+		free(entry->name);
+		bithenge_transform_dec_ref(entry->transform);
+		free(entry);
+		entry = next;
+	}
+	for (int i = 0; i < state->num_params; i++)
+		free(state->parameter_names[i]);
+	free(state->parameter_names);
+}
+
+/** Parse a script file.
+ * @param filename The name of the script file.
+ * @param[out] out Stores the "main" transform.
+ * @return EOK on success, EINVAL on syntax error, or an error code from
+ * errno.h. */
+int bithenge_parse_script(const char *filename, bithenge_transform_t **out)
+{
+	state_t state;
+	state_init(&state, filename);
+	while (state.error == EOK && state.token != TOKEN_EOF)
+		parse_definition(&state);
+	*out = get_named_transform(&state, "main");
+	int rc = state.error;
+	state_destroy(&state);
+	if (rc == EOK && !*out) {
+		fprintf(stderr, "no \"main\" transform\n");
+		rc = EINVAL;
+	}
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/bithenge/src/sequence.c
===================================================================
--- uspace/lib/bithenge/src/sequence.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/sequence.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1146 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Sequence transforms.
+ */
+
+#include <stdlib.h>
+#include <bithenge/blob.h>
+#include <bithenge/expression.h>
+#include <bithenge/sequence.h>
+#include <bithenge/tree.h>
+#include "common.h"
+
+
+
+/***************** seq_node                                  *****************/
+
+typedef struct {
+	bithenge_node_t base;
+	const struct seq_node_ops *ops;
+	bithenge_blob_t *blob;
+	bithenge_scope_t *scope;
+	aoff64_t *ends;
+	size_t num_ends;
+	bool end_on_empty;
+	bithenge_int_t num_xforms;
+} seq_node_t;
+
+typedef struct seq_node_ops {
+	int (*get_transform)(seq_node_t *self, bithenge_transform_t **out,
+	    bithenge_int_t index);
+} seq_node_ops_t;
+
+static bithenge_node_t *seq_as_node(seq_node_t *node)
+{
+	return &node->base;
+}
+
+static seq_node_t *node_as_seq(bithenge_node_t *node)
+{
+	return (seq_node_t *)node;
+}
+
+static int seq_node_field_offset(seq_node_t *self, aoff64_t *out, size_t index)
+{
+	if (index == 0) {
+		*out = 0;
+		return EOK;
+	}
+	index--;
+	aoff64_t prev_offset =
+	    self->num_ends ? self->ends[self->num_ends - 1] : 0;
+	for (; self->num_ends <= index; self->num_ends++) {
+		bithenge_transform_t *subxform;
+		int rc = self->ops->get_transform(self, &subxform,
+		    self->num_ends);
+		if (rc != EOK)
+			return rc;
+
+		bithenge_node_t *subblob_node;
+		bithenge_blob_inc_ref(self->blob);
+		rc = bithenge_new_offset_blob(&subblob_node, self->blob,
+		    prev_offset);
+		if (rc != EOK) {
+			bithenge_transform_dec_ref(subxform);
+			return rc;
+		}
+
+		if (self->end_on_empty) {
+			bool empty;
+			rc = bithenge_blob_empty(
+			    bithenge_node_as_blob(subblob_node), &empty);
+			if (rc == EOK && empty) {
+				self->num_xforms = self->num_ends;
+				rc = ENOENT;
+			}
+			if (rc != EOK) {
+				bithenge_transform_dec_ref(subxform);
+				bithenge_node_dec_ref(subblob_node);
+				return rc;
+			}
+		}
+
+		bithenge_blob_t *subblob = bithenge_node_as_blob(subblob_node);
+		aoff64_t field_size;
+		rc = bithenge_transform_prefix_length(subxform, self->scope,
+		    subblob, &field_size);
+		bithenge_node_dec_ref(subblob_node);
+		bithenge_transform_dec_ref(subxform);
+		if (rc != EOK)
+			return rc;
+
+		if (self->num_xforms == -1) {
+			aoff64_t *new_ends = realloc(self->ends,
+			    (self->num_ends + 1)*sizeof(*new_ends));
+			if (!new_ends)
+				return ENOMEM;
+			self->ends = new_ends;
+		}
+
+		prev_offset = self->ends[self->num_ends] =
+		    prev_offset + field_size;
+	}
+	*out = self->ends[index];
+	return EOK;
+}
+
+static int seq_node_subtransform(seq_node_t *self, bithenge_node_t **out,
+    size_t index)
+{
+	aoff64_t start_pos;
+	int rc = seq_node_field_offset(self, &start_pos, index);
+	if (rc != EOK)
+		return rc;
+
+	bithenge_transform_t *subxform;
+	rc = self->ops->get_transform(self, &subxform, index);
+	if (rc != EOK)
+		return rc;
+
+	if (index == self->num_ends) {
+		/* We can apply the subtransform and cache its prefix length at
+		 * the same time. */
+		bithenge_node_t *blob_node;
+		bithenge_blob_inc_ref(self->blob);
+		rc = bithenge_new_offset_blob(&blob_node, self->blob,
+		    start_pos);
+		if (rc != EOK) {
+			bithenge_transform_dec_ref(subxform);
+			return rc;
+		}
+
+		if (self->end_on_empty) {
+			bool empty;
+			rc = bithenge_blob_empty(
+			    bithenge_node_as_blob(blob_node), &empty);
+			if (rc == EOK && empty) {
+				self->num_xforms = self->num_ends;
+				rc = ENOENT;
+			}
+			if (rc != EOK) {
+				bithenge_transform_dec_ref(subxform);
+				bithenge_node_dec_ref(blob_node);
+				return rc;
+			}
+		}
+
+		aoff64_t size;
+		rc = bithenge_transform_prefix_apply(subxform, self->scope,
+		    bithenge_node_as_blob(blob_node), out, &size);
+		bithenge_node_dec_ref(blob_node);
+		bithenge_transform_dec_ref(subxform);
+		if (rc != EOK)
+			return rc;
+
+		if (self->num_xforms == -1) {
+			aoff64_t *new_ends = realloc(self->ends,
+			    (self->num_ends + 1)*sizeof(*new_ends));
+			if (!new_ends)
+				return ENOMEM;
+			self->ends = new_ends;
+		}
+		self->ends[self->num_ends++] = start_pos + size;
+	} else {
+		aoff64_t end_pos;
+		int rc = seq_node_field_offset(self, &end_pos, index + 1);
+		if (rc != EOK) {
+			bithenge_transform_dec_ref(subxform);
+			return rc;
+		}
+
+		bithenge_node_t *blob_node;
+		bithenge_blob_inc_ref(self->blob);
+		rc = bithenge_new_subblob(&blob_node, self->blob, start_pos,
+		    end_pos - start_pos);
+		if (rc != EOK) {
+			bithenge_transform_dec_ref(subxform);
+			return rc;
+		}
+
+		rc = bithenge_transform_apply(subxform, self->scope, blob_node,
+		    out);
+		bithenge_node_dec_ref(blob_node);
+		bithenge_transform_dec_ref(subxform);
+		if (rc != EOK)
+			return rc;
+	}
+
+	return EOK;
+}
+
+static int seq_node_complete(seq_node_t *self, bool *out)
+{
+	aoff64_t blob_size, end_pos;
+	int rc = bithenge_blob_size(self->blob, &blob_size);
+	if (rc != EOK)
+		return rc;
+	rc = seq_node_field_offset(self, &end_pos, self->num_xforms);
+	if (rc != EOK)
+		return rc;
+	*out = blob_size == end_pos;
+	return EOK;
+}
+
+static void seq_node_destroy(seq_node_t *self)
+{
+	bithenge_scope_dec_ref(self->scope);
+	bithenge_blob_dec_ref(self->blob);
+	free(self->ends);
+}
+
+static void seq_node_set_num_xforms(seq_node_t *self,
+    bithenge_int_t num_xforms)
+{
+	self->num_xforms = num_xforms;
+}
+
+static bithenge_scope_t *seq_node_scope(seq_node_t *self)
+{
+	return self->scope;
+}
+
+static int seq_node_init(seq_node_t *self, const seq_node_ops_t *ops,
+    bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_int_t num_xforms,
+    bool end_on_empty)
+{
+	self->ops = ops;
+	if (num_xforms != -1) {
+		self->ends = malloc(sizeof(*self->ends) * num_xforms);
+		if (!self->ends)
+			return ENOMEM;
+	} else
+		self->ends = NULL;
+	bithenge_blob_inc_ref(blob);
+	self->blob = blob;
+	self->num_xforms = num_xforms;
+	self->num_ends = 0;
+	self->end_on_empty = end_on_empty;
+	self->scope = scope;
+	if (self->scope)
+		bithenge_scope_inc_ref(self->scope);
+	return EOK;
+}
+
+
+
+/***************** bithenge_new_struct                       *****************/
+
+typedef struct {
+	bithenge_transform_t base;
+	bithenge_named_transform_t *subtransforms;
+	size_t num_subtransforms;
+} struct_transform_t;
+
+static bithenge_transform_t *struct_as_transform(struct_transform_t *xform)
+{
+	return &xform->base;
+}
+
+static struct_transform_t *transform_as_struct(bithenge_transform_t *xform)
+{
+	return (struct_transform_t *)xform;
+}
+
+typedef struct {
+	seq_node_t base;
+	struct_transform_t *transform;
+	bool prefix;
+} struct_node_t;
+
+static seq_node_t *struct_as_seq(struct_node_t *node)
+{
+	return &node->base;
+}
+
+static struct_node_t *seq_as_struct(seq_node_t *base)
+{
+	return (struct_node_t *)base;
+}
+
+static bithenge_node_t *struct_as_node(struct_node_t *node)
+{
+	return seq_as_node(struct_as_seq(node));
+}
+
+static struct_node_t *node_as_struct(bithenge_node_t *node)
+{
+	return seq_as_struct(node_as_seq(node));
+}
+
+static int struct_node_for_each(bithenge_node_t *base,
+    bithenge_for_each_func_t func, void *data)
+{
+	int rc = EOK;
+	struct_node_t *self = node_as_struct(base);
+	bithenge_named_transform_t *subxforms =
+	    self->transform->subtransforms;
+
+	for (bithenge_int_t i = 0; subxforms[i].transform; i++) {
+		bithenge_node_t *subxform_result;
+		rc = seq_node_subtransform(struct_as_seq(self),
+		    &subxform_result, i);
+		if (rc != EOK)
+			return rc;
+
+		if (subxforms[i].name) {
+			bithenge_node_t *name_node;
+			rc = bithenge_new_string_node(&name_node,
+			    subxforms[i].name, false);
+			if (rc == EOK) {
+				rc = func(name_node, subxform_result, data);
+				subxform_result = NULL;
+			}
+		} else {
+			if (bithenge_node_type(subxform_result) !=
+			    BITHENGE_NODE_INTERNAL) {
+				rc = EINVAL;
+			} else {
+				rc = bithenge_node_for_each(subxform_result,
+				    func, data);
+			}
+		}
+		bithenge_node_dec_ref(subxform_result);
+		if (rc != EOK)
+			return rc;
+	}
+
+	if (!self->prefix) {
+		bool complete;
+		rc = seq_node_complete(struct_as_seq(self), &complete);
+		if (rc != EOK)
+			return rc;
+		if (!complete)
+			return EINVAL;
+	}
+
+	return rc;
+}
+
+static int struct_node_get(bithenge_node_t *base, bithenge_node_t *key,
+    bithenge_node_t **out)
+{
+	struct_node_t *self = node_as_struct(base);
+
+	int rc = ENOENT;
+	if (bithenge_node_type(key) != BITHENGE_NODE_STRING)
+		goto end;
+	const char *name = bithenge_string_node_value(key);
+
+	const bithenge_named_transform_t *subxforms =
+	    self->transform->subtransforms;
+	for (bithenge_int_t i = 0; subxforms[i].transform; i++) {
+		if (subxforms[i].name && !str_cmp(name, subxforms[i].name)) {
+			rc = seq_node_subtransform(struct_as_seq(self), out, i);
+			goto end;
+		}
+	}
+
+	for (bithenge_int_t i = 0; subxforms[i].transform; i++) {
+		if (subxforms[i].name)
+			continue;
+		bithenge_node_t *subxform_result;
+		rc = seq_node_subtransform(struct_as_seq(self),
+		    &subxform_result, i);
+		if (rc != EOK)
+			goto end;
+		if (bithenge_node_type(subxform_result) !=
+		    BITHENGE_NODE_INTERNAL) {
+			bithenge_node_dec_ref(subxform_result);
+			rc = EINVAL;
+			goto end;
+		}
+		bithenge_node_inc_ref(key);
+		rc = bithenge_node_get(subxform_result, key, out);
+		bithenge_node_dec_ref(subxform_result);
+		if (rc != ENOENT)
+			goto end;
+	}
+
+	rc = ENOENT;
+end:
+	bithenge_node_dec_ref(key);
+	return rc;
+}
+
+static void struct_node_destroy(bithenge_node_t *base)
+{
+	struct_node_t *node = node_as_struct(base);
+
+	/* Treat the scope carefully because of the circular reference. In
+	 * struct_transform_make_node, things are set up so node owns a
+	 * reference to the scope, but scope doesn't own a reference to node,
+	 * so node's reference count is too low. */
+	bithenge_scope_t *scope = seq_node_scope(struct_as_seq(node));
+	if (scope->refs == 1) {
+		/* Mostly normal destroy, but we didn't inc_ref(node) for the
+		 * scope in struct_transform_make_node, so make sure it doesn't
+		 * try to dec_ref. */
+		scope->current_node = NULL;
+		seq_node_destroy(struct_as_seq(node));
+	} else if (scope->refs > 1) {
+		/* The scope is still needed, but node isn't otherwise needed.
+		 * Switch things around so scope owns a reference to node, but
+		 * not vice versa, and scope's reference count is too low. */
+		bithenge_node_inc_ref(base);
+		bithenge_scope_dec_ref(scope);
+		return;
+	} else {
+		/* This happens after the previous case, when scope is no
+		 * longer used and is being destroyed. Since scope is already
+		 * being destroyed, set it to NULL here so we don't try to
+		 * destroy it twice. */
+		struct_as_seq(node)->scope = NULL;
+		seq_node_destroy(struct_as_seq(node));
+	}
+
+	bithenge_transform_dec_ref(struct_as_transform(node->transform));
+	free(node);
+}
+
+static const bithenge_internal_node_ops_t struct_node_ops = {
+	.for_each = struct_node_for_each,
+	.get = struct_node_get,
+	.destroy = struct_node_destroy,
+};
+
+static int struct_node_get_transform(seq_node_t *base,
+    bithenge_transform_t **out, bithenge_int_t index)
+{
+	struct_node_t *self = seq_as_struct(base);
+	*out = self->transform->subtransforms[index].transform;
+	bithenge_transform_inc_ref(*out);
+	return EOK;
+}
+
+static const seq_node_ops_t struct_node_seq_ops = {
+	.get_transform = struct_node_get_transform,
+};
+
+static int struct_transform_make_node(struct_transform_t *self,
+    bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob,
+    bool prefix)
+{
+	struct_node_t *node = malloc(sizeof(*node));
+	if (!node)
+		return ENOMEM;
+
+	int rc = bithenge_init_internal_node(struct_as_node(node),
+	    &struct_node_ops);
+	if (rc != EOK) {
+		free(node);
+		return rc;
+	}
+	bithenge_scope_t *inner;
+	rc = bithenge_scope_new(&inner, scope);
+	if (rc != EOK) {
+		free(node);
+		return rc;
+	}
+
+	rc = seq_node_init(struct_as_seq(node), &struct_node_seq_ops, inner,
+	    blob, self->num_subtransforms, false);
+	if (rc != EOK) {
+		bithenge_scope_dec_ref(inner);
+		free(node);
+		return rc;
+	}
+
+	bithenge_transform_inc_ref(struct_as_transform(self));
+	node->transform = self;
+	node->prefix = prefix;
+
+	/* We should inc_ref(node) here, but that would make a cycle. Instead,
+	 * we leave it 1 too low, so that when the only remaining use of node
+	 * is the scope, node will be destroyed. Also see the comment in
+	 * struct_node_destroy. */
+	bithenge_scope_set_current_node(inner, struct_as_node(node));
+	bithenge_scope_dec_ref(inner);
+
+	*out = struct_as_node(node);
+
+	return EOK;
+}
+
+static int struct_transform_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
+{
+	struct_transform_t *self = transform_as_struct(base);
+	if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
+		return EINVAL;
+	return struct_transform_make_node(self, out, scope,
+	    bithenge_node_as_blob(in), false);
+}
+
+static int struct_transform_prefix_length(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out)
+{
+	struct_transform_t *self = transform_as_struct(base);
+	bithenge_node_t *struct_node;
+	int rc = struct_transform_make_node(self, &struct_node, scope, blob,
+	    true);
+	if (rc != EOK)
+		return rc;
+
+	rc = seq_node_field_offset(node_as_seq(struct_node), out,
+	    self->num_subtransforms);
+	bithenge_node_dec_ref(struct_node);
+	return rc;
+}
+
+static int struct_transform_prefix_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,
+    aoff64_t *out_size)
+{
+	struct_transform_t *self = transform_as_struct(base);
+	int rc = struct_transform_make_node(self, out_node, scope, blob,
+	    true);
+	if (rc != EOK)
+		return rc;
+
+	if (out_size) {
+		rc = seq_node_field_offset(node_as_seq(*out_node), out_size,
+		    self->num_subtransforms);
+		if (rc != EOK) {
+			bithenge_node_dec_ref(*out_node);
+			return rc;
+		}
+	}
+
+	return EOK;
+}
+
+static void free_subtransforms(bithenge_named_transform_t *subtransforms)
+{
+	for (size_t i = 0; subtransforms[i].transform; i++) {
+		free((void *)subtransforms[i].name);
+		bithenge_transform_dec_ref(subtransforms[i].transform);
+	}
+	free(subtransforms);
+}
+
+static void struct_transform_destroy(bithenge_transform_t *base)
+{
+	struct_transform_t *self = transform_as_struct(base);
+	free_subtransforms(self->subtransforms);
+	free(self);
+}
+
+static bithenge_transform_ops_t struct_transform_ops = {
+	.apply = struct_transform_apply,
+	.prefix_length = struct_transform_prefix_length,
+	.prefix_apply = struct_transform_prefix_apply,
+	.destroy = struct_transform_destroy,
+};
+
+/** Create a struct transform. The transform will apply its subtransforms
+ * sequentially to a blob to create an internal node. Each result is either
+ * given a key from @a subtransforms or, if the name is NULL, the result's keys
+ * and values are merged into the struct transform's result. This function
+ * takes ownership of @a subtransforms and the names and references therein.
+ * @param[out] out Stores the created transform.
+ * @param subtransforms The subtransforms and field names.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_struct(bithenge_transform_t **out,
+    bithenge_named_transform_t *subtransforms)
+{
+	int rc;
+	struct_transform_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+	rc = bithenge_init_transform(struct_as_transform(self),
+	    &struct_transform_ops, 0);
+	if (rc != EOK)
+		goto error;
+	self->subtransforms = subtransforms;
+	self->num_subtransforms = 0;
+	for (self->num_subtransforms = 0;
+	    subtransforms[self->num_subtransforms].transform;
+	    self->num_subtransforms++);
+	*out = struct_as_transform(self);
+	return EOK;
+error:
+	free_subtransforms(subtransforms);
+	free(self);
+	return rc;
+}
+
+
+
+/***************** bithenge_repeat_transform                 *****************/
+
+/* TODO: ignore errors */
+
+typedef struct {
+	bithenge_transform_t base;
+	bithenge_expression_t *expr;
+	bithenge_transform_t *xform;
+} repeat_transform_t;
+
+static inline bithenge_transform_t *repeat_as_transform(
+    repeat_transform_t *self)
+{
+	return &self->base;
+}
+
+static inline repeat_transform_t *transform_as_repeat(
+    bithenge_transform_t *base)
+{
+	return (repeat_transform_t *)base;
+}
+
+typedef struct {
+	seq_node_t base;
+	bool prefix;
+	bithenge_int_t count;
+	bithenge_transform_t *xform;
+} repeat_node_t;
+
+static seq_node_t *repeat_as_seq(repeat_node_t *self)
+{
+	return &self->base;
+}
+
+static repeat_node_t *seq_as_repeat(seq_node_t *base)
+{
+	return (repeat_node_t *)base;
+}
+
+static bithenge_node_t *repeat_as_node(repeat_node_t *self)
+{
+	return seq_as_node(repeat_as_seq(self));
+}
+
+static repeat_node_t *node_as_repeat(bithenge_node_t *base)
+{
+	return seq_as_repeat(node_as_seq(base));
+}
+
+static int repeat_node_for_each(bithenge_node_t *base,
+    bithenge_for_each_func_t func, void *data)
+{
+	int rc = EOK;
+	repeat_node_t *self = node_as_repeat(base);
+
+	for (bithenge_int_t i = 0; self->count == -1 || i < self->count; i++) {
+		bithenge_node_t *subxform_result;
+		rc = seq_node_subtransform(repeat_as_seq(self),
+		    &subxform_result, i);
+		if ((rc == EINVAL || rc == ENOENT) && self->count == -1) {
+			self->count = i;
+			seq_node_set_num_xforms(repeat_as_seq(self),
+			    self->count);
+			rc = EOK;
+			break;
+		}
+		if (rc != EOK)
+			return rc;
+
+		bithenge_node_t *key_node;
+		rc = bithenge_new_integer_node(&key_node, i);
+		if (rc != EOK) {
+			bithenge_node_dec_ref(subxform_result);
+			return rc;
+		}
+		rc = func(key_node, subxform_result, data);
+		if (rc != EOK)
+			return rc;
+	}
+
+	if (!self->prefix) {
+		bool complete;
+		rc = seq_node_complete(repeat_as_seq(self), &complete);
+		if (rc != EOK)
+			return rc;
+		if (!complete)
+			return EINVAL;
+	}
+
+	return rc;
+}
+
+static int repeat_node_get(bithenge_node_t *base, bithenge_node_t *key,
+    bithenge_node_t **out)
+{
+	repeat_node_t *self = node_as_repeat(base);
+
+	if (bithenge_node_type(key) != BITHENGE_NODE_INTEGER) {
+		bithenge_node_dec_ref(key);
+		return ENOENT;
+	}
+
+	bithenge_int_t index = bithenge_integer_node_value(key);
+	bithenge_node_dec_ref(key);
+	if (index < 0 || (self->count != -1 && index >= self->count))
+		return ENOENT;
+	return seq_node_subtransform(repeat_as_seq(self), out, index);
+}
+
+static void repeat_node_destroy(bithenge_node_t *base)
+{
+	repeat_node_t *self = node_as_repeat(base);
+	seq_node_destroy(repeat_as_seq(self));
+	bithenge_transform_dec_ref(self->xform);
+	free(self);
+}
+
+static const bithenge_internal_node_ops_t repeat_node_ops = {
+	.for_each = repeat_node_for_each,
+	.get = repeat_node_get,
+	.destroy = repeat_node_destroy,
+};
+
+static int repeat_node_get_transform(seq_node_t *base,
+    bithenge_transform_t **out, bithenge_int_t index)
+{
+	repeat_node_t *self = seq_as_repeat(base);
+	*out = self->xform;
+	bithenge_transform_inc_ref(*out);
+	return EOK;
+}
+
+static const seq_node_ops_t repeat_node_seq_ops = {
+	.get_transform = repeat_node_get_transform,
+};
+
+static int repeat_transform_make_node(repeat_transform_t *self,
+    bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob,
+    bool prefix)
+{
+	bithenge_int_t count = -1;
+	if (self->expr != NULL) {
+		bithenge_node_t *count_node;
+		int rc = bithenge_expression_evaluate(self->expr, scope,
+		    &count_node);
+		if (rc != EOK)
+			return rc;
+		if (bithenge_node_type(count_node) != BITHENGE_NODE_INTEGER) {
+			bithenge_node_dec_ref(count_node);
+			return EINVAL;
+		}
+		count = bithenge_integer_node_value(count_node);
+		bithenge_node_dec_ref(count_node);
+		if (count < 0)
+			return EINVAL;
+	}
+
+	repeat_node_t *node = malloc(sizeof(*node));
+	if (!node)
+		return ENOMEM;
+
+	int rc = bithenge_init_internal_node(repeat_as_node(node),
+	    &repeat_node_ops);
+	if (rc != EOK) {
+		free(node);
+		return rc;
+	}
+
+	rc = seq_node_init(repeat_as_seq(node), &repeat_node_seq_ops, scope,
+	    blob, count, count == -1);
+	if (rc != EOK) {
+		free(node);
+		return rc;
+	}
+
+	bithenge_transform_inc_ref(self->xform);
+	node->xform = self->xform;
+	node->count = count;
+	node->prefix = prefix;
+	*out = repeat_as_node(node);
+	return EOK;
+}
+
+static int repeat_transform_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
+{
+	repeat_transform_t *self = transform_as_repeat(base);
+	if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
+		return EINVAL;
+	return repeat_transform_make_node(self, out, scope,
+	    bithenge_node_as_blob(in), false);
+}
+
+static int repeat_transform_prefix_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,
+    aoff64_t *out_size)
+{
+	repeat_transform_t *self = transform_as_repeat(base);
+	int rc = repeat_transform_make_node(self, out_node, scope, blob, true);
+	if (rc != EOK)
+		return rc;
+
+	if (out_size) {
+		bithenge_int_t count = node_as_repeat(*out_node)->count;
+		if (count != -1) {
+			rc = seq_node_field_offset(node_as_seq(*out_node),
+			    out_size, count);
+			if (rc != EOK) {
+				bithenge_node_dec_ref(*out_node);
+				return rc;
+			}
+		} else {
+			*out_size = 0;
+			for (count = 1; ; count++) {
+				aoff64_t size;
+				rc = seq_node_field_offset(
+				    node_as_seq(*out_node), &size, count);
+				if (rc == EINVAL || rc == ENOENT)
+					break;
+				if (rc != EOK) {
+					bithenge_node_dec_ref(*out_node);
+					return rc;
+				}
+				*out_size = size;
+			}
+		}
+	}
+	return EOK;
+}
+
+static void repeat_transform_destroy(bithenge_transform_t *base)
+{
+	repeat_transform_t *self = transform_as_repeat(base);
+	bithenge_transform_dec_ref(self->xform);
+	bithenge_expression_dec_ref(self->expr);
+	free(self);
+}
+
+static const bithenge_transform_ops_t repeat_transform_ops = {
+	.apply = repeat_transform_apply,
+	.prefix_apply = repeat_transform_prefix_apply,
+	.destroy = repeat_transform_destroy,
+};
+
+/** Create a transform that applies its subtransform repeatedly. Takes a
+ * reference to @a xform and @a expr.
+ * @param[out] out Holds the new transform.
+ * @param xform The subtransform to apply repeatedly.
+ * @param expr Used to calculate the number of times @a xform will be applied.
+ * May be NULL, in which case @a xform will be applied indefinitely.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_repeat_transform(bithenge_transform_t **out,
+    bithenge_transform_t *xform, bithenge_expression_t *expr)
+{
+	int rc;
+	repeat_transform_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_transform(repeat_as_transform(self),
+	    &repeat_transform_ops, 0);
+	if (rc != EOK)
+		goto error;
+
+	self->expr = expr;
+	self->xform = xform;
+	*out = repeat_as_transform(self);
+	return EOK;
+
+error:
+	free(self);
+	bithenge_expression_dec_ref(expr);
+	bithenge_transform_dec_ref(xform);
+	return rc;
+}
+
+
+
+/***************** bithenge_do_while_transform               *****************/
+
+typedef struct {
+	bithenge_transform_t base;
+	bithenge_expression_t *expr;
+	bithenge_transform_t *xform;
+} do_while_transform_t;
+
+static inline bithenge_transform_t *do_while_as_transform(
+    do_while_transform_t *self)
+{
+	return &self->base;
+}
+
+static inline do_while_transform_t *transform_as_do_while(
+    bithenge_transform_t *base)
+{
+	return (do_while_transform_t *)base;
+}
+
+typedef struct {
+	seq_node_t base;
+	bithenge_expression_t *expr;
+	bithenge_transform_t *xform;
+	bithenge_int_t count;
+} do_while_node_t;
+
+static seq_node_t *do_while_as_seq(do_while_node_t *self)
+{
+	return &self->base;
+}
+
+static do_while_node_t *seq_as_do_while(seq_node_t *base)
+{
+	return (do_while_node_t *)base;
+}
+
+static bithenge_node_t *do_while_as_node(do_while_node_t *self)
+{
+	return seq_as_node(do_while_as_seq(self));
+}
+
+static do_while_node_t *node_as_do_while(bithenge_node_t *base)
+{
+	return seq_as_do_while(node_as_seq(base));
+}
+
+static int do_while_node_for_each(bithenge_node_t *base,
+    bithenge_for_each_func_t func, void *data)
+{
+	int rc = EOK;
+	do_while_node_t *self = node_as_do_while(base);
+
+	for (bithenge_int_t i = 0; ; i++) {
+		bithenge_node_t *subxform_result;
+		rc = seq_node_subtransform(do_while_as_seq(self),
+		    &subxform_result, i);
+		if (rc != EOK)
+			return rc;
+
+		bithenge_node_t *key_node;
+		rc = bithenge_new_integer_node(&key_node, i);
+		if (rc != EOK) {
+			bithenge_node_dec_ref(subxform_result);
+			return rc;
+		}
+		bithenge_node_inc_ref(subxform_result);
+		rc = func(key_node, subxform_result, data);
+		if (rc != EOK) {
+			bithenge_node_dec_ref(subxform_result);
+			return rc;
+		}
+
+		bithenge_scope_t *scope;
+		rc = bithenge_scope_new(&scope,
+		    seq_node_scope(do_while_as_seq(self)));
+		if (rc != EOK) {
+			bithenge_node_dec_ref(subxform_result);
+			return rc;
+		}
+		bithenge_scope_set_current_node(scope, subxform_result);
+		bithenge_node_t *expr_result;
+		rc = bithenge_expression_evaluate(self->expr, scope,
+		    &expr_result);
+		bithenge_scope_dec_ref(scope);
+		if (rc != EOK)
+			return rc;
+		if (bithenge_node_type(expr_result) != BITHENGE_NODE_BOOLEAN) {
+			bithenge_node_dec_ref(expr_result);
+			return EINVAL;
+		}
+		bool cond = bithenge_boolean_node_value(expr_result);
+		bithenge_node_dec_ref(expr_result);
+		if (!cond) {
+			self->count = i + 1;
+			seq_node_set_num_xforms(do_while_as_seq(self),
+			    self->count);
+			break;
+		}
+	}
+
+	return rc;
+}
+
+static void do_while_node_destroy(bithenge_node_t *base)
+{
+	do_while_node_t *self = node_as_do_while(base);
+	seq_node_destroy(do_while_as_seq(self));
+	bithenge_expression_dec_ref(self->expr);
+	bithenge_transform_dec_ref(self->xform);
+	free(self);
+}
+
+static const bithenge_internal_node_ops_t do_while_node_ops = {
+	.for_each = do_while_node_for_each,
+	.destroy = do_while_node_destroy,
+};
+
+static int do_while_node_get_transform(seq_node_t *base,
+    bithenge_transform_t **out, bithenge_int_t index)
+{
+	do_while_node_t *self = seq_as_do_while(base);
+	*out = self->xform;
+	bithenge_transform_inc_ref(*out);
+	return EOK;
+}
+
+static const seq_node_ops_t do_while_node_seq_ops = {
+	.get_transform = do_while_node_get_transform,
+};
+
+static int do_while_transform_make_node(do_while_transform_t *self,
+    bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob)
+{
+	do_while_node_t *node = malloc(sizeof(*node));
+	if (!node)
+		return ENOMEM;
+
+	int rc = bithenge_init_internal_node(do_while_as_node(node),
+	    &do_while_node_ops);
+	if (rc != EOK) {
+		free(node);
+		return rc;
+	}
+
+	rc = seq_node_init(do_while_as_seq(node), &do_while_node_seq_ops,
+	    scope, blob, -1, false);
+	if (rc != EOK) {
+		free(node);
+		return rc;
+	}
+
+	bithenge_transform_inc_ref(self->xform);
+	node->xform = self->xform;
+	bithenge_expression_inc_ref(self->expr);
+	node->expr = self->expr;
+	node->count = -1;
+	*out = do_while_as_node(node);
+	return EOK;
+}
+
+static int for_each_noop(bithenge_node_t *key, bithenge_node_t *value,
+    void *data)
+{
+	bithenge_node_dec_ref(key);
+	bithenge_node_dec_ref(value);
+	return EOK;
+}
+
+static int do_while_transform_prefix_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,
+    aoff64_t *out_size)
+{
+	do_while_transform_t *self = transform_as_do_while(base);
+	int rc = do_while_transform_make_node(self, out_node, scope, blob);
+	if (rc != EOK)
+		return rc;
+
+	if (out_size) {
+		rc = bithenge_node_for_each(*out_node, for_each_noop, NULL);
+		if (rc != EOK) {
+			bithenge_node_dec_ref(*out_node);
+			return rc;
+		}
+
+		rc = seq_node_field_offset(node_as_seq(*out_node), out_size,
+		    node_as_do_while(*out_node)->count);
+		if (rc != EOK) {
+			bithenge_node_dec_ref(*out_node);
+			return rc;
+		}
+	}
+
+	return EOK;
+}
+
+static void do_while_transform_destroy(bithenge_transform_t *base)
+{
+	do_while_transform_t *self = transform_as_do_while(base);
+	bithenge_transform_dec_ref(self->xform);
+	bithenge_expression_dec_ref(self->expr);
+	free(self);
+}
+
+static const bithenge_transform_ops_t do_while_transform_ops = {
+	.prefix_apply = do_while_transform_prefix_apply,
+	.destroy = do_while_transform_destroy,
+};
+
+/** Create a transform that applies its subtransform while an expression on the
+ * result returns true. Takes a reference to @a xform and @a expr.
+ * @param[out] out Holds the new transform.
+ * @param xform The subtransform to apply repeatedly.
+ * @param expr Applied in the result of each application of @a xform to
+ * determine whether there will be more.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_do_while_transform(bithenge_transform_t **out,
+    bithenge_transform_t *xform, bithenge_expression_t *expr)
+{
+	int rc;
+	do_while_transform_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = bithenge_init_transform(do_while_as_transform(self),
+	    &do_while_transform_ops, 0);
+	if (rc != EOK)
+		goto error;
+
+	self->expr = expr;
+	self->xform = xform;
+	*out = do_while_as_transform(self);
+	return EOK;
+
+error:
+	free(self);
+	bithenge_expression_dec_ref(expr);
+	bithenge_transform_dec_ref(xform);
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/bithenge/src/source.c
===================================================================
--- uspace/lib/bithenge/src/source.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/source.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Provide various external sources of data.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <bithenge/blob.h>
+#include <bithenge/file.h>
+#include <bithenge/source.h>
+#include "common.h"
+
+#ifdef __HELENOS__
+#include <loc.h>
+#include "helenos/block.h"
+#endif
+
+static inline int hex_digit(char digit)
+{
+	if ('0' <= digit && digit <= '9')
+		return digit - '0' + 0x0;
+	if ('a' <= digit && digit <= 'f')
+		return digit - 'a' + 0xa;
+	if ('A' <= digit && digit <= 'F')
+		return digit - 'A' + 0xA;
+	return -1;
+}
+
+static int blob_from_hex(bithenge_node_t **out, const char *hex)
+{
+	size_t size = str_length(hex);
+	if (size % 2)
+		return EINVAL;
+	size /= 2;
+	char *buffer = malloc(size);
+	if (!buffer)
+		return ENOMEM;
+	for (size_t i = 0; i < size; i++) {
+		int upper = hex_digit(hex[2 * i + 0]);
+		int lower = hex_digit(hex[2 * i + 1]);
+		if (upper == -1 || lower == -1) {
+			free(buffer);
+			return EINVAL;
+		}
+		buffer[i] = upper << 4 | lower;
+	}
+	return bithenge_new_blob_from_buffer(out, buffer, size, true);
+}
+
+/** Create a node from a source described with a string. For instance,
+ * "hex:55aa" will result in a blob node. If there is no colon in the string,
+ * it is assumed to be a filename.
+ * @param[out] out Stores the created node.
+ * @param source Specifies the node to be created.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_node_from_source(bithenge_node_t **out, const char *source)
+{
+	if (str_chr(source, ':')) {
+		if (!str_lcmp(source, "file:", 5)) {
+			// Example: file:/textdemo
+			return bithenge_new_file_blob(out, source + 5);
+#ifdef __HELENOS__
+		} else if (!str_lcmp(source, "block:", 6)) {
+			// Example: block:bd/initrd
+			service_id_t service_id;
+			int rc = loc_service_get_id(source + 6, &service_id, 0);
+			if (rc != EOK)
+				return rc;
+			return bithenge_new_block_blob(out, service_id);
+#endif
+		} else if (!str_lcmp(source, "hex:", 4)) {
+			// Example: hex:04000000
+			return blob_from_hex(out, source + 4);
+		} else {
+			return EINVAL;
+		}
+	}
+	return bithenge_new_file_blob(out, source);
+}
+
+/** @}
+ */
Index: uspace/lib/bithenge/src/transform.c
===================================================================
--- uspace/lib/bithenge/src/transform.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/transform.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1078 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Transforms.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <bithenge/blob.h>
+#include <bithenge/print.h>
+#include <bithenge/transform.h>
+#include "common.h"
+
+
+
+/***************** transform                                 *****************/
+
+/** Initialize a new transform.
+ * @param[out] self Transform to initialize.
+ * @param[in] ops Operations provided by the transform.
+ * @param num_params The number of parameters required. If this is nonzero, the
+ * transform will get its own context with parameters, probably provided by a
+ * param_wrapper. If this is zero, the existing outer context will be used with
+ * whatever parameters it has, so they can be passed to any param_wrappers
+ * within.
+ * @return EOK or an error code from errno.h. */
+int bithenge_init_transform(bithenge_transform_t *self,
+    const bithenge_transform_ops_t *ops, int num_params)
+{
+	assert(ops);
+	assert(ops->apply || ops->prefix_apply);
+	assert(ops->destroy);
+	if (bithenge_should_fail())
+		return ENOMEM;
+	self->ops = ops;
+	self->refs = 1;
+	self->num_params = num_params;
+	return EOK;
+}
+
+static void transform_indestructible(bithenge_transform_t *self)
+{
+	assert(false);
+}
+
+/** Apply a transform. Takes ownership of nothing.
+ * @memberof bithenge_transform_t
+ * @param self The transform.
+ * @param scope The scope.
+ * @param in The input tree.
+ * @param[out] out Where the output tree will be stored.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_transform_apply(bithenge_transform_t *self,
+    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
+{
+	assert(self);
+	assert(self->ops);
+	if (self->ops->apply)
+		return self->ops->apply(self, scope, in, out);
+
+	if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
+		return EINVAL;
+	aoff64_t self_size, whole_size;
+	int rc = bithenge_transform_prefix_apply(self, scope,
+	    bithenge_node_as_blob(in), out, &self_size);
+	if (rc != EOK)
+		return rc;
+	rc = bithenge_blob_size(bithenge_node_as_blob(in), &whole_size);
+	if (rc == EOK && whole_size != self_size)
+		rc = EINVAL;
+	if (rc != EOK) {
+		bithenge_node_dec_ref(*out);
+		return rc;
+	}
+	return EOK;
+}
+
+/** Find the length of the prefix of a blob this transform can use as input. In
+ * other words, figure out how many bytes this transform will use up.  This
+ * method is optional and can return an error, but it must succeed for struct
+ * subtransforms. Takes ownership of nothing.
+ * @memberof bithenge_transform_t
+ * @param self The transform.
+ * @param scope The scope.
+ * @param blob The blob.
+ * @param[out] out Where the prefix length will be stored.
+ * @return EOK on success, ENOTSUP if not supported, or another error code from
+ * errno.h. */
+int bithenge_transform_prefix_length(bithenge_transform_t *self,
+    bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out)
+{
+	assert(self);
+	assert(self->ops);
+	if (self->ops->prefix_length)
+		return self->ops->prefix_length(self, scope, blob, out);
+	if (!self->ops->prefix_apply)
+		return ENOTSUP;
+
+	bithenge_node_t *node;
+	int rc = bithenge_transform_prefix_apply(self, scope, blob, &node,
+	    out);
+	if (rc != EOK)
+		return rc;
+	bithenge_node_dec_ref(node);
+	return EOK;
+}
+
+/** Apply this transform to a prefix of a blob. In other words, feed as much of
+ * the blob into this transform as possible. Takes ownership of nothing.
+ * @memberof bithenge_transform_t
+ * @param self The transform.
+ * @param scope The scope.
+ * @param blob The blob.
+ * @param[out] out_node Holds the result of applying this transform to the
+ * prefix.
+ * @param[out] out_size Holds the size of the prefix. Can be null, in which
+ * case the size is not determined.
+ * @return EOK on success, ENOTSUP if not supported, or another error code from
+ * errno.h. */
+int bithenge_transform_prefix_apply(bithenge_transform_t *self,
+    bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,
+    aoff64_t *out_size)
+{
+	assert(self);
+	assert(self->ops);
+	if (self->ops->prefix_apply)
+		return self->ops->prefix_apply(self, scope, blob, out_node,
+		    out_size);
+	if (!self->ops->prefix_length)
+		return ENOTSUP;
+
+	aoff64_t size;
+	int rc = bithenge_transform_prefix_length(self, scope, blob, &size);
+	if (rc != EOK)
+		return rc;
+	bithenge_node_t *prefix_blob;
+	bithenge_blob_inc_ref(blob);
+	rc = bithenge_new_subblob(&prefix_blob, blob, 0, size);
+	if (rc != EOK)
+		return rc;
+	rc = bithenge_transform_apply(self, scope, prefix_blob, out_node);
+	bithenge_node_dec_ref(prefix_blob);
+	if (out_size)
+		*out_size = size;
+	return rc;
+}
+
+
+
+/***************** scope                                     *****************/
+
+/** Create a transform scope. It must be dereferenced with @a
+ * bithenge_scope_dec_ref after it is used. Takes ownership of nothing.
+ * @memberof bithenge_scope_t
+ * @param[out] out Holds the new scope.
+ * @param outer The outer scope, or NULL.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_scope_new(bithenge_scope_t **out, bithenge_scope_t *outer)
+{
+	bithenge_scope_t *self = malloc(sizeof(*self));
+	if (!self)
+		return ENOMEM;
+	self->refs = 1;
+	if (outer)
+		bithenge_scope_inc_ref(outer);
+	self->outer = outer;
+	self->error = NULL;
+	self->barrier = false;
+	self->num_params = 0;
+	self->params = NULL;
+	self->current_node = NULL;
+	self->in_node = NULL;
+	*out = self;
+	return EOK;
+}
+
+/** Dereference a transform scope.
+ * @memberof bithenge_scope_t
+ * @param self The scope to dereference, or NULL. */
+void bithenge_scope_dec_ref(bithenge_scope_t *self)
+{
+	if (!self)
+		return;
+	if (--self->refs)
+		return;
+	bithenge_node_dec_ref(self->current_node);
+	for (int i = 0; i < self->num_params; i++)
+		bithenge_node_dec_ref(self->params[i]);
+	bithenge_scope_dec_ref(self->outer);
+	free(self->params);
+	free(self->error);
+	free(self);
+}
+
+/** Get the outer scope of a scope, which may be NULL.
+ * @memberof bithenge_scope_t
+ * @param self The scope to examine.
+ * @return The outer scope, which may be NULL. */
+bithenge_scope_t *bithenge_scope_outer(bithenge_scope_t *self)
+{
+	return self->outer;
+}
+
+/** Get the error message stored in the scope, which may be NULL. The error
+ * message only exists as long as the scope does.
+ * @memberof bithenge_scope_t
+ * @param scope The scope to get the error message from.
+ * @return The error message, or NULL. */
+const char *bithenge_scope_get_error(bithenge_scope_t *scope)
+{
+	return scope->error;
+}
+
+/** Set the error message for the scope. The error message is stored in the
+ * outermost scope, but if any scope already has an error message this error
+ * message is ignored.
+ * @memberof bithenge_scope_t
+ * @param scope The scope.
+ * @param format The format string.
+ * @return EINVAL normally, or another error code from errno.h. */
+int bithenge_scope_error(bithenge_scope_t *scope, const char *format, ...)
+{
+	if (scope->error)
+		return EINVAL;
+	while (scope->outer) {
+		scope = scope->outer;
+		if (scope->error)
+			return EINVAL;
+	}
+	size_t space_left = 256;
+	scope->error = malloc(space_left);
+	if (!scope->error)
+		return ENOMEM;
+	char *out = scope->error;
+	va_list ap;
+	va_start(ap, format);
+
+	while (*format) {
+		if (format[0] == '%' && format[1] == 't') {
+			format += 2;
+			int rc = bithenge_print_node_to_string(&out,
+			    &space_left, BITHENGE_PRINT_PYTHON,
+			    va_arg(ap, bithenge_node_t *));
+			if (rc != EOK) {
+				va_end(ap);
+				return rc;
+			}
+		} else {
+			const char *end = str_chr(format, '%');
+			if (!end)
+				end = format + str_length(format);
+			size_t size = min((size_t)(end - format),
+			    space_left - 1);
+			memcpy(out, format, size);
+			format = end;
+			out += size;
+			space_left -= size;
+		}
+	}
+	*out = '\0';
+
+	va_end(ap);
+	return EINVAL;
+}
+
+/** Get the current node being created, which may be NULL.
+ * @memberof bithenge_scope_t
+ * @param scope The scope to get the current node from.
+ * @return The node being created, or NULL. */
+bithenge_node_t *bithenge_scope_get_current_node(bithenge_scope_t *scope)
+{
+	if (scope->current_node)
+		bithenge_node_inc_ref(scope->current_node);
+	return scope->current_node;
+}
+
+/** Set the current node being created. Takes a reference to @a node.
+ * @memberof bithenge_scope_t
+ * @param scope The scope to set the current node in.
+ * @param node The current node being created, or NULL. */
+void bithenge_scope_set_current_node(bithenge_scope_t *scope,
+    bithenge_node_t *node)
+{
+	bithenge_node_dec_ref(scope->current_node);
+	scope->current_node = node;
+}
+
+/** Get the current input node, which may be NULL.
+ * @memberof bithenge_scope_t
+ * @param scope The scope to get the current input node from.
+ * @return The input node, or NULL. */
+bithenge_node_t *bithenge_scope_in_node(bithenge_scope_t *scope)
+{
+	if (scope->in_node)
+		bithenge_node_inc_ref(scope->in_node);
+	return scope->in_node;
+}
+
+/** Set the current input node. Takes a reference to @a node.
+ * @memberof bithenge_scope_t
+ * @param scope The scope to set the input node in.
+ * @param node The input node, or NULL. */
+void bithenge_scope_set_in_node(bithenge_scope_t *scope, bithenge_node_t *node)
+{
+	bithenge_node_dec_ref(scope->in_node);
+	scope->in_node = node;
+}
+
+/** Set a scope as a barrier.
+ * @memberof bithenge_scope_t
+ * @param self The scope to change. */
+void bithenge_scope_set_barrier(bithenge_scope_t *self)
+{
+	self->barrier = true;
+}
+
+/** Check whether a scope is a barrier, meaning that variable lookup stops at
+ * it.
+ * @memberof bithenge_scope_t
+ * @param self The scope to check.
+ * @return Whether the scope is a barrier. */
+bool bithenge_scope_is_barrier(bithenge_scope_t *self)
+{
+	return self->barrier;
+}
+
+/** Allocate parameters. The parameters must then be set with @a
+ * bithenge_scope_set_param. This must not be called on a scope that already
+ * has parameters.
+ * @memberof bithenge_scope_t
+ * @param scope The scope in which to allocate parameters.
+ * @param num_params The number of parameters to allocate.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_scope_alloc_params(bithenge_scope_t *scope, int num_params)
+{
+	scope->params = malloc(sizeof(*scope->params) * num_params);
+	if (!scope->params)
+		return ENOMEM;
+	scope->num_params = num_params;
+	for (int i = 0; i < num_params; i++)
+		scope->params[i] = NULL;
+	return EOK;
+}
+
+/** Set a parameter. Takes a reference to @a node. Note that range checking is
+ * not done in release builds.
+ * @memberof bithenge_scope_t
+ * @param scope The scope in which to allocate parameters.
+ * @param i The index of the parameter to set.
+ * @param node The value to store in the parameter.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_scope_set_param( bithenge_scope_t *scope, int i,
+    bithenge_node_t *node)
+{
+	assert(scope);
+	assert(i >= 0 && i < scope->num_params);
+	if (bithenge_should_fail()) {
+		bithenge_node_dec_ref(node);
+		return ENOMEM;
+	}
+	scope->params[i] = node;
+	return EOK;
+}
+
+/** Get a parameter. Note that range checking is not done in release builds.
+ * @memberof bithenge_scope_t
+ * @param scope The scope to get the parameter from.
+ * @param i The index of the parameter to set.
+ * @param[out] out Stores a new reference to the parameter.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_scope_get_param(bithenge_scope_t *scope, int i,
+    bithenge_node_t **out)
+{
+	assert(scope);
+	if (scope->num_params) {
+		assert(i >= 0 && i < scope->num_params);
+		*out = scope->params[i];
+		bithenge_node_inc_ref(*out);
+		return EOK;
+	} else {
+		return bithenge_scope_get_param(scope->outer, i, out);
+	}
+}
+
+
+
+/***************** barrier_transform                         *****************/
+
+typedef struct {
+	bithenge_transform_t base;
+	bithenge_transform_t *transform;
+} barrier_transform_t;
+
+static inline barrier_transform_t *transform_as_barrier(
+    bithenge_transform_t *base)
+{
+	return (barrier_transform_t *)base;
+}
+
+static inline bithenge_transform_t *barrier_as_transform(
+    barrier_transform_t *self)
+{
+	return &self->base;
+}
+
+static int barrier_transform_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
+{
+	barrier_transform_t *self = transform_as_barrier(base);
+	bithenge_scope_t *inner_scope;
+	int rc = bithenge_scope_new(&inner_scope, scope);
+	if (rc != EOK)
+		return rc;
+	bithenge_scope_set_barrier(inner_scope);
+	bithenge_scope_set_in_node(inner_scope, in);
+	rc = bithenge_transform_apply(self->transform, inner_scope, in, out);
+	bithenge_scope_dec_ref(inner_scope);
+	return rc;
+}
+
+static int barrier_transform_prefix_length(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
+{
+	barrier_transform_t *self = transform_as_barrier(base);
+	bithenge_scope_t *inner_scope;
+	int rc = bithenge_scope_new(&inner_scope, scope);
+	if (rc != EOK)
+		return rc;
+	bithenge_scope_set_barrier(inner_scope);
+	bithenge_scope_set_in_node(inner_scope, bithenge_blob_as_node(in));
+	rc = bithenge_transform_prefix_length(self->transform, inner_scope, in,
+	    out);
+	bithenge_scope_dec_ref(inner_scope);
+	return rc;
+}
+
+static int barrier_transform_prefix_apply(bithenge_transform_t *base,
+    bithenge_scope_t *scope, bithenge_blob_t *in, bithenge_node_t **out_node,
+    aoff64_t *out_length)
+{
+	barrier_transform_t *self = transform_as_barrier(base);
+	bithenge_scope_t *inner_scope;
+	int rc = bithenge_scope_new(&inner_scope, scope);
+	if (rc != EOK)
+		return rc;
+	bithenge_scope_set_barrier(inner_scope);
+	bithenge_scope_set_in_node(inner_scope, bithenge_blob_as_node(in));
+	rc = bithenge_transform_prefix_apply(self->transform, inner_scope, in,
+	    out_node, out_length);
+	bithenge_scope_dec_ref(inner_scope);
+	return rc;
+}
+
+static void barrier_transform_destroy(bithenge_transform_t *base)
+{
+	barrier_transform_t *self = transform_as_barrier(base);
+	bithenge_transform_dec_ref(self->transform);
+	free(self);
+}
+
+static const bithenge_transform_ops_t barrier_transform_ops = {
+	.apply = barrier_transform_apply,
+	.prefix_length = barrier_transform_prefix_length,
+	.prefix_apply = barrier_transform_prefix_apply,
+	.destroy = barrier_transform_destroy,
+};
+
+/** Set the subtransform of a barrier transform. This must be done before the
+ * barrier transform is used. Takes a reference to @a transform.
+ * @param base The barrier transform.
+ * @param transform The subtransform to use for all operations.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_barrier_transform_set_subtransform(bithenge_transform_t *base,
+    bithenge_transform_t *transform)
+{
+	assert(transform);
+	assert(bithenge_transform_num_params(transform) == 0);
+
+	if (bithenge_should_fail()) {
+		bithenge_transform_dec_ref(transform);
+		return ENOMEM;
+	}
+
+	barrier_transform_t *self = transform_as_barrier(base);
+	assert(!self->transform);
+	self->transform = transform;
+	return EOK;
+}
+
+/** Create a wrapper transform that creates a new scope. This ensures nothing
+ * from the outer scope is passed in, other than parameters. The wrapper may
+ * have a different value for num_params. The subtransform must be set with @a
+ * bithenge_barrier_transform_set_subtransform before the result is used.
+ * @param[out] out Holds the created transform.
+ * @param num_params The number of parameters to require, which may be 0.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_barrier_transform(bithenge_transform_t **out, int num_params)
+{
+	int rc;
+	barrier_transform_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+	rc = bithenge_init_transform(barrier_as_transform(self),
+	    &barrier_transform_ops, num_params);
+	if (rc != EOK)
+		goto error;
+	self->transform = NULL;
+	*out = barrier_as_transform(self);
+	return EOK;
+error:
+	free(self);
+	return rc;
+}
+
+
+
+/***************** ascii                                     *****************/
+
+static int ascii_apply(bithenge_transform_t *self, bithenge_scope_t *scope,
+    bithenge_node_t *in, bithenge_node_t **out)
+{
+	int rc;
+	if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
+		return EINVAL;
+	bithenge_blob_t *blob = bithenge_node_as_blob(in);
+	aoff64_t size;
+	rc = bithenge_blob_size(blob, &size);
+	if (rc != EOK)
+		return rc;
+
+	char *buffer = malloc(size + 1);
+	if (!buffer)
+		return ENOMEM;
+	aoff64_t size_read = size;
+	rc = bithenge_blob_read(blob, 0, buffer, &size_read);
+	if (rc != EOK) {
+		free(buffer);
+		return rc;
+	}
+	if (size_read != size) {
+		free(buffer);
+		return EINVAL;
+	}
+	buffer[size] = '\0';
+
+	/* TODO: what if the OS encoding is incompatible with ASCII? */
+	return bithenge_new_string_node(out, buffer, true);
+}
+
+static const bithenge_transform_ops_t ascii_ops = {
+	.apply = ascii_apply,
+	.destroy = transform_indestructible,
+};
+
+/** The ASCII text transform. */
+bithenge_transform_t bithenge_ascii_transform = {
+	&ascii_ops, 1, 0
+};
+
+
+
+/***************** bit                                       *****************/
+
+static int bit_prefix_apply(bithenge_transform_t *self,
+    bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,
+    aoff64_t *out_size)
+{
+	char buffer;
+	aoff64_t size = 1;
+	int rc = bithenge_blob_read_bits(blob, 0, &buffer, &size, true);
+	if (rc != EOK)
+		return rc;
+	if (size != 1)
+		return EINVAL;
+	if (out_size)
+		*out_size = size;
+	return bithenge_new_boolean_node(out_node, (buffer & 1) != 0);
+}
+
+static const bithenge_transform_ops_t bit_ops = {
+	.prefix_apply = bit_prefix_apply,
+	.destroy = transform_indestructible,
+};
+
+/** A transform that decodes a bit as a boolean. */
+bithenge_transform_t bithenge_bit_transform = {
+	&bit_ops, 1, 0
+};
+
+
+
+/***************** bits_be, bits_le                          *****************/
+
+typedef struct {
+	bithenge_blob_t base;
+	bithenge_blob_t *bytes;
+	bool little_endian;
+} bits_xe_blob_t;
+
+static bits_xe_blob_t *blob_as_bits_xe(bithenge_blob_t *base)
+{
+	return (bits_xe_blob_t *)base;
+}
+
+static bithenge_blob_t *bits_xe_as_blob(bits_xe_blob_t *self)
+{
+	return &self->base;
+}
+
+static int bits_xe_size(bithenge_blob_t *base, aoff64_t *out)
+{
+	bits_xe_blob_t *self = blob_as_bits_xe(base);
+	int rc = bithenge_blob_size(self->bytes, out);
+	*out *= 8;
+	return rc;
+}
+
+static uint8_t reverse_byte(uint8_t val)
+{
+	val = ((val & 0x0f) << 4) ^ ((val & 0xf0) >> 4);
+	val = ((val & 0x33) << 2) ^ ((val & 0xcc) >> 2);
+	val = ((val & 0x55) << 1) ^ ((val & 0xaa) >> 1);
+	return val;
+}
+
+static int bits_xe_read_bits(bithenge_blob_t *base, aoff64_t offset,
+    char *buffer, aoff64_t *size, bool little_endian)
+{
+	bits_xe_blob_t *self = blob_as_bits_xe(base);
+	aoff64_t bytes_offset = offset / 8;
+	aoff64_t bit_offset = offset % 8;
+	aoff64_t output_num_bytes = (*size + 7) / 8;
+	aoff64_t bytes_size = (*size + bit_offset + 7) / 8;
+	bool separate_buffer = bit_offset != 0;
+	uint8_t *bytes_buffer;
+	if (separate_buffer) {
+		/* Allocate an extra byte, to make sure byte1 can be read. */
+		bytes_buffer = malloc(bytes_size + 1);
+		if (!bytes_buffer)
+			return ENOMEM;
+	} else
+		bytes_buffer = (uint8_t *)buffer;
+
+	int rc = bithenge_blob_read(self->bytes, bytes_offset,
+	    (char *)bytes_buffer, &bytes_size);
+	if (rc != EOK)
+		goto end;
+	*size = min(*size, bytes_size * 8 - bit_offset);
+
+	if (little_endian != self->little_endian)
+		for (aoff64_t i = 0; i < bytes_size; i++)
+			bytes_buffer[i] = reverse_byte(bytes_buffer[i]);
+
+	if (bit_offset || separate_buffer) {
+		for (aoff64_t i = 0; i < output_num_bytes; i++) {
+			uint8_t byte0 = bytes_buffer[i];
+			uint8_t	byte1 = bytes_buffer[i + 1];
+			buffer[i] = little_endian ?
+			    (byte0 >> bit_offset) ^ (byte1 << (8 - bit_offset)) :
+			    (byte0 << bit_offset) ^ (byte1 >> (8 - bit_offset));
+		}
+	}
+
+end:
+	if (separate_buffer)
+		free(bytes_buffer);
+	return rc;
+}
+
+static void bits_xe_destroy(bithenge_blob_t *base)
+{
+	bits_xe_blob_t *self = blob_as_bits_xe(base);
+	bithenge_blob_dec_ref(self->bytes);
+	free(self);
+}
+
+static const bithenge_random_access_blob_ops_t bits_xe_blob_ops = {
+	.size = bits_xe_size,
+	.read_bits = bits_xe_read_bits,
+	.destroy = bits_xe_destroy,
+};
+
+static int bits_xe_apply(bithenge_transform_t *self, bithenge_scope_t *scope,
+    bithenge_node_t *in, bithenge_node_t **out)
+{
+	if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
+		return EINVAL;
+	bits_xe_blob_t *blob = malloc(sizeof(*blob));
+	if (!blob)
+		return ENOMEM;
+	int rc = bithenge_init_random_access_blob(bits_xe_as_blob(blob),
+	    &bits_xe_blob_ops);
+	if (rc != EOK) {
+		free(blob);
+		return rc;
+	}
+	bithenge_node_inc_ref(in);
+	blob->bytes = bithenge_node_as_blob(in);
+	blob->little_endian = (self == &bithenge_bits_le_transform);
+	*out = bithenge_blob_as_node(bits_xe_as_blob(blob));
+	return EOK;
+}
+
+static const bithenge_transform_ops_t bits_xe_ops = {
+	.apply = bits_xe_apply,
+	.destroy = transform_indestructible,
+};
+
+/** A transform that converts a byte blob to a bit blob, most-significant bit
+ * first. */
+bithenge_transform_t bithenge_bits_be_transform = {
+	&bits_xe_ops, 1, 0
+};
+
+/** A transform that converts a byte blob to a bit blob, least-significant bit
+ * first. */
+bithenge_transform_t bithenge_bits_le_transform = {
+	&bits_xe_ops, 1, 0
+};
+
+
+
+/***************** invalid                                   *****************/
+
+static int invalid_apply(bithenge_transform_t *self, bithenge_scope_t *scope,
+    bithenge_node_t *in, bithenge_node_t **out)
+{
+	return EINVAL;
+}
+
+static const bithenge_transform_ops_t invalid_ops = {
+	.apply = invalid_apply,
+	.destroy = transform_indestructible,
+};
+
+/** A transform that always raises an error. */
+bithenge_transform_t bithenge_invalid_transform = {
+	&invalid_ops, 1, 0
+};
+
+
+
+/***************** known_length                              *****************/
+
+static int known_length_apply(bithenge_transform_t *self,
+    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
+{
+	bithenge_node_t *length_node;
+	int rc = bithenge_scope_get_param(scope, 0, &length_node);
+	if (rc != EOK)
+		return rc;
+	if (bithenge_node_type(length_node) != BITHENGE_NODE_INTEGER) {
+		bithenge_node_dec_ref(length_node);
+		return EINVAL;
+	}
+	bithenge_int_t length = bithenge_integer_node_value(length_node);
+	bithenge_node_dec_ref(length_node);
+
+	if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
+		return EINVAL;
+	aoff64_t size;
+	rc = bithenge_blob_size(bithenge_node_as_blob(in), &size);
+	if (rc != EOK)
+		return rc;
+	if (length != (bithenge_int_t)size)
+		return EINVAL;
+
+	bithenge_node_inc_ref(in);
+	*out = in;
+	return EOK;
+}
+
+static int known_length_prefix_length(bithenge_transform_t *self,
+    bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
+{
+	bithenge_node_t *length_node;
+	int rc = bithenge_scope_get_param(scope, 0, &length_node);
+	if (rc != EOK)
+		return rc;
+	if (bithenge_node_type(length_node) != BITHENGE_NODE_INTEGER) {
+		bithenge_node_dec_ref(length_node);
+		return EINVAL;
+	}
+	bithenge_int_t length = bithenge_integer_node_value(length_node);
+	bithenge_node_dec_ref(length_node);
+
+	*out = (aoff64_t)length;
+	return EOK;
+}
+
+static const bithenge_transform_ops_t known_length_ops = {
+	.apply = known_length_apply,
+	.prefix_length = known_length_prefix_length,
+	.destroy = transform_indestructible,
+};
+
+/** Pass through a blob, but require its length to equal the first argument. */
+bithenge_transform_t bithenge_known_length_transform = {
+	&known_length_ops, 1, 1
+};
+
+static int nonzero_boolean_apply(bithenge_transform_t *self,
+    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
+{
+	if (bithenge_node_type(in) != BITHENGE_NODE_INTEGER)
+		return EINVAL;
+	bool value = bithenge_integer_node_value(in) != 0;
+	return bithenge_new_boolean_node(out, value);
+}
+
+static const bithenge_transform_ops_t nonzero_boolean_ops = {
+	.apply = nonzero_boolean_apply,
+	.destroy = transform_indestructible,
+};
+
+/** A transform that converts integers to booleans, true if nonzero. */
+bithenge_transform_t bithenge_nonzero_boolean_transform = {
+	&nonzero_boolean_ops, 1, 0
+};
+
+static int prefix_length_1(bithenge_transform_t *self, bithenge_scope_t *scope,
+    bithenge_blob_t *blob, aoff64_t *out)
+{
+	*out = 1;
+	return EOK;
+}
+
+static int prefix_length_2(bithenge_transform_t *self, bithenge_scope_t *scope,
+    bithenge_blob_t *blob, aoff64_t *out)
+{
+	*out = 2;
+	return EOK;
+}
+
+static int prefix_length_4(bithenge_transform_t *self, bithenge_scope_t *scope,
+    bithenge_blob_t *blob, aoff64_t *out)
+{
+	*out = 4;
+	return EOK;
+}
+
+static int prefix_length_8(bithenge_transform_t *self, bithenge_scope_t *scope,
+    bithenge_blob_t *blob, aoff64_t *out)
+{
+	*out = 8;
+	return EOK;
+}
+
+/** @cond internal */
+#define MAKE_UINT_TRANSFORM(NAME, TYPE, ENDIAN, PREFIX_LENGTH_FUNC)            \
+	static int NAME##_apply(bithenge_transform_t *self,                    \
+	    bithenge_scope_t *scope, bithenge_node_t *in,                      \
+	    bithenge_node_t **out)                                             \
+	{                                                                      \
+		int rc;                                                        \
+		if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)              \
+			return EINVAL;                                         \
+		bithenge_blob_t *blob = bithenge_node_as_blob(in);             \
+		                                                               \
+		/* Read too many bytes; success means the blob is too long. */ \
+		TYPE val[2];                                                   \
+		aoff64_t size = sizeof(val[0]) + 1;                            \
+		rc = bithenge_blob_read(blob, 0, (char *)val, &size);          \
+		if (rc != EOK)                                                 \
+			return rc;                                             \
+		if (size != sizeof(val[0]))                                    \
+			return EINVAL;                                         \
+		                                                               \
+		return bithenge_new_integer_node(out, ENDIAN(val[0]));         \
+	}                                                                      \
+	                                                                       \
+	static const bithenge_transform_ops_t NAME##_ops = {                   \
+		.apply = NAME##_apply,                                         \
+		.prefix_length = PREFIX_LENGTH_FUNC,                           \
+		.destroy = transform_indestructible,                           \
+	};                                                                     \
+	                                                                       \
+	bithenge_transform_t bithenge_##NAME##_transform = {                   \
+		&NAME##_ops, 1, 0                                              \
+	}
+
+MAKE_UINT_TRANSFORM(uint8   , uint8_t ,                 , prefix_length_1);
+MAKE_UINT_TRANSFORM(uint16le, uint16_t, uint16_t_le2host, prefix_length_2);
+MAKE_UINT_TRANSFORM(uint16be, uint16_t, uint16_t_be2host, prefix_length_2);
+MAKE_UINT_TRANSFORM(uint32le, uint32_t, uint32_t_le2host, prefix_length_4);
+MAKE_UINT_TRANSFORM(uint32be, uint32_t, uint32_t_be2host, prefix_length_4);
+MAKE_UINT_TRANSFORM(uint64le, uint64_t, uint64_t_le2host, prefix_length_8);
+MAKE_UINT_TRANSFORM(uint64be, uint64_t, uint64_t_be2host, prefix_length_8);
+/** @endcond */
+
+
+
+/***************** uint_be, uint_le                          *****************/
+
+static int uint_xe_prefix_apply(bithenge_transform_t *self,
+    bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,
+    aoff64_t *out_size)
+{
+	bool little_endian = (self == &bithenge_uint_le_transform);
+	bithenge_node_t *num_bits_node;
+	int rc = bithenge_scope_get_param(scope, 0, &num_bits_node);
+	if (rc != EOK)
+		return rc;
+	if (bithenge_node_type(num_bits_node) != BITHENGE_NODE_INTEGER) {
+		bithenge_node_dec_ref(num_bits_node);
+		return EINVAL;
+	}
+	bithenge_int_t num_bits = bithenge_integer_node_value(num_bits_node);
+	bithenge_node_dec_ref(num_bits_node);
+	if (num_bits < 0)
+		return EINVAL;
+	if ((size_t)num_bits > sizeof(bithenge_int_t) * 8 - 1)
+		return EINVAL;
+
+	aoff64_t size = num_bits;
+	uint8_t buffer[sizeof(bithenge_int_t)];
+	rc = bithenge_blob_read_bits(blob, 0, (char *)buffer, &size,
+	    little_endian);
+	if (rc != EOK)
+		return rc;
+	if (size != (aoff64_t)num_bits)
+		return EINVAL;
+	if (out_size)
+		*out_size = size;
+
+	bithenge_int_t result = 0;
+	bithenge_int_t num_easy_bytes = num_bits / 8;
+	if (little_endian) {
+		for (bithenge_int_t i = 0; i < num_easy_bytes; i++)
+			result += buffer[i] << 8 * i;
+		if (num_bits % 8)
+			result += (buffer[num_easy_bytes] &
+			    ((1 << num_bits % 8) - 1)) << 8 * num_easy_bytes;
+	} else {
+		for (bithenge_int_t i = 0; i < num_easy_bytes; i++)
+			result += buffer[i] << (num_bits - 8 * (i + 1));
+		if (num_bits % 8)
+			result += buffer[num_easy_bytes] >> (8 - num_bits % 8);
+	}
+
+	return bithenge_new_integer_node(out_node, result);
+}
+
+static const bithenge_transform_ops_t uint_xe_ops = {
+	.prefix_apply = uint_xe_prefix_apply,
+	.destroy = transform_indestructible,
+};
+
+/** A transform that reads an unsigned integer from an arbitrary number of
+ * bits, most-significant bit first. */
+bithenge_transform_t bithenge_uint_be_transform = {
+	&uint_xe_ops, 1, 1
+};
+
+/** A transform that reads an unsigned integer from an arbitrary number of
+ * bits, least-significant bit first. */
+bithenge_transform_t bithenge_uint_le_transform = {
+	&uint_xe_ops, 1, 1
+};
+
+
+
+/***************** zero_terminated                           *****************/
+
+static int zero_terminated_apply(bithenge_transform_t *self,
+    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
+{
+	int rc;
+	if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
+		return EINVAL;
+	bithenge_blob_t *blob = bithenge_node_as_blob(in);
+	aoff64_t size;
+	rc = bithenge_blob_size(blob, &size);
+	if (rc != EOK)
+		return rc;
+	if (size < 1)
+		return EINVAL;
+	char ch;
+	aoff64_t size_read = 1;
+	rc = bithenge_blob_read(blob, size - 1, &ch, &size_read);
+	if (rc != EOK)
+		return rc;
+	if (size_read != 1 || ch != '\0')
+		return EINVAL;
+	bithenge_blob_inc_ref(blob);
+	return bithenge_new_subblob(out, blob, 0, size - 1);
+}
+
+static int zero_terminated_prefix_length(bithenge_transform_t *self,
+    bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out)
+{
+	int rc;
+	char buffer[4096];
+	aoff64_t offset = 0, size_read = sizeof(buffer);
+	do {
+		rc = bithenge_blob_read(blob, offset, buffer, &size_read);
+		if (rc != EOK)
+			return rc;
+		char *found = memchr(buffer, '\0', size_read);
+		if (found) {
+			*out = found - buffer + offset + 1;
+			return EOK;
+		}
+		offset += size_read;
+	} while (size_read == sizeof(buffer));
+	return EINVAL;
+}
+
+static const bithenge_transform_ops_t zero_terminated_ops = {
+	.apply = zero_terminated_apply,
+	.prefix_length = zero_terminated_prefix_length,
+	.destroy = transform_indestructible,
+};
+
+/** The zero-terminated data transform. */
+bithenge_transform_t bithenge_zero_terminated_transform = {
+	&zero_terminated_ops, 1, 0
+};
+
+static bithenge_named_transform_t primitive_transforms[] = {
+	{"ascii", &bithenge_ascii_transform},
+	{"bit", &bithenge_bit_transform},
+	{"bits_be", &bithenge_bits_be_transform},
+	{"bits_le", &bithenge_bits_le_transform},
+	{"known_length", &bithenge_known_length_transform},
+	{"nonzero_boolean", &bithenge_nonzero_boolean_transform},
+	{"uint8", &bithenge_uint8_transform},
+	{"uint16be", &bithenge_uint16be_transform},
+	{"uint16le", &bithenge_uint16le_transform},
+	{"uint32be", &bithenge_uint32be_transform},
+	{"uint32le", &bithenge_uint32le_transform},
+	{"uint64be", &bithenge_uint64be_transform},
+	{"uint64le", &bithenge_uint64le_transform},
+	{"uint_be", &bithenge_uint_be_transform},
+	{"uint_le", &bithenge_uint_le_transform},
+	{"zero_terminated", &bithenge_zero_terminated_transform},
+	{NULL, NULL}
+};
+
+/** An array of named built-in transforms. */
+bithenge_named_transform_t *bithenge_primitive_transforms = primitive_transforms;
+
+/** @}
+ */
Index: uspace/lib/bithenge/src/tree.c
===================================================================
--- uspace/lib/bithenge/src/tree.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/bithenge/src/tree.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2012 Sean Bartell
+ * 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 bithenge
+ * @{
+ */
+/**
+ * @file
+ * Trees and nodes.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <bithenge/blob.h>
+#include <bithenge/tree.h>
+#include "common.h"
+
+static void blob_destroy(bithenge_node_t *base)
+{
+	bithenge_blob_t *self = bithenge_node_as_blob(base);
+	assert(self->base.blob_ops);
+	self->base.blob_ops->destroy(self);
+}
+
+static void node_destroy(bithenge_node_t *self)
+{
+	switch (bithenge_node_type(self)) {
+	case BITHENGE_NODE_BLOB:
+		blob_destroy(self);
+		return;
+	case BITHENGE_NODE_STRING:
+		if (self->string_value.needs_free)
+			free((void *)self->string_value.ptr);
+		break;
+	case BITHENGE_NODE_INTERNAL:
+		self->internal_ops->destroy(self);
+		return;
+	case BITHENGE_NODE_BOOLEAN:
+		return; /* The boolean nodes are allocated statically below. */
+	case BITHENGE_NODE_INTEGER: /* pass-through */
+		break;
+	}
+	free(self);
+}
+
+/** Decrement a node's reference count and free it if appropriate.
+ * @memberof bithenge_node_t
+ * @param node The node to dereference, or NULL. */
+void bithenge_node_dec_ref(bithenge_node_t *node)
+{
+	if (!node)
+		return;
+	assert (node->refs > 0);
+	if (--node->refs == 0)
+		node_destroy(node);
+}
+
+typedef struct {
+	bithenge_node_t *key;
+	bithenge_node_t **out;
+} get_for_each_data_t;
+
+static int get_for_each_func(bithenge_node_t *key, bithenge_node_t *value,
+    void *raw_data)
+{
+	get_for_each_data_t *data = (get_for_each_data_t *)raw_data;
+	bool equal;
+	int rc = bithenge_node_equal(&equal, key, data->key);
+	bithenge_node_dec_ref(key);
+	if (rc != EOK)
+		return rc;
+	if (equal) {
+		*data->out = value;
+		return EEXIST;
+	}
+	bithenge_node_dec_ref(value);
+	return EOK;
+}
+
+/** Get a child of a node. Takes ownership of the key. If the node does not
+ * provide this function, for_each will be used as an alternative, which may be
+ * very slow. Also works for blob nodes to find the byte value at a given
+ * index.
+ * @memberof bithenge_node_t
+ * @param self The internal/blob node to find a child of.
+ * @param key The key to search for.
+ * @param[out] out Holds the found node.
+ * @return EOK on success, ENOENT if not found, or another error code from
+ * errno.h. */
+int bithenge_node_get(bithenge_node_t *self, bithenge_node_t *key,
+    bithenge_node_t **out)
+{
+	if (self->type == BITHENGE_NODE_BLOB) {
+		if (bithenge_node_type(key) != BITHENGE_NODE_INTEGER) {
+			bithenge_node_dec_ref(key);
+			return ENOENT;
+		}
+		bithenge_int_t offset = bithenge_integer_node_value(key);
+		bithenge_node_dec_ref(key);
+		uint8_t byte;
+		aoff64_t size = 1;
+		int rc = bithenge_blob_read(bithenge_node_as_blob(self),
+		    offset, (char *)&byte, &size);
+		if (rc != EOK)
+			return rc;
+		if (size != 1)
+			return ENOENT;
+
+		return bithenge_new_integer_node(out, byte);
+	}
+
+	assert(self->type == BITHENGE_NODE_INTERNAL);
+	if (self->internal_ops->get)
+		return self->internal_ops->get(self, key, out);
+	*out = NULL;
+	get_for_each_data_t data = {key, out};
+	int rc = bithenge_node_for_each(self, get_for_each_func, &data);
+	bithenge_node_dec_ref(key);
+	if (rc == EEXIST && *out)
+		return EOK;
+	if (rc == EOK)
+		rc = ENOENT;
+	bithenge_node_dec_ref(*out);
+	return rc;
+}
+
+/** Initialize an internal node.
+ * @memberof bithenge_node_t
+ * @param[out] self The node.
+ * @param[in] ops The operations provided.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_init_internal_node(bithenge_node_t *self,
+    const bithenge_internal_node_ops_t *ops)
+{
+	self->type = BITHENGE_NODE_INTERNAL;
+	self->refs = 1;
+	self->internal_ops = ops;
+	return EOK;
+}
+
+static void internal_node_indestructible(bithenge_node_t *self)
+{
+	assert(false);
+}
+
+static int empty_internal_node_for_each(bithenge_node_t *base,
+    bithenge_for_each_func_t func, void *data)
+{
+	return EOK;
+}
+
+static int empty_internal_node_get(bithenge_node_t *self, bithenge_node_t *key,
+    bithenge_node_t **out)
+{
+	return ENOENT;
+}
+
+static const bithenge_internal_node_ops_t empty_internal_node_ops = {
+	.for_each = empty_internal_node_for_each,
+	.get = empty_internal_node_get,
+	.destroy = internal_node_indestructible,
+};
+
+static bithenge_node_t empty_internal_node = {
+	BITHENGE_NODE_INTERNAL,
+	1,
+	{ .internal_ops = &empty_internal_node_ops },
+};
+
+/** Create an empty internal node.
+ * @param[out] out Holds the created node.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_empty_internal_node(bithenge_node_t **out)
+{
+	if (bithenge_should_fail())
+		return ENOMEM;
+	bithenge_node_inc_ref(&empty_internal_node);
+	*out = &empty_internal_node;
+	return EOK;
+}
+
+typedef struct
+{
+	bithenge_node_t base;
+	bithenge_node_t **nodes;
+	bithenge_int_t len;
+	bool needs_free;
+} simple_internal_node_t;
+
+static simple_internal_node_t *node_as_simple(bithenge_node_t *node)
+{
+	return (simple_internal_node_t *)node;
+}
+
+static bithenge_node_t *simple_as_node(simple_internal_node_t *node)
+{
+	return &node->base;
+}
+
+static int simple_internal_node_for_each(bithenge_node_t *base,
+    bithenge_for_each_func_t func, void *data)
+{
+	int rc;
+	simple_internal_node_t *self = node_as_simple(base);
+	for (bithenge_int_t i = 0; i < self->len; i++) {
+		bithenge_node_inc_ref(self->nodes[2*i+0]);
+		bithenge_node_inc_ref(self->nodes[2*i+1]);
+		rc = func(self->nodes[2*i+0], self->nodes[2*i+1], data);
+		if (rc != EOK)
+			return rc;
+	}
+	return EOK;
+}
+
+static void simple_internal_node_destroy(bithenge_node_t *base)
+{
+	simple_internal_node_t *self = node_as_simple(base);
+	for (bithenge_int_t i = 0; i < 2 * self->len; i++)
+		bithenge_node_dec_ref(self->nodes[i]);
+	if (self->needs_free)
+		free(self->nodes);
+	free(self);
+}
+
+static bithenge_internal_node_ops_t simple_internal_node_ops = {
+	.for_each = simple_internal_node_for_each,
+	.destroy = simple_internal_node_destroy,
+};
+
+/** Create an internal node from a set of keys and values. This function takes
+ * ownership of a reference to the key and value nodes, and optionally the
+ * array @a nodes.
+ * @memberof bithenge_node_t
+ * @param[out] out Stores the created internal node.
+ * @param nodes The array of key-value pairs. Keys are stored at even indices
+ * and values are stored at odd indices.
+ * @param len The number of key-value pairs in the node array.
+ * @param needs_free If true, when the internal node is destroyed it will free
+ * the nodes array rather than just dereferencing each node inside it.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_simple_internal_node(bithenge_node_t **out,
+    bithenge_node_t **nodes, bithenge_int_t len, bool needs_free)
+{
+	int rc;
+	assert(out);
+	simple_internal_node_t *self = malloc(sizeof(*self));
+	if (!self) {
+		rc = ENOMEM;
+		goto error;
+	}
+	rc = bithenge_init_internal_node(simple_as_node(self),
+	    &simple_internal_node_ops);
+	if (rc != EOK)
+		goto error;
+	self->nodes = nodes;
+	self->len = len;
+	self->needs_free = needs_free;
+	*out = simple_as_node(self);
+	return EOK;
+error:
+	for (bithenge_int_t i = 0; i < 2 * len; i++)
+		bithenge_node_dec_ref(nodes[i]);
+	if (needs_free)
+		free(nodes);
+	free(self);
+	return rc;
+}
+
+static bithenge_node_t false_node = { BITHENGE_NODE_BOOLEAN, 1, .boolean_value = false };
+static bithenge_node_t true_node = { BITHENGE_NODE_BOOLEAN, 1, .boolean_value = true };
+
+/** Create a boolean node.
+ * @memberof bithenge_node_t
+ * @param[out] out Stores the created boolean node.
+ * @param value The value for the node to hold.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_boolean_node(bithenge_node_t **out, bool value)
+{
+	assert(out);
+	if (bithenge_should_fail())
+		return ENOMEM;
+	*out = value ? &true_node : &false_node;
+	(*out)->refs++;
+	return EOK;
+}
+
+/** Create an integer node.
+ * @memberof bithenge_node_t
+ * @param[out] out Stores the created integer node.
+ * @param value The value for the node to hold.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_integer_node(bithenge_node_t **out, bithenge_int_t value)
+{
+	assert(out);
+	bithenge_node_t *self = malloc(sizeof(*self));
+	if (!self)
+		return ENOMEM;
+	self->type = BITHENGE_NODE_INTEGER;
+	self->refs = 1;
+	self->integer_value = value;
+	*out = self;
+	return EOK;
+}
+
+/** Create a string node.
+ * @memberof bithenge_node_t
+ * @param[out] out Stores the created string node. On error, this is unchanged.
+ * @param value The value for the node to hold.
+ * @param needs_free Whether the string should be freed when the node is
+ * destroyed.
+ * @return EOK on success or an error code from errno.h. */
+int bithenge_new_string_node(bithenge_node_t **out, const char *value, bool needs_free)
+{
+	assert(out);
+	bithenge_node_t *self = malloc(sizeof(*self));
+	if (!self) {
+		if (needs_free)
+			free((void *)value);
+		return ENOMEM;
+	}
+	self->type = BITHENGE_NODE_STRING;
+	self->refs = 1;
+	self->string_value.ptr = value;
+	self->string_value.needs_free = needs_free;
+	*out = self;
+	return EOK;
+}
+
+/** Check whether the contents of two nodes are equal. Does not yet work for
+ * internal nodes. Takes ownership of nothing.
+ * @memberof bithenge_node_t
+ * @param[out] out Holds whether the nodes are equal.
+ * @param a, b Nodes to compare.
+ * @return EOK on success or an error code from errno.h.
+ * @todo Add support for internal nodes. */
+int bithenge_node_equal(bool *out, bithenge_node_t *a, bithenge_node_t *b)
+{
+	if (a->type != b->type) {
+		*out = false;
+		return EOK;
+	}
+	switch (a->type) {
+	case BITHENGE_NODE_INTERNAL:
+		*out = false;
+		return EOK;
+	case BITHENGE_NODE_BOOLEAN:
+		*out = a->boolean_value == b->boolean_value;
+		return EOK;
+	case BITHENGE_NODE_INTEGER:
+		*out = a->integer_value == b->integer_value;
+		return EOK;
+	case BITHENGE_NODE_STRING:
+		*out = !str_cmp(a->string_value.ptr, b->string_value.ptr);
+		return EOK;
+	case BITHENGE_NODE_BLOB:
+		return bithenge_blob_equal(out, bithenge_node_as_blob(a),
+		    bithenge_node_as_blob(b));
+	}
+	return EINVAL;
+}
+
+/** @}
+ */
Index: uspace/lib/block/Makefile
===================================================================
--- uspace/lib/block/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/block/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -32,5 +32,5 @@
 
 SOURCES = \
-	libblock.c
+	block.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/block/block.c
===================================================================
--- uspace/lib/block/block.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/block/block.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,923 @@
+/*
+ * Copyright (c) 2008 Jakub Jermar
+ * Copyright (c) 2008 Martin Decky
+ * Copyright (c) 2011 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 libblock
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include "../../srv/vfs/vfs.h"
+#include <ipc/loc.h>
+#include <ipc/services.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <async.h>
+#include <as.h>
+#include <assert.h>
+#include <bd.h>
+#include <fibril_synch.h>
+#include <adt/list.h>
+#include <adt/hash_table.h>
+#include <macros.h>
+#include <mem.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <sys/typefmt.h>
+#include <stacktrace.h>
+#include "block.h"
+
+/** Lock protecting the device connection list */
+static FIBRIL_MUTEX_INITIALIZE(dcl_lock);
+/** Device connection list head. */
+static LIST_INITIALIZE(dcl);
+
+
+typedef struct {
+	fibril_mutex_t lock;
+	size_t lblock_size;       /**< Logical block size. */
+	unsigned blocks_cluster;  /**< Physical blocks per block_t */
+	unsigned block_count;     /**< Total number of blocks. */
+	unsigned blocks_cached;   /**< Number of cached blocks. */
+	hash_table_t block_hash;
+	list_t free_list;
+	enum cache_mode mode;
+} cache_t;
+
+typedef struct {
+	link_t link;
+	service_id_t service_id;
+	async_sess_t *sess;
+	bd_t *bd;
+	void *bb_buf;
+	aoff64_t bb_addr;
+	size_t pblock_size;  /**< Physical block size. */
+	cache_t *cache;
+} devcon_t;
+
+static int read_blocks(devcon_t *, aoff64_t, size_t, void *, size_t);
+static int write_blocks(devcon_t *, aoff64_t, size_t, void *, size_t);
+static aoff64_t ba_ltop(devcon_t *, aoff64_t);
+
+static devcon_t *devcon_search(service_id_t service_id)
+{
+	fibril_mutex_lock(&dcl_lock);
+	
+	list_foreach(dcl, cur) {
+		devcon_t *devcon = list_get_instance(cur, devcon_t, link);
+		if (devcon->service_id == service_id) {
+			fibril_mutex_unlock(&dcl_lock);
+			return devcon;
+		}
+	}
+	
+	fibril_mutex_unlock(&dcl_lock);
+	return NULL;
+}
+
+static int devcon_add(service_id_t service_id, async_sess_t *sess,
+    size_t bsize, bd_t *bd)
+{
+	devcon_t *devcon;
+	
+	devcon = malloc(sizeof(devcon_t));
+	if (!devcon)
+		return ENOMEM;
+	
+	link_initialize(&devcon->link);
+	devcon->service_id = service_id;
+	devcon->sess = sess;
+	devcon->bd = bd;
+	devcon->bb_buf = NULL;
+	devcon->bb_addr = 0;
+	devcon->pblock_size = bsize;
+	devcon->cache = NULL;
+	
+	fibril_mutex_lock(&dcl_lock);
+	list_foreach(dcl, cur) {
+		devcon_t *d = list_get_instance(cur, devcon_t, link);
+		if (d->service_id == service_id) {
+			fibril_mutex_unlock(&dcl_lock);
+			free(devcon);
+			return EEXIST;
+		}
+	}
+	list_append(&devcon->link, &dcl);
+	fibril_mutex_unlock(&dcl_lock);
+	return EOK;
+}
+
+static void devcon_remove(devcon_t *devcon)
+{
+	fibril_mutex_lock(&dcl_lock);
+	list_remove(&devcon->link);
+	fibril_mutex_unlock(&dcl_lock);
+}
+
+int block_init(exch_mgmt_t mgmt, service_id_t service_id,
+    size_t comm_size)
+{
+	bd_t *bd;
+
+	async_sess_t *sess = loc_service_connect(mgmt, service_id,
+	    IPC_FLAG_BLOCKING);
+	if (!sess) {
+		return ENOENT;
+	}
+	
+	int rc = bd_open(sess, &bd);
+	if (rc != EOK) {
+		async_hangup(sess);
+		return rc;
+	}
+	
+	size_t bsize;
+	rc = bd_get_block_size(bd, &bsize);
+	if (rc != EOK) {
+		bd_close(bd);
+		async_hangup(sess);
+		return rc;
+	}
+	
+	rc = devcon_add(service_id, sess, bsize, bd);
+	if (rc != EOK) {
+		bd_close(bd);
+		async_hangup(sess);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+void block_fini(service_id_t service_id)
+{
+	devcon_t *devcon = devcon_search(service_id);
+	assert(devcon);
+	
+	if (devcon->cache)
+		(void) block_cache_fini(service_id);
+	
+	devcon_remove(devcon);
+	
+	if (devcon->bb_buf)
+		free(devcon->bb_buf);
+	
+	bd_close(devcon->bd);
+	async_hangup(devcon->sess);
+	
+	free(devcon);
+}
+
+int block_bb_read(service_id_t service_id, aoff64_t ba)
+{
+	void *bb_buf;
+	int rc;
+
+	devcon_t *devcon = devcon_search(service_id);
+	if (!devcon)
+		return ENOENT;
+	if (devcon->bb_buf)
+		return EEXIST;
+	bb_buf = malloc(devcon->pblock_size);
+	if (!bb_buf)
+		return ENOMEM;
+
+	rc = read_blocks(devcon, 0, 1, bb_buf, devcon->pblock_size);
+	if (rc != EOK) {
+	    	free(bb_buf);
+		return rc;
+	}
+
+	devcon->bb_buf = bb_buf;
+	devcon->bb_addr = ba;
+
+	return EOK;
+}
+
+void *block_bb_get(service_id_t service_id)
+{
+	devcon_t *devcon = devcon_search(service_id);
+	assert(devcon);
+	return devcon->bb_buf;
+}
+
+static size_t cache_key_hash(void *key)
+{
+	aoff64_t *lba = (aoff64_t*)key;
+	return *lba;
+}
+
+static size_t cache_hash(const ht_link_t *item)
+{
+	block_t *b = hash_table_get_inst(item, block_t, hash_link);
+	return b->lba;
+}
+
+static bool cache_key_equal(void *key, const ht_link_t *item)
+{
+	aoff64_t *lba = (aoff64_t*)key;
+	block_t *b = hash_table_get_inst(item, block_t, hash_link);
+	return b->lba == *lba;
+}
+
+
+static hash_table_ops_t cache_ops = {
+	.hash = cache_hash,
+	.key_hash = cache_key_hash,
+	.key_equal = cache_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
+};
+
+int block_cache_init(service_id_t service_id, size_t size, unsigned blocks,
+    enum cache_mode mode)
+{
+	devcon_t *devcon = devcon_search(service_id);
+	cache_t *cache;
+	if (!devcon)
+		return ENOENT;
+	if (devcon->cache)
+		return EEXIST;
+	cache = malloc(sizeof(cache_t));
+	if (!cache)
+		return ENOMEM;
+	
+	fibril_mutex_initialize(&cache->lock);
+	list_initialize(&cache->free_list);
+	cache->lblock_size = size;
+	cache->block_count = blocks;
+	cache->blocks_cached = 0;
+	cache->mode = mode;
+
+	/* Allow 1:1 or small-to-large block size translation */
+	if (cache->lblock_size % devcon->pblock_size != 0) {
+		free(cache);
+		return ENOTSUP;
+	}
+
+	cache->blocks_cluster = cache->lblock_size / devcon->pblock_size;
+
+	if (!hash_table_create(&cache->block_hash, 0, 0, &cache_ops)) {
+		free(cache);
+		return ENOMEM;
+	}
+
+	devcon->cache = cache;
+	return EOK;
+}
+
+int block_cache_fini(service_id_t service_id)
+{
+	devcon_t *devcon = devcon_search(service_id);
+	cache_t *cache;
+	int rc;
+
+	if (!devcon)
+		return ENOENT;
+	if (!devcon->cache)
+		return EOK;
+	cache = devcon->cache;
+	
+	/*
+	 * We are expecting to find all blocks for this device handle on the
+	 * free list, i.e. the block reference count should be zero. Do not
+	 * bother with the cache and block locks because we are single-threaded.
+	 */
+	while (!list_empty(&cache->free_list)) {
+		block_t *b = list_get_instance(list_first(&cache->free_list),
+		    block_t, free_link);
+
+		list_remove(&b->free_link);
+		if (b->dirty) {
+			rc = write_blocks(devcon, b->pba, cache->blocks_cluster,
+			    b->data, b->size);
+			if (rc != EOK)
+				return rc;
+		}
+
+		hash_table_remove_item(&cache->block_hash, &b->hash_link);
+		
+		free(b->data);
+		free(b);
+	}
+
+	hash_table_destroy(&cache->block_hash);
+	devcon->cache = NULL;
+	free(cache);
+
+	return EOK;
+}
+
+#define CACHE_LO_WATERMARK	10	
+#define CACHE_HI_WATERMARK	20	
+static bool cache_can_grow(cache_t *cache)
+{
+	if (cache->blocks_cached < CACHE_LO_WATERMARK)
+		return true;
+	if (!list_empty(&cache->free_list))
+		return false;
+	return true;
+}
+
+static void block_initialize(block_t *b)
+{
+	fibril_mutex_initialize(&b->lock);
+	b->refcnt = 1;
+	b->dirty = false;
+	b->toxic = false;
+	fibril_rwlock_initialize(&b->contents_lock);
+	link_initialize(&b->free_link);
+}
+
+/** Instantiate a block in memory and get a reference to it.
+ *
+ * @param block			Pointer to where the function will store the
+ * 				block pointer on success.
+ * @param service_id		Service ID of the block device.
+ * @param ba			Block address (logical).
+ * @param flags			If BLOCK_FLAGS_NOREAD is specified, block_get()
+ * 				will not read the contents of the block from the
+ *				device.
+ *
+ * @return			EOK on success or a negative error code.
+ */
+int block_get(block_t **block, service_id_t service_id, aoff64_t ba, int flags)
+{
+	devcon_t *devcon;
+	cache_t *cache;
+	block_t *b;
+	link_t *link;
+
+	int rc;
+	
+	devcon = devcon_search(service_id);
+
+	assert(devcon);
+	assert(devcon->cache);
+	
+	cache = devcon->cache;
+
+retry:
+	rc = EOK;
+	b = NULL;
+
+	fibril_mutex_lock(&cache->lock);
+	ht_link_t *hlink = hash_table_find(&cache->block_hash, &ba);
+	if (hlink) {
+found:
+		/*
+		 * We found the block in the cache.
+		 */
+		b = hash_table_get_inst(hlink, block_t, hash_link);
+		fibril_mutex_lock(&b->lock);
+		if (b->refcnt++ == 0)
+			list_remove(&b->free_link);
+		if (b->toxic)
+			rc = EIO;
+		fibril_mutex_unlock(&b->lock);
+		fibril_mutex_unlock(&cache->lock);
+	} else {
+		/*
+		 * The block was not found in the cache.
+		 */
+		if (cache_can_grow(cache)) {
+			/*
+			 * We can grow the cache by allocating new blocks.
+			 * Should the allocation fail, we fail over and try to
+			 * recycle a block from the cache.
+			 */
+			b = malloc(sizeof(block_t));
+			if (!b)
+				goto recycle;
+			b->data = malloc(cache->lblock_size);
+			if (!b->data) {
+				free(b);
+				b = NULL;
+				goto recycle;
+			}
+			cache->blocks_cached++;
+		} else {
+			/*
+			 * Try to recycle a block from the free list.
+			 */
+recycle:
+			if (list_empty(&cache->free_list)) {
+				fibril_mutex_unlock(&cache->lock);
+				rc = ENOMEM;
+				goto out;
+			}
+			link = list_first(&cache->free_list);
+			b = list_get_instance(link, block_t, free_link);
+
+			fibril_mutex_lock(&b->lock);
+			if (b->dirty) {
+				/*
+				 * The block needs to be written back to the
+				 * device before it changes identity. Do this
+				 * while not holding the cache lock so that
+				 * concurrency is not impeded. Also move the
+				 * block to the end of the free list so that we
+				 * do not slow down other instances of
+				 * block_get() draining the free list.
+				 */
+				list_remove(&b->free_link);
+				list_append(&b->free_link, &cache->free_list);
+				fibril_mutex_unlock(&cache->lock);
+				rc = write_blocks(devcon, b->pba,
+				    cache->blocks_cluster, b->data, b->size);
+				if (rc != EOK) {
+					/*
+					 * We did not manage to write the block
+					 * to the device. Keep it around for
+					 * another try. Hopefully, we will grab
+					 * another block next time.
+					 */
+					fibril_mutex_unlock(&b->lock);
+					goto retry;
+				}
+				b->dirty = false;
+				if (!fibril_mutex_trylock(&cache->lock)) {
+					/*
+					 * Somebody is probably racing with us.
+					 * Unlock the block and retry.
+					 */
+					fibril_mutex_unlock(&b->lock);
+					goto retry;
+				}
+				hlink = hash_table_find(&cache->block_hash, &ba);
+				if (hlink) {
+					/*
+					 * Someone else must have already
+					 * instantiated the block while we were
+					 * not holding the cache lock.
+					 * Leave the recycled block on the
+					 * freelist and continue as if we
+					 * found the block of interest during
+					 * the first try.
+					 */
+					fibril_mutex_unlock(&b->lock);
+					goto found;
+				}
+
+			}
+			fibril_mutex_unlock(&b->lock);
+
+			/*
+			 * Unlink the block from the free list and the hash
+			 * table.
+			 */
+			list_remove(&b->free_link);
+			hash_table_remove_item(&cache->block_hash, &b->hash_link);
+		}
+
+		block_initialize(b);
+		b->service_id = service_id;
+		b->size = cache->lblock_size;
+		b->lba = ba;
+		b->pba = ba_ltop(devcon, b->lba);
+		hash_table_insert(&cache->block_hash, &b->hash_link);
+
+		/*
+		 * Lock the block before releasing the cache lock. Thus we don't
+		 * kill concurrent operations on the cache while doing I/O on
+		 * the block.
+		 */
+		fibril_mutex_lock(&b->lock);
+		fibril_mutex_unlock(&cache->lock);
+
+		if (!(flags & BLOCK_FLAGS_NOREAD)) {
+			/*
+			 * The block contains old or no data. We need to read
+			 * the new contents from the device.
+			 */
+			rc = read_blocks(devcon, b->pba, cache->blocks_cluster,
+			    b->data, cache->lblock_size);
+			if (rc != EOK) 
+				b->toxic = true;
+		} else
+			rc = EOK;
+
+		fibril_mutex_unlock(&b->lock);
+	}
+out:
+	if ((rc != EOK) && b) {
+		assert(b->toxic);
+		(void) block_put(b);
+		b = NULL;
+	}
+	*block = b;
+	return rc;
+}
+
+/** Release a reference to a block.
+ *
+ * If the last reference is dropped, the block is put on the free list.
+ *
+ * @param block		Block of which a reference is to be released.
+ *
+ * @return		EOK on success or a negative error code.
+ */
+int block_put(block_t *block)
+{
+	devcon_t *devcon = devcon_search(block->service_id);
+	cache_t *cache;
+	unsigned blocks_cached;
+	enum cache_mode mode;
+	int rc = EOK;
+
+	assert(devcon);
+	assert(devcon->cache);
+	assert(block->refcnt >= 1);
+
+	cache = devcon->cache;
+
+retry:
+	fibril_mutex_lock(&cache->lock);
+	blocks_cached = cache->blocks_cached;
+	mode = cache->mode;
+	fibril_mutex_unlock(&cache->lock);
+
+	/*
+	 * Determine whether to sync the block. Syncing the block is best done
+	 * when not holding the cache lock as it does not impede concurrency.
+	 * Since the situation may have changed when we unlocked the cache, the
+	 * blocks_cached and mode variables are mere hints. We will recheck the
+	 * conditions later when the cache lock is held again.
+	 */
+	fibril_mutex_lock(&block->lock);
+	if (block->toxic)
+		block->dirty = false;	/* will not write back toxic block */
+	if (block->dirty && (block->refcnt == 1) &&
+	    (blocks_cached > CACHE_HI_WATERMARK || mode != CACHE_MODE_WB)) {
+		rc = write_blocks(devcon, block->pba, cache->blocks_cluster,
+		    block->data, block->size);
+		block->dirty = false;
+	}
+	fibril_mutex_unlock(&block->lock);
+
+	fibril_mutex_lock(&cache->lock);
+	fibril_mutex_lock(&block->lock);
+	if (!--block->refcnt) {
+		/*
+		 * Last reference to the block was dropped. Either free the
+		 * block or put it on the free list. In case of an I/O error,
+		 * free the block.
+		 */
+		if ((cache->blocks_cached > CACHE_HI_WATERMARK) ||
+		    (rc != EOK)) {
+			/*
+			 * Currently there are too many cached blocks or there
+			 * was an I/O error when writing the block back to the
+			 * device.
+			 */
+			if (block->dirty) {
+				/*
+				 * We cannot sync the block while holding the
+				 * cache lock. Release everything and retry.
+				 */
+				block->refcnt++;
+				fibril_mutex_unlock(&block->lock);
+				fibril_mutex_unlock(&cache->lock);
+				goto retry;
+			}
+			/*
+			 * Take the block out of the cache and free it.
+			 */
+			hash_table_remove_item(&cache->block_hash, &block->hash_link);
+			fibril_mutex_unlock(&block->lock);
+			free(block->data);
+			free(block);
+			cache->blocks_cached--;
+			fibril_mutex_unlock(&cache->lock);
+			return rc;
+		}
+		/*
+		 * Put the block on the free list.
+		 */
+		if (cache->mode != CACHE_MODE_WB && block->dirty) {
+			/*
+			 * We cannot sync the block while holding the cache
+			 * lock. Release everything and retry.
+			 */
+			block->refcnt++;
+			fibril_mutex_unlock(&block->lock);
+			fibril_mutex_unlock(&cache->lock);
+			goto retry;
+		}
+		list_append(&block->free_link, &cache->free_list);
+	}
+	fibril_mutex_unlock(&block->lock);
+	fibril_mutex_unlock(&cache->lock);
+
+	return rc;
+}
+
+/** Read sequential data from a block device.
+ *
+ * @param service_id	Service ID of the block device.
+ * @param buf		Buffer for holding one block
+ * @param bufpos	Pointer to the first unread valid offset within the
+ * 			communication buffer.
+ * @param buflen	Pointer to the number of unread bytes that are ready in
+ * 			the communication buffer.
+ * @param pos		Device position to be read.
+ * @param dst		Destination buffer.
+ * @param size		Size of the destination buffer.
+ * @param block_size	Block size to be used for the transfer.
+ *
+ * @return		EOK on success or a negative return code on failure.
+ */
+int block_seqread(service_id_t service_id, void *buf, size_t *bufpos,
+    size_t *buflen, aoff64_t *pos, void *dst, size_t size)
+{
+	size_t offset = 0;
+	size_t left = size;
+	size_t block_size;
+	devcon_t *devcon;
+
+	devcon = devcon_search(service_id);
+	assert(devcon);
+	block_size = devcon->pblock_size;
+	
+	while (left > 0) {
+		size_t rd;
+		
+		if (*bufpos + left < *buflen)
+			rd = left;
+		else
+			rd = *buflen - *bufpos;
+		
+		if (rd > 0) {
+			/*
+			 * Copy the contents of the communication buffer to the
+			 * destination buffer.
+			 */
+			memcpy(dst + offset, buf + *bufpos, rd);
+			offset += rd;
+			*bufpos += rd;
+			*pos += rd;
+			left -= rd;
+		}
+		
+		if (*bufpos == *buflen) {
+			/* Refill the communication buffer with a new block. */
+			int rc;
+
+			rc = read_blocks(devcon, *pos / block_size, 1, buf,
+			    devcon->pblock_size);
+			if (rc != EOK) {
+				return rc;
+			}
+			
+			*bufpos = 0;
+			*buflen = block_size;
+		}
+	}
+	
+	return EOK;
+}
+
+/** Read blocks directly from device (bypass cache).
+ *
+ * @param service_id	Service ID of the block device.
+ * @param ba		Address of first block (physical).
+ * @param cnt		Number of blocks.
+ * @param src		Buffer for storing the data.
+ *
+ * @return		EOK on success or negative error code on failure.
+ */
+int block_read_direct(service_id_t service_id, aoff64_t ba, size_t cnt, void *buf)
+{
+	devcon_t *devcon;
+
+	devcon = devcon_search(service_id);
+	assert(devcon);
+
+	return read_blocks(devcon, ba, cnt, buf, devcon->pblock_size * cnt);
+}
+
+/** Write blocks directly to device (bypass cache).
+ *
+ * @param service_id	Service ID of the block device.
+ * @param ba		Address of first block (physical).
+ * @param cnt		Number of blocks.
+ * @param src		The data to be written.
+ *
+ * @return		EOK on success or negative error code on failure.
+ */
+int block_write_direct(service_id_t service_id, aoff64_t ba, size_t cnt,
+    const void *data)
+{
+	devcon_t *devcon;
+
+	devcon = devcon_search(service_id);
+	assert(devcon);
+
+	return write_blocks(devcon, ba, cnt, (void *)data, devcon->pblock_size * cnt);
+}
+
+/** Get device block size.
+ *
+ * @param service_id	Service ID of the block device.
+ * @param bsize		Output block size.
+ *
+ * @return		EOK on success or negative error code on failure.
+ */
+int block_get_bsize(service_id_t service_id, size_t *bsize)
+{
+	devcon_t *devcon;
+
+	devcon = devcon_search(service_id);
+	assert(devcon);
+
+	return bd_get_block_size(devcon->bd, bsize);
+}
+
+/** Get number of blocks on device.
+ *
+ * @param service_id	Service ID of the block device.
+ * @param nblocks	Output number of blocks.
+ *
+ * @return		EOK on success or negative error code on failure.
+ */
+int block_get_nblocks(service_id_t service_id, aoff64_t *nblocks)
+{
+	devcon_t *devcon = devcon_search(service_id);
+	assert(devcon);
+	
+	return bd_get_num_blocks(devcon->bd, nblocks);
+}
+
+/** Read bytes directly from the device (bypass cache)
+ * 
+ * @param service_id	Service ID of the block device.
+ * @param abs_offset	Absolute offset in bytes where to start reading
+ * @param bytes			Number of bytes to read
+ * @param data			Buffer that receives the data
+ * 
+ * @return		EOK on success or negative error code on failure.
+ */
+int block_read_bytes_direct(service_id_t service_id, aoff64_t abs_offset,
+    size_t bytes, void *data)
+{
+	int rc;
+	size_t phys_block_size;
+	size_t buf_size;
+	void *buffer;
+	aoff64_t first_block;
+	aoff64_t last_block;
+	size_t blocks;
+	size_t offset;
+	
+	rc = block_get_bsize(service_id, &phys_block_size);
+	if (rc != EOK) {
+		return rc;
+	}
+	
+	/* calculate data position and required space */
+	first_block = abs_offset / phys_block_size;
+	offset = abs_offset % phys_block_size;
+	last_block = (abs_offset + bytes - 1) / phys_block_size;
+	blocks = last_block - first_block + 1;
+	buf_size = blocks * phys_block_size;
+	
+	/* read the data into memory */
+	buffer = malloc(buf_size);
+	if (buffer == NULL) {
+		return ENOMEM;
+	}
+	
+	rc = block_read_direct(service_id, first_block, blocks, buffer);
+	if (rc != EOK) {
+		free(buffer);
+		return rc;
+	}
+	
+	/* copy the data from the buffer */
+	memcpy(data, buffer + offset, bytes);
+	free(buffer);
+	
+	return EOK;
+}
+
+/** Get TOC from device.
+ *
+ * @param service_id Service ID of the block device.
+ * @param session    Starting session.
+ *
+ * @return Allocated TOC structure.
+ * @return NULL on failure.
+ *
+ */
+toc_block_t *block_get_toc(service_id_t service_id, uint8_t session)
+{
+	devcon_t *devcon = devcon_search(service_id);
+	toc_block_t *toc = NULL;
+	int rc;
+	
+	assert(devcon);
+	
+	toc = (toc_block_t *) malloc(sizeof(toc_block_t));
+	if (toc == NULL)
+		return NULL;
+	
+	rc = bd_read_toc(devcon->bd, session, toc, sizeof(toc_block_t));
+	if (rc != EOK) {
+		free(toc);
+		return NULL;
+	}
+	
+	return toc;
+}
+
+/** Read blocks from block device.
+ *
+ * @param devcon	Device connection.
+ * @param ba		Address of first block.
+ * @param cnt		Number of blocks.
+ * @param src		Buffer for storing the data.
+ *
+ * @return		EOK on success or negative error code on failure.
+ */
+static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt, void *buf,
+    size_t size)
+{
+	assert(devcon);
+	
+	int rc = bd_read_blocks(devcon->bd, ba, cnt, buf, size);
+	if (rc != EOK) {
+		printf("Error %d reading %zu blocks starting at block %" PRIuOFF64
+		    " from device handle %" PRIun "\n", rc, cnt, ba,
+		    devcon->service_id);
+#ifndef NDEBUG
+		stacktrace_print();
+#endif
+	}
+	
+	return rc;
+}
+
+/** Write block to block device.
+ *
+ * @param devcon	Device connection.
+ * @param ba		Address of first block.
+ * @param cnt		Number of blocks.
+ * @param src		Buffer containing the data to write.
+ *
+ * @return		EOK on success or negative error code on failure.
+ */
+static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt, void *data,
+    size_t size)
+{
+	assert(devcon);
+	
+	int rc = bd_write_blocks(devcon->bd, ba, cnt, data, size);
+	if (rc != EOK) {
+		printf("Error %d writing %zu blocks starting at block %" PRIuOFF64
+		    " to device handle %" PRIun "\n", rc, cnt, ba, devcon->service_id);
+#ifndef NDEBUG
+		stacktrace_print();
+#endif
+	}
+	
+	return rc;
+}
+
+/** Convert logical block address to physical block address. */
+static aoff64_t ba_ltop(devcon_t *devcon, aoff64_t lba)
+{
+	assert(devcon->cache != NULL);
+	return lba * devcon->cache->blocks_cluster;
+}
+
+/** @}
+ */
Index: uspace/lib/block/block.h
===================================================================
--- uspace/lib/block/block.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/block/block.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2008 Jakub Jermar
+ * Copyright (c) 2008 Martin Decky
+ * Copyright (c) 2011 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 libblock 
+ * @{
+ */ 
+/**
+ * @file
+ */
+
+#ifndef LIBBLOCK_LIBBLOCK_H_
+#define LIBBLOCK_LIBBLOCK_H_
+
+#include <stdint.h>
+#include <async.h>
+#include "../../srv/vfs/vfs.h"
+#include <fibril_synch.h>
+#include <adt/hash_table.h>
+#include <adt/list.h>
+
+/*
+ * Flags that can be used with block_get().
+ */
+
+/** 
+ * This macro is a symbolic value for situations where no special flags are
+ * needed.
+ */
+#define BLOCK_FLAGS_NONE	0
+
+/**
+ * When the client of block_get() intends to overwrite the current contents of
+ * the block, this flag is used to avoid the unnecessary read.
+ */
+#define BLOCK_FLAGS_NOREAD	1
+
+typedef struct block {
+	/** Mutex protecting the reference count. */
+	fibril_mutex_t lock;
+	/** Number of references to the block_t structure. */
+	unsigned refcnt;
+	/** If true, the block needs to be written back to the block device. */
+	bool dirty;
+	/** If true, the blcok does not contain valid data. */
+	bool toxic;
+	/** Readers / Writer lock protecting the contents of the block. */
+	fibril_rwlock_t contents_lock;
+	/** Service ID of service providing the block device. */
+	service_id_t service_id;
+	/** Logical block address */
+	aoff64_t lba;
+	/** Physical block address */
+	aoff64_t pba;
+	/** Size of the block. */
+	size_t size;
+	/** Link for placing the block into the free block list. */
+	link_t free_link;
+	/** Link for placing the block into the block hash table. */ 
+	ht_link_t hash_link;
+	/** Buffer with the block data. */
+	void *data;
+} block_t;
+
+/** Caching mode */
+enum cache_mode {
+	/** Write-Through */
+	CACHE_MODE_WT,
+	/** Write-Back */
+	CACHE_MODE_WB
+};
+
+typedef struct {
+	uint16_t size;
+	uint8_t first_session;
+	uint8_t last_session;
+	
+	uint8_t res0;
+	uint8_t adr_ctrl;
+	uint8_t first_track;
+	uint8_t res1;
+	
+	uint32_t first_lba;
+} __attribute__((packed)) toc_block_t;
+
+extern int block_init(exch_mgmt_t, service_id_t, size_t);
+extern void block_fini(service_id_t);
+
+extern int block_bb_read(service_id_t, aoff64_t);
+extern void *block_bb_get(service_id_t);
+
+extern int block_cache_init(service_id_t, size_t, unsigned, enum cache_mode);
+extern int block_cache_fini(service_id_t);
+
+extern int block_get(block_t **, service_id_t, aoff64_t, int);
+extern int block_put(block_t *);
+
+extern int block_seqread(service_id_t, void *, size_t *, size_t *, aoff64_t *,
+    void *, size_t);
+
+extern int block_get_bsize(service_id_t, size_t *);
+extern int block_get_nblocks(service_id_t, aoff64_t *);
+extern toc_block_t *block_get_toc(service_id_t, uint8_t);
+extern int block_read_direct(service_id_t, aoff64_t, size_t, void *);
+extern int block_read_bytes_direct(service_id_t, aoff64_t, size_t, void *);
+extern int block_write_direct(service_id_t, aoff64_t, size_t, const void *);
+
+#endif
+
+/** @}
+ */
Index: pace/lib/block/libblock.c
===================================================================
--- uspace/lib/block/libblock.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,1028 +1,0 @@
-/*
- * Copyright (c) 2008 Jakub Jermar
- * Copyright (c) 2008 Martin Decky
- * Copyright (c) 2011 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 libblock
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include "libblock.h"
-#include "../../srv/vfs/vfs.h"
-#include <ipc/loc.h>
-#include <ipc/bd.h>
-#include <ipc/services.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include <async.h>
-#include <as.h>
-#include <assert.h>
-#include <fibril_synch.h>
-#include <adt/list.h>
-#include <adt/hash_table.h>
-#include <macros.h>
-#include <mem.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <sys/typefmt.h>
-#include <stacktrace.h>
-
-/** Lock protecting the device connection list */
-static FIBRIL_MUTEX_INITIALIZE(dcl_lock);
-/** Device connection list head. */
-static LIST_INITIALIZE(dcl);
-
-#define CACHE_BUCKETS_LOG2  10
-#define CACHE_BUCKETS       (1 << CACHE_BUCKETS_LOG2)
-
-typedef struct {
-	fibril_mutex_t lock;
-	size_t lblock_size;       /**< Logical block size. */
-	unsigned blocks_cluster;  /**< Physical blocks per block_t */
-	unsigned block_count;     /**< Total number of blocks. */
-	unsigned blocks_cached;   /**< Number of cached blocks. */
-	hash_table_t block_hash;
-	list_t free_list;
-	enum cache_mode mode;
-} cache_t;
-
-typedef struct {
-	link_t link;
-	service_id_t service_id;
-	async_sess_t *sess;
-	fibril_mutex_t comm_area_lock;
-	void *comm_area;
-	size_t comm_size;
-	void *bb_buf;
-	aoff64_t bb_addr;
-	size_t pblock_size;  /**< Physical block size. */
-	cache_t *cache;
-} devcon_t;
-
-static int read_blocks(devcon_t *, aoff64_t, size_t);
-static int write_blocks(devcon_t *, aoff64_t, size_t);
-static int get_block_size(async_sess_t *, size_t *);
-static int get_num_blocks(async_sess_t *, aoff64_t *);
-static aoff64_t ba_ltop(devcon_t *, aoff64_t);
-
-static devcon_t *devcon_search(service_id_t service_id)
-{
-	fibril_mutex_lock(&dcl_lock);
-	
-	list_foreach(dcl, cur) {
-		devcon_t *devcon = list_get_instance(cur, devcon_t, link);
-		if (devcon->service_id == service_id) {
-			fibril_mutex_unlock(&dcl_lock);
-			return devcon;
-		}
-	}
-	
-	fibril_mutex_unlock(&dcl_lock);
-	return NULL;
-}
-
-static int devcon_add(service_id_t service_id, async_sess_t *sess,
-    size_t bsize, void *comm_area, size_t comm_size)
-{
-	devcon_t *devcon;
-	
-	if (comm_size < bsize)
-		return EINVAL;
-	
-	devcon = malloc(sizeof(devcon_t));
-	if (!devcon)
-		return ENOMEM;
-	
-	link_initialize(&devcon->link);
-	devcon->service_id = service_id;
-	devcon->sess = sess;
-	fibril_mutex_initialize(&devcon->comm_area_lock);
-	devcon->comm_area = comm_area;
-	devcon->comm_size = comm_size;
-	devcon->bb_buf = NULL;
-	devcon->bb_addr = 0;
-	devcon->pblock_size = bsize;
-	devcon->cache = NULL;
-	
-	fibril_mutex_lock(&dcl_lock);
-	list_foreach(dcl, cur) {
-		devcon_t *d = list_get_instance(cur, devcon_t, link);
-		if (d->service_id == service_id) {
-			fibril_mutex_unlock(&dcl_lock);
-			free(devcon);
-			return EEXIST;
-		}
-	}
-	list_append(&devcon->link, &dcl);
-	fibril_mutex_unlock(&dcl_lock);
-	return EOK;
-}
-
-static void devcon_remove(devcon_t *devcon)
-{
-	fibril_mutex_lock(&dcl_lock);
-	list_remove(&devcon->link);
-	fibril_mutex_unlock(&dcl_lock);
-}
-
-int block_init(exch_mgmt_t mgmt, service_id_t service_id,
-    size_t comm_size)
-{
-	void *comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE,
-	    MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
-	if (!comm_area)
-		return ENOMEM;
-	
-	async_sess_t *sess = loc_service_connect(mgmt, service_id,
-	    IPC_FLAG_BLOCKING);
-	if (!sess) {
-		munmap(comm_area, comm_size);
-		return ENOENT;
-	}
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_share_out_start(exch, comm_area,
-	    AS_AREA_READ | AS_AREA_WRITE);
-	async_exchange_end(exch);
-	
-	if (rc != EOK) {
-		munmap(comm_area, comm_size);
-		async_hangup(sess);
-		return rc;
-	}
-	
-	size_t bsize;
-	rc = get_block_size(sess, &bsize);
-	
-	if (rc != EOK) {
-		munmap(comm_area, comm_size);
-		async_hangup(sess);
-		return rc;
-	}
-	
-	rc = devcon_add(service_id, sess, bsize, comm_area, comm_size);
-	if (rc != EOK) {
-		munmap(comm_area, comm_size);
-		async_hangup(sess);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-void block_fini(service_id_t service_id)
-{
-	devcon_t *devcon = devcon_search(service_id);
-	assert(devcon);
-	
-	if (devcon->cache)
-		(void) block_cache_fini(service_id);
-	
-	devcon_remove(devcon);
-	
-	if (devcon->bb_buf)
-		free(devcon->bb_buf);
-	
-	munmap(devcon->comm_area, devcon->comm_size);
-	async_hangup(devcon->sess);
-	
-	free(devcon);
-}
-
-int block_bb_read(service_id_t service_id, aoff64_t ba)
-{
-	void *bb_buf;
-	int rc;
-
-	devcon_t *devcon = devcon_search(service_id);
-	if (!devcon)
-		return ENOENT;
-	if (devcon->bb_buf)
-		return EEXIST;
-	bb_buf = malloc(devcon->pblock_size);
-	if (!bb_buf)
-		return ENOMEM;
-
-	fibril_mutex_lock(&devcon->comm_area_lock);
-	rc = read_blocks(devcon, 0, 1);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&devcon->comm_area_lock);
-	    	free(bb_buf);
-		return rc;
-	}
-	memcpy(bb_buf, devcon->comm_area, devcon->pblock_size);
-	fibril_mutex_unlock(&devcon->comm_area_lock);
-
-	devcon->bb_buf = bb_buf;
-	devcon->bb_addr = ba;
-
-	return EOK;
-}
-
-void *block_bb_get(service_id_t service_id)
-{
-	devcon_t *devcon = devcon_search(service_id);
-	assert(devcon);
-	return devcon->bb_buf;
-}
-
-static hash_index_t cache_hash(unsigned long *key)
-{
-	return MERGE_LOUP32(key[0], key[1]) & (CACHE_BUCKETS - 1);
-}
-
-static int cache_compare(unsigned long *key, hash_count_t keys, link_t *item)
-{
-	block_t *b = hash_table_get_instance(item, block_t, hash_link);
-	return b->lba == MERGE_LOUP32(key[0], key[1]);
-}
-
-static void cache_remove_callback(link_t *item)
-{
-}
-
-static hash_table_operations_t cache_ops = {
-	.hash = cache_hash,
-	.compare = cache_compare,
-	.remove_callback = cache_remove_callback
-};
-
-int block_cache_init(service_id_t service_id, size_t size, unsigned blocks,
-    enum cache_mode mode)
-{
-	devcon_t *devcon = devcon_search(service_id);
-	cache_t *cache;
-	if (!devcon)
-		return ENOENT;
-	if (devcon->cache)
-		return EEXIST;
-	cache = malloc(sizeof(cache_t));
-	if (!cache)
-		return ENOMEM;
-	
-	fibril_mutex_initialize(&cache->lock);
-	list_initialize(&cache->free_list);
-	cache->lblock_size = size;
-	cache->block_count = blocks;
-	cache->blocks_cached = 0;
-	cache->mode = mode;
-
-	/* Allow 1:1 or small-to-large block size translation */
-	if (cache->lblock_size % devcon->pblock_size != 0) {
-		free(cache);
-		return ENOTSUP;
-	}
-
-	cache->blocks_cluster = cache->lblock_size / devcon->pblock_size;
-
-	if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 2,
-	    &cache_ops)) {
-		free(cache);
-		return ENOMEM;
-	}
-
-	devcon->cache = cache;
-	return EOK;
-}
-
-int block_cache_fini(service_id_t service_id)
-{
-	devcon_t *devcon = devcon_search(service_id);
-	cache_t *cache;
-	int rc;
-
-	if (!devcon)
-		return ENOENT;
-	if (!devcon->cache)
-		return EOK;
-	cache = devcon->cache;
-	
-	/*
-	 * We are expecting to find all blocks for this device handle on the
-	 * free list, i.e. the block reference count should be zero. Do not
-	 * bother with the cache and block locks because we are single-threaded.
-	 */
-	while (!list_empty(&cache->free_list)) {
-		block_t *b = list_get_instance(list_first(&cache->free_list),
-		    block_t, free_link);
-
-		list_remove(&b->free_link);
-		if (b->dirty) {
-			memcpy(devcon->comm_area, b->data, b->size);
-			rc = write_blocks(devcon, b->pba, cache->blocks_cluster);
-			if (rc != EOK)
-				return rc;
-		}
-
-		unsigned long key[2] = {
-			LOWER32(b->lba),
-			UPPER32(b->lba)
-		};
-		hash_table_remove(&cache->block_hash, key, 2);
-		
-		free(b->data);
-		free(b);
-	}
-
-	hash_table_destroy(&cache->block_hash);
-	devcon->cache = NULL;
-	free(cache);
-
-	return EOK;
-}
-
-#define CACHE_LO_WATERMARK	10	
-#define CACHE_HI_WATERMARK	20	
-static bool cache_can_grow(cache_t *cache)
-{
-	if (cache->blocks_cached < CACHE_LO_WATERMARK)
-		return true;
-	if (!list_empty(&cache->free_list))
-		return false;
-	return true;
-}
-
-static void block_initialize(block_t *b)
-{
-	fibril_mutex_initialize(&b->lock);
-	b->refcnt = 1;
-	b->dirty = false;
-	b->toxic = false;
-	fibril_rwlock_initialize(&b->contents_lock);
-	link_initialize(&b->free_link);
-	link_initialize(&b->hash_link);
-}
-
-/** Instantiate a block in memory and get a reference to it.
- *
- * @param block			Pointer to where the function will store the
- * 				block pointer on success.
- * @param service_id		Service ID of the block device.
- * @param ba			Block address (logical).
- * @param flags			If BLOCK_FLAGS_NOREAD is specified, block_get()
- * 				will not read the contents of the block from the
- *				device.
- *
- * @return			EOK on success or a negative error code.
- */
-int block_get(block_t **block, service_id_t service_id, aoff64_t ba, int flags)
-{
-	devcon_t *devcon;
-	cache_t *cache;
-	block_t *b;
-	link_t *l;
-	unsigned long key[2] = {
-		LOWER32(ba),
-		UPPER32(ba)
-	};
-
-	int rc;
-	
-	devcon = devcon_search(service_id);
-
-	assert(devcon);
-	assert(devcon->cache);
-	
-	cache = devcon->cache;
-
-retry:
-	rc = EOK;
-	b = NULL;
-
-	fibril_mutex_lock(&cache->lock);
-	l = hash_table_find(&cache->block_hash, key);
-	if (l) {
-found:
-		/*
-		 * We found the block in the cache.
-		 */
-		b = hash_table_get_instance(l, block_t, hash_link);
-		fibril_mutex_lock(&b->lock);
-		if (b->refcnt++ == 0)
-			list_remove(&b->free_link);
-		if (b->toxic)
-			rc = EIO;
-		fibril_mutex_unlock(&b->lock);
-		fibril_mutex_unlock(&cache->lock);
-	} else {
-		/*
-		 * The block was not found in the cache.
-		 */
-		if (cache_can_grow(cache)) {
-			/*
-			 * We can grow the cache by allocating new blocks.
-			 * Should the allocation fail, we fail over and try to
-			 * recycle a block from the cache.
-			 */
-			b = malloc(sizeof(block_t));
-			if (!b)
-				goto recycle;
-			b->data = malloc(cache->lblock_size);
-			if (!b->data) {
-				free(b);
-				b = NULL;
-				goto recycle;
-			}
-			cache->blocks_cached++;
-		} else {
-			/*
-			 * Try to recycle a block from the free list.
-			 */
-recycle:
-			if (list_empty(&cache->free_list)) {
-				fibril_mutex_unlock(&cache->lock);
-				rc = ENOMEM;
-				goto out;
-			}
-			l = list_first(&cache->free_list);
-			b = list_get_instance(l, block_t, free_link);
-
-			fibril_mutex_lock(&b->lock);
-			if (b->dirty) {
-				/*
-				 * The block needs to be written back to the
-				 * device before it changes identity. Do this
-				 * while not holding the cache lock so that
-				 * concurrency is not impeded. Also move the
-				 * block to the end of the free list so that we
-				 * do not slow down other instances of
-				 * block_get() draining the free list.
-				 */
-				list_remove(&b->free_link);
-				list_append(&b->free_link, &cache->free_list);
-				fibril_mutex_unlock(&cache->lock);
-				fibril_mutex_lock(&devcon->comm_area_lock);
-				memcpy(devcon->comm_area, b->data, b->size);
-				rc = write_blocks(devcon, b->pba,
-				    cache->blocks_cluster);
-				fibril_mutex_unlock(&devcon->comm_area_lock);
-				if (rc != EOK) {
-					/*
-					 * We did not manage to write the block
-					 * to the device. Keep it around for
-					 * another try. Hopefully, we will grab
-					 * another block next time.
-					 */
-					fibril_mutex_unlock(&b->lock);
-					goto retry;
-				}
-				b->dirty = false;
-				if (!fibril_mutex_trylock(&cache->lock)) {
-					/*
-					 * Somebody is probably racing with us.
-					 * Unlock the block and retry.
-					 */
-					fibril_mutex_unlock(&b->lock);
-					goto retry;
-				}
-				l = hash_table_find(&cache->block_hash, key);
-				if (l) {
-					/*
-					 * Someone else must have already
-					 * instantiated the block while we were
-					 * not holding the cache lock.
-					 * Leave the recycled block on the
-					 * freelist and continue as if we
-					 * found the block of interest during
-					 * the first try.
-					 */
-					fibril_mutex_unlock(&b->lock);
-					goto found;
-				}
-
-			}
-			fibril_mutex_unlock(&b->lock);
-
-			/*
-			 * Unlink the block from the free list and the hash
-			 * table.
-			 */
-			list_remove(&b->free_link);
-			unsigned long temp_key[2] = {
-				LOWER32(b->lba),
-				UPPER32(b->lba)
-			};
-			hash_table_remove(&cache->block_hash, temp_key, 2);
-		}
-
-		block_initialize(b);
-		b->service_id = service_id;
-		b->size = cache->lblock_size;
-		b->lba = ba;
-		b->pba = ba_ltop(devcon, b->lba);
-		hash_table_insert(&cache->block_hash, key, &b->hash_link);
-
-		/*
-		 * Lock the block before releasing the cache lock. Thus we don't
-		 * kill concurrent operations on the cache while doing I/O on
-		 * the block.
-		 */
-		fibril_mutex_lock(&b->lock);
-		fibril_mutex_unlock(&cache->lock);
-
-		if (!(flags & BLOCK_FLAGS_NOREAD)) {
-			/*
-			 * The block contains old or no data. We need to read
-			 * the new contents from the device.
-			 */
-			fibril_mutex_lock(&devcon->comm_area_lock);
-			rc = read_blocks(devcon, b->pba, cache->blocks_cluster);
-			memcpy(b->data, devcon->comm_area, cache->lblock_size);
-			fibril_mutex_unlock(&devcon->comm_area_lock);
-			if (rc != EOK) 
-				b->toxic = true;
-		} else
-			rc = EOK;
-
-		fibril_mutex_unlock(&b->lock);
-	}
-out:
-	if ((rc != EOK) && b) {
-		assert(b->toxic);
-		(void) block_put(b);
-		b = NULL;
-	}
-	*block = b;
-	return rc;
-}
-
-/** Release a reference to a block.
- *
- * If the last reference is dropped, the block is put on the free list.
- *
- * @param block		Block of which a reference is to be released.
- *
- * @return		EOK on success or a negative error code.
- */
-int block_put(block_t *block)
-{
-	devcon_t *devcon = devcon_search(block->service_id);
-	cache_t *cache;
-	unsigned blocks_cached;
-	enum cache_mode mode;
-	int rc = EOK;
-
-	assert(devcon);
-	assert(devcon->cache);
-	assert(block->refcnt >= 1);
-
-	cache = devcon->cache;
-
-retry:
-	fibril_mutex_lock(&cache->lock);
-	blocks_cached = cache->blocks_cached;
-	mode = cache->mode;
-	fibril_mutex_unlock(&cache->lock);
-
-	/*
-	 * Determine whether to sync the block. Syncing the block is best done
-	 * when not holding the cache lock as it does not impede concurrency.
-	 * Since the situation may have changed when we unlocked the cache, the
-	 * blocks_cached and mode variables are mere hints. We will recheck the
-	 * conditions later when the cache lock is held again.
-	 */
-	fibril_mutex_lock(&block->lock);
-	if (block->toxic)
-		block->dirty = false;	/* will not write back toxic block */
-	if (block->dirty && (block->refcnt == 1) &&
-	    (blocks_cached > CACHE_HI_WATERMARK || mode != CACHE_MODE_WB)) {
-		fibril_mutex_lock(&devcon->comm_area_lock);
-		memcpy(devcon->comm_area, block->data, block->size);
-		rc = write_blocks(devcon, block->pba, cache->blocks_cluster);
-		fibril_mutex_unlock(&devcon->comm_area_lock);
-		block->dirty = false;
-	}
-	fibril_mutex_unlock(&block->lock);
-
-	fibril_mutex_lock(&cache->lock);
-	fibril_mutex_lock(&block->lock);
-	if (!--block->refcnt) {
-		/*
-		 * Last reference to the block was dropped. Either free the
-		 * block or put it on the free list. In case of an I/O error,
-		 * free the block.
-		 */
-		if ((cache->blocks_cached > CACHE_HI_WATERMARK) ||
-		    (rc != EOK)) {
-			/*
-			 * Currently there are too many cached blocks or there
-			 * was an I/O error when writing the block back to the
-			 * device.
-			 */
-			if (block->dirty) {
-				/*
-				 * We cannot sync the block while holding the
-				 * cache lock. Release everything and retry.
-				 */
-				block->refcnt++;
-				fibril_mutex_unlock(&block->lock);
-				fibril_mutex_unlock(&cache->lock);
-				goto retry;
-			}
-			/*
-			 * Take the block out of the cache and free it.
-			 */
-			unsigned long key[2] = {
-				LOWER32(block->lba),
-				UPPER32(block->lba)
-			};
-			hash_table_remove(&cache->block_hash, key, 2);
-			fibril_mutex_unlock(&block->lock);
-			free(block->data);
-			free(block);
-			cache->blocks_cached--;
-			fibril_mutex_unlock(&cache->lock);
-			return rc;
-		}
-		/*
-		 * Put the block on the free list.
-		 */
-		if (cache->mode != CACHE_MODE_WB && block->dirty) {
-			/*
-			 * We cannot sync the block while holding the cache
-			 * lock. Release everything and retry.
-			 */
-			block->refcnt++;
-			fibril_mutex_unlock(&block->lock);
-			fibril_mutex_unlock(&cache->lock);
-			goto retry;
-		}
-		list_append(&block->free_link, &cache->free_list);
-	}
-	fibril_mutex_unlock(&block->lock);
-	fibril_mutex_unlock(&cache->lock);
-
-	return rc;
-}
-
-/** Read sequential data from a block device.
- *
- * @param service_id	Service ID of the block device.
- * @param bufpos	Pointer to the first unread valid offset within the
- * 			communication buffer.
- * @param buflen	Pointer to the number of unread bytes that are ready in
- * 			the communication buffer.
- * @param pos		Device position to be read.
- * @param dst		Destination buffer.
- * @param size		Size of the destination buffer.
- * @param block_size	Block size to be used for the transfer.
- *
- * @return		EOK on success or a negative return code on failure.
- */
-int block_seqread(service_id_t service_id, size_t *bufpos, size_t *buflen,
-    aoff64_t *pos, void *dst, size_t size)
-{
-	size_t offset = 0;
-	size_t left = size;
-	size_t block_size;
-	devcon_t *devcon;
-
-	devcon = devcon_search(service_id);
-	assert(devcon);
-	block_size = devcon->pblock_size;
-	
-	fibril_mutex_lock(&devcon->comm_area_lock);
-	while (left > 0) {
-		size_t rd;
-		
-		if (*bufpos + left < *buflen)
-			rd = left;
-		else
-			rd = *buflen - *bufpos;
-		
-		if (rd > 0) {
-			/*
-			 * Copy the contents of the communication buffer to the
-			 * destination buffer.
-			 */
-			memcpy(dst + offset, devcon->comm_area + *bufpos, rd);
-			offset += rd;
-			*bufpos += rd;
-			*pos += rd;
-			left -= rd;
-		}
-		
-		if (*bufpos == *buflen) {
-			/* Refill the communication buffer with a new block. */
-			int rc;
-
-			rc = read_blocks(devcon, *pos / block_size, 1);
-			if (rc != EOK) {
-				fibril_mutex_unlock(&devcon->comm_area_lock);
-				return rc;
-			}
-			
-			*bufpos = 0;
-			*buflen = block_size;
-		}
-	}
-	fibril_mutex_unlock(&devcon->comm_area_lock);
-	
-	return EOK;
-}
-
-/** Read blocks directly from device (bypass cache).
- *
- * @param service_id	Service ID of the block device.
- * @param ba		Address of first block (physical).
- * @param cnt		Number of blocks.
- * @param src		Buffer for storing the data.
- *
- * @return		EOK on success or negative error code on failure.
- */
-int block_read_direct(service_id_t service_id, aoff64_t ba, size_t cnt, void *buf)
-{
-	devcon_t *devcon;
-	int rc;
-
-	devcon = devcon_search(service_id);
-	assert(devcon);
-	
-	fibril_mutex_lock(&devcon->comm_area_lock);
-
-	rc = read_blocks(devcon, ba, cnt);
-	if (rc == EOK)
-		memcpy(buf, devcon->comm_area, devcon->pblock_size * cnt);
-
-	fibril_mutex_unlock(&devcon->comm_area_lock);
-
-	return rc;
-}
-
-/** Write blocks directly to device (bypass cache).
- *
- * @param service_id	Service ID of the block device.
- * @param ba		Address of first block (physical).
- * @param cnt		Number of blocks.
- * @param src		The data to be written.
- *
- * @return		EOK on success or negative error code on failure.
- */
-int block_write_direct(service_id_t service_id, aoff64_t ba, size_t cnt,
-    const void *data)
-{
-	devcon_t *devcon;
-	int rc;
-
-	devcon = devcon_search(service_id);
-	assert(devcon);
-	
-	fibril_mutex_lock(&devcon->comm_area_lock);
-
-	memcpy(devcon->comm_area, data, devcon->pblock_size * cnt);
-	rc = write_blocks(devcon, ba, cnt);
-
-	fibril_mutex_unlock(&devcon->comm_area_lock);
-
-	return rc;
-}
-
-/** Get device block size.
- *
- * @param service_id	Service ID of the block device.
- * @param bsize		Output block size.
- *
- * @return		EOK on success or negative error code on failure.
- */
-int block_get_bsize(service_id_t service_id, size_t *bsize)
-{
-	devcon_t *devcon;
-
-	devcon = devcon_search(service_id);
-	assert(devcon);
-	
-	return get_block_size(devcon->sess, bsize);
-}
-
-/** Get number of blocks on device.
- *
- * @param service_id	Service ID of the block device.
- * @param nblocks	Output number of blocks.
- *
- * @return		EOK on success or negative error code on failure.
- */
-int block_get_nblocks(service_id_t service_id, aoff64_t *nblocks)
-{
-	devcon_t *devcon = devcon_search(service_id);
-	assert(devcon);
-	
-	return get_num_blocks(devcon->sess, nblocks);
-}
-
-/** Read bytes directly from the device (bypass cache)
- * 
- * @param service_id	Service ID of the block device.
- * @param abs_offset	Absolute offset in bytes where to start reading
- * @param bytes			Number of bytes to read
- * @param data			Buffer that receives the data
- * 
- * @return		EOK on success or negative error code on failure.
- */
-int block_read_bytes_direct(service_id_t service_id, aoff64_t abs_offset,
-    size_t bytes, void *data)
-{
-	int rc;
-	size_t phys_block_size;
-	size_t buf_size;
-	void *buffer;
-	aoff64_t first_block;
-	aoff64_t last_block;
-	size_t blocks;
-	size_t offset;
-	
-	rc = block_get_bsize(service_id, &phys_block_size);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	/* calculate data position and required space */
-	first_block = abs_offset / phys_block_size;
-	offset = abs_offset % phys_block_size;
-	last_block = (abs_offset + bytes - 1) / phys_block_size;
-	blocks = last_block - first_block + 1;
-	buf_size = blocks * phys_block_size;
-	
-	/* read the data into memory */
-	buffer = malloc(buf_size);
-	if (buffer == NULL) {
-		return ENOMEM;
-	}
-	
-	rc = block_read_direct(service_id, first_block, blocks, buffer);
-	if (rc != EOK) {
-		free(buffer);
-		return rc;
-	}
-	
-	/* copy the data from the buffer */
-	memcpy(data, buffer + offset, bytes);
-	free(buffer);
-	
-	return EOK;
-}
-
-/** Get TOC from device.
- *
- * @param service_id Service ID of the block device.
- * @param session    Starting session.
- *
- * @return Allocated TOC structure.
- * @return NULL on failure.
- *
- */
-toc_block_t *block_get_toc(service_id_t service_id, uint8_t session)
-{
-	devcon_t *devcon = devcon_search(service_id);
-	assert(devcon);
-	
-	toc_block_t *toc = NULL;
-	
-	fibril_mutex_lock(&devcon->comm_area_lock);
-	
-	async_exch_t *exch = async_exchange_begin(devcon->sess);
-	int rc = async_req_1_0(exch, BD_READ_TOC, session);
-	async_exchange_end(exch);
-	
-	if (rc == EOK) {
-		toc = (toc_block_t *) malloc(sizeof(toc_block_t));
-		if (toc != NULL) {
-			memset(toc, 0, sizeof(toc_block_t));
-			memcpy(toc, devcon->comm_area,
-			    min(devcon->pblock_size, sizeof(toc_block_t)));
-		}
-	}
-	
-	
-	fibril_mutex_unlock(&devcon->comm_area_lock);
-	
-	return toc;
-}
-
-/** Read blocks from block device.
- *
- * @param devcon	Device connection.
- * @param ba		Address of first block.
- * @param cnt		Number of blocks.
- * @param src		Buffer for storing the data.
- *
- * @return		EOK on success or negative error code on failure.
- */
-static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
-{
-	assert(devcon);
-	
-	async_exch_t *exch = async_exchange_begin(devcon->sess);
-	int rc = async_req_3_0(exch, BD_READ_BLOCKS, LOWER32(ba),
-	    UPPER32(ba), cnt);
-	async_exchange_end(exch);
-	
-	if (rc != EOK) {
-		printf("Error %d reading %zu blocks starting at block %" PRIuOFF64
-		    " from device handle %" PRIun "\n", rc, cnt, ba,
-		    devcon->service_id);
-#ifndef NDEBUG
-		stacktrace_print();
-#endif
-	}
-	
-	return rc;
-}
-
-/** Write block to block device.
- *
- * @param devcon	Device connection.
- * @param ba		Address of first block.
- * @param cnt		Number of blocks.
- * @param src		Buffer containing the data to write.
- *
- * @return		EOK on success or negative error code on failure.
- */
-static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
-{
-	assert(devcon);
-	
-	async_exch_t *exch = async_exchange_begin(devcon->sess);
-	int rc = async_req_3_0(exch, BD_WRITE_BLOCKS, LOWER32(ba),
-	    UPPER32(ba), cnt);
-	async_exchange_end(exch);
-	
-	if (rc != EOK) {
-		printf("Error %d writing %zu blocks starting at block %" PRIuOFF64
-		    " to device handle %" PRIun "\n", rc, cnt, ba, devcon->service_id);
-#ifndef NDEBUG
-		stacktrace_print();
-#endif
-	}
-	
-	return rc;
-}
-
-/** Get block size used by the device. */
-static int get_block_size(async_sess_t *sess, size_t *bsize)
-{
-	sysarg_t bs;
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_req_0_1(exch, BD_GET_BLOCK_SIZE, &bs);
-	async_exchange_end(exch);
-	
-	if (rc == EOK)
-		*bsize = (size_t) bs;
-	
-	return rc;
-}
-
-/** Get total number of blocks on block device. */
-static int get_num_blocks(async_sess_t *sess, aoff64_t *nblocks)
-{
-	sysarg_t nb_l;
-	sysarg_t nb_h;
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	int rc = async_req_0_2(exch, BD_GET_NUM_BLOCKS, &nb_l, &nb_h);
-	async_exchange_end(exch);
-	
-	if (rc == EOK)
-		*nblocks = (aoff64_t) MERGE_LOUP32(nb_l, nb_h);
-	
-	return rc;
-}
-
-/** Convert logical block address to physical block address. */
-static aoff64_t ba_ltop(devcon_t *devcon, aoff64_t lba)
-{
-	assert(devcon->cache != NULL);
-	return lba * devcon->cache->blocks_cluster;
-}
-
-/** @}
- */
Index: pace/lib/block/libblock.h
===================================================================
--- uspace/lib/block/libblock.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,137 +1,0 @@
-/*
- * Copyright (c) 2008 Jakub Jermar
- * Copyright (c) 2008 Martin Decky
- * Copyright (c) 2011 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 libblock 
- * @{
- */ 
-/**
- * @file
- */
-
-#ifndef LIBBLOCK_LIBBLOCK_H_
-#define LIBBLOCK_LIBBLOCK_H_
-
-#include <stdint.h>
-#include <async.h>
-#include "../../srv/vfs/vfs.h"
-#include <fibril_synch.h>
-#include <adt/hash_table.h>
-#include <adt/list.h>
-
-/*
- * Flags that can be used with block_get().
- */
-
-/** 
- * This macro is a symbolic value for situations where no special flags are
- * needed.
- */
-#define BLOCK_FLAGS_NONE	0
-
-/**
- * When the client of block_get() intends to overwrite the current contents of
- * the block, this flag is used to avoid the unnecessary read.
- */
-#define BLOCK_FLAGS_NOREAD	1
-
-typedef struct block {
-	/** Mutex protecting the reference count. */
-	fibril_mutex_t lock;
-	/** Number of references to the block_t structure. */
-	unsigned refcnt;
-	/** If true, the block needs to be written back to the block device. */
-	bool dirty;
-	/** If true, the blcok does not contain valid data. */
-	bool toxic;
-	/** Readers / Writer lock protecting the contents of the block. */
-	fibril_rwlock_t contents_lock;
-	/** Service ID of service providing the block device. */
-	service_id_t service_id;
-	/** Logical block address */
-	aoff64_t lba;
-	/** Physical block address */
-	aoff64_t pba;
-	/** Size of the block. */
-	size_t size;
-	/** Link for placing the block into the free block list. */
-	link_t free_link;
-	/** Link for placing the block into the block hash table. */ 
-	link_t hash_link;
-	/** Buffer with the block data. */
-	void *data;
-} block_t;
-
-/** Caching mode */
-enum cache_mode {
-	/** Write-Through */
-	CACHE_MODE_WT,
-	/** Write-Back */
-	CACHE_MODE_WB
-};
-
-typedef struct {
-	uint16_t size;
-	uint8_t first_session;
-	uint8_t last_session;
-	
-	uint8_t res0;
-	uint8_t adr_ctrl;
-	uint8_t first_track;
-	uint8_t res1;
-	
-	uint32_t first_lba;
-} __attribute__((packed)) toc_block_t;
-
-extern int block_init(exch_mgmt_t, service_id_t, size_t);
-extern void block_fini(service_id_t);
-
-extern int block_bb_read(service_id_t, aoff64_t);
-extern void *block_bb_get(service_id_t);
-
-extern int block_cache_init(service_id_t, size_t, unsigned, enum cache_mode);
-extern int block_cache_fini(service_id_t);
-
-extern int block_get(block_t **, service_id_t, aoff64_t, int);
-extern int block_put(block_t *);
-
-extern int block_seqread(service_id_t, size_t *, size_t *, aoff64_t *, void *,
-    size_t);
-
-extern int block_get_bsize(service_id_t, size_t *);
-extern int block_get_nblocks(service_id_t, aoff64_t *);
-extern toc_block_t *block_get_toc(service_id_t, uint8_t);
-extern int block_read_direct(service_id_t, aoff64_t, size_t, void *);
-extern int block_read_bytes_direct(service_id_t, aoff64_t, size_t, void *);
-extern int block_write_direct(service_id_t, aoff64_t, size_t, const void *);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -62,4 +62,6 @@
 	generic/ddi.c \
 	generic/as.c \
+	generic/bd.c \
+	generic/bd_srv.c \
 	generic/cap.c \
 	generic/cfg.c \
@@ -69,6 +71,11 @@
 	generic/device/hw_res_parsed.c \
 	generic/device/char_dev.c \
+	generic/device/clock_dev.c \
+	generic/device/battery_dev.c \
+	generic/device/graph_dev.c \
 	generic/device/nic.c \
 	generic/device/pci.c \
+	generic/device/ahci.c \
+	generic/dlfcn.c \
 	generic/elf/elf_load.c \
 	generic/event.c \
@@ -91,7 +98,11 @@
 	generic/inetping.c \
 	generic/io/asprintf.c \
+	generic/io/input.c \
 	generic/io/io.c \
+	generic/io/chargrid.c \
+	generic/io/output.c \
 	generic/io/printf.c \
 	generic/io/log.c \
+	generic/io/logctl.c \
 	generic/io/klog.c \
 	generic/io/snprintf.c \
@@ -99,7 +110,13 @@
 	generic/io/vsnprintf.c \
 	generic/io/printf_core.c \
+	generic/io/con_srv.c \
 	generic/io/console.c \
+	generic/io/visualizer.c \
+	generic/io/window.c \
 	generic/iplink.c \
 	generic/iplink_srv.c \
+	generic/ieee_double.c \
+	generic/power_of_ten.c \
+	generic/double_to_str.c \
 	generic/malloc.c \
 	generic/sysinfo.c \
@@ -111,5 +128,4 @@
 	generic/adt/list.c \
 	generic/adt/hash_table.c \
-	generic/adt/hash_set.c \
 	generic/adt/dynamic_fifo.c \
 	generic/adt/char_map.c \
@@ -132,5 +148,4 @@
 ifeq ($(CONFIG_RTLD),y)
 	GENERIC_SOURCES += \
-		generic/dlfcn.c \
 		generic/rtld/rtld.c \
 		generic/rtld/dynamic.c \
Index: uspace/lib/c/arch/abs32le/_link.ld.in
===================================================================
--- uspace/lib/c/arch/abs32le/_link.ld.in	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/abs32le/_link.ld.in	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -14,16 +14,19 @@
 SECTIONS {
 #ifdef LOADER
-	.interp : {
-		*(.interp);
-	} :interp
-	
 	. = 0x70001000 + SIZEOF_HEADERS;
 #else
 	. = 0x1000 + SIZEOF_HEADERS;
 #endif
+	
 	.text : {
 		*(.text .text.*);
 		*(.rodata .rodata.*);
 	} :text
+	
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp :text
+#endif
 	
 	. = . + 0x1000;
Index: uspace/lib/c/arch/abs32le/include/types.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/types.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/abs32le/include/types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,4 +47,5 @@
 
 typedef uint32_t sysarg_t;
+typedef int32_t native_t;
 
 typedef int32_t ssize_t;
Index: uspace/lib/c/arch/amd64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/amd64/_link.ld.in	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/amd64/_link.ld.in	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -15,12 +15,9 @@
 SECTIONS {
 #ifdef LOADER
-	.interp : {
-		*(.interp);
-	} :interp
-	
 	. = 0x70001000 + SIZEOF_HEADERS;
 #else
 	. = 0x1000 + SIZEOF_HEADERS;
 #endif
+	
 	.init : {
 		*(.init);
@@ -31,4 +28,10 @@
 		*(.rodata .rodata.*);
 	} :text
+	
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp :text
+#endif
 	
 	. = . + 0x1000;
Index: uspace/lib/c/arch/amd64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/amd64/include/elf_linux.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/amd64/include/elf_linux.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -66,4 +66,16 @@
 	uint64_t rsp;
 	uint64_t ss;
+
+	/*
+	 * The following registers need to be part of elf_regs_t.
+	 * Unfortunately, we don't have any information about them in our
+	 * istate_t.
+	 */
+	uint64_t unused_fs_base;
+	uint64_t unused_gs_base;
+	uint64_t unused_ds;
+	uint64_t unused_es;
+	uint64_t unused_fs;
+	uint64_t unused_gs;
 } elf_regs_t;
 
@@ -91,4 +103,14 @@
 	elf_regs->rsp = istate->rsp;
 	elf_regs->ss = istate->ss;
+
+	/*
+	 * Reset the registers for which there is not enough info in istate_t.
+	 */
+	elf_regs->unused_fs_base = 0;
+	elf_regs->unused_gs_base = 0;
+	elf_regs->unused_ds = 0;
+	elf_regs->unused_es = 0;
+	elf_regs->unused_fs = 0;
+	elf_regs->unused_gs = 0;
 }
 
Index: uspace/lib/c/arch/amd64/include/types.h
===================================================================
--- uspace/lib/c/arch/amd64/include/types.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/amd64/include/types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,4 +47,5 @@
 
 typedef uint64_t sysarg_t;
+typedef int64_t native_t;
 
 typedef int64_t ssize_t;
Index: uspace/lib/c/arch/arm32/Makefile.common
===================================================================
--- uspace/lib/c/arch/arm32/Makefile.common	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/arm32/Makefile.common	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -28,5 +28,6 @@
 #
 
-GCC_CFLAGS += -ffixed-r9 -mtp=soft -fno-omit-frame-pointer -march=armv4
+BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
+GCC_CFLAGS += -ffixed-r9 -mtp=soft -fno-omit-frame-pointer -march=armv4 -mapcs-frame
 
 ENDIANESS = LE
Index: uspace/lib/c/arch/arm32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/arm32/_link.ld.in	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/arm32/_link.ld.in	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -14,12 +14,9 @@
 SECTIONS {
 #ifdef LOADER
-	.interp : {
-		*(.interp);
-	} :interp
-	
 	. = 0x70001000 + SIZEOF_HEADERS;
 #else
 	. = 0x1000 + SIZEOF_HEADERS;
 #endif
+	
 	.init : {
 		*(.init);
@@ -30,4 +27,10 @@
 		*(.rodata .rodata.*);
 	} :text
+	
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp :text
+#endif
 	
 	. = . + 0x1000;
Index: uspace/lib/c/arch/arm32/include/types.h
===================================================================
--- uspace/lib/c/arch/arm32/include/types.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/arm32/include/types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -48,4 +48,5 @@
 
 typedef uint32_t sysarg_t;
+typedef int32_t native_t;
 
 typedef int32_t ssize_t;
Index: uspace/lib/c/arch/arm32/src/fibril.S
===================================================================
--- uspace/lib/c/arch/arm32/src/fibril.S	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/arm32/src/fibril.S	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,5 +35,5 @@
 	stmia r0!, {sp, lr}
 	stmia r0!, {r4-r11}
-
+	
 	# return 1
 	mov r0, #1
@@ -43,6 +43,6 @@
 	ldmia r0!, {sp, lr}
 	ldmia r0!, {r4-r11}
-
-	#return 0
+	
+	# return 0
 	mov r0, #0
 	mov pc, lr
Index: uspace/lib/c/arch/arm32/src/stacktrace_asm.S
===================================================================
--- uspace/lib/c/arch/arm32/src/stacktrace_asm.S	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/arm32/src/stacktrace_asm.S	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,4 +41,4 @@
 
 stacktrace_pc_get:
-	mov r0, lr 
+	mov r0, lr
 	mov pc, lr
Index: uspace/lib/c/arch/arm32/src/thread_entry.s
===================================================================
--- uspace/lib/c/arch/arm32/src/thread_entry.s	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/arm32/src/thread_entry.s	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,4 +42,4 @@
 	push {fp, ip, lr, pc}
 	sub fp, ip, #4
-
-        b __thread_main
+	
+	b __thread_main
Index: uspace/lib/c/arch/ia32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ia32/_link.ld.in	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/ia32/_link.ld.in	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -19,9 +19,4 @@
 
 SECTIONS {
-#if defined(LOADER) || defined(DLEXE)
-	.interp : {
-		*(.interp);
-	} :interp
-#endif
 #ifdef LOADER
 	. = 0x70001000 + SIZEOF_HEADERS;
@@ -29,4 +24,5 @@
 	. = 0x1000 + SIZEOF_HEADERS;
 #endif
+	
 	.init : {
 		*(.init);
@@ -37,5 +33,5 @@
 		*(.rodata .rodata.*);
 	} :text
-
+	
 #if defined(SHLIB) || defined(DLEXE)
 	.rel.plt : {
@@ -66,4 +62,11 @@
 	} :text
 #endif
+	
+#if defined(LOADER) || defined(DLEXE)
+	.interp : {
+		*(.interp);
+	} :interp :text
+#endif
+	
 	. = . + 0x1000;
 	
@@ -80,12 +83,13 @@
 #if defined(SHLIB) || defined(DLEXE)
 	.data.rel : {
-                *(.data.rel .data.rel.*);
+		*(.data.rel .data.rel.*);
 	} :data
-
+	
 	.got : {
-                *(.got);
+		*(.got);
 	} :data
+	
 	.got.plt : {
-                *(.got.plt);
+		*(.got.plt);
 	} :data
 #endif
Index: uspace/lib/c/arch/ia32/include/types.h
===================================================================
--- uspace/lib/c/arch/ia32/include/types.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/ia32/include/types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,4 +47,5 @@
 
 typedef uint32_t sysarg_t;
+typedef int32_t native_t;
 
 typedef int32_t ssize_t;
Index: uspace/lib/c/arch/ia64/Makefile.common
===================================================================
--- uspace/lib/c/arch/ia64/Makefile.common	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/ia64/Makefile.common	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -27,5 +27,15 @@
 #
 
-GCC_CFLAGS += -fno-unwind-tables
+#
+# FIXME:
+#
+# The -fno-selective-scheduling and -fno-selective-scheduling2 options
+# should be removed as soon as a bug in GCC concerning unchecked
+# speculative loads is fixed.
+#
+# See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53975 for reference.
+#
+
+GCC_CFLAGS += -fno-unwind-tables -fno-selective-scheduling -fno-selective-scheduling2
 
 ENDIANESS = LE
Index: uspace/lib/c/arch/ia64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ia64/_link.ld.in	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/ia64/_link.ld.in	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -14,18 +14,12 @@
 SECTIONS {
 #ifdef LOADER
-	.interp : {
-		*(.interp);
-	} :interp
-	
 	. = 0x800000000 + SIZEOF_HEADERS;
 #else
 	. = 0x4000 + SIZEOF_HEADERS;
 #endif
-	/*
-	 * XXX This is just a work around. Problem: .init section does not
-	 * have the proper alignment.
-	 */
+	
+	/* Workaround proper alignment of the .init section */
 	. = ALIGN(., 16);
-
+	
 	.init : {
 		*(.init);
@@ -36,4 +30,10 @@
 		*(.rodata .rodata.*);
 	} :text
+	
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp :text
+#endif
 	
 	. = . + 0x4000;
Index: uspace/lib/c/arch/ia64/include/types.h
===================================================================
--- uspace/lib/c/arch/ia64/include/types.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/ia64/include/types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -57,4 +57,5 @@
 
 typedef uint64_t sysarg_t;
+typedef int64_t native_t;
 
 typedef int64_t ssize_t;
Index: uspace/lib/c/arch/mips32/Makefile.common
===================================================================
--- uspace/lib/c/arch/mips32/Makefile.common	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/mips32/Makefile.common	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -27,5 +27,6 @@
 #
 
-GCC_CFLAGS += -mips3 -mabi=32
+GCC_CFLAGS += -msoft-float -mips3 -mabi=32
+BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
 
 ENDIANESS = LE
Index: uspace/lib/c/arch/mips32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/mips32/_link.ld.in	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/mips32/_link.ld.in	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -14,12 +14,9 @@
 SECTIONS {
 #ifdef LOADER
-	.interp : {
-		*(.interp);
-	} :interp
-	
 	. = 0x70004000 + SIZEOF_HEADERS;
 #else
 	. = 0x4000 + SIZEOF_HEADERS;
 #endif
+	
 	.init : {
 		*(.init);
@@ -30,4 +27,10 @@
 		*(.rodata .rodata.*);
 	} :text
+	
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp :text
+#endif
 	
 	. = . + 0x4000;
Index: uspace/lib/c/arch/mips32/include/types.h
===================================================================
--- uspace/lib/c/arch/mips32/include/types.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/mips32/include/types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -48,4 +48,5 @@
 
 typedef uint32_t sysarg_t;
+typedef int32_t native_t;
 
 typedef int32_t ssize_t;
Index: uspace/lib/c/arch/mips32eb/Makefile.common
===================================================================
--- uspace/lib/c/arch/mips32eb/Makefile.common	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/mips32eb/Makefile.common	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -27,5 +27,6 @@
 #
 
-GCC_CFLAGS += -mips3 -mabi=32
+GCC_CFLAGS += -msoft-float -mips3 -mabi=32
+BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
 
 ENDIANESS = BE
Index: uspace/lib/c/arch/mips64/Makefile.common
===================================================================
--- uspace/lib/c/arch/mips64/Makefile.common	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/mips64/Makefile.common	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -27,5 +27,6 @@
 #
 
-GCC_CFLAGS += -mips3 -mabi=64
+GCC_CFLAGS += -msoft-float -mips3 -mabi=64
+BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
 AFLAGS = -64
 
Index: uspace/lib/c/arch/mips64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/mips64/_link.ld.in	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/mips64/_link.ld.in	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -15,12 +15,9 @@
 SECTIONS {
 #ifdef LOADER
-	.interp : {
-		*(.interp);
-	} :interp
-	
 	. = 0x70004000 + SIZEOF_HEADERS;
 #else
 	. = 0x4000 + SIZEOF_HEADERS;
 #endif
+	
 	.init : {
 		*(.init);
@@ -31,4 +28,10 @@
 		*(.rodata .rodata.*);
 	} :text
+	
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp :text
+#endif
 	
 	. = . + 0x4000;
Index: uspace/lib/c/arch/mips64/include/types.h
===================================================================
--- uspace/lib/c/arch/mips64/include/types.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/mips64/include/types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -48,4 +48,5 @@
 
 typedef uint64_t sysarg_t;
+typedef int64_t native_t;
 
 typedef int64_t ssize_t;
Index: uspace/lib/c/arch/ppc32/Makefile.common
===================================================================
--- uspace/lib/c/arch/ppc32/Makefile.common	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/ppc32/Makefile.common	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -28,4 +28,5 @@
 
 GCC_CFLAGS += -mcpu=powerpc -msoft-float -m32
+BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
 AFLAGS = -a32
 
Index: uspace/lib/c/arch/ppc32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ppc32/_link.ld.in	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/ppc32/_link.ld.in	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -15,12 +15,9 @@
 SECTIONS {
 #ifdef LOADER
-	.interp : {
-		*(.interp);
-	} :interp
-	
 	. = 0x70001000 + SIZEOF_HEADERS;
 #else
 	. = 0x1000 + SIZEOF_HEADERS;
 #endif
+	
 	.init : {
 		*(.init);
@@ -31,4 +28,10 @@
 		*(.rodata .rodata.*);
 	} :text
+	
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp :text
+#endif
 	
 	. = . + 0x1000;
Index: uspace/lib/c/arch/ppc32/include/types.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/types.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/ppc32/include/types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,4 +47,5 @@
 
 typedef uint32_t sysarg_t;
+typedef int32_t native_t;
 
 typedef int32_t ssize_t;
Index: uspace/lib/c/arch/sparc64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/sparc64/_link.ld.in	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/sparc64/_link.ld.in	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -14,12 +14,9 @@
 SECTIONS {
 #ifdef LOADER
-	.interp : {
-		*(.interp);
-	} :interp
-	
 	. = 0x70004000 + SIZEOF_HEADERS;
 #else
 	. = 0x4000 + SIZEOF_HEADERS;
 #endif
+	
 	.init : {
 		*(.init);
@@ -30,4 +27,10 @@
 		*(.rodata .rodata.*);
 	} :text
+	
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp :text
+#endif
 	
 	. = . + 0x4000;
Index: uspace/lib/c/arch/sparc64/include/types.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/types.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/arch/sparc64/include/types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,4 +47,5 @@
 
 typedef uint64_t sysarg_t;
+typedef int64_t native_t;
 
 typedef int64_t ssize_t;
Index: pace/lib/c/generic/adt/hash_set.c
===================================================================
--- uspace/lib/c/generic/adt/hash_set.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,382 +1,0 @@
-/*
- * Copyright (c) 2008 Jakub Jermar
- * Copyright (c) 2011 Radim Vansa
- * 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 <adt/hash_set.h>
-#include <adt/list.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <assert.h>
-#include <str.h>
-
-/** Create chained hash set
- *
- * @param     h         Hash set structure to be initialized.
- * @param[in] hash      Hash function
- * @param[in] equals    Equals function
- * @param[in] init_size Initial hash set size
- *
- * @return True on success
- *
- */
-int hash_set_init(hash_set_t *h, hash_set_hash hash, hash_set_equals equals,
-    size_t init_size)
-{
-	assert(h);
-	assert(hash);
-	assert(equals);
-	
-	if (init_size < HASH_SET_MIN_SIZE)
-		init_size = HASH_SET_MIN_SIZE;
-	
-	h->table = malloc(init_size * sizeof(link_t));
-	if (!h->table)
-		return false;
-	
-	for (size_t i = 0; i < init_size; i++)
-		list_initialize(&h->table[i]);
-	
-	h->size = init_size;
-	h->count = 0;
-	h->hash = hash;
-	h->equals = equals;
-	
-	return true;
-}
-
-/** Destroy a hash table instance.
- *
- * @param h Hash table to be destroyed.
- *
- */
-void hash_set_destroy(hash_set_t *h)
-{
-	assert(h);
-	free(h->table);
-}
-
-/** Rehash the internal table to new table
- *
- * @param h         Original hash set
- * @param new_table Memory for the new table
- * @param new_size  Size of the new table
- */
-static void hash_set_rehash(hash_set_t *h, list_t *new_table,
-    size_t new_size)
-{
-	assert(new_size >= HASH_SET_MIN_SIZE);
-	
-	for (size_t bucket = 0; bucket < new_size; bucket++)
-		list_initialize(&new_table[bucket]);
-	
-	for (size_t bucket = 0; bucket < h->size; bucket++) {
-		link_t *cur;
-		link_t *next;
-		
-		for (cur = h->table[bucket].head.next;
-		    cur != &h->table[bucket].head;
-		    cur = next) {
-			next = cur->next;
-			list_append(cur, &new_table[h->hash(cur) % new_size]);
-		}
-	}
-	
-	list_t *old_table = h->table;
-	h->table = new_table;
-	free(old_table);
-	h->size = new_size;
-}
-
-/** Insert item into the set.
- *
- * If the set already contains equivalent object,
- * the function fails.
- *
- * @param h    Hash table.
- * @param key  Array of all keys necessary to compute hash index.
- * @param item Item to be inserted into the hash table.
- *
- * @return True if the object was inserted
- * @return Ffalse if the set already contained equivalent object.
- *
- */
-int hash_set_insert(hash_set_t *h, link_t *item)
-{
-	assert(item);
-	assert(h);
-	assert(h->hash);
-	assert(h->equals);
-	
-	unsigned long hash = h->hash(item);
-	unsigned long chain = hash % h->size;
-	
-	list_foreach(h->table[chain], cur) {
-		if (h->equals(cur, item))
-			return false;
-	}
-	
-	if (h->count + 1 > h->size) {
-		size_t new_size = h->size * 2;
-		list_t *temp = malloc(new_size * sizeof(list_t));
-		if (temp != NULL)
-			hash_set_rehash(h, temp, new_size);
-		
-		/*
-		 * If the allocation fails, just use the same
-		 * old table and try to rehash next time.
-		 */
-		chain = hash % h->size;
-	}
-	
-	h->count++;
-	list_append(item, &h->table[chain]);
-	
-	return true;
-}
-
-/** Search the hash set for a matching object and return it
- *
- * @param h    Hash set
- * @param item The item that should equal to the matched object
- *
- * @return Matching item on success, NULL if there is no such item.
- *
- */
-link_t *hash_set_find(hash_set_t *h, const link_t *item)
-{
-	assert(h);
-	assert(h->hash);
-	assert(h->equals);
-	
-	unsigned long chain = h->hash(item) % h->size;
-	
-	list_foreach(h->table[chain], cur) {
-		if (h->equals(cur, item))
-			return cur;
-	}
-	
-	return NULL;
-}
-
-/** Remove first matching object from the hash set and return it
- *
- * @param h    Hash set.
- * @param item The item that should be equal to the matched object
- *
- * @return The removed item or NULL if this is not found.
- *
- */
-link_t *hash_set_remove(hash_set_t *h, const link_t *item)
-{
-	assert(h);
-	assert(h->hash);
-	assert(h->equals);
-	
-	link_t *cur = hash_set_find(h, item);
-	if (cur) {
-		list_remove(cur);
-		
-		h->count--;
-		if (4 * h->count < h->size && h->size > HASH_SET_MIN_SIZE) {
-			size_t new_size = h->size / 2;
-			if (new_size < HASH_SET_MIN_SIZE)
-				/* possible e.g. if init_size == HASH_SET_MIN_SIZE + 1 */
-				new_size = HASH_SET_MIN_SIZE;
-			
-			list_t *temp = malloc(new_size * sizeof (list_t));
-			if (temp != NULL)
-				hash_set_rehash(h, temp, new_size);
-		}
-	}
-	
-	return cur;
-}
-
-/** Remove all elements for which the function returned non-zero
- *
- * The function can also destroy the element.
- *
- * @param h   Hash set.
- * @param f   Function to be applied.
- * @param arg Argument to be passed to the function.
- *
- */
-void hash_set_remove_selected(hash_set_t *h, int (*f)(link_t *, void *),
-    void *arg)
-{
-	assert(h);
-	assert(h->table);
-	
-	for (size_t bucket = 0; bucket < h->size; bucket++) {
-		link_t *prev = &h->table[bucket].head;
-		link_t *cur;
-		link_t *next;
-		
-		for (cur = h->table[bucket].head.next;
-		    cur != &h->table[bucket].head;
-		    cur = next) {
-			next = cur->next;
-			if (f(cur, arg)) {
-				prev->next = next;
-				next->prev = prev;
-				h->count--;
-			} else
-				prev = cur;
-		}
-	}
-	
-	if (4 * h->count < h->size && h->size > HASH_SET_MIN_SIZE) {
-		size_t new_size = h->size / 2;
-		if (new_size < HASH_SET_MIN_SIZE)
-			/* possible e.g. if init_size == HASH_SET_MIN_SIZE + 1 */
-			new_size = HASH_SET_MIN_SIZE;
-		
-		list_t *temp = malloc(new_size * sizeof (list_t));
-		if (temp != NULL)
-			hash_set_rehash(h, temp, new_size);
-	}
-}
-
-/** Apply function to all items in hash set
- *
- * @param h   Hash set.
- * @param f   Function to be applied.
- * @param arg Argument to be passed to the function.
- *
- */
-void hash_set_apply(hash_set_t *h, void (*f)(link_t *, void *), void *arg)
-{
-	assert(h);
-	assert(h->table);
-	
-	for (size_t bucket = 0; bucket < h->size; bucket++) {
-		link_t *cur;
-		link_t *next;
-		
-		for (cur = h->table[bucket].head.next;
-		    cur != &h->table[bucket].head;
-		    cur = next) {
-			
-			/*
-			 * The next pointer must be stored prior to the functor
-			 * call to allow using destructor as the functor (the
-			 * free function could overwrite the cur->next pointer).
-			 */
-			next = cur->next;
-			f(cur, arg);
-		}
-	}
-}
-
-/** Remove all elements from the set.
- *
- * The table is reallocated to the minimum size.
- *
- * @param h   Hash set
- * @param f   Function (destructor?) applied to all element. Can be NULL.
- * @param arg Argument to the destructor.
- *
- */
-void hash_set_clear(hash_set_t *h, void (*f)(link_t *, void *), void *arg)
-{
-	assert(h);
-	assert(h->table);
-	
-	for (size_t bucket = 0; bucket < h->size; bucket++) {
-		link_t *cur;
-		link_t *next;
-		
-		for (cur = h->table[bucket].head.next;
-		    cur != &h->table[bucket].head;
-		    cur = next) {
-			next = cur->next;
-			list_remove(cur);
-			if (f != NULL)
-				f(cur, arg);
-		}
-	}
-	
-	assert(h->size >= HASH_SET_MIN_SIZE);
-	list_t *new_table =
-	    realloc(h->table, HASH_SET_MIN_SIZE * sizeof(list_t));
-	
-	/* We are shrinking, therefore we shouldn't get NULL */
-	assert(new_table);
-	
-	if (h->table != new_table) {
-		/* Init the lists, pointers to itself are used in them */
-		for (size_t bucket = 0; bucket < HASH_SET_MIN_SIZE; ++bucket)
-			list_initialize(&new_table[bucket]);
-		
-		h->table = new_table;
-	}
-	
-	h->count = 0;
-	h->size = HASH_SET_MIN_SIZE;
-}
-
-/** Get hash set size
- *
- * @param hHash set
- *
- * @return Number of elements in the set.
- *
- */
-size_t hash_set_count(const hash_set_t *h)
-{
-	assert(h);
-	return h->count;
-}
-
-/** Check whether element is contained in the hash set
- *
- * @param h    Hash set
- * @param item Item that should be equal to the matched object
- *
- * @return True if the hash set contains equal object
- * @return False otherwise
- *
- */
-int hash_set_contains(const hash_set_t *h, const link_t *item)
-{
-	/*
-	 * The hash_set_find cannot accept constant hash set,
-	 * because we can modify the returned element. But in
-	 * this case we are using it safely.
-	 */
-	return hash_set_find((hash_set_t *) h, item) != NULL;
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/adt/hash_table.c
===================================================================
--- uspace/lib/c/generic/adt/hash_table.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/adt/hash_table.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -1,4 +1,6 @@
 /*
  * Copyright (c) 2008 Jakub Jermar
+ * Copyright (c) 2012 Adam Hraska
+ * 
  * All rights reserved.
  *
@@ -34,5 +36,15 @@
 
 /*
- * This is an implementation of generic chained hash table.
+ * This is an implementation of a generic resizable chained hash table.
+ * 
+ * The table grows to 2*n+1 buckets each time, starting at n == 89, 
+ * per Thomas Wang's recommendation:
+ * http://www.concentric.net/~Ttwang/tech/hashsize.htm
+ * 
+ * This policy produces prime table sizes for the first five resizes
+ * and generally produces table sizes which are either prime or 
+ * have fairly large (prime/odd) divisors. Having a prime table size
+ * mitigates the use of suboptimal hash functions and distributes
+ * items over the whole table.
  */
 
@@ -44,38 +56,99 @@
 #include <str.h>
 
+/* Optimal initial bucket count. See comment above. */
+#define HT_MIN_BUCKETS  89
+/* The table is resized when the average load per bucket exceeds this number. */
+#define HT_MAX_LOAD     2
+
+
+static size_t round_up_size(size_t);
+static bool alloc_table(size_t, list_t **);
+static void clear_items(hash_table_t *);
+static void resize(hash_table_t *, size_t);
+static void grow_if_needed(hash_table_t *);
+static void shrink_if_needed(hash_table_t *);
+
+/* Dummy do nothing callback to invoke in place of remove_callback == NULL. */
+static void nop_remove_callback(ht_link_t *item)
+{
+	/* no-op */
+}
+
+
 /** Create chained hash table.
  *
  * @param h        Hash table structure. Will be initialized by this call.
- * @param m        Number of hash table buckets.
+ * @param init_size Initial desired number of hash table buckets. Pass zero
+ *                 if you want the default initial size. 
  * @param max_keys Maximal number of keys needed to identify an item.
- * @param op       Hash table operations structure.
+ * @param op       Hash table operations structure. remove_callback()
+ *                 is optional and can be NULL if no action is to be taken
+ *                 upon removal. equal() is optional if and only if
+ *                 hash_table_insert_unique() will never be invoked.
+ *                 All other operations are mandatory. 
  *
  * @return True on success
  *
  */
-bool hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,
-    hash_table_operations_t *op)
+bool hash_table_create(hash_table_t *h, size_t init_size, size_t max_load,
+    hash_table_ops_t *op)
 {
 	assert(h);
-	assert(op && op->hash && op->compare);
-	assert(max_keys > 0);
-	
-	h->entry = malloc(m * sizeof(list_t));
-	if (!h->entry)
+	assert(op && op->hash && op->key_hash && op->key_equal);
+	
+	/* Check for compulsory ops. */
+	if (!op || !op->hash || !op->key_hash || !op->key_equal)
 		return false;
 	
-	memset((void *) h->entry, 0,  m * sizeof(list_t));
-	
-	hash_count_t i;
-	for (i = 0; i < m; i++)
-		list_initialize(&h->entry[i]);
-	
-	h->entries = m;
-	h->max_keys = max_keys;
+	h->bucket_cnt = round_up_size(init_size);
+	
+	if (!alloc_table(h->bucket_cnt, &h->bucket))
+		return false;
+	
+	h->max_load = (max_load == 0) ? HT_MAX_LOAD : max_load;
+	h->item_cnt = 0;
 	h->op = op;
+	h->full_item_cnt = h->max_load * h->bucket_cnt;
+	h->apply_ongoing = false;
+
+	if (h->op->remove_callback == NULL) {
+		h->op->remove_callback = nop_remove_callback;
+	}
 	
 	return true;
 }
 
+/** Destroy a hash table instance.
+ *
+ * @param h Hash table to be destroyed.
+ *
+ */
+void hash_table_destroy(hash_table_t *h)
+{
+	assert(h && h->bucket);
+	assert(!h->apply_ongoing);
+	
+	clear_items(h);
+	
+	free(h->bucket);
+
+	h->bucket = 0;
+	h->bucket_cnt = 0;
+}
+
+/** Returns true if there are no items in the table. */
+bool hash_table_empty(hash_table_t *h)
+{
+	assert(h && h->bucket);
+	return h->item_cnt == 0;
+}
+
+/** Returns the number of items in the table. */
+size_t hash_table_size(hash_table_t *h)
+{
+	assert(h && h->bucket);
+	return h->item_cnt;
+}
+
 /** Remove all elements from the hash table
  *
@@ -84,29 +157,32 @@
 void hash_table_clear(hash_table_t *h)
 {
-	for (hash_count_t chain = 0; chain < h->entries; ++chain) {
-		link_t *cur;
-		link_t *next;
-		
-		for (cur = h->entry[chain].head.next;
-		    cur != &h->entry[chain].head;
-		    cur = next) {
-			next = cur->next;
+	assert(h && h->bucket);
+	assert(!h->apply_ongoing);
+	
+	clear_items(h);
+	
+	/* Shrink the table to its minimum size if possible. */
+	if (HT_MIN_BUCKETS < h->bucket_cnt) {
+		resize(h, HT_MIN_BUCKETS);
+	}
+}
+
+/** Unlinks and removes all items but does not resize. */
+static void clear_items(hash_table_t *h)
+{
+	if (h->item_cnt == 0)
+		return;
+	
+	for (size_t idx = 0; idx < h->bucket_cnt; ++idx) {
+		list_foreach_safe(h->bucket[idx], cur, next) {
+			assert(cur);
+			ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
+			
 			list_remove(cur);
-			h->op->remove_callback(cur);
-		}
-	}
-}
-
-/** Destroy a hash table instance.
- *
- * @param h Hash table to be destroyed.
- *
- */
-void hash_table_destroy(hash_table_t *h)
-{
-	assert(h);
-	assert(h->entry);
-	
-	free(h->entry);
+			h->op->remove_callback(cur_link);
+		}
+	}
+	
+	h->item_cnt = 0;
 }
 
@@ -117,13 +193,52 @@
  * @param item Item to be inserted into the hash table.
  */
-void hash_table_insert(hash_table_t *h, unsigned long key[], link_t *item)
+void hash_table_insert(hash_table_t *h, ht_link_t *item)
 {
 	assert(item);
-	assert(h && h->op && h->op->hash && h->op->compare);
-	
-	hash_index_t chain = h->op->hash(key);
-	assert(chain < h->entries);
-	
-	list_append(item, &h->entry[chain]);
+	assert(h && h->bucket);
+	assert(!h->apply_ongoing);
+	
+	size_t idx = h->op->hash(item) % h->bucket_cnt;
+	
+	list_append(&item->link, &h->bucket[idx]);
+	++h->item_cnt;
+	grow_if_needed(h);
+}
+
+
+/** Insert item into a hash table if not already present.
+ *
+ * @param h    Hash table.
+ * @param key  Array of all keys necessary to compute hash index.
+ * @param item Item to be inserted into the hash table.
+ * 
+ * @return False if such an item had already been inserted. 
+ * @return True if the inserted item was the only item with such a lookup key.
+ */
+bool hash_table_insert_unique(hash_table_t *h, ht_link_t *item)
+{
+	assert(item);
+	assert(h && h->bucket && h->bucket_cnt);
+	assert(h->op && h->op->hash && h->op->equal);
+	assert(!h->apply_ongoing);
+	
+	size_t idx = h->op->hash(item) % h->bucket_cnt;
+	
+	/* Check for duplicates. */
+	list_foreach(h->bucket[idx], cur) {
+		/* 
+		 * We could filter out items using their hashes first, but 
+		 * calling equal() might very well be just as fast.
+		 */
+		ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
+		if (h->op->equal(cur_link, item))
+			return false;
+	}
+	
+	list_append(&item->link, &h->bucket[idx]);
+	++h->item_cnt;
+	grow_if_needed(h);
+	
+	return true;
 }
 
@@ -136,20 +251,45 @@
  *
  */
-link_t *hash_table_find(hash_table_t *h, unsigned long key[])
-{
-	assert(h && h->op && h->op->hash && h->op->compare);
-	
-	hash_index_t chain = h->op->hash(key);
-	assert(chain < h->entries);
-	
-	list_foreach(h->entry[chain], cur) {
-		if (h->op->compare(key, h->max_keys, cur)) {
-			/*
-			 * The entry is there.
-			 */
-			return cur;
-		}
-	}
-	
+ht_link_t *hash_table_find(const hash_table_t *h, void *key)
+{
+	assert(h && h->bucket);
+	
+	size_t idx = h->op->key_hash(key) % h->bucket_cnt;
+
+	list_foreach(h->bucket[idx], cur) {
+		ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
+		/* 
+		 * Is this is the item we are looking for? We could have first 
+		 * checked if the hashes match but op->key_equal() may very well be 
+		 * just as fast as op->hash().
+		 */
+		if (h->op->key_equal(key, cur_link)) {
+			return cur_link;
+		}
+	}
+	
+	return NULL;
+}
+
+/** Find the next item equal to item. */
+ht_link_t *hash_table_find_next(const hash_table_t *h, ht_link_t *item)
+{
+	assert(item);
+	assert(h && h->bucket);
+
+	/* Traverse the circular list until we reach the starting item again. */
+	for (link_t *cur = item->link.next; cur != &item->link; cur = cur->next) {
+		assert(cur);
+		ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
+		/* 
+		 * Is this is the item we are looking for? We could have first 
+		 * checked if the hashes match but op->equal() may very well be 
+		 * just as fast as op->hash().
+		 */
+		if (h->op->equal(cur_link, item)) {
+			return cur_link;
+		}
+	}
+
 	return NULL;
 }
@@ -163,76 +303,170 @@
  *             the hash table.
  * @param keys Number of keys in the 'key' array.
- *
- */
-void hash_table_remove(hash_table_t *h, unsigned long key[], hash_count_t keys)
-{
-	assert(h && h->op && h->op->hash && h->op->compare &&
-	    h->op->remove_callback);
-	assert(keys <= h->max_keys);
-	
-	if (keys == h->max_keys) {
-		/*
-		 * All keys are known, hash_table_find() can be used to find the
-		 * entry.
+ * 
+ * @return Returns the number of removed items.
+ */
+size_t hash_table_remove(hash_table_t *h, void *key)
+{
+	assert(h && h->bucket);
+	assert(!h->apply_ongoing);
+	
+	size_t idx = h->op->key_hash(key) % h->bucket_cnt;
+
+	size_t removed = 0;
+	
+	list_foreach_safe(h->bucket[idx], cur, next) {
+		ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
+		
+		if (h->op->key_equal(key, cur_link)) {
+			++removed;
+			list_remove(cur);
+			h->op->remove_callback(cur_link);
+		}
+	}
+
+	h->item_cnt -= removed;
+	shrink_if_needed(h);
+	
+	return removed;
+}
+
+/** Removes an item already present in the table. The item must be in the table.*/
+void hash_table_remove_item(hash_table_t *h, ht_link_t *item)
+{
+	assert(item);
+	assert(h && h->bucket);
+	assert(link_in_use(&item->link));
+
+	list_remove(&item->link);
+	--h->item_cnt;
+	h->op->remove_callback(item);
+	shrink_if_needed(h);
+}
+
+/** Apply function to all items in hash table.
+ *
+ * @param h   Hash table.
+ * @param f   Function to be applied. Return false if no more items 
+ *            should be visited. The functor may only delete the supplied
+ *            item. It must not delete the successor of the item passed 
+ *            in the first argument.
+ * @param arg Argument to be passed to the function.
+ */
+void hash_table_apply(hash_table_t *h, bool (*f)(ht_link_t *, void *), void *arg)
+{	
+	assert(f);
+	assert(h && h->bucket);
+	
+	if (h->item_cnt == 0)
+		return;
+	
+	h->apply_ongoing = true;
+	
+	for (size_t idx = 0; idx < h->bucket_cnt; ++idx) {
+		list_foreach_safe(h->bucket[idx], cur, next) {
+			ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
+			/* 
+			 * The next pointer had already been saved. f() may safely 
+			 * delete cur (but not next!).
+			 */
+			if (!f(cur_link, arg))
+				return;
+		}
+	}
+	
+	h->apply_ongoing = false;
+	
+	shrink_if_needed(h);
+	grow_if_needed(h);
+}
+
+/** Rounds up size to the nearest suitable table size. */
+static size_t round_up_size(size_t size)
+{
+	size_t rounded_size = HT_MIN_BUCKETS;
+	
+	while (rounded_size < size) {
+		rounded_size = 2 * rounded_size + 1;
+	}
+	
+	return rounded_size;
+}
+
+/** Allocates and initializes the desired number of buckets. True if successful.*/
+static bool alloc_table(size_t bucket_cnt, list_t **pbuckets)
+{
+	assert(pbuckets && HT_MIN_BUCKETS <= bucket_cnt);
+		
+	list_t *buckets = malloc(bucket_cnt * sizeof(list_t));
+	if (!buckets)
+		return false;
+	
+	for (size_t i = 0; i < bucket_cnt; i++)
+		list_initialize(&buckets[i]);
+
+	*pbuckets = buckets;
+	return true;
+}
+
+
+/** Shrinks the table if the table is only sparely populated. */
+static inline void shrink_if_needed(hash_table_t *h)
+{
+	if (h->item_cnt <= h->full_item_cnt / 4 && HT_MIN_BUCKETS < h->bucket_cnt) {
+		/* 
+		 * Keep the bucket_cnt odd (possibly also prime). 
+		 * Shrink from 2n + 1 to n. Integer division discards the +1.
 		 */
-		
-		link_t *cur = hash_table_find(h, key);
-		if (cur) {
-			list_remove(cur);
-			h->op->remove_callback(cur);
-		}
-		
+		size_t new_bucket_cnt = h->bucket_cnt / 2;
+		resize(h, new_bucket_cnt);
+	}
+}
+
+/** Grows the table if table load exceeds the maximum allowed. */
+static inline void grow_if_needed(hash_table_t *h)
+{
+	/* Grow the table if the average bucket load exceeds the maximum. */
+	if (h->full_item_cnt < h->item_cnt) {
+		/* Keep the bucket_cnt odd (possibly also prime). */
+		size_t new_bucket_cnt = 2 * h->bucket_cnt + 1;
+		resize(h, new_bucket_cnt);
+	}
+}
+
+/** Allocates and rehashes items to a new table. Frees the old table. */
+static void resize(hash_table_t *h, size_t new_bucket_cnt) 
+{
+	assert(h && h->bucket);
+	assert(HT_MIN_BUCKETS <= new_bucket_cnt);
+	
+	/* We are traversing the table and resizing would mess up the buckets. */
+	if (h->apply_ongoing)
 		return;
-	}
-	
-	/*
-	 * Fewer keys were passed.
-	 * Any partially matching entries are to be removed.
-	 */
-	hash_index_t chain;
-	for (chain = 0; chain < h->entries; chain++) {
-		for (link_t *cur = h->entry[chain].head.next;
-		    cur != &h->entry[chain].head;
-		    cur = cur->next) {
-			if (h->op->compare(key, keys, cur)) {
-				link_t *hlp;
-				
-				hlp = cur;
-				cur = cur->prev;
-				
-				list_remove(hlp);
-				h->op->remove_callback(hlp);
-				
-				continue;
+	
+	list_t *new_buckets;
+
+	/* Leave the table as is if we cannot resize. */
+	if (!alloc_table(new_bucket_cnt, &new_buckets))
+		return;
+	
+	if (0 < h->item_cnt) {
+		/* Rehash all the items to the new table. */
+		for (size_t old_idx = 0; old_idx < h->bucket_cnt; ++old_idx) {
+			list_foreach_safe(h->bucket[old_idx], cur, next) {
+				ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
+
+				size_t new_idx = h->op->hash(cur_link) % new_bucket_cnt;
+				list_remove(cur);
+				list_append(cur, &new_buckets[new_idx]);
 			}
 		}
 	}
-}
-
-/** Apply function to all items in hash table.
- *
- * @param h   Hash table.
- * @param f   Function to be applied.
- * @param arg Argument to be passed to the function.
- *
- */
-void hash_table_apply(hash_table_t *h, void (*f)(link_t *, void *), void *arg)
-{	
-	for (hash_index_t bucket = 0; bucket < h->entries; bucket++) {
-		link_t *cur;
-		link_t *next;
-
-		for (cur = h->entry[bucket].head.next; cur != &h->entry[bucket].head;
-		    cur = next) {
-			/*
-			 * The next pointer must be stored prior to the functor
-			 * call to allow using destructor as the functor (the
-			 * free function could overwrite the cur->next pointer).
-			 */
-			next = cur->next;
-			f(cur, arg);
-		}
-	}
-}
+	
+	free(h->bucket);
+	h->bucket = new_buckets;
+	h->bucket_cnt = new_bucket_cnt;
+	h->full_item_cnt = h->max_load * h->bucket_cnt;
+}
+
 
 /** @}
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/async.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -114,7 +114,6 @@
 #include <stdlib.h>
 #include <macros.h>
-
-#define CLIENT_HASH_TABLE_BUCKETS  32
-#define CONN_HASH_TABLE_BUCKETS    32
+#include "private/libc.h"
+
 
 /** Session data */
@@ -204,5 +203,5 @@
 /* Client connection data */
 typedef struct {
-	link_t link;
+	ht_link_t link;
 	
 	task_id_t in_task_id;
@@ -216,5 +215,5 @@
 	
 	/** Hash table link. */
-	link_t link;
+	ht_link_t link;
 	
 	/** Incoming client task ID. */
@@ -392,31 +391,31 @@
 static LIST_INITIALIZE(timeout_list);
 
-static hash_index_t client_hash(unsigned long key[])
-{
-	assert(key);
-	
-	return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
-}
-
-static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	assert(key);
-	assert(keys == 2);
-	assert(item);
-	
-	client_t *client = hash_table_get_instance(item, client_t, link);
-	return (key[0] == LOWER32(client->in_task_id) &&
-	    (key[1] == UPPER32(client->in_task_id)));
-}
-
-static void client_remove(link_t *item)
-{
-}
+static size_t client_key_hash(void *k)
+{
+	task_id_t key = *(task_id_t*)k;
+	return key;
+}
+
+static size_t client_hash(const ht_link_t *item)
+{
+	client_t *client = hash_table_get_inst(item, client_t, link);
+	return client_key_hash(&client->in_task_id);
+}
+
+static bool client_key_equal(void *k, const ht_link_t *item)
+{
+	task_id_t key = *(task_id_t*)k;
+	client_t *client = hash_table_get_inst(item, client_t, link);
+	return key == client->in_task_id;
+}
+
 
 /** Operations for the client hash table. */
-static hash_table_operations_t client_hash_table_ops = {
+static hash_table_ops_t client_hash_table_ops = {
 	.hash = client_hash,
-	.compare = client_compare,
-	.remove_callback = client_remove
+	.key_hash = client_key_hash,
+	.key_equal = client_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
 };
 
@@ -428,38 +427,31 @@
  *
  */
-static hash_index_t conn_hash(unsigned long key[])
-{
-	assert(key);
-	
-	return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS);
-}
-
-/** Compare hash table item with a key.
- *
- * @param key  Array containing the source phone hash as the only item.
- * @param keys Expected 1 but ignored.
- * @param item Connection hash table item.
- *
- * @return True on match, false otherwise.
- *
- */
-static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	assert(key);
-	assert(item);
-	
-	connection_t *conn = hash_table_get_instance(item, connection_t, link);
-	return (key[0] == conn->in_phone_hash);
-}
-
-static void conn_remove(link_t *item)
-{
-}
+static size_t conn_key_hash(void *key)
+{
+	sysarg_t in_phone_hash  = *(sysarg_t*)key;
+	return in_phone_hash ;
+}
+
+static size_t conn_hash(const ht_link_t *item)
+{
+	connection_t *conn = hash_table_get_inst(item, connection_t, link);
+	return conn_key_hash(&conn->in_phone_hash);
+}
+
+static bool conn_key_equal(void *key, const ht_link_t *item)
+{
+	sysarg_t in_phone_hash = *(sysarg_t*)key;
+	connection_t *conn = hash_table_get_inst(item, connection_t, link);
+	return (in_phone_hash == conn->in_phone_hash);
+}
+
 
 /** Operations for the connection hash table. */
-static hash_table_operations_t conn_hash_table_ops = {
+static hash_table_ops_t conn_hash_table_ops = {
 	.hash = conn_hash,
-	.compare = conn_compare,
-	.remove_callback = conn_remove
+	.key_hash = conn_key_hash,
+	.key_equal = conn_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
 };
 
@@ -509,6 +501,5 @@
 	futex_down(&async_futex);
 	
-	unsigned long key = call->in_phone_hash;
-	link_t *hlp = hash_table_find(&conn_hash_table, &key);
+	ht_link_t *hlp = hash_table_find(&conn_hash_table, &call->in_phone_hash);
 	
 	if (!hlp) {
@@ -517,5 +508,5 @@
 	}
 	
-	connection_t *conn = hash_table_get_instance(hlp, connection_t, link);
+	connection_t *conn = hash_table_get_inst(hlp, connection_t, link);
 	
 	msg_t *msg = malloc(sizeof(*msg));
@@ -637,5 +628,5 @@
 	
 	if (usecs) {
-		gettimeofday(&conn->wdata.to_event.expires, NULL);
+		getuptime(&conn->wdata.to_event.expires);
 		tv_add(&conn->wdata.to_event.expires, usecs);
 	} else
@@ -697,14 +688,10 @@
 static client_t *async_client_get(task_id_t client_id, bool create)
 {
-	unsigned long key[2] = {
-		LOWER32(client_id),
-		UPPER32(client_id),
-	};
 	client_t *client = NULL;
 
 	futex_down(&async_futex);
-	link_t *lnk = hash_table_find(&client_hash_table, key);
+	ht_link_t *lnk = hash_table_find(&client_hash_table, &client_id);
 	if (lnk) {
-		client = hash_table_get_instance(lnk, client_t, link);
+		client = hash_table_get_inst(lnk, client_t, link);
 		atomic_inc(&client->refcnt);
 	} else if (create) {
@@ -715,5 +702,5 @@
 		
 			atomic_set(&client->refcnt, 1);
-			hash_table_insert(&client_hash_table, key, &client->link);
+			hash_table_insert(&client_hash_table, &client->link);
 		}
 	}
@@ -726,13 +713,9 @@
 {
 	bool destroy;
-	unsigned long key[2] = {
-		LOWER32(client->in_task_id),
-		UPPER32(client->in_task_id)
-	};
-	
+
 	futex_down(&async_futex);
 	
 	if (atomic_predec(&client->refcnt) == 0) {
-		hash_table_remove(&client_hash_table, key, 2);
+		hash_table_remove(&client_hash_table, &client->in_task_id);
 		destroy = true;
 	} else
@@ -830,6 +813,5 @@
 	 */
 	futex_down(&async_futex);
-	unsigned long key = fibril_connection->in_phone_hash;
-	hash_table_remove(&conn_hash_table, &key, 1);
+	hash_table_remove(&conn_hash_table, &fibril_connection->in_phone_hash);
 	futex_up(&async_futex);
 	
@@ -915,8 +897,7 @@
 	
 	/* Add connection to the connection hash table */
-	unsigned long key = conn->in_phone_hash;
 	
 	futex_down(&async_futex);
-	hash_table_insert(&conn_hash_table, &key, &conn->link);
+	hash_table_insert(&conn_hash_table, &conn->link);
 	futex_up(&async_futex);
 	
@@ -966,5 +947,5 @@
 {
 	struct timeval tv;
-	gettimeofday(&tv, NULL);
+	getuptime(&tv);
 	
 	futex_down(&async_futex);
@@ -1023,5 +1004,5 @@
 			
 			struct timeval tv;
-			gettimeofday(&tv, NULL);
+			getuptime(&tv);
 			
 			if (tv_gteq(&tv, &waiter->to_event.expires)) {
@@ -1110,10 +1091,8 @@
 void __async_init(void)
 {
-	if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS,
-	    2, &client_hash_table_ops))
+	if (!hash_table_create(&client_hash_table, 0, 0, &client_hash_table_ops))
 		abort();
 	
-	if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS,
-	    1, &conn_hash_table_ops))
+	if (!hash_table_create(&conn_hash_table, 0, 0, &conn_hash_table_ops))
 		abort();
 	
@@ -1330,5 +1309,5 @@
 		timeout = 0;
 
-	gettimeofday(&msg->wdata.to_event.expires, NULL);
+	getuptime(&msg->wdata.to_event.expires);
 	tv_add(&msg->wdata.to_event.expires, timeout);
 	
@@ -1412,5 +1391,5 @@
 	msg->wdata.fid = fibril_get_id();
 	
-	gettimeofday(&msg->wdata.to_event.expires, NULL);
+	getuptime(&msg->wdata.to_event.expires);
 	tv_add(&msg->wdata.to_event.expires, timeout);
 	
@@ -2166,5 +2145,6 @@
 int async_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
 {
-	return ipc_share_in_finalize(callid, src, flags);
+	return ipc_answer_3(callid, EOK, (sysarg_t) src, (sysarg_t) flags,
+	    (sysarg_t) __entry);
 }
 
@@ -2233,5 +2213,5 @@
 int async_share_out_finalize(ipc_callid_t callid, void **dst)
 {
-	return ipc_share_out_finalize(callid, dst);
+	return ipc_answer_2(callid, EOK, (sysarg_t) __entry, (sysarg_t) dst);
 }
 
@@ -2317,5 +2297,5 @@
 int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
 {
-	return ipc_data_read_finalize(callid, src, size);
+	return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) size);
 }
 
@@ -2420,5 +2400,5 @@
 int async_data_write_finalize(ipc_callid_t callid, void *dst, size_t size)
 {
-	return ipc_data_write_finalize(callid, dst, size);
+	return ipc_answer_2(callid, EOK, (sysarg_t) dst, (sysarg_t) size);
 }
 
Index: uspace/lib/c/generic/bd.c
===================================================================
--- uspace/lib/c/generic/bd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/bd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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
+ * @brief IP link client stub
+ */
+
+#include <async.h>
+#include <assert.h>
+#include <bd.h>
+#include <errno.h>
+#include <ipc/bd.h>
+#include <ipc/services.h>
+#include <loc.h>
+#include <macros.h>
+#include <stdlib.h>
+
+static void bd_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+int bd_open(async_sess_t *sess, bd_t **rbd)
+{
+	bd_t *bd = calloc(1, sizeof(bd_t));
+	if (bd == NULL)
+		return ENOMEM;
+	
+	bd->sess = sess;
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	int rc = async_connect_to_me(exch, 0, 0, 0, bd_cb_conn, bd);
+	async_exchange_end(exch);
+	
+	if (rc != EOK)
+		goto error;
+	
+	*rbd = bd;
+	return EOK;
+	
+error:
+	if (bd != NULL)
+		free(bd);
+	
+	return rc;
+}
+
+void bd_close(bd_t *bd)
+{
+	/* XXX Synchronize with bd_cb_conn */
+	free(bd);
+}
+
+int bd_read_blocks(bd_t *bd, aoff64_t ba, size_t cnt, void *data, size_t size)
+{
+	async_exch_t *exch = async_exchange_begin(bd->sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_3(exch, BD_READ_BLOCKS, LOWER32(ba),
+	    UPPER32(ba), cnt, &answer);
+	int rc = async_data_read_start(exch, data, size);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+
+	if (retval != EOK)
+		return retval;
+
+	return EOK;
+}
+
+int bd_read_toc(bd_t *bd, uint8_t session, void *buf, size_t size)
+{
+	async_exch_t *exch = async_exchange_begin(bd->sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, BD_READ_TOC, session, &answer);
+	int rc = async_data_read_start(exch, buf, size);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+
+	if (retval != EOK)
+		return retval;
+
+	return EOK;
+}
+
+int bd_write_blocks(bd_t *bd, aoff64_t ba, size_t cnt, const void *data,
+    size_t size)
+{
+	async_exch_t *exch = async_exchange_begin(bd->sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_3(exch, BD_WRITE_BLOCKS, LOWER32(ba),
+	    UPPER32(ba), cnt, &answer);
+	int rc = async_data_write_start(exch, data, size);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	if (retval != EOK)
+		return retval;
+
+	return EOK;
+}
+
+int bd_get_block_size(bd_t *bd, size_t *rbsize)
+{
+	sysarg_t bsize;
+	async_exch_t *exch = async_exchange_begin(bd->sess);
+
+	int rc = async_req_0_1(exch, BD_GET_BLOCK_SIZE, &bsize);
+	async_exchange_end(exch);
+
+	if (rc != EOK)
+		return rc;
+
+	*rbsize = bsize;
+	return EOK;
+}
+
+int bd_get_num_blocks(bd_t *bd, aoff64_t *rnb)
+{
+	sysarg_t nb_l;
+	sysarg_t nb_h;
+	async_exch_t *exch = async_exchange_begin(bd->sess);
+
+	int rc = async_req_0_2(exch, BD_GET_NUM_BLOCKS, &nb_l, &nb_h);
+	async_exchange_end(exch);
+
+	if (rc != EOK)
+		return rc;
+
+	*rnb = (aoff64_t) MERGE_LOUP32(nb_l, nb_h);
+	return EOK;
+}
+
+static void bd_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	bd_t *bd = (bd_t *)arg;
+
+	(void)bd;
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		default:
+			async_answer_0(callid, ENOTSUP);
+		}
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/bd_srv.c
===================================================================
--- uspace/lib/c/generic/bd_srv.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/bd_srv.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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
+ * @brief Block device server stub
+ */
+#include <errno.h>
+#include <ipc/bd.h>
+#include <macros.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <bd_srv.h>
+
+static void bd_read_blocks_srv(bd_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	aoff64_t ba;
+	size_t cnt;
+	void *buf;
+	size_t size;
+	int rc;
+	ipc_callid_t rcallid;
+
+	ba = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
+	cnt = IPC_GET_ARG3(*call);
+
+	if (!async_data_read_receive(&rcallid, &size)) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	buf = malloc(size);
+	if (buf == NULL) {
+		async_answer_0(rcallid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	if (srv->srvs->ops->read_blocks == NULL) {
+		async_answer_0(rcallid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->read_blocks(srv, ba, cnt, buf, size);
+	if (rc != EOK) {
+		async_answer_0(rcallid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	async_data_read_finalize(rcallid, buf, size);
+
+	free(buf);
+	async_answer_0(callid, EOK);
+}
+
+static void bd_read_toc_srv(bd_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	uint8_t session;
+	void *buf;
+	size_t size;
+	int rc;
+	ipc_callid_t rcallid;
+
+	session = IPC_GET_ARG1(*call);
+
+	if (!async_data_read_receive(&rcallid, &size)) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	buf = malloc(size);
+	if (buf == NULL) {
+		async_answer_0(rcallid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	if (srv->srvs->ops->read_toc == NULL) {
+		async_answer_0(rcallid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->read_toc(srv, session, buf, size);
+	if (rc != EOK) {
+		async_answer_0(rcallid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	async_data_read_finalize(rcallid, buf, size);
+
+	free(buf);
+	async_answer_0(callid, EOK);
+}
+
+static void bd_write_blocks_srv(bd_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	aoff64_t ba;
+	size_t cnt;
+	void *data;
+	size_t size;
+	int rc;
+
+	ba = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
+	cnt = IPC_GET_ARG3(*call);
+
+	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	if (srv->srvs->ops->write_blocks == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->write_blocks(srv, ba, cnt, data, size);
+	free(data);
+	async_answer_0(callid, rc);
+}
+
+static void bd_get_block_size_srv(bd_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int rc;
+	size_t block_size;
+
+	if (srv->srvs->ops->get_block_size == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->get_block_size(srv, &block_size);
+	async_answer_1(callid, rc, block_size);
+}
+
+static void bd_get_num_blocks_srv(bd_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int rc;
+	aoff64_t num_blocks;
+
+	if (srv->srvs->ops->get_num_blocks == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->get_num_blocks(srv, &num_blocks);
+	async_answer_2(callid, rc, LOWER32(num_blocks), UPPER32(num_blocks));
+}
+
+static bd_srv_t *bd_srv_create(bd_srvs_t *srvs)
+{
+	bd_srv_t *srv;
+
+	srv = calloc(1, sizeof(srv));
+	if (srv == NULL)
+		return NULL;
+
+	srv->srvs = srvs;
+	return srv;
+}
+
+void bd_srvs_init(bd_srvs_t *srvs)
+{
+	srvs->ops = NULL;
+	srvs->sarg = NULL;
+}
+
+int bd_conn(ipc_callid_t iid, ipc_call_t *icall, bd_srvs_t *srvs)
+{
+	bd_srv_t *srv;
+	int rc;
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	srv = bd_srv_create(srvs);
+	if (srv == NULL)
+		return ENOMEM;
+
+	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (sess == NULL)
+		return ENOMEM;
+
+	srv->client_sess = sess;
+
+	rc = srvs->ops->open(srvs, srv);
+	if (rc != EOK)
+		return rc;
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		sysarg_t method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(callid, EOK);
+			break;
+		}
+
+		switch (method) {
+		case BD_READ_BLOCKS:
+			bd_read_blocks_srv(srv, callid, &call);
+			break;
+		case BD_READ_TOC:
+			bd_read_toc_srv(srv, callid, &call);
+			break;
+		case BD_WRITE_BLOCKS:
+			bd_write_blocks_srv(srv, callid, &call);
+			break;
+		case BD_GET_BLOCK_SIZE:
+			bd_get_block_size_srv(srv, callid, &call);
+			break;
+		case BD_GET_NUM_BLOCKS:
+			bd_get_num_blocks_srv(srv, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
+
+	rc = srvs->ops->close(srv);
+	free(srv);
+
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/device/ahci.c
===================================================================
--- uspace/lib/c/generic/device/ahci.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/device/ahci.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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 <ipc/dev_iface.h>
+#include <assert.h>
+#include <device/ahci.h>
+#include <errno.h>
+#include <async.h>
+#include <ipc/services.h>
+#include <stdio.h>
+#include <as.h>
+
+typedef enum {
+	IPC_M_AHCI_GET_SATA_DEVICE_NAME,
+	IPC_M_AHCI_GET_NUM_BLOCKS,
+	IPC_M_AHCI_GET_BLOCK_SIZE,
+	IPC_M_AHCI_READ_BLOCKS,
+	IPC_M_AHCI_WRITE_BLOCKS,
+} ahci_iface_funcs_t;
+
+#define MAX_NAME_LENGTH  1024
+
+#define LO(ptr) \
+	((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) & 0xffffffff))
+
+#define HI(ptr) \
+	((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) >> 32))
+
+async_sess_t* ahci_get_sess(devman_handle_t funh, char **name)
+{
+	// FIXME: Use a better way than substring match
+	
+	*name = NULL;
+	
+	char devn[MAX_NAME_LENGTH];
+	int rc = devman_fun_get_name(funh, devn, MAX_NAME_LENGTH);
+	if (rc != EOK)
+		return NULL;
+	
+	size_t devn_size = str_size(devn);
+	
+	if ((devn_size > 5) && (str_lcmp(devn, "ahci_", 5) == 0)) {
+		async_sess_t *sess = devman_device_connect(EXCHANGE_PARALLEL,
+		    funh, IPC_FLAG_BLOCKING);
+		
+		if (sess) {
+			*name = str_dup(devn);
+			return sess;
+		}
+	}
+	
+	return NULL;
+}
+
+int ahci_get_sata_device_name(async_sess_t *sess, size_t sata_dev_name_length,
+    char *sata_dev_name)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (!exch)
+		return EINVAL;
+	
+	aid_t req = async_send_2(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
+	    IPC_M_AHCI_GET_SATA_DEVICE_NAME, sata_dev_name_length, NULL);
+	
+	async_data_read_start(exch, sata_dev_name, sata_dev_name_length);
+	
+	sysarg_t rc;
+	async_wait_for(req, &rc);
+	
+	return rc;
+}
+
+int ahci_get_num_blocks(async_sess_t *sess, uint64_t *blocks)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (!exch)
+		return EINVAL;
+	
+	sysarg_t blocks_hi;
+	sysarg_t blocks_lo;
+	int rc = async_req_1_2(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
+	    IPC_M_AHCI_GET_NUM_BLOCKS, &blocks_hi, &blocks_lo);
+	
+	async_exchange_end(exch);
+	
+	if (rc == EOK) {
+		*blocks = (((uint64_t) blocks_hi) << 32)
+		    | (((uint64_t) blocks_lo) & 0xffffffff);
+	}
+	
+	return rc;
+}
+
+int ahci_get_block_size(async_sess_t *sess, size_t *blocks_size)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (!exch)
+		return EINVAL;
+	
+	sysarg_t bs;
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
+	    IPC_M_AHCI_GET_BLOCK_SIZE, &bs);
+	
+	async_exchange_end(exch);
+	
+	if (rc == EOK)
+		*blocks_size = (size_t) bs;
+	
+	return rc;
+}
+
+int ahci_read_blocks(async_sess_t *sess, uint64_t blocknum, size_t count,
+    void *buf)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (!exch)
+		return EINVAL;
+	
+	aid_t req;
+	req = async_send_4(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
+	    IPC_M_AHCI_READ_BLOCKS, HI(blocknum),  LO(blocknum), count, NULL);
+	
+	async_share_out_start(exch, buf, AS_AREA_READ | AS_AREA_WRITE);
+	
+	async_exchange_end(exch);
+	
+	sysarg_t rc;
+	async_wait_for(req, &rc);
+	
+	return rc;
+}
+
+int ahci_write_blocks(async_sess_t *sess, uint64_t blocknum, size_t count,
+    void* buf)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (!exch)
+		return EINVAL;
+	
+	aid_t req = async_send_4(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
+	    IPC_M_AHCI_WRITE_BLOCKS, HI(blocknum),  LO(blocknum), count, NULL);
+	
+	async_share_out_start(exch, buf, AS_AREA_READ | AS_AREA_WRITE);
+	
+	async_exchange_end(exch);
+	
+	sysarg_t rc;
+	async_wait_for(req, &rc);
+	
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/device/battery_dev.c
===================================================================
--- uspace/lib/c/generic/device/battery_dev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/device/battery_dev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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 <ipc/dev_iface.h>
+#include <device/battery_dev.h>
+#include <errno.h>
+#include <async.h>
+#include <time.h>
+
+/** Read the current battery status from the device
+ *
+ * @param sess     Session of the device
+ * @param status   Current status of the battery
+ *
+ * @return         EOK on success or a negative error code
+ */
+int
+battery_status_get(async_sess_t *sess, battery_status_t *batt_status)
+{
+	sysarg_t status;
+
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	int const rc = async_req_1_1(exch, DEV_IFACE_ID(BATTERY_DEV_IFACE),
+	    BATTERY_STATUS_GET, &status);
+
+	async_exchange_end(exch);
+
+	if (rc == EOK)
+		*batt_status = (battery_status_t) status;
+
+	return rc;
+}
+
+/** Read the current battery charge level from the device
+ *
+ * @param sess     Session of the device
+ * @param level    Battery charge level (0 - 100)
+ *
+ * @return         EOK on success or a negative error code
+ */
+int
+battery_charge_level_get(async_sess_t *sess, int *level)
+{
+	sysarg_t charge_level;
+
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	int const rc = async_req_1_1(exch, DEV_IFACE_ID(BATTERY_DEV_IFACE),
+	    BATTERY_CHARGE_LEVEL_GET, &charge_level);
+
+	async_exchange_end(exch);
+
+	if (rc == EOK)
+		*level = (int) charge_level;
+
+	return rc;
+}
+
+/** @}
+ */
+
Index: uspace/lib/c/generic/device/clock_dev.c
===================================================================
--- uspace/lib/c/generic/device/clock_dev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/device/clock_dev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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 <ipc/dev_iface.h>
+#include <device/clock_dev.h>
+#include <errno.h>
+#include <async.h>
+#include <time.h>
+
+/** Read the current time from the device
+ *
+ * @param sess     Session of the device
+ * @param t        The current time that will be read from the device
+ *
+ * @return         EOK on success or a negative error code
+ */
+int
+clock_dev_time_get(async_sess_t *sess, struct tm *t)
+{
+	aid_t req;
+	int ret;
+
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	req = async_send_1(exch, DEV_IFACE_ID(CLOCK_DEV_IFACE),
+	    CLOCK_DEV_TIME_GET, NULL);
+	ret = async_data_read_start(exch, t, sizeof(*t));
+
+	async_exchange_end(exch);
+
+	sysarg_t rc;
+	if (ret != EOK) {
+		async_forget(req);
+		return ret;
+	}
+
+	async_wait_for(req, &rc);
+	return (int)rc;
+}
+
+/** Set the current time
+ *
+ * @param sess   Session of the device
+ * @param t      The current time that will be written to the device
+ *
+ * @return       EOK on success or a negative error code
+ */
+int
+clock_dev_time_set(async_sess_t *sess, struct tm *t)
+{
+	aid_t req;
+	int ret;
+
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	req = async_send_1(exch, DEV_IFACE_ID(CLOCK_DEV_IFACE),
+	    CLOCK_DEV_TIME_SET, NULL);
+	ret = async_data_write_start(exch, t, sizeof(*t));
+
+	async_exchange_end(exch);
+
+	sysarg_t rc;
+	if (ret != EOK) {
+		async_forget(req);
+		return ret;
+	}
+
+	async_wait_for(req, &rc);
+	return (int)rc;
+}
+
+/** @}
+ */
+
Index: uspace/lib/c/generic/device/graph_dev.c
===================================================================
--- uspace/lib/c/generic/device/graph_dev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/device/graph_dev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 <errno.h>
+#include <ipc/dev_iface.h>
+#include <device/graph_dev.h>
+
+int graph_dev_connect(async_sess_t *sess)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_1_0(exch, DEV_IFACE_ID(GRAPH_DEV_IFACE), GRAPH_DEV_CONNECT);
+	async_exchange_end(exch);
+
+	return ret;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/dlfcn.c
===================================================================
--- uspace/lib/c/generic/dlfcn.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/dlfcn.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,4 +38,6 @@
 #include <stdlib.h>
 #include <dlfcn.h>
+
+#ifdef CONFIG_RTLD
 
 #include <rtld/module.h>
@@ -87,4 +89,18 @@
 }
 
+#else /* CONFIG_RTLD not defined */
+
+void *dlopen(const char *path, int flag)
+{
+	return NULL;
+}
+
+void *dlsym(void *mod, const char *sym_name)
+{
+	return NULL;
+}
+
+#endif
+
 /** @}
  */
Index: uspace/lib/c/generic/double_to_str.c
===================================================================
--- uspace/lib/c/generic/double_to_str.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/double_to_str.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,785 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * 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.
+ */
+
+#include <double_to_str.h>
+
+#include "private/power_of_ten.h"
+#include <ieee_double.h>
+
+#include <stdint.h>
+#include <assert.h>
+#include <bool.h>
+
+/*
+ * Floating point numbers are converted from their binary representation
+ * into a decimal string using the algorithm described in:
+ *   Printing floating-point numbers quickly and accurately with integers
+ *   Loitsch, 2010
+ */
+
+/** The computation assumes a significand of 64 bits. */
+static const int significand_width = 64;
+
+/* Scale exponents to interval [alpha, gamma] to simplify conversion. */
+static const int alpha = -59;
+static const int gamma = -32;
+
+
+/** Returns true if the most-significant bit of num.significand is set. */
+static bool is_normalized(fp_num_t num)
+{
+	assert(8*sizeof(num.significand) == significand_width);
+
+	/* Normalized == most significant bit of the significand is set. */
+	return (num.significand & (1ULL << (significand_width - 1))) != 0;
+}
+
+/** Returns a normalized num with the MSbit set. */
+static fp_num_t normalize(fp_num_t num)
+{
+	const uint64_t top10bits = 0xffc0000000000000ULL;
+
+	/* num usually comes from ieee_double with top 10 bits zero. */
+	while (0 == (num.significand & top10bits)) {
+		num.significand <<= 10;
+		num.exponent -= 10;
+	}
+
+	while (!is_normalized(num)) {
+		num.significand <<= 1;
+		--num.exponent;
+	}
+
+	return num;
+}
+
+
+/** Returns x * y with an error of less than 0.5 ulp. */
+static fp_num_t multiply(fp_num_t x, fp_num_t y)
+{
+	assert(/* is_normalized(x) && */ is_normalized(y));
+	
+	const uint32_t low_bits = -1;
+
+	uint64_t a, b, c, d;
+	a = x.significand >> 32;
+	b = x.significand & low_bits;
+	c = y.significand >> 32;
+	d = y.significand & low_bits;
+
+	uint64_t bd, ad, bc, ac;
+	bd = b * d;
+	ad = a * d;
+	
+	bc = b * c;
+	ac = a * c;
+
+	/* Denote 32 bit parts of x a y as: x == a b, y == c d. Then:
+	 *        a  b    
+	 *  *     c  d
+	 *  ----------
+	 *       ad bd .. multiplication of 32bit parts results in 64bit parts
+	 *  + ac bc
+	 *  ----------
+	 *       [b|d] .. Depicts 64 bit intermediate results and how
+	 *     [a|d]      the 32 bit parts of these results overlap and
+	 *     [b|c]      contribute to the final result.
+	 *  +[a|c]
+	 *  ----------
+	 *   [ret]
+	 *  [tmp]
+	 */
+	uint64_t tmp = (bd >> 32) + (ad & low_bits) + (bc & low_bits);
+
+	/* Round upwards. */
+	tmp += 1U << 31;
+
+	fp_num_t ret;
+	ret.significand = ac + (bc >> 32) + (ad >> 32) + (tmp >> 32);
+	ret.exponent = x.exponent + y.exponent + significand_width;
+	
+	return ret;			
+}
+
+
+/** Returns a - b. Both must have the same exponent. */
+static fp_num_t subtract(fp_num_t a, fp_num_t b)
+{
+	assert(a.exponent == b.exponent);
+	assert(a.significand >= b.significand);
+
+	fp_num_t result;
+	
+	result.significand = a.significand - b.significand;
+	result.exponent = a.exponent;
+
+	return result;
+}
+
+
+/** Returns the interval [low, high] of numbers that convert to binary val. */
+static void get_normalized_bounds(ieee_double_t val, fp_num_t *high, 
+	fp_num_t *low, fp_num_t *val_dist)
+{
+	/* 
+	 * Only works if val comes directly from extract_ieee_double without
+	 * being manipulated in any way (eg it must not be normalized). 
+	 */
+	assert(!is_normalized(val.pos_val));
+
+	high->significand = (val.pos_val.significand << 1) + 1;
+	high->exponent = val.pos_val.exponent - 1;
+
+	/* val_dist = high - val */
+	val_dist->significand = 1;
+	val_dist->exponent = val.pos_val.exponent - 1;
+
+	/* Distance from both lower and upper bound is the same. */
+	if (!val.is_accuracy_step) {
+		low->significand = (val.pos_val.significand << 1) - 1;
+		low->exponent = val.pos_val.exponent - 1;
+	} else {
+		low->significand = (val.pos_val.significand << 2) - 1;
+		low->exponent = val.pos_val.exponent - 2;
+	}
+
+	*high = normalize(*high);
+
+	/* 
+	 * Lower bound may not be normalized if subtracting 1 unit
+	 * reset the most-significant bit to 0. 
+	 */
+	low->significand = low->significand << (low->exponent - high->exponent);
+	low->exponent = high->exponent;
+
+	val_dist->significand = 
+		val_dist->significand << (val_dist->exponent - high->exponent);
+	val_dist->exponent = high->exponent;
+}
+
+/** Determines the interval of numbers that have the binary representation 
+ *  of val.
+ * 
+ * Numbers in the range [scaled_upper_bound - bounds_delta, scaled_upper_bound]
+ * have the same double binary representation as val. 
+ *
+ * Bounds are scaled by 10^scale so that alpha <= exponent <= gamma.
+ * Moreover, scaled_upper_bound is normalized.
+ *
+ * val_dist is the scaled distance from val to the upper bound, ie
+ * val_dist == (upper_bound - val) * 10^scale
+ */
+static void calc_scaled_bounds(ieee_double_t val, fp_num_t *scaled_upper_bound, 
+	fp_num_t *bounds_delta, fp_num_t *val_dist, int *scale)
+{
+	fp_num_t upper_bound, lower_bound;
+
+	get_normalized_bounds(val, &upper_bound, &lower_bound, val_dist);
+
+	assert(upper_bound.exponent == lower_bound.exponent);
+	assert(is_normalized(upper_bound));
+	assert(normalize(val.pos_val).exponent == upper_bound.exponent);
+
+	/* 
+	 * Find such a cached normalized power of 10 that if multiplied
+	 * by upper_bound the binary exponent of upper_bound almost vanishes, 
+	 * ie:
+	 *   upper_scaled := upper_bound * 10^scale
+	 *   alpha <= upper_scaled.exponent <= gamma
+	 *   alpha <= upper_bound.exponent + pow_10.exponent + 64 <= gamma
+	 */
+	fp_num_t scaling_power_of_10;
+	int lower_bin_exp = alpha - upper_bound.exponent - significand_width;
+
+	get_power_of_ten(lower_bin_exp, &scaling_power_of_10, scale);
+
+	int scale_exp = scaling_power_of_10.exponent;
+	assert(alpha <= upper_bound.exponent + scale_exp + significand_width);
+	assert(upper_bound.exponent + scale_exp + significand_width <= gamma);
+
+	fp_num_t upper_scaled = multiply(upper_bound, scaling_power_of_10);
+	fp_num_t lower_scaled = multiply(lower_bound, scaling_power_of_10);
+	*val_dist = multiply(*val_dist, scaling_power_of_10);
+
+	assert(alpha <= upper_scaled.exponent && upper_scaled.exponent <= gamma);
+
+	/* 
+	 * Any value between lower and upper bound would be represented
+	 * in binary as the double val originated from. The bounds were
+	 * however scaled by an imprecise power of 10 (error less than 
+	 * 1 ulp) so the scaled bounds have an error of less than 1 ulp. 
+	 * Conservatively round the lower bound up and the upper bound 
+	 * down by 1 ulp just to be on the safe side. It avoids pronouncing
+	 * produced decimal digits as correct if such a decimal number
+	 * is close to the bounds to within 1 ulp. 
+	 */
+	upper_scaled.significand -= 1;
+	lower_scaled.significand += 1;
+
+	*bounds_delta = subtract(upper_scaled, lower_scaled);
+	*scaled_upper_bound = upper_scaled;
+}
+
+
+/** Rounds the last digit of buf so that it is closest to the converted number.*/
+static void round_last_digit(uint64_t rest, uint64_t w_dist, uint64_t delta,
+	uint64_t digit_val_diff, char *buf, int len)
+{
+	/*
+	 *  | <------- delta -------> |
+	 *  |    | <---- w_dist ----> |
+	 *  |    |       | <- rest -> |
+	 *  |    |       |            |
+	 *  |    |       ` buffer     |
+	 *  |    ` w                  ` upper
+	 *  ` lower
+	 *
+	 * delta = upper - lower .. conservative/safe interval
+	 * w_dist = upper - w    
+	 * upper = "number represented by digits in buf" + rest
+	 * 
+	 * Changing buf[len - 1] changes the value represented by buf 
+	 * by digit_val_diff * scaling, where scaling is shared by
+	 * all parameters. 
+	 *
+	 */
+
+	/* Current number in buf is greater than the double being converted */
+	bool cur_greater_w = rest < w_dist;
+	/* Rounding down by one would keep buf in between bounds (in safe rng). */
+	bool next_in_val_rng = cur_greater_w && (rest + digit_val_diff < delta);
+	/* Rounding down by one would bring buf closer to the processed number. */
+	bool next_closer = next_in_val_rng 
+		&& (rest + digit_val_diff < w_dist || rest - w_dist < w_dist - rest);
+
+	/* Of the shortest strings pick the one that is closest to the actual 
+	   floating point number. */
+	while (next_closer) {
+		assert('0' < buf[len - 1]);
+		assert(0 < digit_val_diff);
+
+		--buf[len - 1];
+		rest += digit_val_diff;
+
+		cur_greater_w = rest < w_dist;
+		next_in_val_rng = cur_greater_w && (rest + digit_val_diff < delta);
+		next_closer = next_in_val_rng 
+			&& (rest + digit_val_diff < w_dist || rest - w_dist < w_dist - rest);
+	}
+}
+
+
+/** Generates the shortest accurate decimal string representation.
+ *
+ * Outputs (mostly) the shortest accurate string representation 
+ * for the number scaled_upper - val_dist. Numbers in the interval
+ * [scaled_upper - delta, scaled_upper] have the same binary
+ * floating point representation and will therefore share the
+ * shortest string representation (up to the rounding of the last
+ * digit to bring the shortest string also the closest to the
+ * actual number). 
+ *
+ * @param scaled_upper Scaled upper bound of numbers that have the
+ *              same binary representation as the converted number.
+ *              Scaled by 10^-scale so that alpha <= exponent <= gamma.
+ * @param delta scaled_upper - delta is the lower bound of numbers
+ *              that share the same binary representation in double.
+ * @param val_dist scaled_upper - val_dist is the number whose
+ *              decimal string we're generating.
+ * @param scale Decimal scaling of the value to convert (ie scaled_upper).
+ * @param buf   Buffer to store the string representation. Must be large 
+ *              enough to store all digits and a null terminator. At most
+ *              MAX_DOUBLE_STR_LEN digits will be written (not counting
+ *              the null terminator).
+ * @param buf_size Size of buf in bytes. 
+ * @param dec_exponent Will be set to the decimal exponent of the number 
+ *              string in buf.
+ *
+ * @return Number of digits; negative on failure (eg buffer too small).
+ */
+static int gen_dec_digits(fp_num_t scaled_upper, fp_num_t delta, 
+	fp_num_t val_dist, int scale, char *buf, size_t buf_size, int *dec_exponent)
+{
+	/* 
+	 * The integral part of scaled_upper is 5 to 32 bits long while 
+	 * the remaining fractional part is 59 to 32 bits long because:
+	 * -59 == alpha <= scaled_upper.e <= gamma == -32
+	 *
+	 *  | <------- delta -------> |
+	 *  |    | <--- val_dist ---> |
+	 *  |    |    |<- remainder ->|
+	 *  |    |    |               |
+	 *  |    |    ` buffer        |
+	 *  |    ` val                ` upper
+	 *  ` lower
+	 *
+	 */ 
+	assert(scaled_upper.significand != 0);
+	assert(alpha <= scaled_upper.exponent && scaled_upper.exponent <= gamma);
+	assert(scaled_upper.exponent == delta.exponent);
+	assert(scaled_upper.exponent == val_dist.exponent);
+	assert(val_dist.significand <= delta.significand);
+
+	/* We'll produce at least one digit and a null terminator. */
+	if (buf_size < 2) {
+		return -1;
+	}
+
+	/* one is number 1 encoded with the same exponent as scaled_upper */
+	fp_num_t one;
+	one.significand = ((uint64_t) 1) << (-scaled_upper.exponent);
+	one.exponent = scaled_upper.exponent;
+
+	/*
+	 * Extract the integral part of scaled_upper. 
+	 *  upper / one == upper >> -one.e 
+	 */
+	uint32_t int_part = (uint32_t)(scaled_upper.significand >> (-one.exponent));
+	
+	/* 
+	 * Fractional part of scaled_upper.
+	 *  upper % one == upper & (one.f - 1) 
+	 */
+	uint64_t frac_part = scaled_upper.significand & (one.significand - 1);
+
+	/*
+	 * The integral part of upper has at least 5 bits (64 + alpha) and 
+	 * at most 32 bits (64 + gamma). The integral part has at most 10 
+	 * decimal digits, so kappa <= 10. 
+	 */
+	int kappa = 10;
+	uint32_t div = 1000000000;
+	size_t len = 0;
+
+	/* Produce decimal digits for the integral part of upper. */
+	while (kappa > 0) {
+		int digit = int_part / div;
+		int_part %= div;
+
+		--kappa;
+
+		/* Skip leading zeros. */
+		if (digit != 0 || len != 0) {
+			/* Current length + new digit + null terminator <= buf_size */
+			if (len + 2 <= buf_size) {
+				buf[len] = '0' + digit;
+				++len;
+			} else {
+				return -1;
+			}
+		}
+
+		/* 
+		 * Difference between the so far produced decimal number and upper
+		 * is calculated as: remaining_int_part * one + frac_part 
+		 */
+		uint64_t remainder = (((uint64_t)int_part) << -one.exponent) + frac_part;
+
+		/* The produced decimal number would convert back to upper. */
+		if (remainder <= delta.significand) {
+			assert(0 < len && len < buf_size);
+			*dec_exponent = kappa - scale;
+			buf[len] = '\0';
+
+			/* Of the shortest representations choose the numerically closest. */
+			round_last_digit(remainder, val_dist.significand, delta.significand,
+				(uint64_t)div << (-one.exponent), buf, len);
+			return len;
+		}
+
+		div /= 10;
+	}
+
+	/* Generate decimal digits for the fractional part of upper. */
+	do {
+		/*
+		 * Does not overflow because at least 5 upper bits were
+		 * taken by the integral part and are now unused in frac_part. 
+		 */
+		frac_part *= 10;
+		delta.significand *= 10;
+		val_dist.significand *= 10;
+
+		/* frac_part / one */
+		int digit = (int)(frac_part >> (-one.exponent));
+		
+		/* frac_part %= one */
+		frac_part &= one.significand - 1;
+
+		--kappa;
+
+		/* Skip leading zeros. */
+		if (digit == 0 && len == 0) {
+			continue;
+		}
+
+		/* Current length + new digit + null terminator <= buf_size */
+		if (len + 2 <= buf_size) {
+			buf[len] = '0' + digit;
+			++len;
+		} else {
+			return -1;
+		}
+	} while (frac_part > delta.significand);
+
+	assert(0 < len && len < buf_size);
+
+	*dec_exponent = kappa - scale;
+	buf[len] = '\0';
+
+	/* Of the shortest representations choose the numerically closest one. */
+	round_last_digit(frac_part, val_dist.significand, delta.significand, 
+		one.significand, buf, len);
+
+	return len;
+}
+
+/** Produce a string for 0.0 */
+static int zero_to_str(char *buf, size_t buf_size, int *dec_exponent)
+{
+	if (2 <= buf_size) {
+		buf[0] = '0';
+		buf[1] = '\0';
+		*dec_exponent = 0;
+		return 1;
+	} else {
+		return -1;
+	}
+}
+
+
+/** Converts a non-special double into its shortest accurate string 
+ *  representation.
+ *
+ * Produces an accurate string representation, ie the string will 
+ * convert back to the same binary double (eg via strtod). In the
+ * vast majority of cases (99%) the string will be the shortest such
+ * string that is also the closest to the value of any shortest
+ * string representations. Therefore, no trailing zeros are ever
+ * produced.
+ *
+ * Conceptually, the value is: buf * 10^dec_exponent
+ *
+ * Never outputs trailing zeros.
+ *
+ * @param ieee_val Binary double description to convert. Must be the product
+ *                 of extract_ieee_double and it must not be a special number.
+ * @param buf      Buffer to store the string representation. Must be large 
+ *                 enough to store all digits and a null terminator. At most
+ *                 MAX_DOUBLE_STR_LEN digits will be written (not counting
+ *                 the null terminator).
+ * @param buf_size Size of buf in bytes.
+ * @param dec_exponent Will be set to the decimal exponent of the number 
+ *                 string in buf.
+ *
+ * @return The number of printed digits. A negative value indicates
+ *         an error: buf too small (or ieee_val.is_special).
+ */
+int double_to_short_str(ieee_double_t ieee_val, char *buf, size_t buf_size, 
+	int *dec_exponent)
+{
+	/* The whole computation assumes 64bit significand. */
+	assert(sizeof(ieee_val.pos_val.significand) == sizeof(uint64_t));
+
+	if (ieee_val.is_special) {
+		return -1;
+	}
+
+	/* Zero cannot be normalized. Handle it here. */
+	if (0 == ieee_val.pos_val.significand) {
+		return zero_to_str(buf, buf_size, dec_exponent);
+	}
+
+	fp_num_t scaled_upper_bound;
+	fp_num_t delta;
+	fp_num_t val_dist;
+	int scale;
+
+	calc_scaled_bounds(ieee_val, &scaled_upper_bound, 
+		&delta, &val_dist, &scale);
+
+	int len = gen_dec_digits(scaled_upper_bound, delta, val_dist, scale, 
+		buf, buf_size, dec_exponent);
+
+	assert(len <= MAX_DOUBLE_STR_LEN);
+	return len;
+}
+
+/** Generates a fixed number of decimal digits of w_scaled.
+ *
+ * double == w_scaled * 10^-scale, where alpha <= w_scaled.e <= gamma
+ *
+ * @param w_scaled Scaled number by 10^-scale so that
+ *              alpha <= exponent <= gamma
+ * @param scale Decimal scaling of the value to convert (ie w_scaled).
+ * @param signif_d_cnt Maximum number of significant digits to output. 
+ *              Negative if as many as possible are requested.
+ * @param frac_d_cnt   Maximum number of fractional digits to output.
+ *              Negative if as many as possible are requested.
+ *              Eg. if 2 then 1.234 -> "1.23"; if 2 then 3e-9 -> "0".
+ * @param buf   Buffer to store the string representation. Must be large 
+ *              enough to store all digits and a null terminator. At most
+ *              MAX_DOUBLE_STR_LEN digits will be written (not counting
+ *              the null terminator).
+ * @param buf_size Size of buf in bytes. 
+ *
+ * @return Number of digits; negative on failure (eg buffer too small).
+ */
+static int gen_fixed_dec_digits(fp_num_t w_scaled, int scale, int signif_d_cnt, 
+	int frac_d_cnt, char *buf, size_t buf_size, int *dec_exponent)
+{
+	/* We'll produce at least one digit and a null terminator. */
+	if (0 == signif_d_cnt || buf_size < 2) {
+		return -1;
+	}
+
+	/* 
+	 * The integral part of w_scaled is 5 to 32 bits long while the 
+	 * remaining fractional part is 59 to 32 bits long because:
+	 * -59 == alpha <= w_scaled.e <= gamma == -32
+	 * 
+	 * Therefore:
+	 *  | 5..32 bits | 32..59 bits | == w_scaled == w * 10^scale
+	 *  |  int_part  |  frac_part  |
+	 *  |0 0  ..  0 1|0 0   ..  0 0| == one == 1.0
+	 *  |      0     |0 0   ..  0 1| == w_err == 1 * 2^w_scaled.e  
+	*/
+	assert(alpha <= w_scaled.exponent && w_scaled.exponent <= gamma);
+	assert(0 != w_scaled.significand);
+
+	/* 
+	 * Scaling the number being converted by 10^scale introduced
+	 * an error of less that 1 ulp. The actual value of w_scaled
+	 * could lie anywhere between w_scaled.signif +/- w_err. 
+	 * Scale the error locally as we scale the fractional part
+	 * of w_scaled.
+	 */
+	uint64_t w_err = 1;
+
+	/* one is number 1.0 encoded with the same exponent as w_scaled */
+	fp_num_t one;
+	one.significand = ((uint64_t) 1) << (-w_scaled.exponent);
+	one.exponent = w_scaled.exponent;
+
+	/* Extract the integral part of w_scaled. 
+	   w_scaled / one == w_scaled >> -one.e */
+	uint32_t int_part = (uint32_t)(w_scaled.significand >> (-one.exponent));
+
+	/* Fractional part of w_scaled.
+	   w_scaled % one == w_scaled & (one.f - 1) */
+	uint64_t frac_part = w_scaled.significand & (one.significand - 1);
+
+	size_t len = 0;
+	/* 
+	 * The integral part of w_scaled has at least 5 bits (64 + alpha = 5) 
+	 * and at most 32 bits (64 + gamma = 32). The integral part has 
+	 * at most 10 decimal digits, so kappa <= 10. 
+	 */
+	int kappa = 10;
+	uint32_t div = 1000000000;
+
+	int rem_signif_d_cnt = signif_d_cnt;
+	int rem_frac_d_cnt = 
+		(frac_d_cnt >= 0) ? (kappa - scale + frac_d_cnt) : INT_MAX;
+
+	/* Produce decimal digits for the integral part of w_scaled. */
+	while (kappa > 0 && rem_signif_d_cnt != 0 && rem_frac_d_cnt > 0) {
+		int digit = int_part / div;
+		int_part %= div;
+
+		div /= 10;
+		--kappa;
+		--rem_frac_d_cnt;
+
+		/* Skip leading zeros. */
+		if (digit == 0 && len == 0) {
+			continue;
+		}
+
+		/* Current length + new digit + null terminator <= buf_size */
+		if (len + 2 <= buf_size) {
+			buf[len] = '0' + digit;
+			++len;
+			--rem_signif_d_cnt;
+		} else {
+			return -1;
+		}
+	}
+
+	/* Generate decimal digits for the fractional part of w_scaled. */
+	while (w_err <= frac_part && rem_signif_d_cnt != 0 && rem_frac_d_cnt > 0) {
+		/*
+		 * Does not overflow because at least 5 upper bits were
+		 * taken by the integral part and are now unused in frac_part. 
+		 */
+		frac_part *= 10;
+		w_err *= 10;
+
+		/* frac_part / one */
+		int digit = (int)(frac_part >> (-one.exponent));
+		
+		/* frac_part %= one */
+		frac_part &= one.significand - 1;
+
+		--kappa;
+		--rem_frac_d_cnt;
+
+		/* Skip leading zeros. */
+		if (digit == 0 && len == 0) {
+			continue;
+		}
+
+		/* Current length + new digit + null terminator <= buf_size */
+		if (len + 2 <= buf_size) {
+			buf[len] = '0' + digit;
+			++len;
+			--rem_signif_d_cnt;
+		} else {
+			return -1;
+		}
+	};
+
+	assert(/* 0 <= len && */ len < buf_size);
+
+	if (0 < len) {
+		*dec_exponent = kappa - scale;
+		assert(frac_d_cnt < 0 || -frac_d_cnt <= *dec_exponent);
+	} else {
+		/* 
+		 * The number of fractional digits was too limiting to produce 
+		 * any digits. 
+		 */
+		assert(rem_frac_d_cnt <= 0 || w_scaled.significand == 0);
+		*dec_exponent = 0;
+		buf[0] = '0';
+		len = 1;
+	}
+
+	if (len < buf_size) {
+		buf[len] = '\0';
+		assert(signif_d_cnt < 0 || (int)len <= signif_d_cnt);
+		return len;
+	} else {
+		return -1;
+	}
+}
+
+
+/** Converts a non-special double into its string representation.
+ *
+ * Conceptually, the truncated double value is: buf * 10^dec_exponent
+ *
+ * Conversion errors are tracked, so all produced digits except the
+ * last one are accurate. Garbage digits are never produced.
+ * If the requested number of digits cannot be produced accurately 
+ * due to conversion errors less digits are produced than requested 
+ * and the last digit has an error of +/- 1 (so if '7' is the last
+ * converted digit it might have been converted to any of '6'..'8'
+ * had the conversion been completely precise). 
+ *
+ * If no error occurs at least one digit is output. 
+ *
+ * The conversion stops once the requested number of significant or 
+ * fractional digits is reached or the conversion error is too large 
+ * to generate any more digits (whichever happens first).
+ *
+ * Any digits following the first (most-significant) digit (this digit
+ * included) are counted as significant digits; eg:
+ *   1.4,    4 signif -> "1400" * 10^-3, ie 1.400
+ *   1000.3, 1 signif -> "1" * 10^3      ie 1000
+ *   0.003,  2 signif -> "30" * 10^-4    ie 0.003
+ *   9.5     1 signif -> "9" * 10^0,     ie 9
+ *
+ * Any digits following the decimal point are counted as fractional digits.
+ * This includes the zeros that would appear between the decimal point
+ * and the first non-zero fractional digit. If fewer fractional digits
+ * are requested than would allow to place the most-significant digit
+ * a "0" is output. Eg:
+ *   1.4,   3 frac -> "1400" * 10^-3,   ie 1.400
+ *   12.34  4 frac -> "123400" * 10^-4, ie 12.3400
+ *   3e-99  4 frac -> "0" * 10^0,       ie 0
+ *   0.009  2 frac -> "0" * 10^-2,      ie 0
+ *
+ * @param ieee_val Binary double description to convert. Must be the product
+ *                 of extract_ieee_double and it must not be a special number.
+ * @param signif_d_cnt Maximum number of significant digits to produce.
+ *                 The output is not rounded. 
+ *                 Set to a negative value to generate as many digits
+ *                 as accurately possible.
+ * @param frac_d_cnt Maximum number of fractional digits to produce including
+ *                 any zeros immediately trailing the decimal point. 
+ *                 The output is not rounded. 
+ *                 Set to a negative value to generate as many digits
+ *                 as accurately possible.
+ * @param buf      Buffer to store the string representation. Must be large 
+ *                 enough to store all digits and a null terminator. At most
+ *                 MAX_DOUBLE_STR_LEN digits will be written (not counting
+ *                 the null terminator).
+ * @param buf_size Size of buf in bytes.
+ * @param dec_exponent Set to the decimal exponent of the number string 
+ *                 in buf.
+ *
+ * @return The number of output digits. A negative value indicates
+ *         an error: buf too small (or ieee_val.is_special, or 
+ *         signif_d_cnt == 0).
+ */
+int double_to_fixed_str(ieee_double_t ieee_val, int signif_d_cnt,
+	int frac_d_cnt, char *buf, size_t buf_size, int *dec_exponent)
+{
+	/* The whole computation assumes 64bit significand. */
+	assert(sizeof(ieee_val.pos_val.significand) == sizeof(uint64_t));
+
+	if (ieee_val.is_special) {
+		return -1;
+	}
+
+	/* Zero cannot be normalized. Handle it here. */
+	if (0 == ieee_val.pos_val.significand) {
+		return zero_to_str(buf, buf_size, dec_exponent);
+	}
+
+	/* Normalize and scale. */
+	fp_num_t w = normalize(ieee_val.pos_val);
+
+	int lower_bin_exp = alpha - w.exponent - significand_width;
+
+	int scale;
+	fp_num_t scaling_power_of_10;
+
+	get_power_of_ten(lower_bin_exp, &scaling_power_of_10, &scale);
+
+	fp_num_t w_scaled = multiply(w, scaling_power_of_10);
+
+	/* Produce decimal digits from the scaled number. */
+	int len = gen_fixed_dec_digits(w_scaled, scale, signif_d_cnt, frac_d_cnt, 
+		buf, buf_size, dec_exponent);
+
+	assert(len <= MAX_DOUBLE_STR_LEN);
+	return len;
+}
+
Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/fibril_synch.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -379,5 +379,5 @@
 	futex_down(&async_futex);
 	if (timeout) {
-		gettimeofday(&wdata.to_event.expires, NULL);
+		getuptime(&wdata.to_event.expires);
 		tv_add(&wdata.to_event.expires, timeout);
 		async_insert_timeout(&wdata);
Index: uspace/lib/c/generic/ieee_double.c
===================================================================
--- uspace/lib/c/generic/ieee_double.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/ieee_double.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * 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.
+ */
+
+#include <ieee_double.h>
+
+#include <assert.h>
+
+/** Returns an easily processible description of the double val.
+ */
+ieee_double_t extract_ieee_double(double val)
+{
+	const uint64_t significand_mask = 0xfffffffffffffULL;
+	const uint64_t exponent_mask = 0x7ff0000000000000ULL;
+	const int exponent_shift = 64 - 11 - 1;
+	const uint64_t sign_mask = 0x8000000000000000ULL;
+	
+	const int special_exponent = 0x7ff;
+	const int denormal_exponent = 0;
+	const uint64_t hidden_bit = (1ULL << 52);
+	const int exponent_bias = 1075;
+
+	assert(sizeof(val) == sizeof(uint64_t));
+
+	union {
+		uint64_t num;
+		double val;
+	} bits;
+
+	bits.val = val;
+
+	/* 
+	 * Extract the binary ieee representation of the double. 
+	 * Relies on integers having the same endianness as doubles.
+	 */
+	uint64_t num = bits.num;	
+
+	ieee_double_t ret;
+
+	/* Determine the sign. */
+	ret.is_negative = ((num & sign_mask) != 0);
+
+	/* Extract the exponent. */
+	int raw_exponent = (num & exponent_mask) >> exponent_shift;
+
+	/* The extracted raw significand may not contain the hidden bit */
+	uint64_t raw_significand = num & significand_mask;
+
+	ret.is_special = (raw_exponent == special_exponent);
+
+	/* NaN or infinity */
+	if (ret.is_special) {
+		ret.is_infinity = (raw_significand == 0);
+		ret.is_nan = (raw_significand != 0);
+
+		/* These are not valid for special numbers but init them anyway. */
+		ret.is_denormal = true;
+		ret.is_accuracy_step = false;
+		ret.pos_val.significand = 0;
+		ret.pos_val.exponent = 0;
+	} else {
+		ret.is_infinity = false;
+		ret.is_nan = false;
+
+		ret.is_denormal = (raw_exponent == denormal_exponent);
+
+		/* Denormal or zero. */
+		if (ret.is_denormal) {
+			ret.pos_val.significand = raw_significand;
+			ret.pos_val.exponent = 1 - exponent_bias;
+			ret.is_accuracy_step = false;
+		} else {
+			ret.pos_val.significand = raw_significand + hidden_bit;
+			ret.pos_val.exponent = raw_exponent - exponent_bias;
+
+			/* The predecessor is closer to val than the successor 
+			 * if val is a normal value of the form 2^k (hence
+			 * raw_significand == 0) with the only exception being 
+			 * the smallest normal (raw_exponent == 1). The smallest 
+			 * normal's predecessor is the largest denormal and denormals 
+			 * do not get an extra bit of precision because their exponent 
+			 * stays the same (ie it does not decrease from k to k-1).
+			 */
+			ret.is_accuracy_step = (raw_significand == 0) && (raw_exponent != 1);
+		}
+	}
+
+	return ret;
+}
+
Index: uspace/lib/c/generic/io/chargrid.c
===================================================================
--- uspace/lib/c/generic/io/chargrid.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/io/chargrid.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * 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 <io/style.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <assert.h>
+#include <bool.h>
+#include <as.h>
+#include <io/chargrid.h>
+
+/** Create a chargrid.
+ *
+ * @param[in] cols  Number of columns.
+ * @param[in] rows  Number of rows.
+ * @param[in] flags Chargrid flags.
+ *
+ * @return New chargrid.
+ * @return NULL on failure.
+ *
+ */
+chargrid_t *chargrid_create(sysarg_t cols, sysarg_t rows,
+    chargrid_flag_t flags)
+{
+	size_t size =
+	    sizeof(chargrid_t) + cols * rows * sizeof(charfield_t);
+	chargrid_t *scrbuf;
+	
+	if ((flags & CHARGRID_FLAG_SHARED) == CHARGRID_FLAG_SHARED) {
+		scrbuf = (chargrid_t *) as_area_create(AS_AREA_ANY, size,
+		    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
+		if (scrbuf == AS_MAP_FAILED)
+			return NULL;
+	} else {
+		scrbuf = (chargrid_t *) malloc(size);
+		if (scrbuf == NULL)
+			return NULL;
+	}
+	
+	scrbuf->size = size;
+	scrbuf->flags = flags;
+	scrbuf->cols = cols;
+	scrbuf->rows = rows;
+	scrbuf->cursor_visible = false;
+	
+	scrbuf->attrs.type = CHAR_ATTR_STYLE;
+	scrbuf->attrs.val.style = STYLE_NORMAL;
+	
+	scrbuf->top_row = 0;
+	chargrid_clear(scrbuf);
+	
+	return scrbuf;
+}
+
+void chargrid_destroy(chargrid_t *srcbuf)
+{
+	// TODO
+}
+
+bool chargrid_cursor_at(chargrid_t *scrbuf, sysarg_t col, sysarg_t row)
+{
+	return ((scrbuf->cursor_visible) && (scrbuf->col == col) &&
+	    (scrbuf->row == row));
+}
+
+sysarg_t chargrid_get_top_row(chargrid_t *scrbuf)
+{
+	return scrbuf->top_row;
+}
+
+static sysarg_t chargrid_update_rows(chargrid_t *scrbuf)
+{
+	if (scrbuf->row == scrbuf->rows) {
+		scrbuf->row = scrbuf->rows - 1;
+		scrbuf->top_row = (scrbuf->top_row + 1) % scrbuf->rows;
+		chargrid_clear_row(scrbuf, scrbuf->row);
+		
+		return scrbuf->rows;
+	}
+	
+	return 2;
+}
+
+static sysarg_t chargrid_update_cols(chargrid_t *scrbuf)
+{
+	/* Column overflow */
+	if (scrbuf->col == scrbuf->cols) {
+		scrbuf->col = 0;
+		scrbuf->row++;
+		return chargrid_update_rows(scrbuf);
+	}
+	
+	return 1;
+}
+
+/** Store one character to chargrid.
+ *
+ * Its position is determined by scrbuf->col
+ * and scrbuf->row.
+ *
+ * @param scrbuf Chargrid.
+ * @param ch     Character to store.
+ * @param update Update coordinates.
+ *
+ * @return Number of rows which have been affected. In usual
+ *         situations this is 1. If the current position was
+ *         updated to a new row, this value is 2.
+ *
+ */
+sysarg_t chargrid_putchar(chargrid_t *scrbuf, wchar_t ch, bool update)
+{
+	assert(scrbuf->col < scrbuf->cols);
+	assert(scrbuf->row < scrbuf->rows);
+	
+	charfield_t *field =
+	    chargrid_charfield_at(scrbuf, scrbuf->col, scrbuf->row);
+	
+	field->ch = ch;
+	field->attrs = scrbuf->attrs;
+	field->flags |= CHAR_FLAG_DIRTY;
+	
+	if (update) {
+		scrbuf->col++;
+		return chargrid_update_cols(scrbuf);
+	}
+	
+	return 1;
+}
+
+/** Jump to a new row in chargrid.
+ *
+ * @param scrbuf Chargrid.
+ *
+ * @return Number of rows which have been affected. In usual
+ *         situations this is 2 (the original row and the new
+ *         row).
+ *
+ */
+sysarg_t chargrid_newline(chargrid_t *scrbuf)
+{
+	assert(scrbuf->col < scrbuf->cols);
+	assert(scrbuf->row < scrbuf->rows);
+	
+	scrbuf->col = 0;
+	scrbuf->row++;
+	
+	return chargrid_update_rows(scrbuf);
+}
+
+/** Jump to a new row in chargrid.
+ *
+ * @param scrbuf   Chargrid.
+ * @param tab_size Tab size.
+ *
+ * @return Number of rows which have been affected. In usual
+ *         situations this is 1. If the current position was
+ *         updated to a new row, this value is 2.
+ *
+ */
+sysarg_t chargrid_tabstop(chargrid_t *scrbuf, sysarg_t tab_size)
+{
+	assert(scrbuf->col < scrbuf->cols);
+	assert(scrbuf->row < scrbuf->rows);
+	
+	sysarg_t spaces = tab_size - scrbuf->cols % tab_size;
+	sysarg_t flush = 1;
+	
+	for (sysarg_t i = 0; i < spaces; i++)
+		flush += chargrid_putchar(scrbuf, ' ', true) - 1;
+	
+	return flush;
+}
+
+/** Jump to the previous character in chargrid.
+ *
+ * Currently no scrollback is supported.
+ *
+ * @param scrbuf Chargrid.
+ *
+ * @return Number of rows which have been affected. In usual
+ *         situations this is 1. If the current position was
+ *         updated to the previous row, this value is 2.
+ * @return 0 if no backspace is possible.
+ *
+ */
+sysarg_t chargrid_backspace(chargrid_t *scrbuf)
+{
+	assert(scrbuf->col < scrbuf->cols);
+	assert(scrbuf->row < scrbuf->rows);
+	
+	if ((scrbuf->col == 0) && (scrbuf->row == 0))
+		return 0;
+	
+	if (scrbuf->col == 0) {
+		scrbuf->col = scrbuf->cols - 1;
+		scrbuf->row--;
+		
+		chargrid_putchar(scrbuf, ' ', false);
+		return 2;
+	}
+	
+	scrbuf->col--;
+	chargrid_putchar(scrbuf, ' ', false);
+	return 1;
+}
+
+/** Clear the chargrid.
+ *
+ * @param scrbuf Chargrid.
+ *
+ */
+void chargrid_clear(chargrid_t *scrbuf)
+{
+	for (size_t pos = 0; pos < (scrbuf->cols * scrbuf->rows); pos++) {
+		scrbuf->data[pos].ch = 0;
+		scrbuf->data[pos].attrs = scrbuf->attrs;
+		scrbuf->data[pos].flags = CHAR_FLAG_DIRTY;
+	}
+	
+	scrbuf->col = 0;
+	scrbuf->row = 0;
+}
+
+/** Update current chargrid coordinates
+ *
+ * @param scrbuf Chargrid.
+ * @param col    New column.
+ * @param row    New row.
+ *
+ */
+void chargrid_set_cursor(chargrid_t *scrbuf, sysarg_t col, sysarg_t row)
+{
+	scrbuf->col = col;
+	scrbuf->row = row;
+}
+
+void chargrid_set_cursor_visibility(chargrid_t *scrbuf, bool visible)
+{
+	scrbuf->cursor_visible = visible;
+}
+
+/** Get current chargrid coordinates
+ *
+ * @param scrbuf Chargrid.
+ * @param col    Column.
+ * @param row    Row.
+ *
+ */
+void chargrid_get_cursor(chargrid_t *scrbuf, sysarg_t *col,
+    sysarg_t *row)
+{
+	assert(col);
+	assert(row);
+	
+	*col = scrbuf->col;
+	*row = scrbuf->row;
+}
+
+bool chargrid_get_cursor_visibility(chargrid_t *scrbuf)
+{
+	return scrbuf->cursor_visible;
+}
+
+/** Clear one buffer row.
+ *
+ * @param scrbuf Chargrid.
+ * @param row    Row to clear.
+ *
+ */
+void chargrid_clear_row(chargrid_t *scrbuf, sysarg_t row)
+{
+	for (sysarg_t col = 0; col < scrbuf->cols; col++) {
+		charfield_t *field =
+		    chargrid_charfield_at(scrbuf, col, row);
+		
+		field->ch = 0;
+		field->attrs = scrbuf->attrs;
+		field->flags |= CHAR_FLAG_DIRTY;
+	}
+}
+
+/** Set chargrid style.
+ *
+ * @param scrbuf Chargrid.
+ * @param style  Style.
+ *
+ */
+void chargrid_set_style(chargrid_t *scrbuf, console_style_t style)
+{
+	scrbuf->attrs.type = CHAR_ATTR_STYLE;
+	scrbuf->attrs.val.style = style;
+}
+
+/** Set chargrid color.
+ *
+ * @param scrbuf  Chargrid.
+ * @param bgcolor Background color.
+ * @param fgcolor Foreground color.
+ * @param attr    Color attribute.
+ *
+ */
+void chargrid_set_color(chargrid_t *scrbuf, console_color_t bgcolor,
+    console_color_t fgcolor, console_color_attr_t attr)
+{
+	scrbuf->attrs.type = CHAR_ATTR_INDEX;
+	scrbuf->attrs.val.index.bgcolor = bgcolor;
+	scrbuf->attrs.val.index.fgcolor = fgcolor;
+	scrbuf->attrs.val.index.attr = attr;
+}
+
+/** Set chargrid RGB color.
+ *
+ * @param scrbuf  Chargrid.
+ * @param bgcolor Background color.
+ * @param fgcolor Foreground color.
+ *
+ */
+void chargrid_set_rgb_color(chargrid_t *scrbuf, pixel_t bgcolor,
+    pixel_t fgcolor)
+{
+	scrbuf->attrs.type = CHAR_ATTR_RGB;
+	scrbuf->attrs.val.rgb.bgcolor = bgcolor;
+	scrbuf->attrs.val.rgb.fgcolor = fgcolor;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/io/con_srv.c
===================================================================
--- uspace/lib/c/generic/io/con_srv.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/io/con_srv.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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
+ * @brief Console protocol server stub
+ */
+#include <errno.h>
+#include <ipc/console.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <io/con_srv.h>
+
+static void con_read_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	void *buf;
+	size_t size;
+	int rc;
+	ipc_callid_t rcallid;
+
+	if (!async_data_read_receive(&rcallid, &size)) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	buf = malloc(size);
+	if (buf == NULL) {
+		async_answer_0(rcallid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	if (srv->srvs->ops->read == NULL) {
+		async_answer_0(rcallid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->read(srv, buf, size);
+	if (rc < 0) {
+		async_answer_0(rcallid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	async_data_read_finalize(rcallid, buf, size);
+	free(buf);
+
+	if (rc >= 0)
+		async_answer_1(callid, EOK, rc);
+	else
+		async_answer_0(callid, rc);
+}
+
+static void con_write_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	void *data;
+	size_t size;
+	int rc;
+
+	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	if (srv->srvs->ops->write == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->write(srv, data, size);
+	free(data);
+
+	if (rc >= 0)
+		async_answer_1(callid, EOK, rc);
+	else
+		async_answer_0(callid, rc);
+}
+
+static void con_sync_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	if (srv->srvs->ops->sync == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->sync(srv);
+	async_answer_0(callid, EOK);
+}
+
+static void con_clear_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	if (srv->srvs->ops->clear == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->clear(srv);
+	async_answer_0(callid, EOK);
+}
+
+static void con_set_pos_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	sysarg_t col;
+	sysarg_t row;
+
+	col = IPC_GET_ARG1(*call);
+	row = IPC_GET_ARG2(*call);
+
+	if (srv->srvs->ops->set_pos == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->set_pos(srv, col, row);
+	async_answer_0(callid, EOK);
+}
+
+static void con_get_pos_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int rc;
+	sysarg_t col;
+	sysarg_t row;
+
+	if (srv->srvs->ops->get_pos == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->get_pos(srv, &col, &row);
+	async_answer_2(callid, rc, col, row);
+}
+
+static void con_get_size_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int rc;
+	sysarg_t cols;
+	sysarg_t rows;
+
+	if (srv->srvs->ops->get_size == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->get_size(srv, &cols, &rows);
+	async_answer_2(callid, rc, cols, rows);
+}
+
+static void con_get_color_cap_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int rc;
+	console_caps_t ccap;
+
+	if (srv->srvs->ops->get_color_cap == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->get_color_cap(srv, &ccap);
+	async_answer_1(callid, rc, (sysarg_t)ccap);
+}
+
+static void con_set_style_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	console_style_t style;
+
+	style = IPC_GET_ARG1(*call);
+
+	if (srv->srvs->ops->set_style == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->set_style(srv, style);
+	async_answer_0(callid, EOK);
+}
+
+static void con_set_color_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	console_color_t bgcolor;
+	console_color_t fgcolor;
+	console_color_attr_t flags;
+
+	bgcolor = IPC_GET_ARG1(*call);
+	fgcolor = IPC_GET_ARG2(*call);
+	flags = IPC_GET_ARG3(*call);
+
+	if (srv->srvs->ops->set_color == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->set_color(srv, bgcolor, fgcolor, flags);
+	async_answer_0(callid, EOK);
+}
+
+static void con_set_rgb_color_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	pixel_t bgcolor;
+	pixel_t fgcolor;
+
+	bgcolor = IPC_GET_ARG1(*call);
+	fgcolor = IPC_GET_ARG2(*call);
+
+	if (srv->srvs->ops->set_rgb_color == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->set_rgb_color(srv, bgcolor, fgcolor);
+	async_answer_0(callid, EOK);
+}
+
+static void con_set_cursor_visibility_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	bool show;
+
+	show = IPC_GET_ARG1(*call);
+
+	if (srv->srvs->ops->set_cursor_visibility == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	srv->srvs->ops->set_cursor_visibility(srv, show);
+	async_answer_0(callid, EOK);
+}
+
+static void con_get_event_srv(con_srv_t *srv, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int rc;
+	kbd_event_t event;
+
+	if (srv->srvs->ops->get_event == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = srv->srvs->ops->get_event(srv, &event);
+	async_answer_4(callid, rc, event.type, event.key, event.mods, event.c);
+}
+
+static con_srv_t *con_srv_create(con_srvs_t *srvs)
+{
+	con_srv_t *srv;
+
+	srv = calloc(1, sizeof(*srv));
+	if (srv == NULL)
+		return NULL;
+
+	srv->srvs = srvs;
+	return srv;
+}
+
+void con_srvs_init(con_srvs_t *srvs)
+{
+	srvs->ops = NULL;
+	srvs->sarg = NULL;
+	srvs->abort_timeout = 0;
+	srvs->aborted = false;
+}
+
+int con_conn(ipc_callid_t iid, ipc_call_t *icall, con_srvs_t *srvs)
+{
+	con_srv_t *srv;
+	int rc;
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	srv = con_srv_create(srvs);
+	if (srv == NULL)
+		return ENOMEM;
+
+/*	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (sess == NULL)
+		return ENOMEM;
+
+	srv->client_sess = sess;
+*/
+	srv->client_sess = NULL;
+
+	rc = srvs->ops->open(srvs, srv);
+	if (rc != EOK)
+		return rc;
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = 0;
+
+		while (callid == 0) {
+			/* XXX Need to be able to abort immediately */
+			callid = async_get_call_timeout(&call,
+			    srvs->abort_timeout);
+
+			if (srv->srvs->aborted) {
+				if (callid != 0)
+					async_answer_0(callid, EINTR);
+				break;
+			}
+		}
+
+		if (callid == 0)
+			break;
+
+		sysarg_t method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(callid, EOK);
+			break;
+		}
+
+		switch (method) {
+		case VFS_OUT_READ:
+			con_read_srv(srv, callid, &call);
+			break;
+		case VFS_OUT_WRITE:
+			con_write_srv(srv, callid, &call);
+			break;
+		case VFS_OUT_SYNC:
+			con_sync_srv(srv, callid, &call);
+			break;
+		case CONSOLE_CLEAR:
+			con_clear_srv(srv, callid, &call);
+			break;
+		case CONSOLE_SET_POS:
+			con_set_pos_srv(srv, callid, &call);
+			break;
+		case CONSOLE_GET_POS:
+			con_get_pos_srv(srv, callid, &call);
+			break;
+		case CONSOLE_GET_SIZE:
+			con_get_size_srv(srv, callid, &call);
+			break;
+		case CONSOLE_GET_COLOR_CAP:
+			con_get_color_cap_srv(srv, callid, &call);
+			break;
+		case CONSOLE_SET_STYLE:
+			con_set_style_srv(srv, callid, &call);
+			break;
+		case CONSOLE_SET_COLOR:
+			con_set_color_srv(srv, callid, &call);
+			break;
+		case CONSOLE_SET_RGB_COLOR:
+			con_set_rgb_color_srv(srv, callid, &call);
+			break;
+		case CONSOLE_SET_CURSOR_VISIBILITY:
+			con_set_cursor_visibility_srv(srv, callid, &call);
+			break;
+		case CONSOLE_GET_EVENT:
+			con_get_event_srv(srv, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+		}
+	}
+
+	rc = srvs->ops->close(srv);
+	free(srv);
+
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/io/console.c
===================================================================
--- uspace/lib/c/generic/io/console.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/io/console.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,5 +38,4 @@
 #include <async.h>
 #include <errno.h>
-#include <stdio.h>
 #include <malloc.h>
 #include <vfs/vfs_sess.h>
@@ -126,5 +125,5 @@
 {
 	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	async_req_1_0(exch, CONSOLE_CURSOR_VISIBILITY, (show != false));
+	async_req_1_0(exch, CONSOLE_SET_CURSOR_VISIBILITY, (show != false));
 	async_exchange_end(exch);
 }
@@ -151,5 +150,5 @@
 {
 	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
-	async_req_2_0(exch, CONSOLE_GOTO, col, row);
+	async_req_2_0(exch, CONSOLE_SET_POS, col, row);
 	async_exchange_end(exch);
 }
Index: uspace/lib/c/generic/io/input.c
===================================================================
--- uspace/lib/c/generic/io/input.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/io/input.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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
+ * @brief Input protocol client stub
+ */
+
+#include <async.h>
+#include <assert.h>
+#include <errno.h>
+#include <io/kbd_event.h>
+#include <io/input.h>
+#include <ipc/input.h>
+#include <stdlib.h>
+
+static void input_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+int input_open(async_sess_t *sess, input_ev_ops_t *ev_ops,
+    void *arg, input_t **rinput)
+{
+	input_t *input = calloc(1, sizeof(input_t));
+	if (input == NULL)
+		return ENOMEM;
+
+	input->sess = sess;
+	input->ev_ops = ev_ops;
+	input->user = arg;
+
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	int rc = async_connect_to_me(exch, 0, 0, 0, input_cb_conn, input);
+	async_exchange_end(exch);
+
+	if (rc != EOK)
+		goto error;
+
+	*rinput = input;
+	return EOK;
+
+error:
+	if (input != NULL)
+		free(input);
+
+	return rc;
+}
+
+void input_close(input_t *input)
+{
+	/* XXX Synchronize with input_cb_conn */
+	free(input);
+}
+
+int input_yield(input_t *input)
+{
+	async_exch_t *exch = async_exchange_begin(input->sess);
+
+	int rc = async_req_0_0(exch, INPUT_YIELD);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+int input_reclaim(input_t *input)
+{
+	async_exch_t *exch = async_exchange_begin(input->sess);
+
+	int rc = async_req_0_0(exch, INPUT_RECLAIM);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
+static void input_ev_key(input_t *input, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	kbd_event_type_t type;
+	keycode_t key;
+	keymod_t mods;
+	wchar_t c;
+	int rc;
+
+	type = IPC_GET_ARG1(*call);
+	key = IPC_GET_ARG2(*call);
+	mods = IPC_GET_ARG3(*call);
+	c = IPC_GET_ARG4(*call);
+
+	rc = input->ev_ops->key(input, type, key, mods, c);
+	async_answer_0(callid, rc);
+}
+
+static void input_ev_move(input_t *input, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int dx;
+	int dy;
+	int rc;
+
+	dx = IPC_GET_ARG1(*call);
+	dy = IPC_GET_ARG2(*call);
+
+	rc = input->ev_ops->move(input, dx, dy);
+	async_answer_0(callid, rc);
+}
+
+static void input_ev_abs_move(input_t *input, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	unsigned x;
+	unsigned y;
+	unsigned max_x;
+	unsigned max_y;
+	int rc;
+
+	x = IPC_GET_ARG1(*call);
+	y = IPC_GET_ARG2(*call);
+	max_x = IPC_GET_ARG3(*call);
+	max_y = IPC_GET_ARG4(*call);
+
+	rc = input->ev_ops->abs_move(input, x, y, max_x, max_y);
+	async_answer_0(callid, rc);
+}
+
+static void input_ev_button(input_t *input, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int bnum;
+	int press;
+	int rc;
+
+	bnum = IPC_GET_ARG1(*call);
+	press = IPC_GET_ARG2(*call);
+
+	rc = input->ev_ops->button(input, bnum, press);
+	async_answer_0(callid, rc);
+}
+
+static void input_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	input_t *input = (input_t *)arg;
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case INPUT_EVENT_KEY:
+			input_ev_key(input, callid, &call);
+			break;
+		case INPUT_EVENT_MOVE:
+			input_ev_move(input, callid, &call);
+			break;
+		case INPUT_EVENT_ABS_MOVE:
+			input_ev_abs_move(input, callid, &call);
+			break;
+		case INPUT_EVENT_BUTTON:
+			input_ev_button(input, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+		}
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/io/log.c
===================================================================
--- uspace/lib/c/generic/io/log.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/io/log.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,58 +38,190 @@
 #include <stdlib.h>
 #include <stdio.h>
-
+#include <async.h>
 #include <io/log.h>
-
-/** Serialization mutex for logging functions. */
-static FIBRIL_MUTEX_INITIALIZE(log_serializer);
-
-/** Current log level. */
-static log_level_t log_level;
-
-static FILE *log_stream;
-
+#include <ipc/logger.h>
+#include <ns.h>
+
+/** Id of the first log we create at logger. */
+static sysarg_t default_log_id;
+
+/** Log messages are printed under this name. */
 static const char *log_prog_name;
 
-/** Prefixes for individual logging levels. */
+/** Names of individual log levels. */
 static const char *log_level_names[] = {
-	[LVL_FATAL] = "Fatal error",
-	[LVL_ERROR] = "Error",
-	[LVL_WARN] = "Warning",
-	[LVL_NOTE] = "Note",
-	[LVL_DEBUG] = "Debug",
-	[LVL_DEBUG2] = "Debug2"
+	"fatal",
+	"error",
+	"warn",
+	"note",
+	"debug",
+	"debug2",
+	NULL
 };
 
+/** IPC session with the logger service. */
+static async_sess_t *logger_session;
+
+/** Maximum length of a single log message (in bytes). */
+#define MESSAGE_BUFFER_SIZE 4096
+
+/** Send formatted message to the logger service.
+ *
+ * @param session Initialized IPC session with the logger.
+ * @param log Log to use.
+ * @param level Verbosity level of the message.
+ * @param message The actual message.
+ * @return Error code of the conversion or EOK on success.
+ */
+static int logger_message(async_sess_t *session, log_t log, log_level_t level, char *message)
+{
+	async_exch_t *exchange = async_exchange_begin(session);
+	if (exchange == NULL) {
+		return ENOMEM;
+	}
+	if (log == LOG_DEFAULT)
+		log = default_log_id;
+
+	// FIXME: remove when all USB drivers use libc logging explicitly
+	str_rtrim(message, '\n');
+
+	aid_t reg_msg = async_send_2(exchange, LOGGER_WRITER_MESSAGE,
+	    log, level, NULL);
+	int rc = async_data_write_start(exchange, message, str_size(message));
+	sysarg_t reg_msg_rc;
+	async_wait_for(reg_msg, &reg_msg_rc);
+
+	async_exchange_end(exchange);
+
+	/*
+	 * Getting ENAK means no-one wants our message. That is not an
+	 * error at all.
+	 */
+	if (rc == ENAK)
+		rc = EOK;
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	return reg_msg_rc;
+}
+
+/** Get name of the log level.
+ *
+ * @param level The log level.
+ * @return String name or "unknown".
+ */
+const char *log_level_str(log_level_t level)
+{
+	if (level >= LVL_LIMIT)
+		return "unknown";
+	else
+		return log_level_names[level];
+}
+
+/** Convert log level name to the enum.
+ *
+ * @param[in] name Log level name or log level number.
+ * @param[out] level_out Where to store the result (set to NULL to ignore).
+ * @return Error code of the conversion or EOK on success.
+ */
+int log_level_from_str(const char *name, log_level_t *level_out)
+{
+	log_level_t level = LVL_FATAL;
+
+	while (log_level_names[level] != NULL) {
+		if (str_cmp(name, log_level_names[level]) == 0) {
+			if (level_out != NULL)
+				*level_out = level;
+			return EOK;
+		}
+		level++;
+	}
+
+	/* Maybe user specified number directly. */
+	char *end_ptr;
+	int level_int = strtol(name, &end_ptr, 0);
+	if ((end_ptr == name) || (str_length(end_ptr) != 0))
+		return EINVAL;
+	if (level_int < 0)
+		return ERANGE;
+	if (level_int >= (int) LVL_LIMIT)
+		return ERANGE;
+
+	if (level_out != NULL)
+		*level_out = (log_level_t) level_int;
+
+	return EOK;
+}
+
 /** Initialize the logging system.
  *
- * @param prog_name	Program name, will be printed as part of message
- * @param level		Minimum message level to print
- */
-int log_init(const char *prog_name, log_level_t level)
-{
-	assert(level < LVL_LIMIT);
-	log_level = level;
-
-	log_stream = stdout;
+ * @param prog_name Program name, will be printed as part of message
+ */
+int log_init(const char *prog_name)
+{
 	log_prog_name = str_dup(prog_name);
 	if (log_prog_name == NULL)
 		return ENOMEM;
 
+	logger_session = service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_LOGGER, LOGGER_INTERFACE_WRITER, 0);
+	if (logger_session == NULL) {
+		return ENOMEM;
+	}
+
+	default_log_id = log_create(prog_name, LOG_NO_PARENT);
+
 	return EOK;
 }
 
+/** Create a new (sub-) log.
+ *
+ * This function always returns a valid log_t. In case of errors,
+ * @c parent is returned and errors are silently ignored.
+ *
+ * @param name Log name under which message will be reported (appended to parents name).
+ * @param parent Parent log.
+ * @return Opaque identifier of the newly created log.
+ */
+log_t log_create(const char *name, log_t parent)
+{
+	async_exch_t *exchange = async_exchange_begin(logger_session);
+	if (exchange == NULL)
+		return parent;
+
+	if (parent == LOG_DEFAULT)
+		parent = default_log_id;
+
+	ipc_call_t answer;
+	aid_t reg_msg = async_send_1(exchange, LOGGER_WRITER_CREATE_LOG,
+	    parent, &answer);
+	int rc = async_data_write_start(exchange, name, str_size(name));
+	sysarg_t reg_msg_rc;
+	async_wait_for(reg_msg, &reg_msg_rc);
+
+	async_exchange_end(exchange);
+
+	if ((rc != EOK) || (reg_msg_rc != EOK))
+		return parent;
+
+	return IPC_GET_ARG1(answer);
+}
+
 /** Write an entry to the log.
  *
- * @param level		Message verbosity level. Message is only printed
- *			if verbosity is less than or equal to current
- *			reporting level.
- * @param fmt		Format string (no traling newline).
- */
-void log_msg(log_level_t level, const char *fmt, ...)
+ * The message is printed only if the verbosity level is less than or
+ * equal to currently set reporting level of the log.
+ *
+ * @param ctx Log to use (use LOG_DEFAULT if you have no idea what it means).
+ * @param level Severity level of the message.
+ * @param fmt Format string in printf-like format (without trailing newline).
+ */
+void log_msg(log_t ctx, log_level_t level, const char *fmt, ...)
 {
 	va_list args;
 
 	va_start(args, fmt);
-	log_msgv(level, fmt, args);
+	log_msgv(ctx, level, fmt, args);
 	va_end(args);
 }
@@ -97,25 +229,20 @@
 /** Write an entry to the log (va_list variant).
  *
- * @param level		Message verbosity level. Message is only printed
- *			if verbosity is less than or equal to current
- *			reporting level.
- * @param fmt		Format string (no trailing newline)
- */
-void log_msgv(log_level_t level, const char *fmt, va_list args)
+ * @param ctx Log to use (use LOG_DEFAULT if you have no idea what it means).
+ * @param level Severity level of the message.
+ * @param fmt Format string in printf-like format (without trailing newline).
+ * @param args Arguments.
+ */
+void log_msgv(log_t ctx, log_level_t level, const char *fmt, va_list args)
 {
 	assert(level < LVL_LIMIT);
 
-	/* Higher number means higher verbosity. */
-	if (level <= log_level) {
-		fibril_mutex_lock(&log_serializer);
-
-		fprintf(log_stream, "%s: %s: ", log_prog_name,
-		    log_level_names[level]);
-		vfprintf(log_stream, fmt, args);
-		fputc('\n', log_stream);
-		fflush(log_stream);
-
-		fibril_mutex_unlock(&log_serializer);
-	}
+	char *message_buffer = malloc(MESSAGE_BUFFER_SIZE);
+	if (message_buffer == NULL)
+		return;
+
+	vsnprintf(message_buffer, MESSAGE_BUFFER_SIZE, fmt, args);
+	logger_message(logger_session, ctx, level, message_buffer);
+	free(message_buffer);
 }
 
Index: uspace/lib/c/generic/io/logctl.c
===================================================================
--- uspace/lib/c/generic/io/logctl.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/io/logctl.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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
+ * @{
+ */
+
+#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <io/logctl.h>
+#include <ipc/logger.h>
+#include <sysinfo.h>
+#include <ns.h>
+#include <str.h>
+
+/** IPC session with the logger service. */
+static async_sess_t *logger_session = NULL;
+
+static int start_logger_exchange(async_exch_t **exchange_out)
+{
+	assert(exchange_out != NULL);
+
+	if (logger_session == NULL) {
+		logger_session = service_connect_blocking(EXCHANGE_SERIALIZE,
+		    SERVICE_LOGGER, LOGGER_INTERFACE_CONTROL, 0);
+		if (logger_session == NULL)
+			return ENOMEM;
+	}
+
+	assert(logger_session != NULL);
+
+	async_exch_t *exchange = async_exchange_begin(logger_session);
+	if (exchange == NULL)
+		return ENOMEM;
+
+	*exchange_out = exchange;
+
+	return EOK;
+}
+
+/** Set default reported log level (global setting).
+ *
+ * This setting affects all logger clients whose reporting level was
+ * not yet changed.
+ *
+ * If logging level of client A is changed with logctl_set_log_level()
+ * to some level, this call will have no effect at that client's reporting
+ * level. Even if the actual value of the reporting level of client A is
+ * the same as current (previous) default log level.
+ *
+ * @param new_level New reported logging level.
+ * @return Error code of the conversion or EOK on success.
+ */
+int logctl_set_default_level(log_level_t new_level)
+{
+	async_exch_t *exchange = NULL;
+	int rc = start_logger_exchange(&exchange);
+	if (rc != EOK)
+		return rc;
+
+	rc = (int) async_req_1_0(exchange,
+	    LOGGER_CONTROL_SET_DEFAULT_LEVEL, new_level);
+
+	async_exchange_end(exchange);
+
+	return rc;
+}
+
+/** Set reported log level of a single log.
+ *
+ * @see logctl_set_default_level
+ *
+ * @param logname Log name.
+ * @param new_level New reported logging level.
+ * @return Error code of the conversion or EOK on success.
+ */
+int logctl_set_log_level(const char *logname, log_level_t new_level)
+{
+	async_exch_t *exchange = NULL;
+	int rc = start_logger_exchange(&exchange);
+	if (rc != EOK)
+		return rc;
+
+	aid_t reg_msg = async_send_1(exchange, LOGGER_CONTROL_SET_LOG_LEVEL,
+	    new_level, NULL);
+	rc = async_data_write_start(exchange, logname, str_size(logname));
+	sysarg_t reg_msg_rc;
+	async_wait_for(reg_msg, &reg_msg_rc);
+
+	async_exchange_end(exchange);
+
+	if (rc != EOK)
+		return rc;
+
+	return (int) reg_msg_rc;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/io/output.c
===================================================================
--- uspace/lib/c/generic/io/output.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/io/output.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2011 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <as.h>
+#include <ipc/output.h>
+#include <io/concaps.h>
+#include <io/output.h>
+
+int output_yield(async_sess_t *sess)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_0_0(exch, OUTPUT_YIELD);
+	async_exchange_end(exch);
+	
+	return ret;
+}
+
+int output_claim(async_sess_t *sess)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_0_0(exch, OUTPUT_CLAIM);
+	async_exchange_end(exch);
+	
+	return ret;
+}
+
+int output_get_dimensions(async_sess_t *sess, sysarg_t *maxx, sysarg_t *maxy)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_0_2(exch, OUTPUT_GET_DIMENSIONS, maxx, maxy);
+	async_exchange_end(exch);
+	
+	return ret;
+}
+
+int output_get_caps(async_sess_t *sess, console_caps_t *ccaps)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	sysarg_t rv;
+	int ret = async_req_0_1(exch, OUTPUT_GET_CAPS, &rv);
+	
+	async_exchange_end(exch);
+	
+	if (ret == EOK)
+		*ccaps = (console_caps_t) rv;
+	
+	return ret;
+}
+
+frontbuf_handle_t output_frontbuf_create(async_sess_t *sess,
+    chargrid_t *frontbuf)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, OUTPUT_FRONTBUF_CREATE, &answer);
+	int rc = async_share_out_start(exch, frontbuf, AS_AREA_READ
+	    | AS_AREA_WRITE | AS_AREA_CACHEABLE);
+	
+	async_exchange_end(exch);
+	
+	sysarg_t ret;
+	async_wait_for(req, &ret);
+	
+	if ((rc != EOK) || (ret != EOK))
+		return 0;
+	
+	return (frontbuf_handle_t) IPC_GET_ARG1(answer);
+}
+
+int output_set_style(async_sess_t *sess, console_style_t style)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_1_0(exch, OUTPUT_SET_STYLE, style);
+	async_exchange_end(exch);
+	
+	return ret;
+}
+
+int output_cursor_update(async_sess_t *sess, frontbuf_handle_t frontbuf)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_1_0(exch, OUTPUT_CURSOR_UPDATE, frontbuf);
+	async_exchange_end(exch);
+	
+	return ret;
+}
+
+int output_update(async_sess_t *sess, frontbuf_handle_t frontbuf)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_1_0(exch, OUTPUT_UPDATE, frontbuf);
+	async_exchange_end(exch);
+	
+	return ret;
+}
+
+int output_damage(async_sess_t *sess, frontbuf_handle_t frontbuf, sysarg_t col,
+    sysarg_t row, sysarg_t cols, sysarg_t rows)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_5_0(exch, OUTPUT_DAMAGE, frontbuf, col, row,
+	    cols, rows);
+	async_exchange_end(exch);
+	
+	return ret;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/io/printf_core.c
===================================================================
--- uspace/lib/c/generic/io/printf_core.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/io/printf_core.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,8 +42,16 @@
 #include <ctype.h>
 #include <str.h>
+#include <double_to_str.h>
+#include <ieee_double.h>
+#include <assert.h>
+#include <macros.h>
+
 
 /** show prefixes 0x or 0 */
 #define __PRINTF_FLAG_PREFIX       0x00000001
 
+/** show the decimal point even if no fractional digits present */
+#define __PRINTF_FLAG_DECIMALPT    0x00000001
+
 /** signed / unsigned number */
 #define __PRINTF_FLAG_SIGNED       0x00000002
@@ -66,4 +74,8 @@
 /** number has - sign */
 #define __PRINTF_FLAG_NEGATIVE     0x00000100
+
+/** don't print trailing zeros in the fractional part */
+#define __PRINTF_FLAG_NOFRACZEROS  0x00000200
+
 
 /**
@@ -110,4 +122,47 @@
 static const char invalch = U_SPECIAL;
 
+
+
+/** Unformatted double number string representation. */
+typedef struct {
+	/** Buffer with len digits, no sign or leading zeros. */
+	char *str;
+	/** Number of digits in str. */
+	int len;
+	/** Decimal exponent, ie number = str * 10^dec_exp */
+	int dec_exp;
+	/** True if negative. */
+	bool neg;
+} double_str_t;
+
+
+
+/** Returns the sign character or 0 if no sign should be printed. */
+static int get_sign_char(bool negative, uint32_t flags)
+{
+	if (negative) {
+		return '-';
+	} else if (flags & __PRINTF_FLAG_SHOWPLUS) {
+		return '+';
+	} else if (flags & __PRINTF_FLAG_SPACESIGN) {
+		return ' ';
+	} else {
+		return 0;
+	}
+}
+
+/** Prints count times character ch. */
+static int print_padding(char ch, int count, printf_spec_t *ps)
+{
+	for (int i = 0; i < count; ++i) {
+		if (ps->str_write(&ch, 1, ps->data) < 0) {
+			return -1;
+		}
+	}
+
+	return count;
+}
+
+
 /** Print one or more characters without adding newline.
  *
@@ -281,6 +336,7 @@
 		return printf_putstr(nullstr, ps);
 	
-	/* Print leading spaces. */
 	size_t strw = str_length(str);
+
+	/* Precision unspecified - print everything. */
 	if ((precision == 0) || (precision > strw))
 		precision = strw;
@@ -329,6 +385,7 @@
 		return printf_putstr(nullstr, ps);
 	
-	/* Print leading spaces. */
 	size_t strw = wstr_length(str);
+
+	/* Precision not specified - print everything. */
 	if ((precision == 0) || (precision > strw))
 		precision = strw;
@@ -377,4 +434,9 @@
     uint32_t flags, printf_spec_t *ps)
 {
+	/* Precision not specified. */
+	if (precision < 0) {
+		precision = 0;
+	}
+	
 	const char *digits;
 	if (flags & __PRINTF_FLAG_BIGCHARS)
@@ -525,4 +587,656 @@
 	
 	return ((int) counter);
+}
+
+/** Prints a special double (ie NaN, infinity) padded to width characters. */
+static int print_special(ieee_double_t val, int width, uint32_t flags, 
+	printf_spec_t *ps)
+{
+	assert(val.is_special);
+
+	char sign = get_sign_char(val.is_negative, flags);
+
+	const int str_len = 3;
+	const char *str;
+	
+	if (flags & __PRINTF_FLAG_BIGCHARS) {
+		str = val.is_infinity ? "INF" : "NAN";
+	} else {
+		str = val.is_infinity ? "inf" : "nan";
+	}
+
+	int padding_len = max(0, width - ((sign ? 1 : 0) + str_len));
+
+	int counter = 0;
+	int ret;
+
+	/* Leading padding. */
+	if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
+		if ((ret = print_padding(' ', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	if (sign) {
+		if ((ret = ps->str_write(&sign, 1, ps->data)) < 0)
+			return -1;
+		
+		counter += ret;
+	}
+
+	if ((ret = ps->str_write(str, str_len, ps->data)) < 0)
+		return -1;
+	
+	counter += ret;
+
+
+	/* Trailing padding. */
+	if (flags & __PRINTF_FLAG_LEFTALIGNED) {
+		if ((ret = print_padding(' ', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	return counter;
+}
+
+/** Trims trailing zeros but leaves a single "0" intact. */
+static void fp_trim_trailing_zeros(char *buf, int *len, int *dec_exp)
+{
+	/* Cut the zero off by adjusting the exponent. */
+	while (2 <= *len && '0' == buf[*len - 1]) {
+		--*len;
+		++*dec_exp;
+	}
+}
+
+/** Textually round up the last digit thereby eliminating it. */
+static void fp_round_up(char *buf, int *len, int *dec_exp)
+{
+	assert(1 <= *len);
+
+	char *last_digit = &buf[*len - 1];
+
+	int carry = ('5' <= *last_digit);
+
+	/* Cut the digit off by adjusting the exponent. */
+	--*len;
+	++*dec_exp;
+	--last_digit;
+
+	if (carry) {
+		/* Skip all the digits to cut off/round to zero. */
+		while (buf <= last_digit && '9' == *last_digit) {
+			--last_digit;
+		}
+
+		/* last_digit points to the last digit to round but not '9' */
+		if (buf <= last_digit) {
+			*last_digit += 1;
+			int new_len = last_digit - buf + 1;
+			*dec_exp += *len - new_len;
+			*len = new_len;
+		} else {
+			/* All len digits rounded to 0. */
+			buf[0] = '1';
+			*dec_exp += *len;
+			*len = 1;
+		}
+	} else {
+		/* The only digit was rounded to 0. */
+		if (last_digit < buf) {
+			buf[0] = '0';
+			*dec_exp = 0;
+			*len = 1;
+		}
+	}
+}
+
+
+/** Format and print the double string repressentation according 
+ *  to the %f specifier. 
+ */
+static int print_double_str_fixed(double_str_t *val_str, int precision, int width, 
+	uint32_t flags, printf_spec_t *ps)
+{
+	int len = val_str->len;
+	char *buf = val_str->str;
+	int dec_exp = val_str->dec_exp;
+
+	assert(0 < len);
+	assert(0 <= precision);
+	assert(0 <= dec_exp || -dec_exp <= precision);
+
+	/* Number of integral digits to print (at least leading zero). */
+	int int_len = max(1, len + dec_exp);
+
+	char sign = get_sign_char(val_str->neg, flags);
+
+	/* Fractional portion lengths. */
+	int last_frac_signif_pos = max(0, -dec_exp);
+	int leading_frac_zeros = max(0, last_frac_signif_pos - len);
+	int signif_frac_figs = min(last_frac_signif_pos, len);
+	int trailing_frac_zeros = precision - last_frac_signif_pos;
+	char *buf_frac = buf + len - signif_frac_figs;
+
+	if (flags & __PRINTF_FLAG_NOFRACZEROS) {
+		trailing_frac_zeros = 0;
+	}
+
+	int frac_len = leading_frac_zeros + signif_frac_figs + trailing_frac_zeros;
+
+	bool has_decimal_pt = (0 < frac_len) || (flags & __PRINTF_FLAG_DECIMALPT);
+
+	/* Number of non-padding chars to print. */
+	int num_len = (sign ? 1 : 0) + int_len + (has_decimal_pt ? 1 : 0) + frac_len;
+
+	int padding_len = max(0, width - num_len);
+	int ret = 0;
+	int counter = 0;
+
+	/* Leading padding and sign. */
+
+	if (!(flags & (__PRINTF_FLAG_LEFTALIGNED | __PRINTF_FLAG_ZEROPADDED))) {
+		if ((ret = print_padding(' ', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	if (sign) {
+		if ((ret = ps->str_write(&sign, 1, ps->data)) < 0) 
+			return -1;
+		
+		counter += ret;
+	}
+
+	if (flags & __PRINTF_FLAG_ZEROPADDED) {
+		if ((ret = print_padding('0', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	/* Print the intergral part of the buffer. */
+
+	int buf_int_len = min(len, len + dec_exp);
+
+	if (0 < buf_int_len) {
+		if ((ret = ps->str_write(buf, buf_int_len, ps->data)) < 0) 
+			return -1;
+
+		counter += ret;
+
+		/* Print trailing zeros of the integral part of the number. */
+		if ((ret = print_padding('0', int_len - buf_int_len, ps)) < 0) 
+			return -1;
+	} else {
+		/* Single leading integer 0. */
+		char ch = '0';
+		if ((ret = ps->str_write(&ch, 1, ps->data)) < 0) 
+			return -1;
+	}
+
+	counter += ret;
+	
+	/* Print the decimal point and the fractional part. */
+	if (has_decimal_pt) {
+		char ch = '.';
+
+		if ((ret = ps->str_write(&ch, 1, ps->data)) < 0) 
+			return -1;
+		
+		counter += ret;
+
+		/* Print leading zeros of the fractional part of the number. */
+		if ((ret = print_padding('0', leading_frac_zeros, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+
+		/* Print significant digits of the fractional part of the number. */
+		if (0 < signif_frac_figs) {
+			if ((ret = ps->str_write(buf_frac, signif_frac_figs, ps->data)) < 0) 
+				return -1;
+
+			counter += ret;
+		}
+
+		/* Print trailing zeros of the fractional part of the number. */
+		if ((ret = print_padding('0', trailing_frac_zeros, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	/* Trailing padding. */
+	if (flags & __PRINTF_FLAG_LEFTALIGNED) {
+		if ((ret = print_padding(' ', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	return counter;
+}
+
+
+/** Convert, format and print a double according to the %f specifier. 
+ *
+ * @param g     Double to print.
+ * @param precision Number of fractional digits to print. If 0 no
+ *              decimal point will be printed unless the flag
+ *              __PRINTF_FLAG_DECIMALPT is specified.
+ * @param width Minimum number of characters to display. Pads 
+ *              with '0' or ' ' depending on the set flags;
+ * @param flags Printf flags.
+ * @param ps    Printing functions.
+ *
+ * @return The number of characters printed; negative on failure.
+ */
+static int print_double_fixed(double g, int precision, int width, uint32_t flags, 
+	printf_spec_t *ps)
+{
+	if (flags & __PRINTF_FLAG_LEFTALIGNED) {
+		flags &= ~__PRINTF_FLAG_ZEROPADDED;
+	}
+
+	if (flags & __PRINTF_FLAG_DECIMALPT) {
+		flags &= ~__PRINTF_FLAG_NOFRACZEROS;
+	}
+
+	ieee_double_t val = extract_ieee_double(g);
+
+	if (val.is_special) {
+		return print_special(val, width, flags, ps);
+	} 
+
+	char buf[MAX_DOUBLE_STR_BUF_SIZE];
+	const size_t buf_size = MAX_DOUBLE_STR_BUF_SIZE;
+	double_str_t val_str;
+
+	val_str.str = buf;
+	val_str.neg = val.is_negative;
+
+	if (0 <= precision) {
+		/* 
+		 * Request one more digit so we can round the result. The last
+		 * digit it returns may have an error of at most +/- 1. 
+		 */
+		val_str.len = double_to_fixed_str(val, -1, precision + 1, buf, buf_size, 
+			&val_str.dec_exp);
+
+		/* 
+		 * Round using the last digit to produce precision fractional digits. 
+		 * If less than precision+1 fractional digits were output the last 
+		 * digit is definitely inaccurate so also round to get rid of it. 
+		 */
+		fp_round_up(buf, &val_str.len, &val_str.dec_exp);
+
+		/* Rounding could have introduced trailing zeros. */
+		if (flags & __PRINTF_FLAG_NOFRACZEROS) {
+			fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp);
+		}
+	} else {
+		/* Let the implementation figure out the proper precision. */
+		val_str.len = double_to_short_str(val, buf, buf_size, &val_str.dec_exp);
+		
+		/* Precision needed for the last significant digit. */
+		precision = max(0, -val_str.dec_exp);
+	}
+
+	return print_double_str_fixed(&val_str, precision, width, flags, ps);
+}
+
+/** Prints the decimal exponent part of a %e specifier formatted number. */
+static int print_exponent(int exp_val, uint32_t flags, printf_spec_t *ps)
+{
+	int counter = 0;
+	int ret;
+
+	char exp_ch = (flags & __PRINTF_FLAG_BIGCHARS) ? 'E' : 'e';
+
+	if ((ret = ps->str_write(&exp_ch, 1, ps->data)) < 0) 
+		return -1;
+	
+	counter += ret;
+
+	char exp_sign = (exp_val < 0) ? '-' : '+';
+
+	if ((ret = ps->str_write(&exp_sign, 1, ps->data)) < 0)
+		return -1;
+
+	counter += ret;
+
+	/* Print the exponent. */
+	exp_val = abs(exp_val);
+	
+	char exp_str[4] = { 0 };
+
+	exp_str[0] = '0' + exp_val / 100;
+	exp_str[1] = '0' + (exp_val % 100) / 10 ;
+	exp_str[2] = '0' + (exp_val % 10);
+	
+	int exp_len = (exp_str[0] == '0') ? 2 : 3;
+	const char *exp_str_start = &exp_str[3] - exp_len;
+
+	if ((ret = ps->str_write(exp_str_start, exp_len, ps->data)) < 0) 
+		return -1;
+
+	counter += ret;
+
+	return counter;
+}
+
+
+/** Format and print the double string repressentation according 
+ *  to the %e specifier. 
+ */
+static int print_double_str_scient(double_str_t *val_str, int precision, 
+	int width, uint32_t flags, printf_spec_t *ps)
+{
+	int len = val_str->len;
+	int dec_exp = val_str->dec_exp;
+	char *buf  = val_str->str;
+
+	assert(0 < len);
+
+	char sign = get_sign_char(val_str->neg, flags);
+	bool has_decimal_pt = (0 < precision) || (flags & __PRINTF_FLAG_DECIMALPT);
+	int dec_pt_len = has_decimal_pt ? 1 : 0;
+
+	/* Fractional part lengths. */
+	int signif_frac_figs = len - 1;
+	int trailing_frac_zeros = precision - signif_frac_figs;
+
+	if (flags & __PRINTF_FLAG_NOFRACZEROS) {
+		trailing_frac_zeros = 0;
+	}
+
+	int frac_len = signif_frac_figs + trailing_frac_zeros;
+
+	int exp_val = dec_exp + len - 1;
+	/* Account for exponent sign and 'e'; minimum 2 digits. */
+	int exp_len = 2 + (abs(exp_val) >= 100 ? 3 : 2);
+
+	/* Number of non-padding chars to print. */
+	int num_len = (sign ? 1 : 0) + 1 + dec_pt_len + frac_len + exp_len;
+
+	int padding_len = max(0, width - num_len);
+	int ret = 0;
+	int counter = 0;
+
+	if (!(flags & (__PRINTF_FLAG_LEFTALIGNED | __PRINTF_FLAG_ZEROPADDED))) {
+		if ((ret = print_padding(' ', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	if (sign) {
+		if ((ret = ps->str_write(&sign, 1, ps->data)) < 0) 
+			return -1;
+		
+		counter += ret;
+	}
+
+	if (flags & __PRINTF_FLAG_ZEROPADDED) {
+		if ((ret = print_padding('0', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	/* Single leading integer. */
+	if ((ret = ps->str_write(buf, 1, ps->data)) < 0) 
+		return -1;
+
+	counter += ret;
+
+	/* Print the decimal point and the fractional part. */
+	if (has_decimal_pt) {
+		char ch = '.';
+
+		if ((ret = ps->str_write(&ch, 1, ps->data)) < 0) 
+			return -1;
+		
+		counter += ret;
+
+		/* Print significant digits of the fractional part of the number. */
+		if (0 < signif_frac_figs) {
+			if ((ret = ps->str_write(buf + 1, signif_frac_figs, ps->data)) < 0) 
+				return -1;
+
+			counter += ret;
+		}
+
+		/* Print trailing zeros of the fractional part of the number. */
+		if ((ret = print_padding('0', trailing_frac_zeros, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	/* Print the exponent. */
+	if ((ret = print_exponent(exp_val, flags, ps)) < 0) 
+		return -1;
+
+	counter += ret;
+
+	if (flags & __PRINTF_FLAG_LEFTALIGNED) {
+		if ((ret = print_padding(' ', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	return counter;
+}
+
+
+/** Convert, format and print a double according to the %e specifier. 
+ *
+ * Note that if g is large, the output may be huge (3e100 prints 
+ * with at least 100 digits).
+ *
+ * %e style: [-]d.dddde+dd
+ *  left-justified:  [-]d.dddde+dd[space_pad]
+ *  right-justified: [space_pad][-][zero_pad]d.dddde+dd
+ *
+ * @param g     Double to print.
+ * @param precision Number of fractional digits to print, ie
+ *              precision + 1 significant digits to display. If 0 no
+ *              decimal point will be printed unless the flag
+ *              __PRINTF_FLAG_DECIMALPT is specified. If negative
+ *              the shortest accurate number will be printed.
+ * @param width Minimum number of characters to display. Pads 
+ *              with '0' or ' ' depending on the set flags;
+ * @param flags Printf flags.
+ * @param ps    Printing functions.
+ *
+ * @return The number of characters printed; negative on failure.
+ */
+static int print_double_scientific(double g, int precision, int width, 
+	uint32_t flags, printf_spec_t *ps)
+{
+	if (flags & __PRINTF_FLAG_LEFTALIGNED) {
+		flags &= ~__PRINTF_FLAG_ZEROPADDED;
+	}
+
+	ieee_double_t val = extract_ieee_double(g);
+
+	if (val.is_special) {
+		return print_special(val, width, flags, ps);
+	} 
+
+	char buf[MAX_DOUBLE_STR_BUF_SIZE];
+	const size_t buf_size = MAX_DOUBLE_STR_BUF_SIZE;
+	double_str_t val_str;
+
+	val_str.str = buf;
+	val_str.neg = val.is_negative;
+
+	if (0 <= precision) {
+		/* 
+		 * Request one more digit (in addition to the leading integer) 
+		 * so we can round the result. The last digit it returns may 
+		 * have an error of at most +/- 1. 
+		 */
+		val_str.len = double_to_fixed_str(val, precision + 2, -1, buf, buf_size, 
+			&val_str.dec_exp);
+
+		/* 
+		 * Round the extra digit to produce precision+1 significant digits. 
+		 * If less than precision+2 significant digits were returned the last 
+		 * digit is definitely inaccurate so also round to get rid of it. 
+		 */
+		fp_round_up(buf, &val_str.len, &val_str.dec_exp);
+
+		/* Rounding could have introduced trailing zeros. */
+		if (flags & __PRINTF_FLAG_NOFRACZEROS) {
+			fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp);
+		}
+	} else {
+		/* Let the implementation figure out the proper precision. */
+		val_str.len = double_to_short_str(val, buf, buf_size, &val_str.dec_exp);
+		
+		/* Use all produced digits. */
+		precision = val_str.len - 1;
+	}
+
+	return print_double_str_scient(&val_str, precision, width, flags, ps);
+}
+
+
+/** Convert, format and print a double according to the %g specifier. 
+ *
+ * %g style chooses between %f and %e. 
+ *
+ * @param g     Double to print.
+ * @param precision Number of significant digits to display; excluding
+ *              any leading zeros from this count. If negative
+ *              the shortest accurate number will be printed.
+ * @param width Minimum number of characters to display. Pads 
+ *              with '0' or ' ' depending on the set flags;
+ * @param flags Printf flags.
+ * @param ps    Printing functions.
+ *
+ * @return The number of characters printed; negative on failure.
+ */
+static int print_double_generic(double g, int precision, int width, 
+	uint32_t flags, printf_spec_t *ps)
+{
+	ieee_double_t val = extract_ieee_double(g);
+
+	if (val.is_special) {
+		return print_special(val, width, flags, ps);
+	} 
+
+	char buf[MAX_DOUBLE_STR_BUF_SIZE];
+	const size_t buf_size = MAX_DOUBLE_STR_BUF_SIZE;
+	int dec_exp;
+	int len;
+
+	/* Honor the user requested number of significant digits. */
+	if (0 <= precision) {
+		/* 
+		 * Do a quick and dirty conversion of a single digit to determine 
+		 * the decimal exponent.
+		 */
+		len = double_to_fixed_str(val, 1, -1, buf, buf_size, &dec_exp);
+		assert(0 < len);
+
+		precision = max(1, precision);
+
+		if (-4 <= dec_exp && dec_exp < precision) {
+			precision = precision - (dec_exp + 1);
+			return print_double_fixed(g, precision, width, 
+				flags | __PRINTF_FLAG_NOFRACZEROS, ps);
+		} else {
+			--precision;
+			return print_double_scientific(g, precision, width, 
+				flags | __PRINTF_FLAG_NOFRACZEROS, ps);
+		}
+	} else {
+		/* Convert to get the decimal exponent and digit count.*/
+		len = double_to_short_str(val, buf, buf_size, &dec_exp);
+		assert(0 < len);
+
+		if (flags & __PRINTF_FLAG_LEFTALIGNED) {
+			flags &= ~__PRINTF_FLAG_ZEROPADDED;
+		}
+
+		double_str_t val_str;
+		val_str.str = buf;
+		val_str.len = len;
+		val_str.neg = val.is_negative;
+		val_str.dec_exp = dec_exp;
+
+		int first_digit_pos = len + dec_exp;
+		int last_digit_pos = dec_exp;
+
+		/* The whole number (15 digits max) fits between dec places 15 .. -6 */
+		if (len <= 15 && -6 <= last_digit_pos && first_digit_pos <= 15) {
+			/* Precision needed for the last significant digit. */
+			precision = max(0, -val_str.dec_exp);
+			return print_double_str_fixed(&val_str, precision, width, flags, ps);
+		} else {
+			/* Use all produced digits. */
+			precision = val_str.len - 1;
+			return print_double_str_scient(&val_str, precision, width, flags, ps);
+		}
+	}
+}
+
+
+/** Convert, format and print a double according to the specifier. 
+ *
+ * Depending on the specifier it prints the double using the styles
+ * %g, %f or %e by means of print_double_generic(), print_double_fixed(),
+ * print_double_scientific().
+ *
+ * @param g     Double to print.
+ * @param spec  Specifier of the style to print in; one of: 'g','G','f','F',
+ *              'e','E'.
+ * @param precision Number of fractional digits to display. If negative
+ *              the shortest accurate number will be printed for style %g;
+ *              negative precision defaults to 6 for styles %f, %e.
+ * @param width Minimum number of characters to display. Pads 
+ *              with '0' or ' ' depending on the set flags;
+ * @param flags Printf flags.
+ * @param ps    Printing functions.
+ *
+ * @return The number of characters printed; negative on failure.
+ */
+static int print_double(double g, char spec, int precision, int width, 
+	uint32_t flags, printf_spec_t *ps)
+{
+	switch (spec) {
+	case 'F':
+		flags |= __PRINTF_FLAG_BIGCHARS;
+		/* Fall through.*/
+	case 'f':
+		precision = (precision < 0) ? 6 : precision;
+		return print_double_fixed(g, precision, width, flags, ps);
+
+	case 'E':
+		flags |= __PRINTF_FLAG_BIGCHARS;
+		/* Fall through.*/
+	case 'e':
+		precision = (precision < 0) ? 6 : precision;
+		return print_double_scientific(g, precision, width, flags, ps);
+
+	case 'G':
+		flags |= __PRINTF_FLAG_BIGCHARS;
+		/* Fall through.*/
+	case 'g':
+		return print_double_generic(g, precision, width, flags, ps);
+
+	default:
+		assert(false);
+		return -1;
+	}
 }
 
@@ -656,4 +1370,5 @@
 				case '#':
 					flags |= __PRINTF_FLAG_PREFIX;
+					flags |= __PRINTF_FLAG_DECIMALPT;
 					break;
 				case '-':
@@ -701,9 +1416,10 @@
 			
 			/* Precision and '*' operator */
-			int precision = 0;
+			int precision = -1;
 			if (uc == '.') {
 				i = nxt;
 				uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
 				if (isdigit(uc)) {
+					precision = 0;
 					while (true) {
 						precision *= 10;
@@ -723,6 +1439,6 @@
 					precision = (int) va_arg(ap, int);
 					if (precision < 0) {
-						/* Ignore negative precision */
-						precision = 0;
+						/* Ignore negative precision - use default instead */
+						precision = -1;
 					}
 				}
@@ -774,4 +1490,6 @@
 			 */
 			case 's':
+				precision = max(0,  precision);
+				
 				if (qualifier == PrintfQualifierLong)
 					retval = print_wstr(va_arg(ap, wchar_t *), width, precision, flags, ps);
@@ -797,4 +1515,25 @@
 					goto out;
 				};
+				
+				counter += retval;
+				j = nxt;
+				goto next_char;
+				
+			/*
+			 * Floating point values
+			 */
+			case 'G':
+			case 'g':
+			case 'F':
+			case 'f':
+			case 'E':
+			case 'e':
+				retval = print_double(va_arg(ap, double), uc, precision, 
+					width, flags, ps);
+				
+				if (retval < 0) {
+					counter = -counter;
+					goto out;
+				}
 				
 				counter += retval;
Index: uspace/lib/c/generic/io/visualizer.c
===================================================================
--- uspace/lib/c/generic/io/visualizer.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/io/visualizer.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 <errno.h>
+#include <as.h>
+#include <ipc/graph.h>
+#include <io/visualizer.h>
+
+int visualizer_claim(async_sess_t *sess, sysarg_t notif_callback_id)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_1_0(exch, VISUALIZER_CLAIM, notif_callback_id);
+	async_exchange_end(exch);
+
+	return ret;
+}
+
+int visualizer_yield(async_sess_t *sess)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_0_0(exch, VISUALIZER_YIELD);
+	async_exchange_end(exch);
+
+	return ret;
+}
+
+int visualizer_enumerate_modes(async_sess_t *sess, vslmode_t *mode, sysarg_t nth)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, VISUALIZER_ENUMERATE_MODES, nth, &answer);
+
+	int rc = async_data_read_start(exch, mode, sizeof(vslmode_t));
+
+	async_exchange_end(exch);
+
+	sysarg_t ret;
+	async_wait_for(req, &ret);
+
+	if (rc != EOK) {
+		return rc;
+	} else if (ret != EOK) {
+		return ret;
+	} else {
+		return EOK;
+	}
+}
+
+int visualizer_get_default_mode(async_sess_t *sess, vslmode_t *mode)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, VISUALIZER_GET_DEFAULT_MODE, &answer);
+
+	int rc = async_data_read_start(exch, mode, sizeof(vslmode_t));
+
+	async_exchange_end(exch);
+
+	sysarg_t ret;
+	async_wait_for(req, &ret);
+
+	if (rc != EOK) {
+		return rc;
+	} else if (ret != EOK) {
+		return ret;
+	} else {
+		return EOK;
+	}
+}
+
+int visualizer_get_current_mode(async_sess_t *sess, vslmode_t *mode)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, VISUALIZER_GET_CURRENT_MODE, &answer);
+
+	int rc = async_data_read_start(exch, mode, sizeof(vslmode_t));
+
+	async_exchange_end(exch);
+
+	sysarg_t ret;
+	async_wait_for(req, &ret);
+
+	if (rc != EOK) {
+		return rc;
+	} else if (ret != EOK) {
+		return ret;
+	} else {
+		return EOK;
+	}
+}
+
+int visualizer_get_mode(async_sess_t *sess, vslmode_t *mode, sysarg_t index)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, VISUALIZER_GET_MODE, index, &answer);
+
+	int rc = async_data_read_start(exch, mode, sizeof(vslmode_t));
+
+	async_exchange_end(exch);
+
+	sysarg_t ret;
+	async_wait_for(req, &ret);
+
+	if (rc != EOK) {
+		return rc;
+	} else if (ret != EOK) {
+		return ret;
+	} else {
+		return EOK;
+	}
+}
+
+int visualizer_set_mode(async_sess_t *sess, sysarg_t index, sysarg_t version, void *cells)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, VISUALIZER_SET_MODE, index, version, &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) {
+		return rc;
+	} else if (ret != EOK) {
+		return ret;
+	} else {
+		return EOK;
+	}
+}
+
+int visualizer_update_damaged_region(async_sess_t *sess,
+    sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height,
+	sysarg_t x_offset, sysarg_t y_offset)
+{
+#ifdef __32_BITS__
+	sysarg_t offsets = ((x_offset << 16) | (y_offset & 0x0000ffff));
+#else
+	sysarg_t offsets = ((x_offset << 32) | (y_offset & 0xffffffff));
+#endif
+
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_5_0(exch, VISUALIZER_UPDATE_DAMAGED_REGION,
+	    x, y, width, height, offsets);
+	async_exchange_end(exch);
+
+	return ret;
+}
+
+int visualizer_suspend(async_sess_t *sess)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_0_0(exch, VISUALIZER_SUSPEND);
+	async_exchange_end(exch);
+
+	return ret;
+}
+
+int visualizer_wakeup(async_sess_t *sess)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_0_0(exch, VISUALIZER_WAKE_UP);
+	async_exchange_end(exch);
+
+	return ret;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/io/window.c
===================================================================
--- uspace/lib/c/generic/io/window.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/io/window.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 <errno.h>
+#include <as.h>
+#include <ipc/window.h>
+#include <io/window.h>
+
+#include <stdio.h>
+
+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_0_2(exch, WINDOW_REGISTER, in, out);
+	async_exchange_end(exch);
+
+	return ret;
+}
+
+int win_get_event(async_sess_t *sess, window_event_t *event)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, WINDOW_GET_EVENT, &answer);
+
+	int rc = async_data_read_start(exch, event, sizeof(window_event_t));
+
+	async_exchange_end(exch);
+
+	sysarg_t ret;
+	async_wait_for(req, &ret);
+
+	if (rc != EOK) {
+		return rc;
+	} else if (ret != EOK) {
+		return ret;
+	} else {
+		return EOK;
+	}
+}
+
+int win_damage(async_sess_t *sess,
+    sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_4_0(exch, WINDOW_DAMAGE, x, y, width, height);
+	async_exchange_end(exch);
+
+	return ret;
+}
+
+int win_grab(async_sess_t *sess, sysarg_t pos_id, sysarg_t grab_flags)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_2_0(exch, WINDOW_GRAB, pos_id, grab_flags);
+	async_exchange_end(exch);
+
+	return ret;
+}
+
+int win_resize(async_sess_t *sess, sysarg_t width, sysarg_t height, 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);
+
+	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) {
+		return rc;
+	} else if (ret != EOK) {
+		return ret;
+	} else {
+		return EOK;
+	}
+}
+
+int win_close(async_sess_t *sess)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_0_0(exch, WINDOW_CLOSE);
+	async_exchange_end(exch);
+
+	return ret;
+}
+
+int win_close_request(async_sess_t *sess)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_0_0(exch, WINDOW_CLOSE_REQUEST);
+	async_exchange_end(exch);
+
+	return ret;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/ipc.c
===================================================================
--- uspace/lib/c/generic/ipc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/ipc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -48,5 +48,4 @@
 #include <fibril.h>
 #include <macros.h>
-#include "private/libc.h"
 
 /**
@@ -83,101 +82,4 @@
 
 static atomic_t ipc_futex = FUTEX_INITIALIZER;
-
-/** Fast synchronous call.
- *
- * Only three payload arguments can be passed using this function. However,
- * this function is faster than the generic ipc_call_sync_slow() because
- * the payload is passed directly in registers.
- *
- * @param phoneid Phone handle for the call.
- * @param method  Requested method.
- * @param arg1    Service-defined payload argument.
- * @param arg2    Service-defined payload argument.
- * @param arg3    Service-defined payload argument.
- * @param result1 If non-NULL, the return ARG1 will be stored there.
- * @param result2 If non-NULL, the return ARG2 will be stored there.
- * @param result3 If non-NULL, the return ARG3 will be stored there.
- * @param result4 If non-NULL, the return ARG4 will be stored there.
- * @param result5 If non-NULL, the return ARG5 will be stored there.
- *
- * @return Negative values representing IPC errors.
- * @return Otherwise the RETVAL of the answer.
- *
- */
-int ipc_call_sync_fast(int phoneid, sysarg_t method, sysarg_t arg1,
-    sysarg_t arg2, sysarg_t arg3, sysarg_t *result1, sysarg_t *result2,
-    sysarg_t *result3, sysarg_t *result4, sysarg_t *result5)
-{
-	ipc_call_t resdata;
-	int callres = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1,
-	    arg2, arg3, (sysarg_t) &resdata);
-	if (callres)
-		return callres;
-	
-	if (result1)
-		*result1 = IPC_GET_ARG1(resdata);
-	if (result2)
-		*result2 = IPC_GET_ARG2(resdata);
-	if (result3)
-		*result3 = IPC_GET_ARG3(resdata);
-	if (result4)
-		*result4 = IPC_GET_ARG4(resdata);
-	if (result5)
-		*result5 = IPC_GET_ARG5(resdata);
-	
-	return IPC_GET_RETVAL(resdata);
-}
-
-/** Synchronous call transmitting 5 arguments of payload.
- *
- * @param phoneid Phone handle for the call.
- * @param imethod Requested interface and method.
- * @param arg1    Service-defined payload argument.
- * @param arg2    Service-defined payload argument.
- * @param arg3    Service-defined payload argument.
- * @param arg4    Service-defined payload argument.
- * @param arg5    Service-defined payload argument.
- * @param result1 If non-NULL, storage for the first return argument.
- * @param result2 If non-NULL, storage for the second return argument.
- * @param result3 If non-NULL, storage for the third return argument.
- * @param result4 If non-NULL, storage for the fourth return argument.
- * @param result5 If non-NULL, storage for the fifth return argument.
- *
- * @return Negative values representing IPC errors.
- * @return Otherwise the RETVAL of the answer.
- *
- */
-int ipc_call_sync_slow(int phoneid, sysarg_t imethod, sysarg_t arg1,
-    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
-    sysarg_t *result1, sysarg_t *result2, sysarg_t *result3, sysarg_t *result4,
-    sysarg_t *result5)
-{
-	ipc_call_t data;
-	
-	IPC_SET_IMETHOD(data, imethod);
-	IPC_SET_ARG1(data, arg1);
-	IPC_SET_ARG2(data, arg2);
-	IPC_SET_ARG3(data, arg3);
-	IPC_SET_ARG4(data, arg4);
-	IPC_SET_ARG5(data, arg5);
-	
-	int callres = __SYSCALL3(SYS_IPC_CALL_SYNC_SLOW, phoneid,
-	    (sysarg_t) &data, (sysarg_t) &data);
-	if (callres)
-		return callres;
-	
-	if (result1)
-		*result1 = IPC_GET_ARG1(data);
-	if (result2)
-		*result2 = IPC_GET_ARG2(data);
-	if (result3)
-		*result3 = IPC_GET_ARG3(data);
-	if (result4)
-		*result4 = IPC_GET_ARG4(data);
-	if (result5)
-		*result5 = IPC_GET_ARG5(data);
-	
-	return IPC_GET_RETVAL(data);
-}
 
 /** Send asynchronous message via syscall.
@@ -611,98 +513,4 @@
 }
 
-/** Request callback connection.
- *
- * The @a task_id and @a phonehash identifiers returned
- * by the kernel can be used for connection tracking.
- *
- * @param phoneid   Phone handle used for contacting the other side.
- * @param arg1      User defined argument.
- * @param arg2      User defined argument.
- * @param arg3      User defined argument.
- * @param task_id   Identifier of the client task.
- * @param phonehash Opaque identifier of the phone that will
- *                  be used for incoming calls.
- *
- * @return Zero on success or a negative error code.
- *
- */
-int ipc_connect_to_me(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
-    task_id_t *task_id, sysarg_t *phonehash)
-{
-	ipc_call_t data;
-	int rc = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid,
-	    IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, (sysarg_t) &data);
-	if (rc == EOK) {
-		*task_id = data.in_task_id;
-		*phonehash = IPC_GET_ARG5(data);
-	}	
-	return rc;
-}
-
-/** Request cloned connection.
- *
- * @param phoneid Phone handle used for contacting the other side.
- *
- * @return Cloned phone handle on success or a negative error code.
- *
- */
-int ipc_clone_establish(int phoneid)
-{
-	sysarg_t newphid;
-	int res = ipc_call_sync_0_5(phoneid, IPC_M_CLONE_ESTABLISH, NULL,
-	    NULL, NULL, NULL, &newphid);
-	if (res)
-		return res;
-	
-	return newphid;
-}
-
-/** Request new connection.
- *
- * @param phoneid Phone handle used for contacting the other side.
- * @param arg1    User defined argument.
- * @param arg2    User defined argument.
- * @param arg3    User defined argument.
- *
- * @return New phone handle on success or a negative error code.
- *
- */
-int ipc_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
-{
-	sysarg_t newphid;
-	int res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
-	    NULL, NULL, NULL, NULL, &newphid);
-	if (res)
-		return res;
-	
-	return newphid;
-}
-
-/** Request new connection (blocking)
- *
- * If the connection is not available at the moment, the
- * call should block. This has to be, however, implemented
- * on the server side.
- *
- * @param phoneid Phone handle used for contacting the other side.
- * @param arg1    User defined argument.
- * @param arg2    User defined argument.
- * @param arg3    User defined argument.
- *
- * @return New phone handle on success or a negative error code.
- *
- */
-int ipc_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3)
-{
-	sysarg_t newphid;
-	int res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
-	    IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
-	if (res)
-		return res;
-	
-	return newphid;
-}
-
 /** Hang up a phone.
  *
@@ -758,148 +566,4 @@
 }
 
-/** Wrapper for IPC_M_SHARE_IN calls.
- *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param size    Size of the destination address space area.
- * @param arg     User defined argument.
- * @param flags   Storage for received flags. Can be NULL.
- * @param dst     Destination address space area base. Cannot be NULL.
- *
- * @return Zero on success or a negative error code from errno.h.
- *
- */
-int ipc_share_in_start(int phoneid, size_t size, sysarg_t arg,
-    unsigned int *flags, void **dst)
-{
-	sysarg_t _flags = 0;
-	sysarg_t _dst = (sysarg_t) -1;
-	int res = ipc_call_sync_2_4(phoneid, IPC_M_SHARE_IN, (sysarg_t) size,
-	    arg, NULL, &_flags, NULL, &_dst);
-	
-	if (flags)
-		*flags = (unsigned int) _flags;
-	
-	*dst = (void *) _dst;
-	return res;
-}
-
-/** Wrapper for answering the IPC_M_SHARE_IN calls.
- *
- * This wrapper only makes it more comfortable to answer IPC_M_SHARE_IN
- * calls so that the user doesn't have to remember the meaning of each
- * IPC argument.
- *
- * @param callid Hash of the IPC_M_DATA_READ call to answer.
- * @param src    Source address space base.
- * @param flags Flags to be used for sharing. Bits can be only cleared.
- *
- * @return Zero on success or a value from @ref errno.h on failure.
- *
- */
-int ipc_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
-{
-	return ipc_answer_3(callid, EOK, (sysarg_t) src, (sysarg_t) flags,
-	    (sysarg_t) __entry);
-}
-
-/** Wrapper for IPC_M_SHARE_OUT calls.
- *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param src     Source address space area base address.
- * @param flags   Flags to be used for sharing. Bits can be only cleared.
- *
- * @return Zero on success or a negative error code from errno.h.
- *
- */
-int ipc_share_out_start(int phoneid, void *src, unsigned int flags)
-{
-	return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
-	    (sysarg_t) flags);
-}
-
-/** Wrapper for answering the IPC_M_SHARE_OUT calls.
- *
- * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT
- * calls so that the user doesn't have to remember the meaning of each
- * IPC argument.
- *
- * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
- * @param dst    Destination address space area base address.
- *
- * @return Zero on success or a value from @ref errno.h on failure.
- *
- */
-int ipc_share_out_finalize(ipc_callid_t callid, void **dst)
-{
-	return ipc_answer_2(callid, EOK, (sysarg_t) __entry, (sysarg_t) dst);
-}
-
-/** Wrapper for IPC_M_DATA_READ calls.
- *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param dst     Address of the beginning of the destination buffer.
- * @param size    Size of the destination buffer.
- *
- * @return Zero on success or a negative error code from errno.h.
- *
- */
-int ipc_data_read_start(int phoneid, void *dst, size_t size)
-{
-	return ipc_call_sync_2_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
-	    (sysarg_t) size);
-}
-
-/** Wrapper for answering the IPC_M_DATA_READ calls.
- *
- * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
- * calls so that the user doesn't have to remember the meaning of each
- * IPC argument.
- *
- * @param callid Hash of the IPC_M_DATA_READ call to answer.
- * @param src    Source address for the IPC_M_DATA_READ call.
- * @param size   Size for the IPC_M_DATA_READ call. Can be smaller than
- *               the maximum size announced by the sender.
- *
- * @return Zero on success or a value from @ref errno.h on failure.
- *
- */
-int ipc_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
-{
-	return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) size);
-}
-
-/** Wrapper for IPC_M_DATA_WRITE calls.
- *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param src     Address of the beginning of the source buffer.
- * @param size    Size of the source buffer.
- *
- * @return Zero on success or a negative error code from errno.h.
- *
- */
-int ipc_data_write_start(int phoneid, const void *src, size_t size)
-{
-	return ipc_call_sync_2_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
-	    (sysarg_t) size);
-}
-
-/** Wrapper for answering the IPC_M_DATA_WRITE calls.
- *
- * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE
- * calls so that the user doesn't have to remember the meaning of each
- * IPC argument.
- *
- * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
- * @param dst    Final destination address for the IPC_M_DATA_WRITE call.
- * @param size   Final size for the IPC_M_DATA_WRITE call.
- *
- * @return Zero on success or a value from @ref errno.h on failure.
- *
- */
-int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size)
-{
-	return ipc_answer_2(callid, EOK, (sysarg_t) dst, (sysarg_t) size);
-}
-
 /** Connect to a task specified by id.
  *
Index: uspace/lib/c/generic/iplink_srv.c
===================================================================
--- uspace/lib/c/generic/iplink_srv.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/iplink_srv.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -139,4 +139,7 @@
 		if (!method) {
 			/* The other side has hung up */
+		    	fibril_mutex_lock(&srv->lock);
+			srv->connected = false;
+		    	fibril_mutex_unlock(&srv->lock);
 			async_answer_0(callid, EOK);
 			break;
Index: uspace/lib/c/generic/malloc.c
===================================================================
--- uspace/lib/c/generic/malloc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/malloc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -109,4 +109,7 @@
 	(((uintptr_t) (area)->end) - sizeof(heap_block_foot_t))
 
+#define AREA_LAST_BLOCK_HEAD(area) \
+	((uintptr_t) BLOCK_HEAD(((heap_block_foot_t *) AREA_LAST_BLOCK_FOOT(area))))
+
 /** Get header in heap block.
  *
@@ -346,8 +349,18 @@
 		return false;
 	
-	/* Add new free block */
-	size_t net_size = (size_t) (end - area->end);
-	if (net_size > 0)
-		block_init(area->end, net_size, true, area);
+	heap_block_head_t *last_head =
+	    (heap_block_head_t *) AREA_LAST_BLOCK_HEAD(area);
+	
+	if (last_head->free) {
+		/* Add the new space to the last block. */
+		size_t net_size = (size_t) (end - area->end) + last_head->size;
+		malloc_assert(net_size > 0);
+		block_init(last_head, net_size, true, area);
+	} else {
+		/* Add new free block */
+		size_t net_size = (size_t) (end - area->end);
+		if (net_size > 0)
+			block_init(area->end, net_size, true, area);
+	}
 	
 	/* Update heap area parameters */
@@ -355,27 +368,4 @@
 	
 	return true;
-}
-
-/** Try to enlarge any of the heap areas
- *
- * Should be called only inside the critical section.
- *
- * @param size Gross size of item to allocate (bytes).
- *
- */
-static bool heap_grow(size_t size)
-{
-	if (size == 0)
-		return true;
-	
-	/* First try to enlarge some existing area */
-	for (heap_area_t *area = first_heap_area; area != NULL;
-	    area = area->next) {
-		if (area_grow(area, size))
-			return true;
-	}
-	
-	/* Eventually try to create a new area */
-	return area_create(AREA_OVERHEAD(size));
 }
 
@@ -661,4 +651,50 @@
 }
 
+/** Try to enlarge any of the heap areas.
+ *
+ * If successful, allocate block of the given size in the area.
+ * Should be called only inside the critical section.
+ *
+ * @param size  Gross size of item to allocate (bytes).
+ * @param align Memory address alignment.
+ *
+ * @return Allocated block.
+ * @return NULL on failure.
+ *
+ */
+static void *heap_grow_and_alloc(size_t size, size_t align)
+{
+	if (size == 0)
+		return NULL;
+	
+	/* First try to enlarge some existing area */
+	for (heap_area_t *area = first_heap_area; area != NULL;
+	    area = area->next) {
+		
+		if (area_grow(area, size + align)) {
+			heap_block_head_t *first =
+			    (heap_block_head_t *) AREA_LAST_BLOCK_HEAD(area);
+			
+			void *addr =
+			    malloc_area(area, first, NULL, size, align);
+			malloc_assert(addr != NULL);
+			return addr;
+		}
+	}
+	
+	/* Eventually try to create a new area */
+	if (area_create(AREA_OVERHEAD(size + align))) {
+		heap_block_head_t *first =
+		    (heap_block_head_t *) AREA_FIRST_BLOCK_HEAD(last_heap_area);
+		
+		void *addr =
+		    malloc_area(last_heap_area, first, NULL, size, align);
+		malloc_assert(addr != NULL);
+		return addr;
+	}
+	
+	return NULL;
+}
+
 /** Allocate a memory block
  *
@@ -679,16 +715,22 @@
 	
 	size_t falign = lcm(align, BASE_ALIGN);
-	size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign));
-	
-	bool retry = false;
-	heap_block_head_t *split;
-	
-loop:
+	
+	/* Check for integer overflow. */
+	if (falign < align)
+		return NULL;
+	
+	/*
+	 * The size of the allocated block needs to be naturally
+	 * aligned, because the footer structure also needs to reside
+	 * on a naturally aligned address in order to avoid unaligned
+	 * memory accesses.
+	 */
+	size_t gross_size = GROSS_SIZE(ALIGN_UP(size, BASE_ALIGN));
 	
 	/* Try the next fit approach */
-	split = next_fit;
+	heap_block_head_t *split = next_fit;
 	
 	if (split != NULL) {
-		void *addr = malloc_area(split->area, split, NULL, real_size,
+		void *addr = malloc_area(split->area, split, NULL, gross_size,
 		    falign);
 		
@@ -703,5 +745,5 @@
 		    AREA_FIRST_BLOCK_HEAD(area);
 		
-		void *addr = malloc_area(area, first, split, real_size,
+		void *addr = malloc_area(area, first, split, gross_size,
 		    falign);
 		
@@ -710,13 +752,6 @@
 	}
 	
-	if (!retry) {
-		/* Try to grow the heap space */
-		if (heap_grow(real_size)) {
-			retry = true;
-			goto loop;
-		}
-	}
-	
-	return NULL;
+	/* Finally, try to grow heap space and allocate in the new area. */
+	return heap_grow_and_alloc(gross_size, falign);
 }
 
@@ -731,4 +766,6 @@
 void *calloc(const size_t nmemb, const size_t size)
 {
+	// FIXME: Check for overflow
+	
 	void *block = malloc(nmemb * size);
 	if (block == NULL)
@@ -870,5 +907,5 @@
 	if (addr == NULL)
 		return;
-
+	
 	futex_down(&malloc_futex);
 	
Index: uspace/lib/c/generic/power_of_ten.c
===================================================================
--- uspace/lib/c/generic/power_of_ten.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/power_of_ten.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * 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.
+ */
+
+#include "private/power_of_ten.h"
+
+#include <ieee_double.h>
+#include <assert.h>
+
+/** Precomputed normalized rounded-up powers of 10^k.
+ *
+ * The powers were computed using arbitrary precision arithmetic
+ * and rounded up to the top 64 significant bits. Therefore:
+ *   10^dec_exp == significand * 2^bin_exp  +/- 0.5 ulp error
+ *
+ * The smallest interval of binary exponents computed by hand
+ * is [-1083, 987]. Add 200 (exponent change > 3 * 64 bits) 
+ * to both bounds just to be on the safe side; ie [-1283, 1187].
+ */
+static struct {
+	uint64_t significand;
+	int16_t bin_exp;
+	int16_t dec_exp;
+} fp_powers_of_10[] = {
+	{ 0xb8e1cbc28bef0b69ULL, -1286, -368 },
+	{ 0x89bf722840327f82ULL, -1259, -360 },
+	{ 0xcd42a11346f34f7dULL, -1233, -352 },
+	{ 0x98ee4a22ecf3188cULL, -1206, -344 },
+	{ 0xe3e27a444d8d98b8ULL, -1180, -336 },
+	{ 0xa9c98d8ccb009506ULL, -1153, -328 },
+	{ 0xfd00b897478238d1ULL, -1127, -320 },
+	{ 0xbc807527ed3e12bdULL, -1100, -312 },
+	{ 0x8c71dcd9ba0b4926ULL, -1073, -304 },
+	{ 0xd1476e2c07286faaULL, -1047, -296 },
+	{ 0x9becce62836ac577ULL, -1020, -288 },
+	{ 0xe858ad248f5c22caULL, -994, -280 },
+	{ 0xad1c8eab5ee43b67ULL, -967, -272 },
+	{ 0x80fa687f881c7f8eULL, -940, -264 },
+	{ 0xc0314325637a193aULL, -914, -256 },
+	{ 0x8f31cc0937ae58d3ULL, -887, -248 },
+	{ 0xd5605fcdcf32e1d7ULL, -861, -240 },
+	{ 0x9efa548d26e5a6e2ULL, -834, -232 },
+	{ 0xece53cec4a314ebeULL, -808, -224 },
+	{ 0xb080392cc4349dedULL, -781, -216 },
+	{ 0x8380dea93da4bc60ULL, -754, -208 },
+	{ 0xc3f490aa77bd60fdULL, -728, -200 },
+	{ 0x91ff83775423cc06ULL, -701, -192 },
+	{ 0xd98ddaee19068c76ULL, -675, -184 },
+	{ 0xa21727db38cb0030ULL, -648, -176 },
+	{ 0xf18899b1bc3f8ca2ULL, -622, -168 },
+	{ 0xb3f4e093db73a093ULL, -595, -160 },
+	{ 0x8613fd0145877586ULL, -568, -152 },
+	{ 0xc7caba6e7c5382c9ULL, -542, -144 },
+	{ 0x94db483840b717f0ULL, -515, -136 },
+	{ 0xddd0467c64bce4a1ULL, -489, -128 },
+	{ 0xa54394fe1eedb8ffULL, -462, -120 },
+	{ 0xf64335bcf065d37dULL, -436, -112 },
+	{ 0xb77ada0617e3bbcbULL, -409, -104 },
+	{ 0x88b402f7fd75539bULL, -382, -96 },
+	{ 0xcbb41ef979346bcaULL, -356, -88 },
+	{ 0x97c560ba6b0919a6ULL, -329, -80 },
+	{ 0xe2280b6c20dd5232ULL, -303, -72 },
+	{ 0xa87fea27a539e9a5ULL, -276, -64 },
+	{ 0xfb158592be068d2fULL, -250, -56 },
+	{ 0xbb127c53b17ec159ULL, -223, -48 },
+	{ 0x8b61313bbabce2c6ULL, -196, -40 },
+	{ 0xcfb11ead453994baULL, -170, -32 },
+	{ 0x9abe14cd44753b53ULL, -143, -24 },
+	{ 0xe69594bec44de15bULL, -117, -16 },
+	{ 0xabcc77118461cefdULL, -90, -8 },
+	{ 0x8000000000000000ULL, -63, 0 },
+	{ 0xbebc200000000000ULL, -37, 8 },
+	{ 0x8e1bc9bf04000000ULL, -10, 16 },
+	{ 0xd3c21bcecceda100ULL, 16, 24 },
+	{ 0x9dc5ada82b70b59eULL, 43, 32 },
+	{ 0xeb194f8e1ae525fdULL, 69, 40 },
+	{ 0xaf298d050e4395d7ULL, 96, 48 },
+	{ 0x82818f1281ed44a0ULL, 123, 56 },
+	{ 0xc2781f49ffcfa6d5ULL, 149, 64 },
+	{ 0x90e40fbeea1d3a4bULL, 176, 72 },
+	{ 0xd7e77a8f87daf7fcULL, 202, 80 },
+	{ 0xa0dc75f1778e39d6ULL, 229, 88 },
+	{ 0xefb3ab16c59b14a3ULL, 255, 96 },
+	{ 0xb2977ee300c50fe7ULL, 282, 104 },
+	{ 0x850fadc09923329eULL, 309, 112 },
+	{ 0xc646d63501a1511eULL, 335, 120 },
+	{ 0x93ba47c980e98ce0ULL, 362, 128 },
+	{ 0xdc21a1171d42645dULL, 388, 136 },
+	{ 0xa402b9c5a8d3a6e7ULL, 415, 144 },
+	{ 0xf46518c2ef5b8cd1ULL, 441, 152 },
+	{ 0xb616a12b7fe617aaULL, 468, 160 },
+	{ 0x87aa9aff79042287ULL, 495, 168 },
+	{ 0xca28a291859bbf93ULL, 521, 176 },
+	{ 0x969eb7c47859e744ULL, 548, 184 },
+	{ 0xe070f78d3927556bULL, 574, 192 },
+	{ 0xa738c6bebb12d16dULL, 601, 200 },
+	{ 0xf92e0c3537826146ULL, 627, 208 },
+	{ 0xb9a74a0637ce2ee1ULL, 654, 216 },
+	{ 0x8a5296ffe33cc930ULL, 681, 224 },
+	{ 0xce1de40642e3f4b9ULL, 707, 232 },
+	{ 0x9991a6f3d6bf1766ULL, 734, 240 },
+	{ 0xe4d5e82392a40515ULL, 760, 248 },
+	{ 0xaa7eebfb9df9de8eULL, 787, 256 },
+	{ 0xfe0efb53d30dd4d8ULL, 813, 264 },
+	{ 0xbd49d14aa79dbc82ULL, 840, 272 },
+	{ 0x8d07e33455637eb3ULL, 867, 280 },
+	{ 0xd226fc195c6a2f8cULL, 893, 288 },
+	{ 0x9c935e00d4b9d8d2ULL, 920, 296 },
+	{ 0xe950df20247c83fdULL, 946, 304 },
+	{ 0xadd57a27d29339f6ULL, 973, 312 },
+	{ 0x81842f29f2cce376ULL, 1000, 320 },
+	{ 0xc0fe908895cf3b44ULL, 1026, 328 },
+	{ 0x8fcac257558ee4e6ULL, 1053, 336 },
+	{ 0xd6444e39c3db9b0aULL, 1079, 344 },
+	{ 0x9fa42700db900ad2ULL, 1106, 352 },
+	{ 0xede24ae798ec8284ULL, 1132, 360 },
+	{ 0xb13cc3832ef0c9acULL, 1159, 368 },
+	{ 0x840d57e2899d945fULL, 1186, 376 }
+};
+
+
+/** 
+ * Returns the smallest precomputed power of 10 such that 
+ *  binary_exp <= power_of_10.bin_exp
+ * where
+ *  10^decimal_exp = power_of_10.significand * 2^bin_exp 
+ * with an error of 0.5 ulp in the significand.
+ */
+void get_power_of_ten(int binary_exp, fp_num_t *power_of_10, int *decimal_exp)
+{
+	const int powers_count = sizeof(fp_powers_of_10) / sizeof(fp_powers_of_10[0]);
+	const int min_bin_exp = fp_powers_of_10[0].bin_exp;
+	const int max_bin_exp = fp_powers_of_10[powers_count - 1].bin_exp;
+	const int max_bin_exp_diff = 27;
+
+	assert(min_bin_exp <= binary_exp && binary_exp <= max_bin_exp);
+
+	/* 
+	 * Binary exponent difference between adjacent powers of 10 
+	 * is lg(10^8) = 26.575. The starting search index seed_idx
+	 * undershoots the actual position by less than 1.6%, ie it
+	 * skips 26.575/27 = 98.4% of all the smaller powers. This
+	 * translates to at most three extra tests. 
+	 */
+	int seed_idx = (binary_exp - min_bin_exp) / max_bin_exp_diff;
+
+	assert(fp_powers_of_10[seed_idx].bin_exp < binary_exp);
+
+	for (int i = seed_idx; i < powers_count; ++i) {
+		/* Found the smallest power of 10 with bin_exp >= binary_exp. */
+		if (binary_exp <= fp_powers_of_10[i].bin_exp) {
+			assert(fp_powers_of_10[i].bin_exp <= binary_exp + max_bin_exp_diff);
+
+			power_of_10->significand = fp_powers_of_10[i].significand;
+			power_of_10->exponent = fp_powers_of_10[i].bin_exp;
+			*decimal_exp = fp_powers_of_10[i].dec_exp;
+			return;
+		}
+	}
+
+	assert(false);
+}
+
Index: uspace/lib/c/generic/private/power_of_ten.h
===================================================================
--- uspace/lib/c/generic/private/power_of_ten.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/generic/private/power_of_ten.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * 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.
+ */
+
+#ifndef POWER_OF_TEN_H_
+#define POWER_OF_TEN_H_
+
+/* Fwd decl. */
+struct fp_num_t_tag;
+
+extern void get_power_of_ten(int, struct fp_num_t_tag *, int *);
+
+#endif
Index: uspace/lib/c/generic/str.c
===================================================================
--- uspace/lib/c/generic/str.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/str.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -136,4 +136,49 @@
 }
 
+/** Decode a single character from a string to the left.
+ *
+ * Decode a single character from a string of size @a size. Decoding starts
+ * at @a offset and this offset is moved to the beginning of the previous
+ * character. In case of decoding error, offset generally decreases at least
+ * by one. However, offset is never moved before 0.
+ *
+ * @param str    String (not necessarily NULL-terminated).
+ * @param offset Byte offset in string where to start decoding.
+ * @param size   Size of the string (in bytes).
+ *
+ * @return Value of decoded character, U_SPECIAL on decoding error or
+ *         NULL if attempt to decode beyond @a start of str.
+ *
+ */
+wchar_t str_decode_reverse(const char *str, size_t *offset, size_t size)
+{
+	if (*offset == 0)
+		return 0;
+	
+	size_t processed = 0;
+	/* Continue while continuation bytes found */
+	while (*offset > 0 && processed < 4) {
+		uint8_t b = (uint8_t) str[--(*offset)];
+		
+		if (processed == 0 && (b & 0x80) == 0) {
+			/* 0xxxxxxx (Plain ASCII) */
+			return b & 0x7f;
+		}
+		else if ((b & 0xe0) == 0xc0 || (b & 0xf0) == 0xe0 ||
+		    (b & 0xf8) == 0xf0) {
+			/* Start byte */
+			size_t start_offset = *offset;
+			return str_decode(str, &start_offset, size);
+		}
+		else if ((b & 0xc0) != 0x80) {
+			/* Not a continuation byte */
+			return U_SPECIAL;
+		}
+		processed++;
+	}
+	/* Too many continuation bytes */
+	return U_SPECIAL;
+}
+
 /** Encode a single character to string representation.
  *
@@ -399,4 +444,31 @@
 }
 
+/** Get character display width on a character cell display.
+ *
+ * @param ch	Character
+ * @return	Width of character in cells.
+ */
+size_t chr_width(wchar_t ch)
+{
+	return 1;
+}
+
+/** Get string display width on a character cell display.
+ *
+ * @param str	String
+ * @return	Width of string in cells.
+ */
+size_t str_width(const char *str)
+{
+	size_t width = 0;
+	size_t offset = 0;
+	wchar_t ch;
+	
+	while ((ch = str_decode(str, &offset, STR_NO_LIMIT)) != 0)
+		width += chr_width(ch);
+	
+	return width;
+}
+
 /** Check whether character is plain ASCII.
  *
@@ -428,12 +500,17 @@
  *
  * Do a char-by-char comparison of two NULL-terminated strings.
- * The strings are considered equal iff they consist of the same
- * characters on the minimum of their lengths.
+ * The strings are considered equal iff their length is equal
+ * and both strings consist of the same sequence of characters.
+ *
+ * A string S1 is less than another string S2 if it has a character with
+ * lower value at the first character position where the strings differ.
+ * If the strings differ in length, the shorter one is treated as if
+ * padded by characters with a value of zero.
  *
  * @param s1 First string to compare.
  * @param s2 Second string to compare.
  *
- * @return 0 if the strings are equal, -1 if first is smaller,
- *         1 if second smaller.
+ * @return 0 if the strings are equal, -1 if the first is less than the second,
+ *         1 if the second is less than the first.
  *
  */
@@ -466,6 +543,14 @@
  *
  * Do a char-by-char comparison of two NULL-terminated strings.
- * The strings are considered equal iff they consist of the same
- * characters on the minimum of their lengths and the length limit.
+ * The strings are considered equal iff
+ * min(str_length(s1), max_len) == min(str_length(s2), max_len)
+ * and both strings consist of the same sequence of characters,
+ * up to max_len characters.
+ *
+ * A string S1 is less than another string S2 if it has a character with
+ * lower value at the first character position where the strings differ.
+ * If the strings differ in length, the shorter one is treated as if
+ * padded by characters with a value of zero. Only the first max_len
+ * characters are considered.
  *
  * @param s1      First string to compare.
@@ -473,6 +558,6 @@
  * @param max_len Maximum number of characters to consider.
  *
- * @return 0 if the strings are equal, -1 if first is smaller,
- *         1 if second smaller.
+ * @return 0 if the strings are equal, -1 if the first is less than the second,
+ *         1 if the second is less than the first.
  *
  */
@@ -508,4 +593,40 @@
 	return 0;
 
+}
+
+/** Test whether p is a prefix of s.
+ *
+ * Do a char-by-char comparison of two NULL-terminated strings
+ * and determine if p is a prefix of s.
+ *
+ * @param s The string in which to look
+ * @param p The string to check if it is a prefix of s
+ *
+ * @return true iff p is prefix of s else false
+ *
+ */
+bool str_test_prefix(const char *s, const char *p)
+{
+	wchar_t c1 = 0;
+	wchar_t c2 = 0;
+	
+	size_t off1 = 0;
+	size_t off2 = 0;
+
+	while (true) {
+		c1 = str_decode(s, &off1, STR_NO_LIMIT);
+		c2 = str_decode(p, &off2, STR_NO_LIMIT);
+		
+		if (c2 == 0)
+			return true;
+
+		if (c1 != c2)
+			return false;
+		
+		if (c1 == 0)
+			break;
+	}
+
+	return false;
 }
 
@@ -1085,5 +1206,5 @@
 		c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
 		    (c <= '9' ? c - '0' : 0xff)));
-		if (c > base) {
+		if (c >= base) {
 			break;
 		}
Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/task.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -201,4 +201,40 @@
  *
  * This is really just a convenience wrapper over the more complicated
+ * loader API. Arguments are passed in a va_list.
+ *
+ * @param id   If not NULL, the ID of the task is stored here on success.
+ * @param path Pathname of the binary to execute.
+ * @param cnt  Number of arguments.
+ * @param ap   Command-line arguments.
+ *
+ * @return Zero on success or negative error code.
+ *
+ */
+int task_spawn(task_id_t *task_id, const char *path, int cnt, va_list ap)
+{
+	/* Allocate argument list. */
+	const char **arglist = malloc(cnt * sizeof(const char *));
+	if (arglist == NULL)
+		return ENOMEM;
+	
+	/* Fill in arguments. */
+	const char *arg;
+	cnt = 0;
+	do {
+		arg = va_arg(ap, const char *);
+		arglist[cnt++] = arg;
+	} while (arg != NULL);
+	
+	/* Spawn task. */
+	int rc = task_spawnv(task_id, path, arglist);
+	
+	/* Free argument list. */
+	free(arglist);
+	return rc;
+}
+
+/** Create a new task by running an executable from the filesystem.
+ *
+ * This is really just a convenience wrapper over the more complicated
  * loader API. Arguments are passed as a null-terminated list of arguments.
  *
@@ -216,5 +252,4 @@
 	va_list ap;
 	const char *arg;
-	const char **arglist;
 	int cnt = 0;
 	
@@ -226,23 +261,8 @@
 	va_end(ap);
 	
-	/* Allocate argument list. */
-	arglist = malloc(cnt * sizeof(const char *));
-	if (arglist == NULL)
-		return ENOMEM;
-	
-	/* Fill in arguments. */
-	cnt = 0;
 	va_start(ap, path);
-	do {
-		arg = va_arg(ap, const char *);
-		arglist[cnt++] = arg;
-	} while (arg != NULL);
+	int rc = task_spawn(task_id, path, cnt, ap);
 	va_end(ap);
 	
-	/* Spawn task. */
-	int rc = task_spawnv(task_id, path, arglist);
-	
-	/* Free argument list. */
-	free(arglist);
 	return rc;
 }
Index: uspace/lib/c/generic/time.c
===================================================================
--- uspace/lib/c/generic/time.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/time.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -1,4 +1,6 @@
 /*
  * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2011 Petr Koupy
+ * Copyright (c) 2011 Jiri Zarevucky
  * All rights reserved.
  *
@@ -43,5 +45,14 @@
 #include <ddi.h>
 #include <libc.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
 #include <unistd.h>
+#include <loc.h>
+#include <device/clock_dev.h>
+#include <malloc.h>
+
+#define ASCTIME_BUF_LEN 26
 
 /** Pointer to kernel shared variables with time */
@@ -52,4 +63,337 @@
 } *ktime = NULL;
 
+/* Helper functions ***********************************************************/
+
+#define HOURS_PER_DAY (24)
+#define MINS_PER_HOUR (60)
+#define SECS_PER_MIN (60)
+#define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY)
+#define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
+#define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY)
+
+/**
+ * Checks whether the year is a leap year.
+ *
+ * @param year Year since 1900 (e.g. for 1970, the value is 70).
+ * @return true if year is a leap year, false otherwise
+ */
+static bool _is_leap_year(time_t year)
+{
+	year += 1900;
+
+	if (year % 400 == 0)
+		return true;
+	if (year % 100 == 0)
+		return false;
+	if (year % 4 == 0)
+		return true;
+	return false;
+}
+
+/**
+ * Returns how many days there are in the given month of the given year.
+ * Note that year is only taken into account if month is February.
+ *
+ * @param year Year since 1900 (can be negative).
+ * @param mon Month of the year. 0 for January, 11 for December.
+ * @return Number of days in the specified month.
+ */
+static int _days_in_month(time_t year, time_t mon)
+{
+	assert(mon >= 0 && mon <= 11);
+
+	static int month_days[] =
+		{ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+	if (mon == 1) {
+		year += 1900;
+		/* february */
+		return _is_leap_year(year) ? 29 : 28;
+	} else {
+		return month_days[mon];
+	}
+}
+
+/**
+ * For specified year, month and day of month, returns which day of that year
+ * it is.
+ *
+ * For example, given date 2011-01-03, the corresponding expression is:
+ *     _day_of_year(111, 0, 3) == 2
+ *
+ * @param year Year (year 1900 = 0, can be negative).
+ * @param mon Month (January = 0).
+ * @param mday Day of month (First day is 1).
+ * @return Day of year (First day is 0).
+ */
+static int _day_of_year(time_t year, time_t mon, time_t mday)
+{
+	static int mdays[] =
+	    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+	static int leap_mdays[] =
+	    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
+
+	return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1;
+}
+
+/**
+ * Integer division that rounds to negative infinity.
+ * Used by some functions in this file.
+ *
+ * @param op1 Dividend.
+ * @param op2 Divisor.
+ * @return Rounded quotient.
+ */
+static time_t _floor_div(time_t op1, time_t op2)
+{
+	if (op1 >= 0 || op1 % op2 == 0) {
+		return op1 / op2;
+	} else {
+		return op1 / op2 - 1;
+	}
+}
+
+/**
+ * Modulo that rounds to negative infinity.
+ * Used by some functions in this file.
+ *
+ * @param op1 Dividend.
+ * @param op2 Divisor.
+ * @return Remainder.
+ */
+static time_t _floor_mod(time_t op1, time_t op2)
+{
+	int div = _floor_div(op1, op2);
+
+	/* (a / b) * b + a % b == a */
+	/* thus, a % b == a - (a / b) * b */
+
+	int result = op1 - div * op2;
+	
+	/* Some paranoid checking to ensure I didn't make a mistake here. */
+	assert(result >= 0);
+	assert(result < op2);
+	assert(div * op2 + result == op1);
+	
+	return result;
+}
+
+/**
+ * Number of days since the Epoch.
+ * Epoch is 1970-01-01, which is also equal to day 0.
+ *
+ * @param year Year (year 1900 = 0, may be negative).
+ * @param mon Month (January = 0).
+ * @param mday Day of month (first day = 1).
+ * @return Number of days since the Epoch.
+ */
+static time_t _days_since_epoch(time_t year, time_t mon, time_t mday)
+{
+	return (year - 70) * 365 + _floor_div(year - 69, 4) -
+	    _floor_div(year - 1, 100) + _floor_div(year + 299, 400) +
+	    _day_of_year(year, mon, mday);
+}
+
+/**
+ * Seconds since the Epoch. see also _days_since_epoch().
+ * 
+ * @param tm Normalized broken-down time.
+ * @return Number of seconds since the epoch, not counting leap seconds.
+ */
+static time_t _secs_since_epoch(const struct tm *tm)
+{
+	return _days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) *
+	    SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR +
+	    tm->tm_min * SECS_PER_MIN + tm->tm_sec;
+}
+
+/**
+ * Which day of week the specified date is.
+ * 
+ * @param year Year (year 1900 = 0).
+ * @param mon Month (January = 0).
+ * @param mday Day of month (first = 1).
+ * @return Day of week (Sunday = 0).
+ */
+static int _day_of_week(time_t year, time_t mon, time_t mday)
+{
+	/* 1970-01-01 is Thursday */
+	return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7);
+}
+
+/**
+ * Normalizes the broken-down time and optionally adds specified amount of
+ * seconds.
+ * 
+ * @param tm Broken-down time to normalize.
+ * @param sec_add Seconds to add.
+ * @return 0 on success, -1 on overflow
+ */
+static int _normalize_time(struct tm *tm, time_t sec_add)
+{
+	// TODO: DST correction
+
+	/* Set initial values. */
+	time_t sec = tm->tm_sec + sec_add;
+	time_t min = tm->tm_min;
+	time_t hour = tm->tm_hour;
+	time_t day = tm->tm_mday - 1;
+	time_t mon = tm->tm_mon;
+	time_t year = tm->tm_year;
+
+	/* Adjust time. */
+	min += _floor_div(sec, SECS_PER_MIN);
+	sec = _floor_mod(sec, SECS_PER_MIN);
+	hour += _floor_div(min, MINS_PER_HOUR);
+	min = _floor_mod(min, MINS_PER_HOUR);
+	day += _floor_div(hour, HOURS_PER_DAY);
+	hour = _floor_mod(hour, HOURS_PER_DAY);
+
+	/* Adjust month. */
+	year += _floor_div(mon, 12);
+	mon = _floor_mod(mon, 12);
+
+	/* Now the difficult part - days of month. */
+	
+	/* First, deal with whole cycles of 400 years = 146097 days. */
+	year += _floor_div(day, 146097) * 400;
+	day = _floor_mod(day, 146097);
+	
+	/* Then, go in one year steps. */
+	if (mon <= 1) {
+		/* January and February. */
+		while (day > 365) {
+			day -= _is_leap_year(year) ? 366 : 365;
+			year++;
+		}
+	} else {
+		/* Rest of the year. */
+		while (day > 365) {
+			day -= _is_leap_year(year + 1) ? 366 : 365;
+			year++;
+		}
+	}
+	
+	/* Finally, finish it off month per month. */
+	while (day >= _days_in_month(year, mon)) {
+		day -= _days_in_month(year, mon);
+		mon++;
+		if (mon >= 12) {
+			mon -= 12;
+			year++;
+		}
+	}
+	
+	/* Calculate the remaining two fields. */
+	tm->tm_yday = _day_of_year(year, mon, day + 1);
+	tm->tm_wday = _day_of_week(year, mon, day + 1);
+	
+	/* And put the values back to the struct. */
+	tm->tm_sec = (int) sec;
+	tm->tm_min = (int) min;
+	tm->tm_hour = (int) hour;
+	tm->tm_mday = (int) day + 1;
+	tm->tm_mon = (int) mon;
+	
+	/* Casts to work around libc brain-damage. */
+	if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) {
+		tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX);
+		return -1;
+	}
+	
+	tm->tm_year = (int) year;
+	return 0;
+}
+
+/**
+ * Which day the week-based year starts on, relative to the first calendar day.
+ * E.g. if the year starts on December 31st, the return value is -1.
+ *
+ * @param Year since 1900.
+ * @return Offset of week-based year relative to calendar year.
+ */
+static int _wbyear_offset(int year)
+{
+	int start_wday = _day_of_week(year, 0, 1);
+	return _floor_mod(4 - start_wday, 7) - 3;
+}
+
+/**
+ * Returns week-based year of the specified time.
+ *
+ * @param tm Normalized broken-down time.
+ * @return Week-based year.
+ */
+static int _wbyear(const struct tm *tm)
+{
+	int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
+	if (day < 0) {
+		/* Last week of previous year. */
+		return tm->tm_year - 1;
+	}
+	if (day > 364 + _is_leap_year(tm->tm_year)) {
+		/* First week of next year. */
+		return tm->tm_year + 1;
+	}
+	/* All the other days are in the calendar year. */
+	return tm->tm_year;
+}
+
+/**
+ * Week number of the year, assuming weeks start on sunday.
+ * The first Sunday of January is the first day of week 1;
+ * days in the new year before this are in week 0.
+ *
+ * @param tm Normalized broken-down time.
+ * @return The week number (0 - 53).
+ */
+static int _sun_week_number(const struct tm *tm)
+{
+	int first_day = (7 - _day_of_week(tm->tm_year, 0, 1)) % 7;
+	return (tm->tm_yday - first_day + 7) / 7;
+}
+
+/**
+ * Week number of the year, assuming weeks start on monday.
+ * If the week containing January 1st has four or more days in the new year,
+ * then it is considered week 1. Otherwise, it is the last week of the previous
+ * year, and the next week is week 1. Both January 4th and the first Thursday
+ * of January are always in week 1.
+ *
+ * @param tm Normalized broken-down time.
+ * @return The week number (1 - 53).
+ */
+static int _iso_week_number(const struct tm *tm)
+{
+	int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
+	if (day < 0) {
+		/* Last week of previous year. */
+		return 53;
+	}
+	if (day > 364 + _is_leap_year(tm->tm_year)) {
+		/* First week of next year. */
+		return 1;
+	}
+	/* All the other days give correct answer. */
+	return (day / 7 + 1);
+}
+
+/**
+ * Week number of the year, assuming weeks start on monday.
+ * The first Monday of January is the first day of week 1;
+ * days in the new year before this are in week 0. 
+ *
+ * @param tm Normalized broken-down time.
+ * @return The week number (0 - 53).
+ */
+static int _mon_week_number(const struct tm *tm)
+{
+	int first_day = (1 - _day_of_week(tm->tm_year, 0, 1)) % 7;
+	return (tm->tm_yday - first_day + 7) / 7;
+}
+
+/******************************************************************************/
+
+
 /** Add microseconds to given timeval.
  *
@@ -139,4 +483,67 @@
  */
 int gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+	int rc;
+	struct tm t;
+	category_id_t cat_id;
+	size_t svc_cnt;
+	service_id_t *svc_ids = NULL;
+	service_id_t svc_id;
+	char *svc_name = NULL;
+
+	static async_sess_t *clock_conn = NULL;
+
+	if (tz) {
+		tz->tz_minuteswest = 0;
+		tz->tz_dsttime = DST_NONE;
+	}
+
+	if (clock_conn == NULL) {
+		rc = loc_category_get_id("clock", &cat_id, IPC_FLAG_BLOCKING);
+		if (rc != EOK)
+			goto ret_uptime;
+
+		rc = loc_category_get_svcs(cat_id, &svc_ids, &svc_cnt);
+		if (rc != EOK)
+			goto ret_uptime;
+
+		if (svc_cnt == 0)
+			goto ret_uptime;
+
+		rc = loc_service_get_name(svc_ids[0], &svc_name);
+		if (rc != EOK)
+			goto ret_uptime;
+
+		rc = loc_service_get_id(svc_name, &svc_id, 0);
+		if (rc != EOK)
+			goto ret_uptime;
+
+		clock_conn = loc_service_connect(EXCHANGE_SERIALIZE,
+		    svc_id, IPC_FLAG_BLOCKING);
+		if (!clock_conn)
+			goto ret_uptime;
+	}
+
+	rc = clock_dev_time_get(clock_conn, &t);
+	if (rc != EOK)
+		goto ret_uptime;
+
+	tv->tv_usec = 0;
+	tv->tv_sec = mktime(&t);
+
+	free(svc_name);
+	free(svc_ids);
+
+	return EOK;
+
+ret_uptime:
+
+	free(svc_name);
+	free(svc_ids);
+
+	return getuptime(tv);
+}
+
+int getuptime(struct timeval *tv)
 {
 	if (ktime == NULL) {
@@ -160,9 +567,4 @@
 	}
 	
-	if (tz) {
-		tz->tz_minuteswest = 0;
-		tz->tz_dsttime = DST_NONE;
-	}
-	
 	sysarg_t s2 = ktime->seconds2;
 	
@@ -178,5 +580,5 @@
 	} else
 		tv->tv_sec = s1;
-	
+
 	return 0;
 }
@@ -229,4 +631,355 @@
 }
 
+/**
+ * This function first normalizes the provided broken-down time
+ * (moves all values to their proper bounds) and then tries to
+ * calculate the appropriate time_t representation.
+ *
+ * @param tm Broken-down time.
+ * @return time_t representation of the time, undefined value on overflow.
+ */
+time_t mktime(struct tm *tm)
+{
+	// TODO: take DST flag into account
+	// TODO: detect overflow
+
+	_normalize_time(tm, 0);
+	return _secs_since_epoch(tm);
+}
+
+/**
+ * Convert time and date to a string, based on a specified format and
+ * current locale.
+ * 
+ * @param s Buffer to write string to.
+ * @param maxsize Size of the buffer.
+ * @param format Format of the output.
+ * @param tm Broken-down time to format.
+ * @return Number of bytes written.
+ */
+size_t strftime(char *restrict s, size_t maxsize,
+    const char *restrict format, const struct tm *restrict tm)
+{
+	assert(s != NULL);
+	assert(format != NULL);
+	assert(tm != NULL);
+
+	// TODO: use locale
+	static const char *wday_abbr[] = {
+		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+	};
+	static const char *wday[] = {
+		"Sunday", "Monday", "Tuesday", "Wednesday",
+		"Thursday", "Friday", "Saturday"
+	};
+	static const char *mon_abbr[] = {
+		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+	};
+	static const char *mon[] = {
+		"January", "February", "March", "April", "May", "June", "July",
+		"August", "September", "October", "November", "December"
+	};
+	
+	if (maxsize < 1) {
+		return 0;
+	}
+	
+	char *ptr = s;
+	size_t consumed;
+	size_t remaining = maxsize;
+	
+	#define append(...) { \
+		/* FIXME: this requires POSIX-correct snprintf */ \
+		/*        otherwise it won't work with non-ascii chars */ \
+		consumed = snprintf(ptr, remaining, __VA_ARGS__); \
+		if (consumed >= remaining) { \
+			return 0; \
+		} \
+		ptr += consumed; \
+		remaining -= consumed; \
+	}
+	
+	#define recurse(fmt) { \
+		consumed = strftime(ptr, remaining, fmt, tm); \
+		if (consumed == 0) { \
+			return 0; \
+		} \
+		ptr += consumed; \
+		remaining -= consumed; \
+	}
+	
+	#define TO_12H(hour) (((hour) > 12) ? ((hour) - 12) : \
+	    (((hour) == 0) ? 12 : (hour)))
+	
+	while (*format != '\0') {
+		if (*format != '%') {
+			append("%c", *format);
+			format++;
+			continue;
+		}
+		
+		format++;
+		if (*format == '0' || *format == '+') {
+			// TODO: padding
+			format++;
+		}
+		while (isdigit(*format)) {
+			// TODO: padding
+			format++;
+		}
+		if (*format == 'O' || *format == 'E') {
+			// TODO: locale's alternative format
+			format++;
+		}
+		
+		switch (*format) {
+		case 'a':
+			append("%s", wday_abbr[tm->tm_wday]); break;
+		case 'A':
+			append("%s", wday[tm->tm_wday]); break;
+		case 'b':
+			append("%s", mon_abbr[tm->tm_mon]); break;
+		case 'B':
+			append("%s", mon[tm->tm_mon]); break;
+		case 'c':
+			// TODO: locale-specific datetime format
+			recurse("%Y-%m-%d %H:%M:%S"); break;
+		case 'C':
+			append("%02d", (1900 + tm->tm_year) / 100); break;
+		case 'd':
+			append("%02d", tm->tm_mday); break;
+		case 'D':
+			recurse("%m/%d/%y"); break;
+		case 'e':
+			append("%2d", tm->tm_mday); break;
+		case 'F':
+			recurse("%+4Y-%m-%d"); break;
+		case 'g':
+			append("%02d", _wbyear(tm) % 100); break;
+		case 'G':
+			append("%d", _wbyear(tm)); break;
+		case 'h':
+			recurse("%b"); break;
+		case 'H':
+			append("%02d", tm->tm_hour); break;
+		case 'I':
+			append("%02d", TO_12H(tm->tm_hour)); break;
+		case 'j':
+			append("%03d", tm->tm_yday); break;
+		case 'k':
+			append("%2d", tm->tm_hour); break;
+		case 'l':
+			append("%2d", TO_12H(tm->tm_hour)); break;
+		case 'm':
+			append("%02d", tm->tm_mon); break;
+		case 'M':
+			append("%02d", tm->tm_min); break;
+		case 'n':
+			append("\n"); break;
+		case 'p':
+			append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break;
+		case 'P':
+			append("%s", tm->tm_hour < 12 ? "am" : "PM"); break;
+		case 'r':
+			recurse("%I:%M:%S %p"); break;
+		case 'R':
+			recurse("%H:%M"); break;
+		case 's':
+			append("%ld", _secs_since_epoch(tm)); break;
+		case 'S':
+			append("%02d", tm->tm_sec); break;
+		case 't':
+			append("\t"); break;
+		case 'T':
+			recurse("%H:%M:%S"); break;
+		case 'u':
+			append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
+			break;
+		case 'U':
+			append("%02d", _sun_week_number(tm)); break;
+		case 'V':
+			append("%02d", _iso_week_number(tm)); break;
+		case 'w':
+			append("%d", tm->tm_wday); break;
+		case 'W':
+			append("%02d", _mon_week_number(tm)); break;
+		case 'x':
+			// TODO: locale-specific date format
+			recurse("%Y-%m-%d"); break;
+		case 'X':
+			// TODO: locale-specific time format
+			recurse("%H:%M:%S"); break;
+		case 'y':
+			append("%02d", tm->tm_year % 100); break;
+		case 'Y':
+			append("%d", 1900 + tm->tm_year); break;
+		case 'z':
+			// TODO: timezone
+			break;
+		case 'Z':
+			// TODO: timezone
+			break;
+		case '%':
+			append("%%");
+			break;
+		default:
+			/* Invalid specifier, print verbatim. */
+			while (*format != '%') {
+				format--;
+			}
+			append("%%");
+			break;
+		}
+		format++;
+	}
+	
+	#undef append
+	#undef recurse
+	
+	return maxsize - remaining;
+}
+
+
+/** Converts a time value to a broken-down UTC time
+ *
+ * @param time    Time to convert
+ * @param result  Structure to store the result to
+ *
+ * @return        EOK or a negative error code
+ */
+int time_utc2tm(const time_t time, struct tm *restrict result)
+{
+	assert(result != NULL);
+
+	/* Set result to epoch. */
+	result->tm_sec = 0;
+	result->tm_min = 0;
+	result->tm_hour = 0;
+	result->tm_mday = 1;
+	result->tm_mon = 0;
+	result->tm_year = 70; /* 1970 */
+
+	if (_normalize_time(result, time) == -1)
+		return EOVERFLOW;
+
+	return EOK;
+}
+
+/** Converts a time value to a null terminated string of the form
+ *  "Wed Jun 30 21:49:08 1993\n" expressed in UTC.
+ *
+ * @param time   Time to convert.
+ * @param buf    Buffer to store the string to, must be at least
+ *               ASCTIME_BUF_LEN bytes long.
+ *
+ * @return       EOK or a negative error code.
+ */
+int time_utc2str(const time_t time, char *restrict buf)
+{
+	struct tm t;
+	int r;
+
+	if ((r = time_utc2tm(time, &t)) != EOK)
+		return r;
+
+	time_tm2str(&t, buf);
+	return EOK;
+}
+
+
+/**
+ * Converts broken-down time to a string in format
+ * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
+ *
+ * @param timeptr Broken-down time structure.
+ * @param buf     Buffer to store string to, must be at least ASCTIME_BUF_LEN
+ *                bytes long.
+ */
+void time_tm2str(const struct tm *restrict timeptr, char *restrict buf)
+{
+	assert(timeptr != NULL);
+	assert(buf != NULL);
+
+	static const char *wday[] = {
+		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+	};
+	static const char *mon[] = {
+		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+	};
+
+	snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n",
+	    wday[timeptr->tm_wday],
+	    mon[timeptr->tm_mon],
+	    timeptr->tm_mday, timeptr->tm_hour,
+	    timeptr->tm_min, timeptr->tm_sec,
+	    1900 + timeptr->tm_year);
+}
+
+/**
+ * Converts a time value to a broken-down local time, expressed relative
+ * to the user's specified timezone.
+ *
+ * @param timer     Time to convert.
+ * @param result    Structure to store the result to.
+ *
+ * @return          EOK on success or a negative error code.
+ */
+int time_local2tm(const time_t time, struct tm *restrict result)
+{
+	// TODO: deal with timezone
+	// currently assumes system and all times are in GMT
+
+	/* Set result to epoch. */
+	result->tm_sec = 0;
+	result->tm_min = 0;
+	result->tm_hour = 0;
+	result->tm_mday = 1;
+	result->tm_mon = 0;
+	result->tm_year = 70; /* 1970 */
+
+	if (_normalize_time(result, time) == -1)
+		return EOVERFLOW;
+
+	return EOK;
+}
+
+/**
+ * Converts the calendar time to a null terminated string
+ * of the form "Wed Jun 30 21:49:08 1993\n" expressed relative to the
+ * user's specified timezone.
+ * 
+ * @param timer  Time to convert.
+ * @param buf    Buffer to store the string to. Must be at least
+ *               ASCTIME_BUF_LEN bytes long.
+ *
+ * @return       EOK on success or a negative error code.
+ */
+int time_local2str(const time_t time, char *buf)
+{
+	struct tm loctime;
+	int r;
+
+	if ((r = time_local2tm(time, &loctime)) != EOK)
+		return r;
+
+	time_tm2str(&loctime, buf);
+
+	return EOK;
+}
+
+/**
+ * Calculate the difference between two times, in seconds.
+ * 
+ * @param time1 First time.
+ * @param time0 Second time.
+ * @return Time in seconds.
+ */
+double difftime(time_t time1, time_t time0)
+{
+	return (double) (time1 - time0);
+}
+
 /** @}
  */
Index: uspace/lib/c/generic/tls.c
===================================================================
--- uspace/lib/c/generic/tls.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/generic/tls.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,4 +42,5 @@
 #include <str.h>
 #include <align.h>
+#include <unistd.h>
 
 /** Create TLS (Thread Local Storage) data structures.
@@ -57,4 +58,6 @@
 	
 	tcb = __alloc_tls(&data, tls_size);
+	if (!tcb)
+		return NULL;
 	
 	/*
@@ -89,5 +92,8 @@
 
 	result = malloc(sizeof(tcb_t) + size);
+	if (!result)
+		return NULL;
 	*data = ((void *)result) + sizeof(tcb_t);
+
 	return result;
 }
@@ -118,5 +124,6 @@
 	size = ALIGN_UP(size, &_tls_alignment);
 	*data = memalign((uintptr_t) &_tls_alignment, sizeof(tcb_t) + size);
-
+	if (!*data)
+		return NULL;
 	tcb = (tcb_t *) (*data + size);
 	tcb->self = tcb;
Index: uspace/lib/c/include/adt/hash.h
===================================================================
--- uspace/lib/c/include/adt/hash.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/adt/hash.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * 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 genericadt
+ * @{
+ */
+/** @file
+ */
+#ifndef KERN_HASH_H_
+#define KERN_HASH_H_
+
+#include <stdint.h>
+
+/** Produces a uniform hash affecting all output bits from the skewed input. */
+static inline uint32_t hash_mix32(uint32_t hash)
+{
+	/*
+	 * Thomas Wang's modification of Bob Jenkin's hash mixing function:
+	 * http://www.concentric.net/~Ttwang/tech/inthash.htm
+	 * Public domain.
+	 */
+	hash = ~hash + (hash << 15); 
+	hash = hash ^ (hash >> 12);
+	hash = hash + (hash << 2);
+	hash = hash ^ (hash >> 4);
+	hash = hash * 2057; 
+	hash = hash ^ (hash >> 16);
+	return hash;	
+}
+
+/** Produces a uniform hash affecting all output bits from the skewed input. */
+static inline uint64_t hash_mix64(uint64_t hash)
+{
+	/*
+	 * Thomas Wang's public domain 64-bit hash mixing function:
+	 * http://www.concentric.net/~Ttwang/tech/inthash.htm
+	 */
+	hash = (hash ^ 61) ^ (hash >> 16);
+	hash = hash + (hash << 3);
+	hash = hash ^ (hash >> 4);
+	hash = hash * 0x27d4eb2d;
+	hash = hash ^ (hash >> 15);	
+	/* 
+	 * Lower order bits are mixed more thoroughly. Swap them with
+	 * the higher order bits and make the resulting higher order bits
+	 * more usable.
+	 */
+	return (hash << 32) | (hash >> 32);
+}
+
+/** Produces a uniform hash affecting all output bits from the skewed input. */
+static inline size_t hash_mix(size_t hash) 
+{
+#ifdef __32_BITS__
+	return hash_mix32(hash);
+#elif defined(__64_BITS__)
+	return hash_mix64(hash);
+#else
+#error Unknown size_t size - cannot select proper hash mix function.
+#endif
+}
+
+/** Use to create a hash from multiple values.
+ * 
+ * Typical usage:
+ * @code
+ * int car_id;
+ * bool car_convertible;
+ * // ..
+ * size_t hash = 0;
+ * hash = hash_combine(hash, car_id);
+ * hash = hash_combine(hash, car_convertible);
+ * // Now use hash as a hash of both car_id and car_convertible.
+ * @endcode
+ */
+static inline size_t hash_combine(size_t seed, size_t hash)
+{
+	/* 
+	 * todo: use Bob Jenkin's proper mixing hash pass:
+	 * http://burtleburtle.net/bob/c/lookup3.c
+	 */
+	seed ^= hash + 0x9e3779b9 
+		+ ((seed << 5) | (seed >> (sizeof(size_t) * 8 - 5)));
+	return seed;	
+}
+
+#endif
Index: pace/lib/c/include/adt/hash_set.h
===================================================================
--- uspace/lib/c/include/adt/hash_set.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,84 +1,0 @@
-/*
- * Copyright (c) 2006 Jakub Jermar
- * Copyright (c) 2011 Radim Vansa
- * 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_HASH_SET_H_
-#define LIBC_HASH_SET_H_
-
-#include <adt/list.h>
-#include <unistd.h>
-
-#define HASH_SET_MIN_SIZE  8
-
-typedef unsigned long (*hash_set_hash)(const link_t *);
-typedef int (*hash_set_equals)(const link_t *, const link_t *);
-
-/** Hash table structure. */
-typedef struct {
-	list_t *table;
-	
-	/** Current table size */
-	size_t size;
-	
-	/**
-	 * Current number of entries. If count > size,
-	 * the table is rehashed into table with double
-	 * size. If (4 * count < size) && (size > min_size),
-	 * the table is rehashed into table with half the size.
-	 */
-	size_t count;
-	
-	/** Hash function */
-	hash_set_hash hash;
-	
-	/** Hash table item equals function */
-	hash_set_equals equals;
-} hash_set_t;
-
-extern int hash_set_init(hash_set_t *, hash_set_hash, hash_set_equals, size_t);
-extern int hash_set_insert(hash_set_t *, link_t *);
-extern link_t *hash_set_find(hash_set_t *, const link_t *);
-extern int hash_set_contains(const hash_set_t *, const link_t *);
-extern size_t hash_set_count(const hash_set_t *);
-extern link_t *hash_set_remove(hash_set_t *, const link_t *);
-extern void hash_set_remove_selected(hash_set_t *,
-    int (*)(link_t *, void *), void *);
-extern void hash_set_destroy(hash_set_t *);
-extern void hash_set_apply(hash_set_t *, void (*)(link_t *, void *), void *);
-extern void hash_set_clear(hash_set_t *, void (*)(link_t *, void *), void *);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/adt/hash_table.h
===================================================================
--- uspace/lib/c/include/adt/hash_table.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/adt/hash_table.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -1,4 +1,6 @@
 /*
  * Copyright (c) 2006 Jakub Jermar
+ * Copyright (c) 2012 Adam Hraska
+ * 
  * All rights reserved.
  *
@@ -39,58 +41,65 @@
 #include <unistd.h>
 #include <bool.h>
+#include <macros.h>
 
-typedef unsigned long hash_count_t;
-typedef unsigned long hash_index_t;
+/** Opaque hash table link type. */
+typedef struct ht_link {
+	link_t link;
+} ht_link_t;
 
 /** Set of operations for hash table. */
 typedef struct {
-	/** Hash function.
-	 *
-	 * @param key Array of keys needed to compute hash index.
-	 *            All keys must be passed.
-	 *
-	 * @return Index into hash table.
-	 *
-	 */
-	hash_index_t (*hash)(unsigned long key[]);
+	/** Returns the hash of the key stored in the item (ie its lookup key). */
+	size_t (*hash)(const ht_link_t *item);
 	
-	/** Hash table item comparison function.
-	 *
-	 * @param key Array of keys that will be compared with item. It is
-	 *            not necessary to pass all keys.
-	 *
-	 * @return True if the keys match, false otherwise.
-	 *
-	 */
-	int (*compare)(unsigned long key[], hash_count_t keys, link_t *item);
+	/** Returns the hash of the key. */
+	size_t (*key_hash)(void *key);
 	
+	/** True if the items are equal (have the same lookup keys). */
+	bool (*equal)(const ht_link_t *item1, const ht_link_t *item2);
+
+	/** Returns true if the key is equal to the item's lookup key. */
+	bool (*key_equal)(void *key, const ht_link_t *item);
+
 	/** Hash table item removal callback.
+	 * 
+	 * Must not invoke any mutating functions of the hash table.
 	 *
 	 * @param item Item that was removed from the hash table.
-	 *
 	 */
-	void (*remove_callback)(link_t *item);
-} hash_table_operations_t;
+	void (*remove_callback)(ht_link_t *item);
+} hash_table_ops_t;
 
 /** Hash table structure. */
 typedef struct {
-	list_t *entry;
-	hash_count_t entries;
-	hash_count_t max_keys;
-	hash_table_operations_t *op;
+	hash_table_ops_t *op;
+	list_t *bucket;
+	size_t bucket_cnt;
+	size_t full_item_cnt;
+	size_t item_cnt;
+	size_t max_load;
+	bool apply_ongoing;
 } hash_table_t;
 
-#define hash_table_get_instance(item, type, member) \
-    list_get_instance((item), type, member)
+#define hash_table_get_inst(item, type, member) \
+	member_to_inst((item), type, member)
 
-extern bool hash_table_create(hash_table_t *, hash_count_t, hash_count_t,
-    hash_table_operations_t *);
+extern bool hash_table_create(hash_table_t *, size_t, size_t, 
+	hash_table_ops_t *);
+extern void hash_table_destroy(hash_table_t *);
+
+extern bool hash_table_empty(hash_table_t *);
+extern size_t hash_table_size(hash_table_t *);
+
 extern void hash_table_clear(hash_table_t *);
-extern void hash_table_insert(hash_table_t *, unsigned long [], link_t *);
-extern link_t *hash_table_find(hash_table_t *, unsigned long []);
-extern void hash_table_remove(hash_table_t *, unsigned long [], hash_count_t);
-extern void hash_table_destroy(hash_table_t *);
-extern void hash_table_apply(hash_table_t *, void (*)(link_t *, void *),
-    void *);
+extern void hash_table_insert(hash_table_t *, ht_link_t *);
+extern bool hash_table_insert_unique(hash_table_t *, ht_link_t *);
+extern ht_link_t *hash_table_find(const hash_table_t *, void *);
+extern ht_link_t *hash_table_find_next(const hash_table_t *, ht_link_t *);
+extern size_t hash_table_remove(hash_table_t *, void *);
+extern void hash_table_remove_item(hash_table_t *, ht_link_t *);
+extern void hash_table_apply(hash_table_t *, bool (*)(ht_link_t *, void *), 
+	void *);
+
 
 #endif
Index: uspace/lib/c/include/adt/list.h
===================================================================
--- uspace/lib/c/include/adt/list.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/adt/list.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -71,6 +71,43 @@
 	    iterator != &(list).head; iterator = iterator->next)
 
+/** Unlike list_foreach(), allows removing items while traversing a list.
+ * 
+ * @code
+ * list_t mylist;
+ * typedef struct item {
+ *     int value;
+ *     link_t item_link;
+ * } item_t;
+ * 
+ * //..
+ * 
+ * // Print each list element's value and remove the element from the list.
+ * list_foreach_safe(mylist, cur_link, next_link) {
+ *     item_t *cur_item = list_get_instance(cur_link, item_t, item_link);
+ *     printf("%d\n", cur_item->value);
+ *     list_remove(cur_link);
+ * }
+ * @endcode
+ * 
+ * @param list List to traverse.
+ * @param iterator Iterator to the current element of the list.
+ *             The item this iterator points may be safely removed
+ *             from the list.
+ * @param next_iter Iterator to the next element of the list.
+ */
+#define list_foreach_safe(list, iterator, next_iter) \
+	for (link_t *iterator = (list).head.next, \
+		*next_iter = iterator->next; \
+		iterator != &(list).head; \
+		iterator = next_iter, next_iter = iterator->next)
+
 #define assert_link_not_used(link) \
 	assert(((link)->prev == NULL) && ((link)->next == NULL))
+
+/** Returns true if the link is definitely part of a list. False if not sure. */
+static inline int link_in_use(link_t *link)
+{
+	return link->prev != NULL && link->next != NULL;
+}
 
 /** Initialize doubly-linked circular list link
Index: uspace/lib/c/include/bd.h
===================================================================
--- uspace/lib/c/include/bd.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/bd.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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_BD_H_
+#define LIBC_BD_H_
+
+#include <async.h>
+#include <sys/types.h>
+
+typedef struct {
+	async_sess_t *sess;
+} bd_t;
+
+extern int bd_open(async_sess_t *, bd_t **);
+extern void bd_close(bd_t *);
+extern int bd_read_blocks(bd_t *, aoff64_t, size_t, void *, size_t);
+extern int bd_read_toc(bd_t *, uint8_t, void *, size_t);
+extern int bd_write_blocks(bd_t *, aoff64_t, size_t, const void *, size_t);
+extern int bd_get_block_size(bd_t *, size_t *);
+extern int bd_get_num_blocks(bd_t *, aoff64_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/bd_srv.h
===================================================================
--- uspace/lib/c/include/bd_srv.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/bd_srv.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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_BD_SRV_H_
+#define LIBC_BD_SRV_H_
+
+#include <adt/list.h>
+#include <async.h>
+#include <fibril_synch.h>
+#include <bool.h>
+#include <sys/types.h>
+
+typedef struct bd_ops bd_ops_t;
+
+/** Service setup (per sevice) */
+typedef struct {
+	bd_ops_t *ops;
+	void *sarg;
+} bd_srvs_t;
+
+/** Server structure (per client session) */
+typedef struct {
+	bd_srvs_t *srvs;
+	async_sess_t *client_sess;
+	void *carg;
+} bd_srv_t;
+
+typedef struct bd_ops {
+	int (*open)(bd_srvs_t *, bd_srv_t *);
+	int (*close)(bd_srv_t *);
+	int (*read_blocks)(bd_srv_t *, aoff64_t, size_t, void *, size_t);
+	int (*read_toc)(bd_srv_t *, uint8_t, void *, size_t);
+	int (*write_blocks)(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
+	int (*get_block_size)(bd_srv_t *, size_t *);
+	int (*get_num_blocks)(bd_srv_t *, aoff64_t *);
+} bd_ops_t;
+
+extern void bd_srvs_init(bd_srvs_t *);
+
+extern int bd_conn(ipc_callid_t, ipc_call_t *, bd_srvs_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/device/ahci.h
===================================================================
--- uspace/lib/c/include/device/ahci.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/device/ahci.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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
+ * @brief AHCI interface definition.
+ */
+
+#ifndef LIBC_DEVICE_AHCI_H_
+#define LIBC_DEVICE_AHCI_H_
+
+#include <async.h>
+#include <devman.h>
+
+extern async_sess_t* ahci_get_sess(devman_handle_t, char **);
+
+extern int ahci_get_sata_device_name(async_sess_t *, size_t, char *);
+extern int ahci_get_num_blocks(async_sess_t *, uint64_t *);
+extern int ahci_get_block_size(async_sess_t *, size_t *);
+extern int ahci_read_blocks(async_sess_t *, uint64_t, size_t, void *);
+extern int ahci_write_blocks(async_sess_t *, uint64_t, size_t, void *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/device/battery_dev.h
===================================================================
--- uspace/lib/c/include/device/battery_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/device/battery_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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_DEVICE_BATTERY_DEV_H_
+#define LIBC_DEVICE_BATTERY_DEV_H_
+
+#include <async.h>
+
+typedef enum {
+	BATTERY_OK,
+	BATTERY_LOW,
+	BATTERY_NOT_PRESENT,
+} battery_status_t;
+
+typedef enum {
+	BATTERY_STATUS_GET = 0,
+	BATTERY_CHARGE_LEVEL_GET,
+} battery_dev_method_t;
+
+extern int battery_status_get(async_sess_t *, battery_status_t *);
+extern int battery_charge_level_get(async_sess_t *, int *);
+
+#endif
+
Index: uspace/lib/c/include/device/clock_dev.h
===================================================================
--- uspace/lib/c/include/device/clock_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/device/clock_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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_DEVICE_CLOCK_DEV_H_
+#define LIBC_DEVICE_CLOCK_DEV_H_
+
+#include <async.h>
+#include <time.h>
+
+typedef enum {
+	CLOCK_DEV_TIME_GET = 0,
+	CLOCK_DEV_TIME_SET,
+} clock_dev_method_t;
+
+extern int clock_dev_time_get(async_sess_t *, struct tm *);
+extern int clock_dev_time_set(async_sess_t *, struct tm *);
+
+#endif
+
Index: uspace/lib/c/include/device/graph_dev.h
===================================================================
--- uspace/lib/c/include/device/graph_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/device/graph_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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_DEVICE_GRAPH_DEV_H_
+#define LIBC_DEVICE_GRAPH_DEV_H_
+
+#include <async.h>
+
+typedef enum {
+	GRAPH_DEV_CONNECT = 0
+} graph_dev_method_t;
+
+extern int graph_dev_connect(async_sess_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/double_to_str.h
===================================================================
--- uspace/lib/c/include/double_to_str.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/double_to_str.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * 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.
+ */
+
+#ifndef DOUBLE_TO_STR_H_
+#define DOUBLE_TO_STR_H_
+
+#include <unistd.h>
+
+/** Maximum number of digits double_to_*_str conversion functions produce. 
+ *
+ * Both double_to_short_str and double_to_fixed_str generate digits out
+ * of a 64bit unsigned int number representation. The max number of 
+ * of digits is therefore 20. Add 1 to help users who forget to reserve
+ * space for a null terminator.
+ */
+#define MAX_DOUBLE_STR_LEN (20 + 1)
+
+/** Maximum buffer size needed to store the output of double_to_*_str 
+ *  functions. 
+ */
+#define MAX_DOUBLE_STR_BUF_SIZE  21
+
+/* Fwd decl.*/
+struct ieee_double_t_tag;
+
+extern int double_to_short_str(struct ieee_double_t_tag, char *, size_t, int *);
+extern int double_to_fixed_str(struct ieee_double_t_tag, int, int, char *,
+    size_t, int *);
+
+#endif 
Index: uspace/lib/c/include/ieee_double.h
===================================================================
--- uspace/lib/c/include/ieee_double.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/ieee_double.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * 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.
+ */
+
+#ifndef IEEE_DOUBLE_H_
+#define IEEE_DOUBLE_H_
+
+#include <stdint.h>
+#include <bool.h>
+
+/** Represents a non-negative floating point number: significand * 2^exponent */
+typedef struct fp_num_t_tag {
+	/** Significand (aka mantissa). */
+	uint64_t significand;
+	/** Binary exponent. */
+	int exponent;
+} fp_num_t;
+
+/** Double number description according to IEEE 754. */
+typedef struct ieee_double_t_tag {
+	/** The number is a NaN or infinity. */
+	bool is_special;
+	/** Not a number. */
+	bool is_nan;
+	bool is_negative;
+	/** The number denoted infinity. */
+	bool is_infinity;
+	/** The number could not be represented as a normalized double. */
+	bool is_denormal;
+	/**
+	 * The predecessor double is closer than the successor. This happens 
+	 * if a normal number is of the form 2^k and it is not the smallest
+	 * normal number. 
+	 */
+	bool is_accuracy_step;
+	/** 
+	 * If !is_special the double's value is:
+	 *   pos_val.significand * 2^pos_val.exponent
+	 */
+	fp_num_t pos_val;
+} ieee_double_t;
+
+extern ieee_double_t extract_ieee_double(double);
+
+#endif
Index: uspace/lib/c/include/io/charfield.h
===================================================================
--- uspace/lib/c/include/io/charfield.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/charfield.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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_CHARFIELD_H_
+#define LIBC_IO_CHARFIELD_H_
+
+#include <sys/types.h>
+#include <bool.h>
+#include <io/color.h>
+#include <io/style.h>
+#include <io/pixel.h>
+
+typedef enum {
+	CHAR_FLAG_NONE = 0,
+	CHAR_FLAG_DIRTY = 1
+} char_flags_t;
+
+typedef enum {
+	CHAR_ATTR_STYLE,
+	CHAR_ATTR_INDEX,
+	CHAR_ATTR_RGB
+} char_attr_type_t;
+
+typedef struct {
+	console_color_t bgcolor;
+	console_color_t fgcolor;
+	console_color_attr_t attr;
+} char_attr_index_t;
+
+typedef struct {
+	pixel_t bgcolor;
+	pixel_t fgcolor;
+} char_attr_rgb_t;
+
+typedef union {
+	console_style_t style;
+	char_attr_index_t index;
+	char_attr_rgb_t rgb;
+} char_attr_val_t;
+
+typedef struct {
+	char_attr_type_t type;
+	char_attr_val_t val;
+} char_attrs_t;
+
+typedef struct {
+	wchar_t ch;
+	char_attrs_t attrs;
+	char_flags_t flags;
+} charfield_t;
+
+static inline bool attrs_same(char_attrs_t a1, char_attrs_t a2)
+{
+	if (a1.type != a2.type)
+		return false;
+	
+	switch (a1.type) {
+	case CHAR_ATTR_STYLE:
+		return (a1.val.style == a2.val.style);
+	case CHAR_ATTR_INDEX:
+		return (a1.val.index.bgcolor == a2.val.index.bgcolor)
+		    && (a1.val.index.fgcolor == a2.val.index.fgcolor)
+		    && (a1.val.index.attr == a2.val.index.attr);
+	case CHAR_ATTR_RGB:
+		return (a1.val.rgb.bgcolor == a2.val.rgb.bgcolor)
+		    && (a1.val.rgb.fgcolor == a2.val.rgb.fgcolor);
+	}
+	
+	return false;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/chargrid.h
===================================================================
--- uspace/lib/c/include/io/chargrid.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/chargrid.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2011 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 libc
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef LIBC_IO_CHARGRID_H_
+#define LIBC_IO_CHARGRID_H_
+
+#include <sys/types.h>
+#include <io/charfield.h>
+
+typedef enum {
+	CHARGRID_FLAG_NONE = 0,
+	CHARGRID_FLAG_SHARED = 1
+} chargrid_flag_t;
+
+typedef struct {
+	size_t size;            /**< Structure size */
+	chargrid_flag_t flags;  /**< Screenbuffer flags */
+	
+	sysarg_t cols;          /**< Number of columns */
+	sysarg_t rows;          /**< Number of rows */
+	
+	sysarg_t col;           /**< Current column */
+	sysarg_t row;           /**< Current row */
+	bool cursor_visible;    /**< Cursor visibility */
+	
+	char_attrs_t attrs;     /**< Current attributes */
+	
+	sysarg_t top_row;       /**< The first row in the cyclic buffer */
+	charfield_t data[];     /**< Screen contents (cyclic buffer) */
+} chargrid_t;
+
+static inline charfield_t *chargrid_charfield_at(chargrid_t *chargrid,
+    sysarg_t col, sysarg_t row)
+{
+	return chargrid->data +
+	    ((row + chargrid->top_row) % chargrid->rows) * chargrid->cols +
+	    col;
+}
+
+extern chargrid_t *chargrid_create(sysarg_t, sysarg_t,
+    chargrid_flag_t);
+extern void chargrid_destroy(chargrid_t *);
+
+extern bool chargrid_cursor_at(chargrid_t *, sysarg_t, sysarg_t);
+
+extern sysarg_t chargrid_get_top_row(chargrid_t *);
+
+extern sysarg_t chargrid_putchar(chargrid_t *, wchar_t, bool);
+extern sysarg_t chargrid_newline(chargrid_t *);
+extern sysarg_t chargrid_tabstop(chargrid_t *, sysarg_t);
+extern sysarg_t chargrid_backspace(chargrid_t *);
+
+extern void chargrid_clear(chargrid_t *);
+extern void chargrid_clear_row(chargrid_t *, sysarg_t);
+
+extern void chargrid_set_cursor(chargrid_t *, sysarg_t, sysarg_t);
+extern void chargrid_set_cursor_visibility(chargrid_t *, bool);
+extern bool chargrid_get_cursor_visibility(chargrid_t *);
+
+extern void chargrid_get_cursor(chargrid_t *, sysarg_t *, sysarg_t *);
+
+extern void chargrid_set_style(chargrid_t *, console_style_t);
+extern void chargrid_set_color(chargrid_t *, console_color_t,
+    console_color_t, console_color_attr_t);
+extern void chargrid_set_rgb_color(chargrid_t *, pixel_t, pixel_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/con_srv.h
===================================================================
--- uspace/lib/c/include/io/con_srv.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/con_srv.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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_CON_SRV_H_
+#define LIBC_CON_SRV_H_
+
+#include <adt/list.h>
+#include <async.h>
+#include <fibril_synch.h>
+#include <io/color.h>
+#include <io/concaps.h>
+#include <io/kbd_event.h>
+#include <io/pixel.h>
+#include <io/style.h>
+#include <bool.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+typedef struct con_ops con_ops_t;
+
+/** Service setup (per sevice) */
+typedef struct {
+	con_ops_t *ops;
+	void *sarg;
+	/** Period to check for abort */
+	suseconds_t abort_timeout;
+	bool aborted;
+} con_srvs_t;
+
+/** Server structure (per client session) */
+typedef struct {
+	con_srvs_t *srvs;
+	async_sess_t *client_sess;
+	void *carg;
+} con_srv_t;
+
+typedef struct con_ops {
+	int (*open)(con_srvs_t *, con_srv_t *);
+	int (*close)(con_srv_t *);
+	int (*read)(con_srv_t *, void *, size_t);
+	int (*write)(con_srv_t *, void *, size_t);
+	void (*sync)(con_srv_t *);
+	void (*clear)(con_srv_t *);
+	void (*set_pos)(con_srv_t *, sysarg_t col, sysarg_t row);
+	int (*get_pos)(con_srv_t *, sysarg_t *, sysarg_t *);
+	int (*get_size)(con_srv_t *, sysarg_t *, sysarg_t *);
+	int (*get_color_cap)(con_srv_t *, console_caps_t *);
+	void (*set_style)(con_srv_t *, console_style_t);
+	void (*set_color)(con_srv_t *, console_color_t, console_color_t,
+	    console_color_attr_t);
+	void (*set_rgb_color)(con_srv_t *, pixel_t, pixel_t);
+	void (*set_cursor_visibility)(con_srv_t *, bool);
+	int (*get_event)(con_srv_t *, kbd_event_t *);
+} con_ops_t;
+
+extern void con_srvs_init(con_srvs_t *);
+
+extern int con_conn(ipc_callid_t, ipc_call_t *, con_srvs_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/concaps.h
===================================================================
--- uspace/lib/c/include/io/concaps.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/concaps.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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 libcipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IO_CONCAPS_H_
+#define LIBC_IO_CONCAPS_H_
+
+typedef enum {
+	CONSOLE_CAP_NONE = 0,
+	CONSOLE_CAP_STYLE = 1,
+	CONSOLE_CAP_INDEXED = 2,
+	CONSOLE_CAP_RGB = 4
+} console_caps_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/console.h
===================================================================
--- uspace/lib/c/include/io/console.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/io/console.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,15 +37,10 @@
 
 #include <sys/time.h>
+#include <io/concaps.h>
+#include <io/kbd_event.h>
 #include <io/keycode.h>
 #include <async.h>
 #include <bool.h>
 #include <stdio.h>
-
-typedef enum {
-	CONSOLE_CAP_NONE = 0,
-	CONSOLE_CAP_STYLE = 1,
-	CONSOLE_CAP_INDEXED = 2,
-	CONSOLE_CAP_RGB = 4
-} console_caps_t;
 
 /** Console control structure. */
@@ -69,27 +64,4 @@
 	aid_t input_aid;
 } console_ctrl_t;
-
-typedef enum {
-	KEY_PRESS,
-	KEY_RELEASE
-} kbd_event_type_t;
-
-/** Console event structure. */
-typedef struct {
-	/** List handle */
-	link_t link;
-	
-	/** Press or release event. */
-	kbd_event_type_t type;
-	
-	/** Keycode of the key that was pressed or released. */
-	keycode_t key;
-	
-	/** Bitmask of modifiers held. */
-	keymod_t mods;
-	
-	/** The character that was generated or '\0' for none. */
-	wchar_t c;
-} kbd_event_t;
 
 extern console_ctrl_t *console_init(FILE *, FILE *);
Index: uspace/lib/c/include/io/input.h
===================================================================
--- uspace/lib/c/include/io/input.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/input.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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_INPUT_H_
+#define LIBC_IO_INPUT_H_
+
+#include <async.h>
+#include <io/kbd_event.h>
+#include <sys/types.h>
+
+struct input_ev_ops;
+
+typedef struct {
+	async_sess_t *sess;
+	struct input_ev_ops *ev_ops;
+	void *user;
+} input_t;
+
+typedef struct input_ev_ops {
+	int (*key)(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
+	int (*move)(input_t *, int, int);
+	int (*abs_move)(input_t *, unsigned, unsigned, unsigned, unsigned);
+	int (*button)(input_t *, int, int);
+} input_ev_ops_t;
+
+extern int input_open(async_sess_t *, input_ev_ops_t *, void *, input_t **);
+extern void input_close(input_t *);
+extern int input_yield(input_t *);
+extern int input_reclaim(input_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/kbd_event.h
===================================================================
--- uspace/lib/c/include/io/kbd_event.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/kbd_event.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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_KBD_EVENT_H_
+#define LIBC_IO_KBD_EVENT_H_
+
+#include <adt/list.h>
+#include <io/keycode.h>
+
+typedef enum {
+	KEY_PRESS,
+	KEY_RELEASE
+} kbd_event_type_t;
+
+/** Console event structure. */
+typedef struct {
+	/** List handle */
+	link_t link;
+	
+	/** Press or release event. */
+	kbd_event_type_t type;
+	
+	/** Keycode of the key that was pressed or released. */
+	keycode_t key;
+	
+	/** Bitmask of modifiers held. */
+	keymod_t mods;
+	
+	/** The character that was generated or '\0' for none. */
+	wchar_t c;
+} kbd_event_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/klog.h
===================================================================
--- uspace/lib/c/include/io/klog.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/io/klog.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,8 +38,10 @@
 #include <sys/types.h>
 #include <stdarg.h>
+#include <io/verify.h>
 
 extern size_t klog_write(const void *, size_t);
 extern void klog_update(void);
-extern int klog_printf(const char *, ...);
+extern int klog_printf(const char *, ...)
+    PRINTF_ATTRIBUTE(1, 2);
 extern int klog_vprintf(const char *, va_list);
 
Index: uspace/lib/c/include/io/log.h
===================================================================
--- uspace/lib/c/include/io/log.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/io/log.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,20 +36,46 @@
 
 #include <stdarg.h>
+#include <inttypes.h>
+#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;
 
-extern int log_init(const char *, log_level_t);
-extern void log_msg(log_level_t, const char *, ...);
-extern void log_msgv(log_level_t, const char *, va_list);
+/** Log itself (logging target). */
+typedef sysarg_t log_t;
+/** Formatting directive for printing log_t. */
+#define PRIlogctx PRIxn
+
+/** Default log (target). */
+#define LOG_DEFAULT ((log_t) -1)
+
+/** Use when creating new top-level log. */
+#define LOG_NO_PARENT ((log_t) 0)
+
+extern const char *log_level_str(log_level_t);
+extern int log_level_from_str(const char *, log_level_t *);
+
+extern int log_init(const char *);
+extern log_t log_create(const char *, log_t);
+
+extern void log_msg(log_t, log_level_t, const char *, ...)
+    PRINTF_ATTRIBUTE(3, 4);
+extern void log_msgv(log_t, log_level_t, const char *, va_list);
 
 #endif
Index: uspace/lib/c/include/io/logctl.h
===================================================================
--- uspace/lib/c/include/io/logctl.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/logctl.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011-2012 Vojtech Horky
+ * 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
+ * @{
+ */
+
+#ifndef LIBC_IO_LOGCTL_H_
+#define LIBC_IO_LOGCTL_H_
+
+#include <io/log.h>
+
+extern int logctl_set_default_level(log_level_t);
+extern int logctl_set_log_level(const char *, log_level_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/mode.h
===================================================================
--- uspace/lib/c/include/io/mode.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/mode.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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_MODE_H_
+#define LIBC_IO_MODE_H_
+
+#include <abi/fb/visuals.h>
+#include <sys/types.h>
+#include <adt/list.h>
+#include <io/pixel.h>
+#include <io/charfield.h>
+
+typedef struct {
+	sysarg_t width;
+	sysarg_t height;
+} aspect_ratio_t;
+
+typedef union {
+	visual_t pixel_visual;
+	char_attr_type_t field_visual;
+} cell_visual_t;
+
+typedef struct {
+	sysarg_t index;
+	sysarg_t version;
+	
+	sysarg_t refresh_rate;
+	aspect_ratio_t screen_aspect;
+	sysarg_t screen_width;
+	sysarg_t screen_height;
+	
+	aspect_ratio_t cell_aspect;
+	cell_visual_t cell_visual;
+} vslmode_t;
+
+typedef struct {
+	link_t link;
+	vslmode_t mode;
+} vslmode_list_element_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/output.h
===================================================================
--- uspace/lib/c/include/io/output.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/output.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IO_OUTPUT_H_
+#define LIBC_IO_OUTPUT_H_
+
+#include <ipc/output.h>
+#include <io/chargrid.h>
+#include <io/console.h>
+
+extern int output_yield(async_sess_t *);
+extern int output_claim(async_sess_t *);
+extern int output_get_dimensions(async_sess_t *, sysarg_t *, sysarg_t *);
+extern int output_get_caps(async_sess_t *, console_caps_t *);
+
+extern frontbuf_handle_t output_frontbuf_create(async_sess_t *, chargrid_t *);
+
+extern int output_cursor_update(async_sess_t *, frontbuf_handle_t);
+extern int output_set_style(async_sess_t *, console_style_t);
+
+extern int output_update(async_sess_t *, frontbuf_handle_t);
+extern int output_damage(async_sess_t *, frontbuf_handle_t,
+    sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/pixel.h
===================================================================
--- uspace/lib/c/include/io/pixel.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/pixel.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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_PIXEL_H_
+#define LIBC_IO_PIXEL_H_
+
+#include <sys/types.h>
+
+#define NARROW(channel, bits) \
+	((channel) >> (8 - (bits)))
+
+#define ALPHA(pixel)  ((pixel) >> 24)
+#define RED(pixel)    (((pixel) & 0x00ff0000) >> 16)
+#define GREEN(pixel)  (((pixel) & 0x0000ff00) >> 8)
+#define BLUE(pixel)   ((pixel) & 0x000000ff)
+
+#define PIXEL(a, r, g, b) \
+	((((a) & 0xff) << 24) | (((r) & 0xff) << 16) | \
+	(((g) & 0xff) << 8) | ((b) & 0xff))
+
+typedef uint32_t pixel_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/pixelmap.h
===================================================================
--- uspace/lib/c/include/io/pixelmap.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/pixelmap.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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_PIXELMAP_H_
+#define LIBC_IO_PIXELMAP_H_
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <io/pixel.h>
+
+typedef struct {
+	sysarg_t width;
+	sysarg_t height;
+	pixel_t *data;
+} pixelmap_t;
+
+static inline pixel_t *pixelmap_pixel_at(
+    pixelmap_t *pixelmap,
+    sysarg_t x,
+    sysarg_t y)
+{
+	size_t offset = y * pixelmap->width + x;
+	pixel_t *pixel = pixelmap->data + offset;
+	return pixel;
+}
+
+static inline void pixelmap_put_pixel(
+    pixelmap_t * pixelmap,
+    sysarg_t x,
+    sysarg_t y,
+    pixel_t pixel)
+{
+	pixel_t *target = pixelmap_pixel_at(pixelmap, x, y);
+	if (target != NULL) {
+		*target = pixel;
+	}
+}
+
+static inline pixel_t pixelmap_get_pixel(
+    pixelmap_t *pixelmap,
+    sysarg_t x,
+    sysarg_t y)
+{
+	pixel_t *source = pixelmap_pixel_at(pixelmap, x, y);
+	if (source != NULL) {
+		return *source;
+	} else {
+		return 0;
+	}
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/verify.h
===================================================================
--- uspace/lib/c/include/io/verify.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/verify.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IO_VERIFY_H_
+#define LIBC_IO_VERIFY_H_
+
+#ifndef NVERIFY_PRINTF
+
+#define PRINTF_ATTRIBUTE(start, end) \
+	__attribute__((format(gnu_printf, start, end)))
+
+#else /* NVERIFY_PRINTF */
+
+#define PRINTF_ATTRIBUTE(start, end)
+
+#endif /* NVERIFY_PRINTF */
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/visualizer.h
===================================================================
--- uspace/lib/c/include/io/visualizer.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/visualizer.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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_VISUALIZER_H_
+#define LIBC_IO_VISUALIZER_H_
+
+#include <sys/types.h>
+#include <async.h>
+#include <io/mode.h>
+
+extern int visualizer_claim(async_sess_t *, sysarg_t);
+extern int visualizer_yield(async_sess_t *);
+
+extern int visualizer_enumerate_modes(async_sess_t *, vslmode_t *, sysarg_t);
+extern int visualizer_get_default_mode(async_sess_t *, vslmode_t *);
+extern int visualizer_get_current_mode(async_sess_t *, vslmode_t *);
+extern int visualizer_get_mode(async_sess_t *, vslmode_t *, sysarg_t);
+extern int visualizer_set_mode(async_sess_t *, sysarg_t, sysarg_t, void *);
+
+extern int visualizer_update_damaged_region(async_sess_t *,
+    sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+
+extern int visualizer_suspend(async_sess_t *);
+extern int visualizer_wakeup(async_sess_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/window.h
===================================================================
--- uspace/lib/c/include/io/window.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/io/window.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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_WINDOW_H_
+#define LIBC_IO_WINDOW_H_
+
+#include <bool.h>
+#include <sys/types.h>
+#include <async.h>
+#include <loc.h>
+#include <io/console.h>
+
+typedef enum {
+	POS_UPDATE,
+	POS_PRESS,
+	POS_RELEASE
+} pos_event_type_t;
+
+typedef struct {
+	sysarg_t pos_id;
+	pos_event_type_t type;
+	sysarg_t btn_num;
+	sysarg_t hpos;
+	sysarg_t vpos;
+} pos_event_t;
+
+typedef struct {
+	sysarg_t object;
+	sysarg_t slot;
+	sysarg_t argument;
+} sig_event_t;
+
+typedef struct {
+	sysarg_t width;
+	sysarg_t height;
+} rsz_event_t;
+
+typedef enum {
+	ET_KEYBOARD_EVENT,
+	ET_POSITION_EVENT,
+	ET_SIGNAL_EVENT,
+	ET_WINDOW_RESIZE,
+	ET_WINDOW_REFRESH,
+	ET_WINDOW_DAMAGE,
+	ET_WINDOW_CLOSE
+} window_event_type_t;
+
+typedef union {
+	kbd_event_t kbd;
+	pos_event_t pos;
+	sig_event_t sig;
+	rsz_event_t rsz;
+} window_event_data_t;
+
+typedef struct {
+	link_t link;
+	window_event_type_t type;
+	window_event_data_t data;
+} 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 *);
+
+extern int win_get_event(async_sess_t *, window_event_t *);
+
+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_close(async_sess_t *);
+extern int win_close_request(async_sess_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ipc/console.h
===================================================================
--- uspace/lib/c/include/ipc/console.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/ipc/console.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -43,10 +43,10 @@
 	CONSOLE_GET_EVENT,
 	CONSOLE_GET_POS,
-	CONSOLE_GOTO,
+	CONSOLE_SET_POS,
 	CONSOLE_CLEAR,
 	CONSOLE_SET_STYLE,
 	CONSOLE_SET_COLOR,
 	CONSOLE_SET_RGB_COLOR,
-	CONSOLE_CURSOR_VISIBILITY
+	CONSOLE_SET_CURSOR_VISIBILITY
 } console_request_t;
 
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,4 +38,7 @@
 	/** Character device interface */
 	CHAR_DEV_IFACE,
+
+	/** Graphic device interface */
+	GRAPH_DEV_IFACE,
 	
 	/** Network interface controller interface */
@@ -51,4 +54,10 @@
 	/** Interface provided by USB HID devices. */
 	USBHID_DEV_IFACE,
+	/** Interface provided by Real Time Clock devices */
+	CLOCK_DEV_IFACE,
+	/** Interface provided by battery powered devices */
+	BATTERY_DEV_IFACE,
+	/** Interface provided by AHCI devices. */
+	AHCI_DEV_IFACE,
 
 	DEV_IFACE_MAX
Index: uspace/lib/c/include/ipc/graph.h
===================================================================
--- uspace/lib/c/include/ipc/graph.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/ipc/graph.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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_IPC_GRAPH_H_
+#define LIBC_IPC_GRAPH_H_
+
+#include <ipc/common.h>
+
+typedef enum {
+	VISUALIZER_CLAIM = IPC_FIRST_USER_METHOD,
+	VISUALIZER_YIELD,
+	
+	VISUALIZER_ENUMERATE_MODES,
+	VISUALIZER_GET_DEFAULT_MODE,
+	VISUALIZER_GET_CURRENT_MODE,
+	VISUALIZER_GET_MODE,
+	VISUALIZER_SET_MODE,
+	
+	VISUALIZER_UPDATE_DAMAGED_REGION,
+	
+	VISUALIZER_SUSPEND,
+	VISUALIZER_WAKE_UP,
+} visualizer_request_t;
+
+typedef enum {
+	VISUALIZER_MODE_CHANGE = IPC_FIRST_USER_METHOD,
+	VISUALIZER_DISCONNECT
+} visualizer_notif_t;
+
+typedef enum {
+	RENDERER_REQ_NONE = IPC_FIRST_USER_METHOD,
+	// TODO: similar interface as provides libsoftrend
+} renderer_request_t;
+
+typedef enum {
+	RENDERER_NOTIF_NONE = IPC_FIRST_USER_METHOD,
+	// TODO: similar interface as provides libsoftrend
+} renderer_notif_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ipc/input.h
===================================================================
--- uspace/lib/c/include/ipc/input.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/ipc/input.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -46,4 +46,5 @@
 	INPUT_EVENT_KEY = IPC_FIRST_USER_METHOD,
 	INPUT_EVENT_MOVE,
+	INPUT_EVENT_ABS_MOVE,
 	INPUT_EVENT_BUTTON
 } input_notif_t;
Index: uspace/lib/c/include/ipc/ipc.h
===================================================================
--- uspace/lib/c/include/ipc/ipc.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/ipc/ipc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,140 +47,4 @@
 
 typedef void (*ipc_async_callback_t)(void *, int, ipc_call_t *);
-
-/*
- * User-friendly wrappers for ipc_call_sync_fast() and ipc_call_sync_slow().
- * They are in the form ipc_call_sync_m_n(), where m denotes the number of
- * arguments of payload and n denotes number of return values. Whenever
- * possible, the fast version is used.
- */
-
-#define ipc_call_sync_0_0(phoneid, method) \
-	ipc_call_sync_fast((phoneid), (method), 0, 0, 0, 0, 0, 0, 0, 0)
-#define ipc_call_sync_0_1(phoneid, method, res1) \
-	ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), 0, 0, 0, 0)
-#define ipc_call_sync_0_2(phoneid, method, res1, res2) \
-	ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), 0, 0, 0)
-#define ipc_call_sync_0_3(phoneid, method, res1, res2, res3) \
-	ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
-	    0, 0)
-#define ipc_call_sync_0_4(phoneid, method, res1, res2, res3, res4) \
-	ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
-	    (res4), 0)
-#define ipc_call_sync_0_5(phoneid, method, res1, res2, res3, res4, res5) \
-	ipc_call_sync_fast((phoneid), (method), 0, 0, 0, (res1), (res2), (res3), \
-	    (res4), (res5))
-
-#define ipc_call_sync_1_0(phoneid, method, arg1) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, 0, 0, 0, 0, 0)
-#define ipc_call_sync_1_1(phoneid, method, arg1, res1) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), 0, 0, 0, 0)
-#define ipc_call_sync_1_2(phoneid, method, arg1, res1, res2) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), 0, \
-	    0, 0)
-#define ipc_call_sync_1_3(phoneid, method, arg1, res1, res2, res3) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
-	    (res3), 0, 0)
-#define ipc_call_sync_1_4(phoneid, method, arg1, res1, res2, res3, res4) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
-	    (res3), (res4), 0)
-#define ipc_call_sync_1_5(phoneid, method, arg1, res1, res2, res3, res4, \
-    res5) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), 0, 0, (res1), (res2), \
-	    (res3), (res4), (res5))
-
-#define ipc_call_sync_2_0(phoneid, method, arg1, arg2) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, 0, 0, 0, \
-	    0, 0)
-#define ipc_call_sync_2_1(phoneid, method, arg1, arg2, res1) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), 0, 0, \
-	    0, 0)
-#define ipc_call_sync_2_2(phoneid, method, arg1, arg2, res1, res2) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
-	    (res2), 0, 0, 0)
-#define ipc_call_sync_2_3(phoneid, method, arg1, arg2, res1, res2, res3) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
-	    (res2), (res3), 0, 0)
-#define ipc_call_sync_2_4(phoneid, method, arg1, arg2, res1, res2, res3, \
-    res4) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
-	    (res2), (res3), (res4), 0)
-#define ipc_call_sync_2_5(phoneid, method, arg1, arg2, res1, res2, res3, \
-    res4, res5)\
-	ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), 0, (res1), \
-	    (res2), (res3), (res4), (res5))
-
-#define ipc_call_sync_3_0(phoneid, method, arg1, arg2, arg3) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, 0, 0, \
-	    0, 0)
-#define ipc_call_sync_3_1(phoneid, method, arg1, arg2, arg3, res1) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
-	    0, 0, 0, 0)
-#define ipc_call_sync_3_2(phoneid, method, arg1, arg2, arg3, res1, res2) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), (res1), \
-	    (res2), 0, 0, 0)
-#define ipc_call_sync_3_3(phoneid, method, arg1, arg2, arg3, res1, res2, \
-    res3) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (res1), (res2), (res3), 0, 0)
-#define ipc_call_sync_3_4(phoneid, method, arg1, arg2, arg3, res1, res2, \
-    res3, res4) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (res1), (res2), (res3), (res4), 0)
-#define ipc_call_sync_3_5(phoneid, method, arg1, arg2, arg3, res1, res2, \
-    res3, res4, res5) \
-	ipc_call_sync_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (res1), (res2), (res3), (res4), (res5))
-
-#define ipc_call_sync_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
-	ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
-	    0, 0, 0, 0, 0)
-#define ipc_call_sync_4_1(phoneid, method, arg1, arg2, arg3, arg4, res1) \
-	ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
-	    (res1), 0, 0, 0, 0)
-#define ipc_call_sync_4_2(phoneid, method, arg1, arg2, arg3, arg4, res1, res2) \
-	ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), 0, \
-	    (res1), (res2), 0, 0, 0)
-#define ipc_call_sync_4_3(phoneid, method, arg1, arg2, arg3, arg4, res1, res2, \
-    res3) \
-	ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), 0, (res1), (res2), (res3), 0, 0)
-#define ipc_call_sync_4_4(phoneid, method, arg1, arg2, arg3, arg4, res1, res2, \
-    res3, res4) \
-	ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), 0, (res1), (res2), (res3), (res4), 0)
-#define ipc_call_sync_4_5(phoneid, method, arg1, arg2, arg3, arg4, res1, res2, \
-    res3, res4, res5) \
-	ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), 0, (res1), (res2), (res3), (res4), (res5))
-
-#define ipc_call_sync_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
-	ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), 0, 0, 0, 0, 0)
-#define ipc_call_sync_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1) \
-	ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (res1), 0, 0, 0, 0)
-#define ipc_call_sync_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1, \
-    res2) \
-	ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), (arg5), (res1), (res2), 0, 0, 0)
-#define ipc_call_sync_5_3(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1, \
-    res2, res3) \
-	ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), (arg5), (res1), (res2), (res3), 0, 0)
-#define ipc_call_sync_5_4(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1, \
-    res2, res3, res4) \
-	ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), (arg5), (res1), (res2), (res3), (res4), 0)
-#define ipc_call_sync_5_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, res1, \
-    res2, res3, res4, res5) \
-	ipc_call_sync_slow((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), (arg5), (res1), (res2), (res3), (res4), (res5))
-
-extern int ipc_call_sync_fast(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *);
-
-extern int ipc_call_sync_slow(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t, sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *,
-    sysarg_t *);
 
 extern ipc_callid_t ipc_wait_cycle(ipc_call_t *, sysarg_t, unsigned int);
@@ -254,10 +118,4 @@
     sysarg_t, sysarg_t, void *, ipc_async_callback_t, bool);
 
-extern int ipc_clone_establish(int);
-extern int ipc_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t, task_id_t *,
-    sysarg_t *);
-extern int ipc_connect_me_to(int, sysarg_t, sysarg_t, sysarg_t);
-extern int ipc_connect_me_to_blocking(int, sysarg_t, sysarg_t, sysarg_t);
-
 extern int ipc_hangup(int);
 
@@ -267,26 +125,4 @@
     sysarg_t, sysarg_t, sysarg_t, unsigned int);
 
-/*
- * User-friendly wrappers for ipc_share_in_start().
- */
-
-#define ipc_share_in_start_0_0(phoneid, size, dst) \
-	ipc_share_in_start((phoneid), (size), 0, NULL, (dst))
-#define ipc_share_in_start_0_1(phoneid, size, flags, dst) \
-	ipc_share_in_start((phoneid), (size), 0, (flags), (dst))
-#define ipc_share_in_start_1_0(phoneid, size, arg, dst) \
-	ipc_share_in_start((phoneid), (size), (arg), NULL, (dst))
-#define ipc_share_in_start_1_1(phoneid, size, arg, flags, dst) \
-	ipc_share_in_start((phoneid), (size), (arg), (flags), (dst))
-
-extern int ipc_share_in_start(int, size_t, sysarg_t, unsigned int *, void **);
-extern int ipc_share_in_finalize(ipc_callid_t, void *, unsigned int);
-extern int ipc_share_out_start(int, void *, unsigned int);
-extern int ipc_share_out_finalize(ipc_callid_t, void **);
-extern int ipc_data_read_start(int, void *, size_t);
-extern int ipc_data_read_finalize(ipc_callid_t, const void *, size_t);
-extern int ipc_data_write_start(int, const void *, size_t);
-extern int ipc_data_write_finalize(ipc_callid_t, void *, size_t);
-
 extern int ipc_connect_kbox(task_id_t);
 
Index: uspace/lib/c/include/ipc/logger.h
===================================================================
--- uspace/lib/c/include/ipc/logger.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/ipc/logger.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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
+ * @{
+ */
+
+#ifndef LIBC_IPC_LOGGER_H_
+#define LIBC_IPC_LOGGER_H_
+
+#include <ipc/common.h>
+
+typedef enum {
+	/** Set (global) default displayed logging level.
+	 *
+	 * Arguments: new log level.
+	 * Returns: error code
+	 */
+	LOGGER_CONTROL_SET_DEFAULT_LEVEL = IPC_FIRST_USER_METHOD,
+	/** Set displayed level for given log.
+	 *
+	 * Arguments: new log level.
+	 * Returns: error code
+	 * Followed by: string with full log name.
+	 */
+	LOGGER_CONTROL_SET_LOG_LEVEL
+} logger_control_request_t;
+
+typedef enum {
+	/** Create new log.
+	 *
+	 * Arguments: parent log id (0 for top-level log).
+	 * Returns: error code, log id
+	 * Followed by: string with log name.
+	 */
+	LOGGER_WRITER_CREATE_LOG = IPC_FIRST_USER_METHOD,
+	/** Write a message to a given log.
+	 *
+	 * Arguments: log id, message severity level (log_level_t)
+	 * Returns: error code
+	 * Followed by: string with the message.
+	 */
+	LOGGER_WRITER_MESSAGE
+} logger_writer_request_t;
+
+typedef enum {
+	/** Interface for controlling logger behavior. */
+	LOGGER_INTERFACE_CONTROL,
+	/** Interface for servers writing to the log. */
+	LOGGER_INTERFACE_WRITER
+} logger_interface_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ipc/mouseev.h
===================================================================
--- uspace/lib/c/include/ipc/mouseev.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/ipc/mouseev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,4 +47,5 @@
 typedef enum {
 	MOUSEEV_MOVE_EVENT = IPC_FIRST_USER_METHOD,
+	MOUSEEV_ABS_MOVE_EVENT,
 	MOUSEEV_BUTTON_EVENT
 } mouseev_notif_t;
Index: uspace/lib/c/include/ipc/output.h
===================================================================
--- uspace/lib/c/include/ipc/output.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/ipc/output.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012 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 libcipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IPC_OUTPUT_H_
+#define LIBC_IPC_OUTPUT_H_
+
+#include <ipc/common.h>
+
+typedef sysarg_t frontbuf_handle_t;
+
+typedef enum {
+	OUTPUT_YIELD = IPC_FIRST_USER_METHOD,
+	OUTPUT_CLAIM,
+	OUTPUT_GET_DIMENSIONS,
+	OUTPUT_GET_CAPS,
+	
+	OUTPUT_FRONTBUF_CREATE,
+	OUTPUT_FRONTBUF_DESTROY,
+	
+	OUTPUT_CURSOR_UPDATE,
+	OUTPUT_SET_STYLE,
+	OUTPUT_SET_COLOR,
+	OUTPUT_SET_RGB_COLOR,
+	
+	OUTPUT_UPDATE,
+	OUTPUT_DAMAGE
+} output_request_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/c/include/ipc/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/ipc/services.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -45,4 +45,5 @@
 	SERVICE_VFS        = FOURCC('v', 'f', 's', ' '),
 	SERVICE_LOC        = FOURCC('l', 'o', 'c', ' '),
+	SERVICE_LOGGER     = FOURCC('l', 'o', 'g', 'g'),
 	SERVICE_DEVMAN     = FOURCC('d', 'e', 'v', 'n'),
 	SERVICE_IRC        = FOURCC('i', 'r', 'c', ' '),
Index: uspace/lib/c/include/ipc/window.h
===================================================================
--- uspace/lib/c/include/ipc/window.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/c/include/ipc/window.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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_IPC_WINDOW_H_
+#define LIBC_IPC_WINDOW_H_
+
+#include <ipc/vfs.h>
+
+typedef enum {
+	WINDOW_REGISTER = IPC_FIRST_USER_METHOD,
+	WINDOW_GET_EVENT,
+	WINDOW_DAMAGE,
+	WINDOW_GRAB,
+	WINDOW_RESIZE,
+	WINDOW_CLOSE,
+	WINDOW_CLOSE_REQUEST
+} window_request_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/macros.h
===================================================================
--- uspace/lib/c/include/macros.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/macros.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,4 +38,6 @@
 #define min(a, b)  ((a) < (b) ? (a) : (b))
 #define max(a, b)  ((a) > (b) ? (a) : (b))
+#define abs(a)     ((a) >= 0 ? (a) : (-a))
+
 
 #define KiB2SIZE(kb)  ((kb) << 10)
@@ -52,4 +54,10 @@
 	    | ((((uint64_t) (up)) & 0xffffffff) << 32))
 
+#ifndef member_to_inst
+#define member_to_inst(ptr_member, type, member_identif) \
+	((type*) (((void*)(ptr_member)) - ((void*)&(((type*)0)->member_identif))))
+#endif
+
+
 #endif
 
Index: uspace/lib/c/include/stdio.h
===================================================================
--- uspace/lib/c/include/stdio.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/stdio.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -39,15 +39,5 @@
 #include <stdarg.h>
 #include <str.h>
-
-#ifndef NVERIFY_PRINTF
-
-#define PRINTF_ATTRIBUTE(start, end) \
-	__attribute__((format(gnu_printf, start, end)))
-
-#else /* NVERIFY_PRINTF */
-
-#define PRINTF_ATTRIBUTE(start, end)
-
-#endif /* NVERIFY_PRINTF */
+#include <io/verify.h>
 
 #define EOF  (-1)
Index: uspace/lib/c/include/str.h
===================================================================
--- uspace/lib/c/include/str.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/str.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -56,4 +56,5 @@
 
 extern wchar_t str_decode(const char *str, size_t *offset, size_t sz);
+extern wchar_t str_decode_reverse(const char *str, size_t *offset, size_t sz);
 extern int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t sz);
 
@@ -73,4 +74,7 @@
 extern size_t wstr_nlength(const wchar_t *str, size_t size);
 
+extern size_t chr_width(wchar_t ch);
+extern size_t str_width(const char *str);
+
 extern bool ascii_check(wchar_t ch);
 extern bool chr_check(wchar_t ch);
@@ -78,4 +82,6 @@
 extern int str_cmp(const char *s1, const char *s2);
 extern int str_lcmp(const char *s1, const char *s2, size_t max_len);
+
+extern bool str_test_prefix(const char *s, const char *p);
 
 extern void str_cpy(char *dest, size_t size, const char *src);
Index: uspace/lib/c/include/sys/time.h
===================================================================
--- uspace/lib/c/include/sys/time.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/sys/time.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -1,4 +1,6 @@
 /*
  * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2011 Petr Koupy
+ * Copyright (c) 2011 Jiri Zarevucky
  * All rights reserved.
  *
@@ -39,4 +41,5 @@
 
 #define DST_NONE 0
+#define ASCTIME_BUF_LEN 26
 
 typedef long time_t;
@@ -45,4 +48,16 @@
 typedef uint32_t useconds_t;
 typedef uint32_t mseconds_t;
+
+struct tm {
+	int tm_sec;         /* Seconds [0,60]. */
+	int tm_min;         /* Minutes [0,59]. */
+	int tm_hour;        /* Hour [0,23]. */
+	int tm_mday;        /* Day of month [1,31]. */
+	int tm_mon;         /* Month of year [0,11]. */
+	int tm_year;        /* Years since 1900. */
+	int tm_wday;        /* Day of week [0,6] (Sunday = 0). */
+	int tm_yday;        /* Day of year [0,365]. */
+	int tm_isdst;       /* Daylight Savings flag. */
+};
 
 struct timeval {
@@ -61,6 +76,17 @@
 extern int tv_gteq(struct timeval *tv1, struct timeval *tv2);
 extern int gettimeofday(struct timeval *tv, struct timezone *tz);
+extern int getuptime(struct timeval *tv);
 
 extern void udelay(useconds_t);
+
+extern time_t mktime(struct tm *tm);
+extern int time_utc2tm(const time_t time, struct tm *result);
+extern int time_utc2str(const time_t time, char *buf);
+extern void time_tm2str(const struct tm *timeptr, char *buf);
+extern int time_local2tm(const time_t time, struct tm *result);
+extern int time_local2str(const time_t time, char *buf);
+extern double difftime(time_t time1, time_t time0);
+extern size_t strftime(char *restrict s, size_t maxsize,
+    const char *restrict format, const struct tm *restrict tm);
 
 #endif
Index: uspace/lib/c/include/task.h
===================================================================
--- uspace/lib/c/include/task.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/c/include/task.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,4 +38,5 @@
 #include <sys/types.h>
 #include <abi/proc/task.h>
+#include <stdarg.h>
 
 typedef enum {
@@ -48,8 +49,8 @@
 extern int task_kill(task_id_t);
 
-extern task_id_t task_spawn(const char *, const char *const[], int *);
 extern int task_spawnv(task_id_t *, const char *path, const char *const []);
 extern int task_spawnvf(task_id_t *, const char *path, const char *const [],
     int *const []);
+extern int task_spawn(task_id_t *, const char *path, int, va_list ap);
 extern int task_spawnl(task_id_t *, const char *path, ...);
 
Index: uspace/lib/clui/tinput.c
===================================================================
--- uspace/lib/clui/tinput.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/clui/tinput.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -104,5 +104,7 @@
 static void tinput_display_tail(tinput_t *ti, size_t start, size_t pad)
 {
-	wchar_t dbuf[INPUT_MAX_SIZE + 1];
+	wchar_t *dbuf = malloc((INPUT_MAX_SIZE + 1) * sizeof(wchar_t));
+	if (!dbuf)
+		return;	
 	
 	size_t sa;
@@ -146,4 +148,6 @@
 	
 	console_flush(ti->console);
+
+	free(dbuf);
 }
 
@@ -595,11 +599,15 @@
 {
 	unsigned int i;
-	/* Determine the maximum length of the completion in chars */
-	size_t max_length = 0;
+	/* Determine the maximum width of the completion in chars */
+	size_t max_width = 0;
 	for (i = 0; i < cnum; i++)
-		max_length = max(max_length, str_length(compl[i]));
-	
-	unsigned int cols = max(1, (ti->con_cols + 1) / (max_length + 1));
-	unsigned int col_width = ti->con_cols / cols;
+		max_width = max(max_width, str_width(compl[i]));
+	
+	unsigned int cols = max(1, (ti->con_cols + 1) / (max_width + 1));
+	unsigned int padding = 0;
+	if ((cols * max_width) + (cols - 1) < ti->con_cols) {
+		padding = ti->con_cols - (cols * max_width) - (cols - 1);
+	}
+	unsigned int col_width = max_width + padding / cols;
 	unsigned int rows = cnum / cols + ((cnum % cols) != 0);
 	
@@ -607,24 +615,27 @@
 	
 	for (row = 0; row < rows; row++) {
-		bool wlc = false;
+		unsigned int display_col = 0;
 		for (col = 0; col < cols; col++) {
 			size_t compl_idx = col * rows + row;
 			if (compl_idx >= cnum)
 				break;
-			if (col)
+			if (col) {
 				printf(" ");
+				display_col++;
+			}
 			printf("%s", compl[compl_idx]);
-			size_t compl_len = str_length(compl[compl_idx]);
-			if (col == cols -1) {
-				wlc = (compl_len == max_length);
-			}
-			else {
-				for (i = compl_len; i < col_width; i++) {
+			size_t compl_width = str_width(compl[compl_idx]);
+			display_col += compl_width;
+			if (col < cols - 1) {
+				for (i = compl_width; i < col_width; i++) {
 					printf(" ");
+					display_col++;
 				}
 			}
 		}
-		if (!wlc) printf("\n");
-	}
+		if ((display_col % ti->con_cols) > 0)
+			printf("\n");
+	}
+	fflush(stdout);
 }
 
Index: uspace/lib/draw/Makefile
===================================================================
--- uspace/lib/draw/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2011 Petr Koupy
+# 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 = ../..
+LIBRARY = libdraw
+SLIBRARY = libdraw.so.0.0
+LSONAME = libdraw.so0
+EXTRA_CFLAGS += -I$(LIBSOFTREND_PREFIX)
+
+SOURCES = \
+	codec/tga.c \
+	cursor/embedded.c \
+	font/embedded.c \
+	gfx/font-8x16.c \
+	gfx/cursor-11x18.c \
+	drawctx.c \
+	cursor.c \
+	font.c \
+	path.c \
+	source.c \
+	surface.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/draw/codec/tga.c
===================================================================
--- uspace/lib/draw/codec/tga.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/codec/tga.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdlib.h>
+#include <byteorder.h>
+#include <align.h>
+#include <bool.h>
+#include <pixconv.h>
+#include "tga.h"
+
+typedef struct {
+	uint8_t id_length;
+	uint8_t cmap_type;
+	uint8_t img_type;
+	
+	uint16_t cmap_first_entry;
+	uint16_t cmap_entries;
+	uint8_t cmap_bpp;
+	
+	uint16_t startx;
+	uint16_t starty;
+	uint16_t width;
+	uint16_t height;
+	uint8_t img_bpp;
+	uint8_t img_descr;
+} __attribute__((packed)) tga_header_t;
+
+typedef enum {
+	CMAP_NOT_PRESENT = 0,
+	CMAP_PRESENT = 1,
+	CMAP_RESERVED_START = 2,
+	CMAP_PRIVATE_START = 128
+} cmap_type_t;
+
+typedef enum {
+	IMG_EMTPY = 0,
+	IMG_CMAP = 1,
+	IMG_BGRA = 2,
+	IMG_GRAY = 3,
+	IMG_CMAP_RLE = 9,
+	IMG_BGRA_RLE = 10,
+	IMG_GRAY_RLE = 11
+} img_type_t;
+
+typedef struct {
+	cmap_type_t cmap_type;
+	img_type_t img_type;
+	
+	uint16_t cmap_first_entry;
+	uint16_t cmap_entries;
+	uint8_t cmap_bpp;
+	
+	uint16_t startx;
+	uint16_t starty;
+	uint16_t width;
+	uint16_t height;
+	uint8_t img_bpp;
+	uint8_t img_alpha_bpp;
+	uint8_t img_alpha_dir;
+	
+	void *id_data;
+	size_t id_length;
+	
+	void *cmap_data;
+	size_t cmap_length;
+	
+	void *img_data;
+	size_t img_length;
+} tga_t;
+
+/** Decode Truevision TGA header
+ *
+ * @param[in]  data Memory representation of TGA.
+ * @param[in]  size Size of the representation (in bytes).
+ * @param[out] tga  Decoded TGA.
+ *
+ * @return True on succesful decoding.
+ * @return False on failure.
+ */
+static bool decode_tga_header(void *data, size_t size, tga_t *tga)
+{
+	/* Header sanity check */
+	if (size < sizeof(tga_header_t))
+		return false;
+	
+	tga_header_t *head = (tga_header_t *) data;
+	
+	/* Image ID field */
+	tga->id_data = data + sizeof(tga_header_t);
+	tga->id_length = head->id_length;
+	
+	if (size < sizeof(tga_header_t) + tga->id_length)
+		return false;
+	
+	/* Color map type */
+	tga->cmap_type = head->cmap_type;
+	
+	/* Image type */
+	tga->img_type = head->img_type;
+	
+	/* Color map specification */
+	tga->cmap_first_entry = uint16_t_le2host(head->cmap_first_entry);
+	tga->cmap_entries = uint16_t_le2host(head->cmap_entries);
+	tga->cmap_bpp = head->cmap_bpp;
+	tga->cmap_data = tga->id_data + tga->id_length;
+	tga->cmap_length = ALIGN_UP(tga->cmap_entries * tga->cmap_bpp, 8) >> 3;
+	
+	if (size < sizeof(tga_header_t) + tga->id_length +
+	    tga->cmap_length)
+		return false;
+	
+	/* Image specification */
+	tga->startx = uint16_t_le2host(head->startx);
+	tga->starty = uint16_t_le2host(head->starty);
+	tga->width = uint16_t_le2host(head->width);
+	tga->height = uint16_t_le2host(head->height);
+	tga->img_bpp = head->img_bpp;
+	tga->img_alpha_bpp = head->img_descr & 0x0f;
+	tga->img_alpha_dir = (head->img_descr & 0xf0) >> 4;
+	tga->img_data = tga->cmap_data + tga->cmap_length;
+	tga->img_length = ALIGN_UP(tga->width * tga->height * tga->img_bpp, 8) >> 3;
+	
+	if (size < sizeof(tga_header_t) + tga->id_length +
+	    tga->cmap_length + tga->img_length)
+		return false;
+	
+	return true;
+}
+
+/** Decode Truevision TGA format
+ *
+ * Decode Truevision TGA format and create a surface
+ * from it. The supported variants of TGA are currently
+ * limited to uncompressed 24 bit true-color images without
+ * alpha channel.
+ *
+ * @param[in] data  Memory representation of TGA.
+ * @param[in] size  Size of the representation (in bytes).
+ * @param[in] flags Surface creation flags.
+ *
+ * @return Newly allocated surface with the decoded content.
+ * @return NULL on error or unsupported format.
+ */
+surface_t *decode_tga(void *data, size_t size, surface_flags_t flags)
+{
+	tga_t tga;
+	if (!decode_tga_header(data, size, &tga))
+		return NULL;
+	
+	/*
+	 * Check for unsupported features.
+	 */
+	
+	switch (tga.cmap_type) {
+	case CMAP_NOT_PRESENT:
+		break;
+	default:
+		/* Unsupported */
+		return NULL;
+	}
+	
+	switch (tga.img_type) {
+	case IMG_BGRA:
+		if (tga.img_bpp != 24)
+			return NULL;
+		break;
+	case IMG_GRAY:
+		if (tga.img_bpp != 8)
+			return NULL;
+		break;
+	default:
+		/* Unsupported */
+		return NULL;
+	}
+	
+	if (tga.img_alpha_bpp != 0)
+		return NULL;
+	
+	sysarg_t twidth = tga.startx + tga.width;
+	sysarg_t theight = tga.starty + tga.height;
+	
+	surface_t *surface = surface_create(twidth, theight, NULL, flags);
+	if (surface == NULL)
+		return NULL;
+	
+	/*
+	 * TGA is encoded in a bottom-up manner, the true-color
+	 * variant is in BGR 8:8:8 encoding.
+	 */
+	
+	switch (tga.img_type) {
+	case IMG_BGRA:
+		for (sysarg_t y = tga.starty; y < theight; y++) {
+			for (sysarg_t x = tga.startx; x < twidth; x++) {
+				size_t offset =
+				    ((y - tga.starty) * tga.width + (x - tga.startx)) * 3;
+				
+				pixel_t pixel =
+				    bgr_888_2pixel(((uint8_t *) tga.img_data) + offset);
+				surface_put_pixel(surface, x, theight - y - 1, pixel);
+			}
+		}
+		break;
+	case IMG_GRAY:
+		for (sysarg_t y = tga.starty; y < theight; y++) {
+			for (sysarg_t x = tga.startx; x < twidth; x++) {
+				size_t offset =
+				    (y - tga.starty) * tga.width + (x - tga.startx);
+				
+				pixel_t pixel =
+				    gray_8_2pixel(((uint8_t *) tga.img_data) + offset);
+				surface_put_pixel(surface, x, theight - y - 1, pixel);
+			}
+		}
+		break;
+	default:
+		break;
+	}
+	
+	return surface;
+}
+
+/** Encode Truevision TGA format
+ *
+ * Encode Truevision TGA format into an array.
+ *
+ * @param[in]  surface Surface to be encoded into TGA.
+ * @param[out] pdata   Pointer to the resulting array.
+ * @param[out] psize   Pointer to the size of the resulting array.
+ *
+ * @return True on succesful encoding.
+ * @return False on failure.
+ */
+bool encode_tga(surface_t *surface, void **pdata, size_t *psize)
+{
+	// TODO
+	return false;
+}
+
+/** @}
+ */
Index: uspace/lib/draw/codec/tga.h
===================================================================
--- uspace/lib/draw/codec/tga.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/codec/tga.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef DRAW_CODEC_TGA_H_
+#define DRAW_CODEC_TGA_H_
+
+#include <sys/types.h>
+#include "../surface.h"
+
+extern surface_t *decode_tga(void *, size_t, surface_flags_t);
+extern bool encode_tga(surface_t *, void **, size_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/draw/cursor.c
===================================================================
--- uspace/lib/draw/cursor.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/cursor.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <malloc.h>
+
+#include "cursor.h"
+#include "cursor/embedded.h"
+
+void cursor_init(cursor_t *cursor, cursor_decoder_type_t decoder, char *path)
+{
+	switch (decoder) {
+	case CURSOR_DECODER_EMBEDDED:
+		cursor->decoder = &cd_embedded;
+		break;
+	default:
+		cursor->decoder = NULL;
+		break;
+	}
+
+	if (cursor->decoder) {
+		cursor->decoder->init(path, &cursor->state_count, &cursor->decoder_data);
+
+		if (cursor->state_count > 0) {
+			cursor->states = (surface_t **) malloc(sizeof(surface_t *) * cursor->state_count);
+		} else {
+			cursor->states = NULL;
+		}
+
+		if (cursor->states) {
+			for (size_t i = 0; i < cursor->state_count; ++i) {
+				cursor->states[i] = cursor->decoder->render(i);
+			}
+		} else {
+			cursor->state_count = 0;
+		}
+	} else {
+		cursor->state_count = 0;
+		cursor->states = NULL;
+	}
+}
+
+void cursor_release(cursor_t *cursor)
+{
+	if (cursor->states) {
+		for (size_t i = 0; i < cursor->state_count; ++i) {
+			if (cursor->states[i]) {
+				surface_destroy(cursor->states[i]);
+			}
+		}
+		free(cursor->states);
+	}
+
+	if (cursor->decoder) {
+		cursor->decoder->release(cursor->decoder_data);
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/draw/cursor.h
===================================================================
--- uspace/lib/draw/cursor.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/cursor.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef DRAW_CURSOR_H_
+#define DRAW_CURSOR_H_
+
+#include <sys/types.h>
+
+#include "surface.h"
+
+typedef enum {
+	CURSOR_DECODER_EMBEDDED
+} cursor_decoder_type_t;
+
+typedef struct {
+	void (*init)(char *, uint8_t *, void **);
+	surface_t *(*render)(uint8_t);
+	void (*release)(void *);
+} cursor_decoder_t;
+
+typedef struct cursor {
+	uint8_t state_count;
+	surface_t **states;
+	cursor_decoder_t *decoder;
+	void *decoder_data;
+} cursor_t;
+
+extern void cursor_init(cursor_t *, cursor_decoder_type_t, char *);
+extern void cursor_release(cursor_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/draw/cursor/embedded.c
===================================================================
--- uspace/lib/draw/cursor/embedded.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/cursor/embedded.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <assert.h>
+#include <sys/types.h>
+#include <malloc.h>
+
+#include "../gfx/cursor-11x18.h"
+#include "embedded.h"
+#include "../surface.h"
+
+static void cde_init(char *path, uint8_t *state_count, void **data)
+{
+	assert(state_count);
+	assert(data);
+
+	(*state_count) = 1;
+	(*data) = NULL;
+}
+
+static surface_t *cde_render(uint8_t state)
+{
+	if (state != 0) {
+		return NULL;
+	}
+
+	surface_t *surface = surface_create(CURSOR_WIDTH, CURSOR_HEIGHT, NULL, 0);
+
+	if (!surface) {
+		return NULL;
+	}
+	
+	for (unsigned int y = 0; y < CURSOR_HEIGHT; ++y) {
+		for (unsigned int x = 0; x < CURSOR_WIDTH; ++x) {
+			size_t offset = y * ((CURSOR_WIDTH - 1) / 8 + 1) + x / 8;
+			bool visible = cursor_mask[offset] & (1 << (x % 8));
+			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));
+		}
+	}
+
+	return surface;
+}
+
+static void cde_release(void *data)
+{
+	/* no-op */
+}
+
+cursor_decoder_t cd_embedded = {
+	.init = cde_init,
+	.render = cde_render,
+	.release = cde_release
+};
+
+/** @}
+ */
Index: uspace/lib/draw/cursor/embedded.h
===================================================================
--- uspace/lib/draw/cursor/embedded.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/cursor/embedded.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef DRAW_CURSOR_EMBEDDED_H_
+#define DRAW_CURSOR_EMBEDDED_H_
+
+#include "../cursor.h"
+
+extern cursor_decoder_t cd_embedded;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/draw/drawctx.c
===================================================================
--- uspace/lib/draw/drawctx.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/drawctx.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <assert.h>
+#include <adt/list.h>
+#include <malloc.h>
+
+#include "drawctx.h"
+
+void drawctx_init(drawctx_t *context, surface_t *surface)
+{
+	assert(surface);
+	list_initialize(&context->list);
+	context->surface = surface;
+	context->compose = compose_src;
+	context->mask = NULL;
+	context->source = NULL;
+	context->shall_clip = false;
+	context->clip_x = 0;
+	context->clip_y = 0;
+	surface_get_resolution(surface, &context->clip_width, &context->clip_height);
+}
+
+void drawctx_save(drawctx_t *context)
+{
+	drawctx_t *to_save = (drawctx_t *) malloc(sizeof(drawctx_t));
+	if (to_save) {
+		link_initialize(&to_save->link);
+		to_save->compose = context->compose;
+		to_save->mask = context->mask;
+		to_save->source = context->source;
+		to_save->shall_clip = context->shall_clip;
+		to_save->clip_x = context->clip_x;
+		to_save->clip_y = context->clip_y;
+		to_save->clip_width = context->clip_width;
+		to_save->clip_height = context->clip_height;
+		list_append(&to_save->link, &context->list);
+	}
+}
+
+void drawctx_restore(drawctx_t *context)
+{
+	drawctx_t *to_load = (drawctx_t *) list_last(&context->list);
+	if (to_load) {
+		list_remove(&to_load->link);
+		context->compose = to_load->compose;
+		context->mask = to_load->mask;
+		context->source = to_load->source;
+		context->shall_clip = to_load->shall_clip;
+		context->clip_x = to_load->clip_x;
+		context->clip_y = to_load->clip_y;
+		context->clip_width = to_load->clip_width;
+		context->clip_height = to_load->clip_height;
+		free(to_load);
+	}
+}
+
+void drawctx_set_compose(drawctx_t *context, compose_t compose)
+{
+	context->compose = compose;
+}
+
+void drawctx_set_clip(drawctx_t *context,
+    sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height)
+{
+	surface_get_resolution(context->surface,
+	    &context->clip_width, &context->clip_height);
+	context->shall_clip = (x > 0) || (y > 0) ||
+	    (width < context->clip_width) || (height < context->clip_height);
+
+	context->clip_x = x;
+	context->clip_y = y;
+	context->clip_width = width;
+	context->clip_height = height;
+}
+
+void drawctx_set_mask(drawctx_t *context, surface_t *mask)
+{
+	context->mask = mask;
+}
+
+void drawctx_set_source(drawctx_t *context, source_t *source)
+{
+	context->source = source;
+}
+
+void drawctx_set_font(drawctx_t *context, font_t *font)
+{
+	context->font = font;
+}
+
+void drawctx_transfer(drawctx_t *context,
+    sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height)
+{
+	if (!context->source) {
+		return;
+	}
+
+	bool clipped = false;
+	bool masked = false;
+
+	for (sysarg_t _y = y; _y < y + height; ++_y) {
+		for (sysarg_t _x = x; _x < x + width; ++_x) {
+			if (context->shall_clip) {
+				clipped = _x < context->clip_x && _x >= context->clip_width
+				    && _y < context->clip_y && _y >= context->clip_height;
+			}
+			
+			if (context->mask) {
+				pixel_t p = surface_get_pixel(context->mask, _x, _y);
+				masked = p > 0 ? false : true;
+			}
+
+			if (!clipped && !masked) {
+				pixel_t p_src = source_determine_pixel(context->source, _x, _y);
+				pixel_t p_dst = surface_get_pixel(context->surface, _x, _y);
+				pixel_t p_res = context->compose(p_src, p_dst);
+				surface_put_pixel(context->surface, _x, _y, p_res);
+			}
+		}
+	}
+}
+
+void drawctx_stroke(drawctx_t *context, path_t *path)
+{
+	if (!context->source || !path) {
+		return;
+	}
+
+	/* Note:
+	 * Antialiasing could be achieved by up-scaling path coordinates and
+	 * rendering into temporary higher-resolution surface. Then, the temporary
+	 * surface would be set as a source and its damaged region would be
+	 * transferred to the original surface. */
+
+	list_foreach(*((list_t *) path), link) {
+		path_step_t *step = (path_step_t *) link;
+		switch (step->type) {
+		case PATH_STEP_MOVETO:
+			// TODO
+			break;
+		case PATH_STEP_LINETO:
+			// TODO
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+void drawctx_fill(drawctx_t *context, path_t *path)
+{
+	if (!context->source || !path) {
+		return;
+	}
+
+	// TODO
+}
+
+void drawctx_print(drawctx_t *context, const char *text, sysarg_t x, sysarg_t y)
+{
+	if (context->font && context->source) {
+		font_draw_text(context->font, context, context->source, text, x, y);
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/draw/drawctx.h
===================================================================
--- uspace/lib/draw/drawctx.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/drawctx.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef DRAW_DRAWCTX_H_
+#define DRAW_DRAWCTX_H_
+
+#include <sys/types.h>
+#include <bool.h>
+
+#include <compose.h>
+
+#include "surface.h"
+#include "source.h"
+#include "path.h"
+#include "font.h"
+
+typedef struct drawctx {
+	link_t link;
+	list_t list;
+
+	surface_t *surface;
+	compose_t compose;
+	surface_t *mask;
+	source_t *source;
+	font_t *font;
+
+	bool shall_clip;
+	sysarg_t clip_x;
+	sysarg_t clip_y;
+	sysarg_t clip_width;
+	sysarg_t clip_height;
+} drawctx_t;
+
+extern void drawctx_init(drawctx_t *, surface_t *);
+
+extern void drawctx_save(drawctx_t *);
+extern void drawctx_restore(drawctx_t *);
+
+extern void drawctx_set_compose(drawctx_t *, compose_t);
+extern void drawctx_set_clip(drawctx_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+extern void drawctx_set_mask(drawctx_t *, surface_t *);
+extern void drawctx_set_source(drawctx_t *, source_t *);
+extern void drawctx_set_font(drawctx_t *, font_t *);
+
+extern void drawctx_transfer(drawctx_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+extern void drawctx_stroke(drawctx_t *, path_t *);
+extern void drawctx_fill(drawctx_t *, path_t *);
+extern void drawctx_print(drawctx_t *, const char *, sysarg_t, sysarg_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/draw/font.c
===================================================================
--- uspace/lib/draw/font.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/font.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <assert.h>
+#include <malloc.h>
+
+#include "font.h"
+#include "font/embedded.h"
+#include "drawctx.h"
+
+void font_init(font_t *font, font_decoder_type_t decoder, char *path, uint16_t points)
+{
+	font->points = points;
+
+	switch (decoder) {
+	case FONT_DECODER_EMBEDDED:
+		font->decoder = &fd_embedded;
+		break;
+	default:
+		font->decoder = NULL;
+		break;
+	}
+
+	if (font->decoder) {
+		font->decoder->init(path, &font->glyph_count, &font->decoder_data);
+
+		if (font->glyph_count > 0) {
+			font->glyphs = (surface_t **) malloc(sizeof(surface_t *) * font->glyph_count);
+		} else {
+			font->glyphs = NULL;
+		}
+
+		if (font->glyphs) {
+			for (size_t i = 0; i < font->glyph_count; ++i) {
+				font->glyphs[i] = NULL;
+			}
+		} else {
+			font->glyph_count = 0;
+		}
+	} else {
+		font->glyph_count = 0;
+		font->glyphs = NULL;
+		font->decoder_data = NULL;
+	}
+}
+
+void font_release(font_t *font)
+{
+	if (font->glyphs) {
+		for (size_t i = 0; i < font->glyph_count; ++i) {
+			if (font->glyphs[i]) {
+				surface_destroy(font->glyphs[i]);
+			}
+		}
+		free(font->glyphs);
+	}
+	
+	if (font->decoder) {
+		font->decoder->release(font->decoder_data);
+	}
+}
+
+void font_get_box(font_t *font, char *text, sysarg_t *width, sysarg_t *height)
+{
+	assert(width);
+	assert(height);
+
+	(*width) = 0;
+	(*height) = 0;
+
+	if (!text) {
+		return;
+	}
+
+	while (*text) {
+		uint16_t glyph_idx = font->decoder->resolve(*text, font->decoder_data);
+		if (glyph_idx < font->glyph_count) {
+			if (!font->glyphs[glyph_idx]) {
+				font->glyphs[glyph_idx] =
+				    font->decoder->render(glyph_idx, font->points);
+			}
+
+			surface_t *glyph = font->glyphs[glyph_idx];
+			if (glyph) {
+				sysarg_t w;
+				sysarg_t h;
+				surface_get_resolution(glyph, &w, &h);
+				(*width) += w;
+				(*height) = (*height) < h ? h : (*height);
+			}
+		}
+		++text;
+	}
+}
+
+void font_draw_text(font_t *font, drawctx_t *context, source_t *source,
+    const char *text, sysarg_t x, sysarg_t y)
+{
+	assert(context);
+	assert(source);
+
+	drawctx_save(context);
+	drawctx_set_compose(context, compose_over);
+
+	while (*text) {
+		uint16_t glyph_idx = font->decoder->resolve(*text, font->decoder_data);
+		if (glyph_idx < font->glyph_count) {
+			if (!font->glyphs[glyph_idx]) {
+				font->glyphs[glyph_idx] =
+				    font->decoder->render(glyph_idx, font->points);
+			}
+
+			surface_t *glyph = font->glyphs[glyph_idx];
+			if (glyph) {
+				sysarg_t w;
+				sysarg_t h;
+				surface_get_resolution(glyph, &w, &h);
+
+				transform_t transform;
+				transform_identity(&transform);
+				transform_translate(&transform, x, y);
+				source_set_transform(source, transform);
+				source_set_mask(source, glyph, false);
+				drawctx_transfer(context, x, y, w, h);
+
+				x += w;
+			}
+		}
+		++text;
+	}
+
+	drawctx_restore(context);
+	source_set_mask(source, NULL, false);
+}
+
+/** @}
+ */
Index: uspace/lib/draw/font.h
===================================================================
--- uspace/lib/draw/font.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/font.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef DRAW_FONT_H_
+#define DRAW_FONT_H_
+
+#include <sys/types.h>
+
+#include "surface.h"
+#include "source.h"
+
+struct drawctx;
+typedef struct drawctx drawctx_t;
+
+typedef enum {
+	FONT_DECODER_EMBEDDED
+} font_decoder_type_t;
+
+typedef struct {
+	void (*init)(char *, uint16_t *, void **);
+	uint16_t (*resolve)(const wchar_t, void *);
+	surface_t *(*render)(uint16_t, uint16_t);
+	void (*release)(void *);
+} font_decoder_t;
+
+typedef struct font {
+	uint16_t points;
+	uint16_t glyph_count;
+	surface_t **glyphs;
+	font_decoder_t *decoder;
+	void *decoder_data;
+} font_t;
+
+extern void font_init(font_t *, font_decoder_type_t, char *, uint16_t);
+extern void font_release(font_t *);
+
+extern void font_get_box(font_t *, char *, sysarg_t *, sysarg_t *);
+extern void font_draw_text(font_t *, drawctx_t *, source_t *, const char *,
+    sysarg_t, sysarg_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/draw/font/embedded.c
===================================================================
--- uspace/lib/draw/font/embedded.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/font/embedded.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <assert.h>
+#include <sys/types.h>
+#include <malloc.h>
+
+#include "../gfx/font-8x16.h"
+#include "embedded.h"
+#include "../drawctx.h"
+
+static void fde_init(char *path, uint16_t *glyph_count, void **data)
+{
+	assert(glyph_count);
+	assert(data);
+
+	(*glyph_count) = FONT_GLYPHS;
+	(*data) = NULL;
+}
+
+static uint16_t fde_resolve(const wchar_t chr, void *data)
+{
+	return fb_font_glyph(chr);
+}
+
+static surface_t *fde_render(uint16_t glyph, uint16_t points)
+{
+	surface_t *template = surface_create(FONT_WIDTH, FONT_SCANLINES, NULL, 0);
+	if (!template) {
+		return NULL;
+	}
+	for (unsigned int y = 0; y < FONT_SCANLINES; ++y) {
+		for (unsigned int x = 0; x < FONT_WIDTH; ++x) {
+			pixel_t p = (fb_font[glyph][y] & (1 << (7 - x))) ? 
+			    PIXEL(255, 0, 0, 0) : PIXEL(0, 0, 0, 0);
+			surface_put_pixel(template, x, y, p);
+		}
+	}
+
+	source_t source;
+	source_init(&source);
+	source_set_texture(&source, template, false);
+
+	transform_t transform;
+	transform_identity(&transform);
+	if (points != FONT_SCANLINES) {
+		double ratio = ((double) points) / ((double) FONT_SCANLINES);
+		transform_scale(&transform, ratio, ratio);
+		source_set_transform(&source, transform);
+	}
+
+	double width = FONT_WIDTH;
+	double height = FONT_SCANLINES;
+	transform_apply_linear(&transform, &width, &height);
+	surface_t *result =
+	    surface_create((sysarg_t) (width + 0.5), (sysarg_t) (height + 0.5), NULL, 0);
+	if (!result) {
+		surface_destroy(template);
+		return NULL;
+	}
+
+	drawctx_t context;
+	drawctx_init(&context, result);
+	drawctx_set_source(&context, &source);
+	drawctx_transfer(&context, 0, 0,
+	    (sysarg_t) (width + 0.5), (sysarg_t) (height + 0.5));
+
+	surface_destroy(template);
+
+	return result;
+}
+
+static void fde_release(void *data)
+{
+	/* no-op */
+}
+
+font_decoder_t fd_embedded = {
+	.init = fde_init,
+	.resolve = fde_resolve,
+	.render = fde_render,
+	.release = fde_release
+};
+
+/** @}
+ */
Index: uspace/lib/draw/font/embedded.h
===================================================================
--- uspace/lib/draw/font/embedded.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/font/embedded.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef DRAW_FONT_EMBEDDED_H_
+#define DRAW_FONT_EMBEDDED_H_
+
+#include "../font.h"
+
+extern font_decoder_t fd_embedded;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/draw/gfx/cursor-11x18.c
===================================================================
--- uspace/lib/draw/gfx/cursor-11x18.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/gfx/cursor-11x18.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2008 Martin Decky
+ * Copyright (c) 2012 Petr Koupy
+ * 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
+ */
+
+#include "cursor-11x18.h"
+
+uint8_t cursor_texture[] = {
+	0x01, 0x00, 0x03, 0x00, 0x05, 0x00, 0x09, 0x00, 0x11, 0x00, 0x21, 0x00,
+	0x41, 0x00, 0x81, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x04, 0x01, 0x03,
+	0x81, 0x00, 0x89, 0x00, 0x15, 0x01, 0x23, 0x01, 0x21, 0x01, 0xc0, 0x00
+};
+
+uint8_t cursor_mask[] = {
+	0x01, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x3f, 0x00,
+	0x7f, 0x00, 0xff, 0x00, 0xff, 0x01, 0xff, 0x03, 0xff, 0x07, 0xff, 0x03,
+	0xff, 0x00, 0xff, 0x00, 0xf7, 0x01, 0xe3, 0x01, 0xe1, 0x01, 0xc0, 0x00
+};
+
+/** @}
+ */
Index: uspace/lib/draw/gfx/cursor-11x18.h
===================================================================
--- uspace/lib/draw/gfx/cursor-11x18.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/gfx/cursor-11x18.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2008 Martin Decky
+ * Copyright (c) 2012 Petr Koupy
+ * 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
+ */
+
+#ifndef CURSOR_11X18_H_
+#define CURSOR_11X18_H_
+
+#include <sys/types.h>
+
+#define CURSOR_WIDTH   11
+#define CURSOR_HEIGHT  18
+
+extern uint8_t cursor_texture[];
+extern uint8_t cursor_mask[];
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/draw/gfx/font-8x16.c
===================================================================
--- uspace/lib/draw/gfx/font-8x16.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/gfx/font-8x16.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,3272 @@
+/*
+ * Copyright (c) 2000 Dmitry Bolkhovityanov
+ * Copyright (c) 2009 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 genarch
+ * @{
+ */
+/** @file
+ */
+
+#include <sys/types.h>
+#include "font-8x16.h"
+
+/** Convert character to font glyph index
+ *
+ * The font does not cover all Unicode characters.
+ * This function converts the character to an appropriate
+ * glyph in the font or returns an index to the question
+ * mark glyph if no specific glyph exists.
+ *
+ */
+uint16_t fb_font_glyph(const wchar_t ch)
+{
+	if (ch == 0x0000)
+		return 0;
+	
+	if ((ch >= 0x0020) && (ch <= 0x007f))
+		return (ch - 32);
+	
+	if ((ch >= 0x00a0) && (ch <= 0x021f))
+		return (ch - 64);
+	
+	if ((ch >= 0x0222) && (ch <= 0x0233))
+		return (ch - 66);
+	
+	if ((ch >= 0x0250) && (ch <= 0x02ad))
+		return (ch - 94);
+	
+	if ((ch >= 0x02b0) && (ch <= 0x02cf))
+		return (ch - 96);
+	
+	if ((ch >= 0x02d8) && (ch <= 0x02dd))
+		return (ch - 104);
+	
+	if (ch == 0x02ee)
+		return 630;
+	
+	if ((ch >= 0x0300) && (ch <= 0x0301))
+		return (ch - 137);
+	
+	if (ch == 0x0303)
+		return 633;
+	
+	if (ch == 0x0309)
+		return 634;
+	
+	if ((ch >= 0x0312) && (ch <= 0x0314))
+		return (ch - 151);
+	
+	if (ch == 0x0323)
+		return 638;
+	
+	if ((ch >= 0x0340) && (ch <= 0x0341))
+		return (ch - 193);
+	
+	if ((ch >= 0x0374) && (ch <= 0x0375))
+		return (ch - 243);
+	
+	if (ch == 0x037a)
+		return 643;
+	
+	if (ch == 0x037e)
+		return 644;
+	
+	if ((ch >= 0x0384) && (ch <= 0x038a))
+		return (ch - 255);
+	
+	if (ch == 0x038c)
+		return 652;
+	
+	if ((ch >= 0x038e) && (ch <= 0x03a1))
+		return (ch - 257);
+	
+	if ((ch >= 0x03a3) && (ch <= 0x03ce))
+		return (ch - 258);
+	
+	if ((ch >= 0x03d0) && (ch <= 0x03d7))
+		return (ch - 259);
+	
+	if ((ch >= 0x03da) && (ch <= 0x03f3))
+		return (ch - 261);
+	
+	if ((ch >= 0x0400) && (ch <= 0x0486))
+		return (ch - 273);
+	
+	if ((ch >= 0x0488) && (ch <= 0x04ce))
+		return (ch - 274);
+	
+	if ((ch >= 0x04d0) && (ch <= 0x04f5))
+		return (ch - 275);
+	
+	if ((ch >= 0x04f8) && (ch <= 0x04f9))
+		return (ch - 277);
+	
+	if ((ch >= 0x0500) && (ch <= 0x050f))
+		return (ch - 283);
+	
+	if ((ch >= 0x0530) && (ch <= 0x0556))
+		return (ch - 315);
+	
+	if ((ch >= 0x0559) && (ch <= 0x055f))
+		return (ch - 317);
+	
+	if ((ch >= 0x0561) && (ch <= 0x0587))
+		return (ch - 318);
+	
+	if ((ch >= 0x0589) && (ch <= 0x058a))
+		return (ch - 319);
+	
+	if ((ch >= 0x0591) && (ch <= 0x05a1))
+		return (ch - 325);
+	
+	if ((ch >= 0x05a3) && (ch <= 0x05b9))
+		return (ch - 326);
+	
+	if ((ch >= 0x05bb) && (ch <= 0x05c4))
+		return (ch - 327);
+	
+	if ((ch >= 0x05d0) && (ch <= 0x05ea))
+		return (ch - 338);
+	
+	if ((ch >= 0x05f0) && (ch <= 0x05f4))
+		return (ch - 343);
+	
+	if (ch == 0x060c)
+		return 1182;
+	
+	if (ch == 0x061b)
+		return 1183;
+	
+	if (ch == 0x061f)
+		return 1184;
+	
+	if ((ch >= 0x0621) && (ch <= 0x063a))
+		return (ch - 384);
+	
+	if ((ch >= 0x0640) && (ch <= 0x0655))
+		return (ch - 389);
+	
+	if ((ch >= 0x0660) && (ch <= 0x066d))
+		return (ch - 399);
+	
+	if ((ch >= 0x0670) && (ch <= 0x06ed))
+		return (ch - 401);
+	
+	if ((ch >= 0x06f0) && (ch <= 0x06fe))
+		return (ch - 403);
+	
+	if (ch == 0x10d3)
+		return 1388;
+	
+	if (ch == 0x10d7)
+		return 1389;
+	
+	if (ch == 0x10da)
+		return 1390;
+	
+	if (ch == 0x10dd)
+		return 1391;
+	
+	if (ch == 0x10e6)
+		return 1392;
+	
+	if ((ch >= 0x1e00) && (ch <= 0x1e9b))
+		return (ch - 6287);
+	
+	if ((ch >= 0x1ea0) && (ch <= 0x1ef9))
+		return (ch - 6291);
+	
+	if ((ch >= 0x1f00) && (ch <= 0x1f07))
+		return (ch - 6297);
+	
+	if ((ch >= 0x2000) && (ch <= 0x2027))
+		return (ch - 6545);
+	
+	if ((ch >= 0x2030) && (ch <= 0x2046))
+		return (ch - 6553);
+	
+	if ((ch >= 0x2048) && (ch <= 0x204d))
+		return (ch - 6554);
+	
+	if (ch == 0x2070)
+		return 1716;
+	
+	if ((ch >= 0x2074) && (ch <= 0x208f))
+		return (ch - 6591);
+	
+	if ((ch >= 0x20a0) && (ch <= 0x20af))
+		return (ch - 6607);
+	
+	if ((ch >= 0x2100) && (ch <= 0x213a))
+		return (ch - 6687);
+	
+	if ((ch >= 0x2153) && (ch <= 0x2183))
+		return (ch - 6711);
+	
+	if ((ch >= 0x2190) && (ch <= 0x21f3))
+		return (ch - 6723);
+	
+	if ((ch >= 0x2200) && (ch <= 0x22f1))
+		return (ch - 6735);
+	
+	if (ch == 0x2300)
+		return 2211;
+	
+	if (ch == 0x2302)
+		return 2212;
+	
+	if ((ch >= 0x2308) && (ch <= 0x230b))
+		return (ch - 6755);
+	
+	if (ch == 0x2310)
+		return 2217;
+	
+	if (ch == 0x2318)
+		return 2218;
+	
+	if ((ch >= 0x231a) && (ch <= 0x231b))
+		return (ch - 6767);
+	
+	if ((ch >= 0x2320) && (ch <= 0x2321))
+		return (ch - 6771);
+	
+	if ((ch >= 0x2329) && (ch <= 0x232a))
+		return (ch - 6778);
+	
+	if ((ch >= 0x239b) && (ch <= 0x23bd))
+		return (ch - 6890);
+	
+	if (ch == 0x23ce)
+		return 2260;
+	
+	if ((ch >= 0x2409) && (ch <= 0x240d))
+		return (ch - 6964);
+	
+	if ((ch >= 0x2423) && (ch <= 0x2424))
+		return (ch - 6985);
+	
+	if (ch == 0x2426)
+		return 2268;
+	
+	if ((ch >= 0x2500) && (ch <= 0x2595))
+		return (ch - 7203);
+	
+	if ((ch >= 0x25a0) && (ch <= 0x25f7))
+		return (ch - 7213);
+	
+	if ((ch >= 0x2600) && (ch <= 0x2602))
+		return (ch - 7221);
+	
+	if ((ch >= 0x2605) && (ch <= 0x260d))
+		return (ch - 7223);
+	
+	if ((ch >= 0x2610) && (ch <= 0x2613))
+		return (ch - 7225);
+	
+	if (ch == 0x2620)
+		return 2523;
+	
+	if (ch == 0x2622)
+		return 2524;
+	
+	if (ch == 0x2626)
+		return 2525;
+	
+	if ((ch >= 0x2628) && (ch <= 0x262b))
+		return (ch - 7242);
+	
+	if ((ch >= 0x262e) && (ch <= 0x2637))
+		return (ch - 7244);
+	
+	if ((ch >= 0x2639) && (ch <= 0x2653))
+		return (ch - 7245);
+	
+	if ((ch >= 0x2660) && (ch <= 0x2667))
+		return (ch - 7257);
+	
+	if ((ch >= 0x2669) && (ch <= 0x266f))
+		return (ch - 7258);
+	
+	if ((ch >= 0xfb00) && (ch <= 0xfb05))
+		return (ch - 61674);
+	
+	if ((ch >= 0xfb50) && (ch <= 0xfbb1))
+		return (ch - 61748);
+	
+	if ((ch >= 0xfbd3) && (ch <= 0xfbe9))
+		return (ch - 61781);
+	
+	if ((ch >= 0xfbfc) && (ch <= 0xfbff))
+		return (ch - 61799);
+	
+	if ((ch >= 0xfc5b) && (ch <= 0xfc63))
+		return (ch - 61890);
+	
+	if (ch == 0xfc90)
+		return 2722;
+	
+	if ((ch >= 0xfcf2) && (ch <= 0xfcf4))
+		return (ch - 62031);
+	
+	if ((ch >= 0xfd3c) && (ch <= 0xfd3f))
+		return (ch - 62102);
+	
+	if (ch == 0xfdf2)
+		return 2730;
+	
+	if ((ch >= 0xfe50) && (ch <= 0xfe52))
+		return (ch - 62373);
+	
+	if ((ch >= 0xfe54) && (ch <= 0xfe66))
+		return (ch - 62374);
+	
+	if ((ch >= 0xfe68) && (ch <= 0xfe6b))
+		return (ch - 62375);
+	
+	if ((ch >= 0xfe70) && (ch <= 0xfe72))
+		return (ch - 62379);
+	
+	if (ch == 0xfe74)
+		return 2760;
+	
+	if ((ch >= 0xfe76) && (ch <= 0xfefc))
+		return (ch - 62381);
+	
+	if (ch == 0xfeff)
+		return 2896;
+	
+	return 2898;
+}
+
+uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES] = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x30, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00},
+	{0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x99, 0xa5, 0xa1, 0xa1, 0xa5, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x44, 0xba, 0xb2, 0xaa, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd8, 0x30, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf6, 0xc0, 0xc0, 0xc0, 0x00},
+	{0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00},
+	{0x00, 0xe0, 0x30, 0x62, 0x36, 0xec, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x0c, 0x38, 0x00},
+	{0x30, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x18, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x3c, 0x42, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7a, 0xc4, 0xce, 0xce, 0xd6, 0xd6, 0xe6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x66, 0x66, 0xec, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0x1c, 0x3c, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xc4, 0xce, 0xd6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x7c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x0c, 0x18, 0x0e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x0c, 0x18, 0x0e, 0x00},
+	{0x0c, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x3e, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x18, 0x30, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x6c, 0x38, 0x10, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x6c, 0x38, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x18, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x18, 0x30, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x10, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0xff, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0xf8, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7e, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7e, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x3c, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x3c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x30, 0x1c, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x30, 0x1c, 0x00},
+	{0x18, 0x18, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf7, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7b, 0x7b, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x00, 0xee, 0x66, 0x66, 0x66, 0x66, 0x66, 0xf6, 0x06, 0x66, 0x3c, 0x00},
+	{0x08, 0x1c, 0x22, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x04, 0x0e, 0x1b, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x30, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x30},
+	{0x6c, 0x38, 0x10, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x66, 0x66, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0x30, 0x30, 0x30, 0x36, 0x36, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x78, 0xe0, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x1e, 0x78, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x18, 0x18, 0x30},
+	{0x6c, 0x38, 0x10, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x60, 0x60, 0xc0, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0xcc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0xcc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6e, 0xd8, 0xd8, 0xd8, 0xde, 0xd8, 0xd8, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xd6, 0xd6, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x18, 0x18, 0x30},
+	{0x6c, 0x38, 0x10, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x6c, 0x38, 0x10, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x18, 0x0c, 0x38, 0x00},
+	{0x6c, 0x38, 0x10, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x10, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x78, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x78, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x38, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x38, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0xcc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x30, 0x60, 0x38, 0x00},
+	{0x10, 0x38, 0x44, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0xf8, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0xb3, 0xb3, 0x33, 0x3e, 0x33, 0x33, 0x33, 0x33, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x64, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x62, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xe6, 0xe6, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0xe0, 0xe0, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x06, 0x06, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x03, 0x3e, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x03, 0x7e, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xb6, 0xb3, 0x33, 0x33, 0x33, 0x33, 0x33, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x4c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0x4c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x18, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0xfe, 0xcc, 0x8c, 0x2c, 0x3c, 0x2c, 0x0c, 0x8c, 0xcc, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x06, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc2, 0xc0, 0x78, 0xc0, 0xc0, 0xc2, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x00},
+	{0x00, 0x00, 0x1c, 0x36, 0x32, 0x30, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x00},
+	{0x00, 0x03, 0x3e, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x38, 0x6c, 0x38, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xf3, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x6d, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc8, 0x38, 0x70, 0xd0, 0x38, 0x38, 0x6c, 0x64, 0xc6, 0xc2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0xec, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x76, 0x7e, 0x7e, 0x6e, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0xc0, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x73, 0xdf, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x03, 0x03, 0x03, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0xdf, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x03, 0x03, 0x03, 0x00},
+	{0x00, 0x00, 0x7e, 0xb3, 0xb3, 0x33, 0x3e, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x78, 0x6c, 0x6c, 0xe6, 0x06, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x38, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x0c, 0x38, 0x60, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x62, 0x30, 0x18, 0x18, 0x30, 0x62, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd8, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x0c, 0x6c, 0x38, 0x00},
+	{0x00, 0x00, 0x7e, 0xfe, 0x9a, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x36, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00},
+	{0x03, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xee, 0x6c, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x63, 0xb3, 0xb3, 0x33, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x06, 0x0d, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0xf0, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x7e, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0xfc, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x7c, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc0, 0x60, 0x30, 0x18, 0x7c, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x60, 0x30, 0x78, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x7c, 0xc0, 0xc6, 0x7c, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x7e, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x60, 0x60, 0x78, 0x0c, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x60, 0x78, 0x0c, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x18, 0x4c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x70, 0x60, 0x60, 0xf0, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x1b, 0x0e, 0x04, 0xf7, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf5, 0xda, 0xd8, 0xdf, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3d, 0x1a, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0x6f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xcb, 0xf6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf3, 0x63, 0x60, 0x67, 0x63, 0x63, 0x63, 0x67, 0x6f, 0xff, 0x03, 0x1b, 0x0e, 0x00},
+	{0x00, 0x00, 0xe3, 0x63, 0x60, 0x67, 0x63, 0x63, 0x63, 0x63, 0x63, 0xf3, 0x03, 0x33, 0x1e, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xfb, 0xfb, 0xfb, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xf8, 0xff, 0xfb, 0xfb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x33, 0x1e, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x00, 0xb7, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x33, 0x1e, 0x00},
+	{0x6c, 0x38, 0x10, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x00, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x78, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x10, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x30, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x28, 0x10, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x78, 0x30, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x10, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x00, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x30, 0x30, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xdf, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x3e, 0xcc, 0x78, 0x00},
+	{0x6c, 0x38, 0x10, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x6c, 0x38, 0x10, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x6c, 0x38, 0x10, 0xfe, 0x0c, 0x18, 0x30, 0x7c, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00},
+	{0x00, 0x1b, 0x0e, 0x04, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
+	{0x00, 0x00, 0xf7, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xdc, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0xd8, 0xd8, 0xdf, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0x6f, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xdb, 0xfb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x70, 0x60, 0x60, 0x60, 0x60, 0xe0, 0x00},
+	{0x60, 0x30, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x38, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x38, 0x6c, 0x38, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x7a, 0xc4, 0xce, 0xce, 0xd6, 0xe6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7a, 0xc4, 0xce, 0xd6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x3c, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x1c, 0x74, 0x06, 0x06, 0x06, 0x06, 0x1c, 0xf0, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0e, 0x3c, 0x06, 0x06, 0x1c, 0xf0, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xfc, 0x06, 0x0c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc0, 0xfc, 0x06, 0x0c, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x7c, 0x00, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x00, 0x72, 0x9c, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x00, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x5c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xdc, 0xe6, 0x7c, 0x80, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0d, 0x06, 0x00},
+	{0x00, 0x00, 0x06, 0x0d, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x6c, 0x8e, 0x16, 0x26, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xcd, 0x0d, 0x38, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xdc, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x06, 0x06, 0x1f, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
+	{0x00, 0x00, 0x00, 0x06, 0x0d, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x46, 0x6c, 0x2c, 0x2c, 0x38, 0x18, 0x18, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x64, 0x28, 0x38, 0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xdc, 0x6c, 0x0c, 0x0c, 0x0e, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x7b, 0xde, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x78, 0x58, 0x3e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x7f, 0x63, 0x66, 0x6c, 0x7e, 0x63, 0xf3, 0x03, 0x33, 0x1e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6e, 0x06, 0x06, 0x06, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0xc0, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x03, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xd8, 0xd8, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xdc, 0x6c, 0x0c, 0x0d, 0x06, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0x60, 0x60, 0x6c, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x66, 0x6c, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xfc, 0xc0, 0xd8, 0x70, 0x00},
+	{0x00, 0x00, 0x0e, 0x1b, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x98, 0xd8, 0x70, 0x00},
+	{0x00, 0x00, 0x0e, 0x1b, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x98, 0xd8, 0x70, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0xd8, 0x70, 0x00},
+	{0x00, 0x00, 0x70, 0xd8, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x3b, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3e, 0x60, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x06, 0x06, 0x03, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xcb, 0xfe, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x7e, 0xc7, 0x7c, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0x70, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x76, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x03, 0x7e, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x0c, 0x00, 0x1c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7e, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xcc, 0x6c, 0x3c, 0x3c, 0x6c, 0xcc, 0x0c, 0x0c, 0x0e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x06, 0x0d, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x1c, 0x18, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0x70, 0x30, 0xfc, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0x6f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xdb, 0xdb, 0xde, 0xde, 0xdb, 0x6b, 0x03, 0x1b, 0x0e, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xdb, 0xdd, 0x6f, 0x04, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x60, 0x60, 0xf6, 0x6d, 0x6c, 0x66, 0x63, 0x6b, 0x36, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x26, 0x6d, 0x6c, 0xfc, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x3c, 0x0c, 0x2c, 0x18, 0x00},
+	{0x00, 0x00, 0x20, 0x60, 0x60, 0xf6, 0x6d, 0x6c, 0x6c, 0x6e, 0x6d, 0x36, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd8, 0xc0, 0xfe, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x03, 0x0e, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6d, 0x6c, 0x66, 0x63, 0x6b, 0xf6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6f, 0x6b, 0x63, 0x66, 0x6c, 0x6d, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xd6, 0x7c, 0x6c, 0x28, 0xc6, 0xd6, 0x7c, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xf0, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xc0, 0xf0, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xb0, 0xd8, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x18, 0xd8, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x18, 0xd8, 0x68, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xd8, 0xd8, 0xf0, 0xd8, 0xd8, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc6, 0xd6, 0x7c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xd8, 0xd8, 0x78, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd8, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd8, 0xc0, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x70, 0xc0, 0x70, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0x70, 0x18, 0x70, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x20, 0x20, 0x70, 0x70, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xd8, 0xd8, 0x70, 0x70, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x1c, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x6c, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x34, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00},
+	{0xc0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x34, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x3e, 0x32, 0x30, 0x34, 0x3c, 0x34, 0x30, 0x30, 0x32, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x33, 0x33, 0x33, 0x33, 0x3f, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x36, 0x36, 0x77, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x82, 0x44, 0x7c, 0x44, 0x00, 0x82, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x62, 0x30, 0x18, 0x18, 0x30, 0x62, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x92, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x6c, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x6c, 0x60, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x46, 0x6c, 0x2c, 0x2c, 0x38, 0x18, 0x18, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x30, 0x18, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x46, 0x7c, 0x18, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0x20, 0x30, 0x10, 0x38, 0x38, 0x6c, 0x64, 0xc6, 0xc2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf6, 0xc0, 0xc0, 0xc0, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x66, 0x6c, 0x3c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x3c, 0x30, 0x60, 0x3c, 0x60, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x46, 0x2c, 0x2c, 0x18, 0x30, 0x68, 0x68, 0xc4, 0xc2, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x6c, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x36, 0x1e, 0xc6, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc2, 0x65, 0x24, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x21, 0x32, 0x12, 0x1c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc2, 0x65, 0x24, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xa6, 0x2c, 0x38, 0x68, 0xca, 0xc4, 0x0c, 0x18, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x3c, 0x06, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x32, 0x30, 0x30, 0x3c, 0x34, 0x30, 0x30, 0x30, 0x30, 0x00},
+	{0x00, 0x60, 0x30, 0x30, 0x60, 0x63, 0xff, 0xc6, 0x06, 0x0c, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x60, 0x60, 0xfe, 0xfe, 0x0c, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xac, 0x26, 0x26, 0x0b, 0x0b, 0x1b, 0x1b, 0x1b, 0x1b, 0x03, 0x02, 0x04, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x28, 0x4c, 0x14, 0x24, 0x06, 0x02, 0x02, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6d, 0x03, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6d, 0x03, 0x7e, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xd6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x06, 0x76, 0x9c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x7c, 0xd6, 0x66, 0x06, 0x06, 0x66, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x3c, 0x60, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x26, 0x1c, 0x70, 0xc0, 0xc2, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0x68, 0x38, 0x30, 0x38, 0x38, 0x4c, 0x4c, 0x86, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xba, 0x30, 0x38, 0x28, 0x4c, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0xc0, 0xcc, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xdc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x7e, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x1c, 0x18, 0x7e, 0x58, 0x18, 0x18, 0x18, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xa6, 0x2c, 0x38, 0x68, 0xca, 0xc4, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0xc0, 0x60, 0x3c, 0x06, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
+	{0x30, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xb2, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x03, 0x06, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xf8, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xd8, 0xd8, 0xd8, 0xde, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xd8, 0xfe, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xb2, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x18, 0x00, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x38, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfe, 0xc6, 0x82, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0xc6, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfe, 0x06, 0x02, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xff, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0xb0, 0xb0, 0x30, 0x3c, 0x36, 0x36, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x3e, 0x06, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x9c, 0xb6, 0xb6, 0xb6, 0xf6, 0xb6, 0xb6, 0xb6, 0xb6, 0x9c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0xcc, 0xcc, 0xcc, 0x7c, 0x6c, 0x6c, 0x6c, 0x6c, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x7c, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfe, 0xc6, 0x82, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfe, 0x06, 0x02, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xff, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb0, 0x30, 0x3c, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3e, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xb6, 0xb6, 0xf6, 0xb6, 0xb6, 0x9c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xcc, 0xcc, 0x7c, 0x6c, 0x6c, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0xf8, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xf8, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd8, 0xd8, 0xde, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xfe, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0xf8, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x38, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0xfc, 0xb4, 0x30, 0x3c, 0x36, 0x36, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x30, 0xfc, 0xb4, 0x30, 0x3c, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xce, 0xdb, 0xd9, 0xd8, 0xfe, 0xd8, 0xd8, 0xd9, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xdb, 0xd8, 0xfe, 0xd8, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0x6c, 0xfe, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x6c, 0x7c, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x88, 0x8c, 0x9c, 0x96, 0xf6, 0xb6, 0xbf, 0xab, 0xeb, 0xeb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x8c, 0x9c, 0xf6, 0xbe, 0xab, 0xeb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x6c, 0x6c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x6c, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0xa3, 0xb2, 0x96, 0xfc, 0x9c, 0xbe, 0xaa, 0xab, 0xeb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xa3, 0x96, 0xfe, 0xab, 0xab, 0xeb, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x7c, 0xc6, 0x06, 0x06, 0x7c, 0x06, 0x06, 0x06, 0x7c, 0xc0, 0x7c, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0x86, 0x06, 0x7c, 0x06, 0x06, 0x7c, 0xc0, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x96, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x10, 0x96, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc2, 0xc6, 0xc6, 0xc4, 0xcc, 0x6c, 0x68, 0x78, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x64, 0x6c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0xc2, 0xc6, 0xc4, 0xc4, 0x6c, 0x68, 0x78, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0xc2, 0xc6, 0x64, 0x6c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd8, 0xd8, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6f, 0x03, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6f, 0x03, 0x06, 0x1c, 0x00},
+	{0x00, 0x10, 0x7c, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x7c, 0xd6, 0xc6, 0xc6, 0xc6, 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x00},
+	{0x04, 0x7c, 0x40, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x04, 0x7c, 0x40, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x54, 0x00, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0x54, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x3c, 0x0c, 0x0c, 0x0c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0x78, 0x18, 0x18, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x06, 0x3c, 0x0f, 0x18, 0x18, 0xf0, 0x3c, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x04, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x40, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x04, 0x7c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x66, 0x00, 0xc3, 0x00, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x50, 0x46, 0x00, 0x82, 0x41, 0x00, 0x62, 0x0a, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0xc6, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x6e, 0x64, 0x7a, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x6e, 0x64, 0x7a, 0x60, 0x60, 0xf0, 0x00},
+	{0x02, 0x06, 0xfe, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x02, 0x06, 0xfe, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0xf8, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0xf8, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xf6, 0x06, 0x16, 0x0c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x78, 0x6c, 0x66, 0xf6, 0x06, 0x16, 0x0c, 0x00},
+	{0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xdc, 0xf8, 0xdc, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xdc, 0xf8, 0xdc, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0xf6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0xf0, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf3, 0xb3, 0xb3, 0x36, 0x3c, 0x3c, 0x36, 0x33, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0xb6, 0xbc, 0x3c, 0x36, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xdf, 0xdb, 0xd9, 0xd8, 0xf8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xdb, 0xd9, 0xf8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0xd8, 0xd8, 0xd8, 0xde, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x0b, 0x06, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xfe, 0xdb, 0xdb, 0xdb, 0x03, 0x0b, 0x06, 0x00},
+	{0x00, 0x00, 0x7c, 0xc2, 0xcc, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xcc, 0x7a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc2, 0xcc, 0xd6, 0xd6, 0xcc, 0x7a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x0c, 0x04, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x0c, 0x04, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x3c, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xf6, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7f, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7f, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0x7e, 0x16, 0x16, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0x7e, 0x16, 0x16, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x33, 0xb3, 0xb3, 0x7f, 0x30, 0x30, 0x30, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xb3, 0x7f, 0x30, 0x30, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x33, 0xb3, 0xb3, 0x7f, 0x30, 0x30, 0x30, 0x33, 0x1e, 0x0c, 0x18, 0x0e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xb3, 0x7f, 0x30, 0x30, 0x33, 0x1e, 0x0c, 0x18, 0x0e, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x06, 0x16, 0x0c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x06, 0x16, 0x0c, 0x00},
+	{0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x06, 0x16, 0x0c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x06, 0x16, 0x0c, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0e, 0x0c, 0x08, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0e, 0x0c, 0x08, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x06, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x86, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00},
+	{0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x3e, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x3e, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x66, 0xcc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0xcc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x7c, 0xcd, 0xcd, 0xcd, 0xcd, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcd, 0xcd, 0xcd, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0x8c, 0x0c, 0x38, 0x0d, 0x0d, 0x0d, 0x0d, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x0c, 0x39, 0x0d, 0x0d, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x06, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0xcd, 0xcd, 0xcd, 0xcd, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xfd, 0xcd, 0xcd, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xce, 0xc6, 0xc6, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x1b, 0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5a, 0x18, 0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x64, 0x94, 0xba, 0x52, 0x4c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x7b, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x7f, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x7e, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x0c, 0xd8, 0xfe, 0xc3, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x06, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xcf, 0xd6, 0xd6, 0xd6, 0xd6, 0xcc, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x7f, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x06, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xf6, 0xd6, 0xd6, 0xd6, 0xd6, 0xcc, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0x7f, 0x24, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0xf0, 0x3c, 0x0e, 0x04, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x6c, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0c, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x30, 0x60, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcf, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x7c, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x60, 0x60, 0x60, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x6c, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x16, 0x16, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x76, 0x1e, 0x0e, 0x0c, 0xd8, 0xfe, 0xc3, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x30, 0x18, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x63, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xfe, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd0, 0xd0, 0xd0, 0x7c, 0x16, 0x16, 0x16, 0xd6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x06, 0x3c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x1c, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7f, 0x0c, 0x0c, 0x0c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x0c, 0x0c, 0x0c, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x0f, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x0c, 0x18, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x7e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xcf, 0xd6, 0xd6, 0xcc, 0xc0, 0xc0, 0xc0, 0x00},
+	{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x7f, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3e, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xf6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xca, 0xc0, 0xc0, 0xc0, 0x00},
+	{0x00, 0x00, 0x60, 0x38, 0x0c, 0x7f, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x1c, 0x0c, 0x18, 0x3c, 0x64, 0x66, 0x62, 0x63, 0x3d, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0c, 0x0c, 0x0f, 0x00},
+	{0x00, 0x00, 0x0e, 0x18, 0x30, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0f, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x3e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x3e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7e, 0x06, 0x06, 0x06, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x76, 0x1c, 0x18, 0x30, 0x60, 0x3e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x0f, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x10, 0xdc, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x76, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xfe, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd0, 0xd0, 0x7c, 0x16, 0x16, 0x16, 0x16, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xcc, 0xcc, 0xcc, 0xcc, 0x77, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x6c},
+	{0x18, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x38, 0x10, 0x38, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x60, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x0c, 0x00},
+	{0x10, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x74, 0xd6, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xc0, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x03, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x18, 0x30, 0x00},
+	{0x0c, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1b, 0x36, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x44, 0xaa, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x0a, 0x0c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0x50, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x3c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x6c, 0xd8, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x08, 0x30},
+	{0x60, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0xa0, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0x10, 0x10},
+	{0x18, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x06, 0x03, 0x00},
+	{0x48, 0xa8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x33, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x06, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x60, 0x66, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18},
+	{0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x18, 0x03, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x66, 0x76, 0xdc, 0xcc, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x0c, 0x0c, 0x1c, 0x36, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xcc, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xee, 0x66, 0x66, 0x66, 0x66, 0x66, 0x2c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x4c, 0xcc, 0xcc, 0xec, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x46, 0xc6, 0xc6, 0xe6, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xee, 0x66, 0x66, 0x6c, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x70, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xee, 0x66, 0x66, 0x34, 0x18, 0x0c, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x66, 0x64, 0x6c, 0x6e, 0x60, 0x60, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xf6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x66, 0x66, 0xc6, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x20, 0x1e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x02, 0x3c, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x20, 0x1c, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x18, 0x20, 0x1c, 0x20, 0x00, 0x00},
+	{0x00, 0x30, 0x40, 0x38, 0x40, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x28, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x88, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x20, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x40, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x40, 0x30, 0x4e, 0x49, 0x39, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x24, 0x00},
+	{0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x12, 0xca, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00},
+	{0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x14, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00},
+	{0x0a, 0x2a, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x01, 0x7e, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x10, 0x0c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x10, 0x0c, 0x10},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x70, 0x70, 0x38, 0x18, 0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x44, 0xfc, 0xf8, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x4a, 0xfe, 0xf4, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x20, 0x40, 0x30, 0x10, 0x20, 0x42, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x2c, 0x44, 0x42, 0x82, 0x82, 0xfe, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xf8, 0x78, 0x08, 0x08, 0x08, 0x0c, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x82, 0xc6, 0xc6, 0x6c, 0x28, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x10, 0x38, 0x28, 0x6c, 0xc6, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xf8, 0x88, 0xf8, 0x78, 0x08, 0x0c, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x91, 0x92, 0x64, 0x08, 0x10, 0x26, 0x49, 0x89, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x18, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0xfe, 0x7c, 0x38, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x06, 0x29, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x06, 0x28, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x06, 0x28, 0x5e, 0x00, 0x00, 0x00},
+	{0x00, 0x07, 0x08, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x04, 0x03, 0x14, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x04, 0x03, 0x04, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x23, 0x54, 0x33, 0x24, 0x40, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x04, 0x03, 0x04, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0x81, 0x7e, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x08, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00},
+	{0x06, 0x08, 0x06, 0x08, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x08, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x94, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x88, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x94, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x20, 0x38, 0x28, 0x70, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x38, 0x28, 0x70, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x00, 0x08, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x00, 0x14, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x08, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x1c, 0x6a, 0x04, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x14, 0x08, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x12, 0x04, 0x18, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x15, 0x88, 0x88, 0x8a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x88, 0x90, 0x65, 0x00, 0x02, 0x00, 0x00, 0x00},
+	{0x00, 0x04, 0x00, 0x0a, 0x00, 0x01, 0x15, 0x88, 0x88, 0x90, 0x65, 0x00, 0x02, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x90, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x2a, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x00, 0x50, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x00},
+	{0x0a, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x00, 0x01, 0x02, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x20, 0x40, 0x3e, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x01, 0x02, 0x05, 0x0b, 0x48, 0x84, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x00, 0x29, 0x01, 0x19, 0x21, 0x19, 0xa1, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x05, 0x0b, 0x48, 0x84, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xa4, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x44, 0x09, 0xa2, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x08, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x02, 0x2a, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x14, 0x00, 0x08, 0x00},
+	{0x00, 0x08, 0x00, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x04, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x08, 0x14, 0x08, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0x3c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x38, 0x40, 0x38, 0x40, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x40, 0x38, 0x40, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x12, 0x2c, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x3c, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x28, 0x18, 0x10, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x08, 0x08, 0x08, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x20, 0x47, 0x88, 0x08, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x50, 0x20, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x08, 0x00, 0x08},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x14, 0x00, 0x08},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x80, 0x60, 0x80, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0x40, 0x43, 0x55, 0x7e, 0x80, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x2a, 0x20, 0x26, 0x2a, 0x7c, 0x80, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0e, 0x1c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x14, 0x08, 0x14, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x2c, 0x10, 0x28, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x15, 0x8a, 0x90, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x5a, 0xa5, 0x66, 0x5b, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x5a, 0x66, 0xa5, 0x5a, 0x00},
+	{0x00, 0x00, 0x18, 0x66, 0x42, 0x42, 0x81, 0x99, 0x99, 0x81, 0x42, 0x42, 0x66, 0x18, 0x00, 0x00},
+	{0x08, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x26, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0c, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x8a, 0x90, 0x60},
+	{0x32, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x0c, 0x04, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x30, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x28, 0x54, 0xaa, 0x92, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x82, 0xfe, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x14, 0x08},
+	{0x08, 0x14, 0x22, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x10, 0x10, 0x10},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x70, 0x70, 0x38, 0x18, 0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x44, 0xfc, 0xf8, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x4a, 0xfe, 0xf4, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x4e, 0xf0, 0xfe, 0x7c, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x38, 0x2c, 0x44, 0x42, 0x82, 0x92, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x60, 0x7e, 0x3c, 0x30, 0x60, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x82, 0xc6, 0xc6, 0x6c, 0x28, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x10, 0x38, 0x28, 0x6c, 0xc6, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xf8, 0x88, 0xf8, 0x78, 0x08, 0x0c, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x88, 0x88, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x40, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x88, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x20, 0x1e, 0x20, 0x00, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x3c, 0x40, 0x54, 0x54, 0x54, 0x54, 0x40, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x92, 0x92, 0x4c, 0x30, 0x4c, 0x02, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0xaa, 0xaa, 0xaa, 0x82, 0x82, 0x40, 0x30, 0x4c, 0x02, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x82, 0x82, 0x44, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x82, 0x82, 0x40, 0x30, 0x4c, 0x02, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x38, 0x6c, 0x38},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x38, 0x6c, 0x38},
+	{0x18, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x0c, 0xec, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x7c, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x30, 0x30, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x60, 0x0c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x30, 0x18, 0x70, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x30, 0x18, 0x70, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x10, 0x38, 0x6c, 0x00},
+	{0x60, 0x30, 0x00, 0x7c, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x7c, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x76, 0xdc, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x76, 0xdc, 0x00},
+	{0x6c, 0x38, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x18, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0x38, 0x6c, 0x64, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x30, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0c, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x60, 0x30, 0xe0, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x30, 0x18, 0x70, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x6c, 0x38, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x6c, 0x38, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x76, 0xdc, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x76, 0xdc, 0x00},
+	{0x0c, 0x18, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x0c, 0xec, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x7c, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x7c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x7e, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x10, 0x38, 0x6c, 0x00},
+	{0x0c, 0x18, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x30, 0x30, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x10, 0x38, 0x6c, 0x00},
+	{0x0c, 0x18, 0x72, 0x9c, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x00, 0x72, 0x9c, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+	{0x18, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+	{0x18, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x7c, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x7c, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x60, 0x6c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0x70, 0x1c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x60, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x44, 0x38, 0x10, 0x7c, 0xc6, 0xc6, 0x70, 0x1c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x44, 0x38, 0x10, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x18, 0x18, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x06, 0x16, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x7e, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x7e, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x08, 0x1c, 0x36, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x6c, 0x6c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x6c, 0x6c, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x76, 0xdc, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x76, 0xdc, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x10, 0x38, 0x6c, 0x00},
+	{0x0c, 0x18, 0x72, 0x9c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x76, 0xdc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0xcc, 0x00, 0xfc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x18, 0x18, 0x00},
+	{0x60, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x30, 0x30, 0x00},
+	{0x30, 0x30, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x10, 0x38, 0x44, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x10, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x18, 0x0c, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0x38, 0x6c, 0x64, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
+	{0x38, 0x0c, 0x18, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x0c, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x16, 0x38, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x16, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0xc0, 0x68, 0x1c, 0x36, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0xc0, 0x68, 0x1c, 0x36, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x13, 0x3a, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x10, 0x28, 0x54, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x10, 0x38, 0x44, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
+	{0x0c, 0x18, 0x44, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x44, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x44, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x44, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x08, 0x54, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x08, 0x54, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x72, 0x9c, 0x44, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x72, 0x9c, 0x44, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x38, 0x0c, 0x18, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x23, 0x76, 0x88, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x26, 0x70, 0xd8, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0xc4, 0x6e, 0x11, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0xc0, 0x64, 0x0e, 0x1b, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x10, 0x38, 0x44, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x10, 0x38, 0x44, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x38, 0x0c, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x38, 0x0c, 0x18, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x23, 0x76, 0x88, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x26, 0x70, 0xd8, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0xc4, 0x6e, 0x11, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0xc0, 0x64, 0x0e, 0x1b, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x13, 0x3a, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x10, 0x28, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x18, 0x33, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1b, 0x33, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x33, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x63, 0x33, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x70, 0x1b, 0x33, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0x1b, 0x33, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x68, 0xb3, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x68, 0xb3, 0x03, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
+	{0x38, 0x0c, 0x18, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0x18, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x33, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1b, 0x33, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x33, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x63, 0x33, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x70, 0x1b, 0x33, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0x1b, 0x33, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x68, 0xb3, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x68, 0xb3, 0x03, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
+	{0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x0c, 0x18, 0xf6, 0x06, 0x00},
+	{0x38, 0x0c, 0x18, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x3a, 0x5c, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x18, 0x18, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x30, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x60, 0x6c, 0xc6, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xcc, 0x66, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x60, 0x66, 0xcc, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xc6, 0x6c, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x34, 0x58, 0x0c, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x34, 0x58, 0x30, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0xfe, 0x00, 0xa4, 0xaa, 0xea, 0xea, 0xa6, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xa4, 0xea, 0xaa, 0xaa, 0xa6, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xea, 0x8a, 0xce, 0x8e, 0xea, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xea, 0x8e, 0xca, 0x8a, 0xea, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xca, 0x2e, 0x4a, 0x2a, 0xca, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xaa, 0xae, 0xea, 0x2a, 0x2a, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0x6a, 0x8e, 0xca, 0xaa, 0x4a, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0x38, 0x20, 0x30, 0x20, 0x20, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0x30, 0x28, 0x30, 0x20, 0x20, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xea, 0x4a, 0x4e, 0x4a, 0x4a, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0x28, 0x28, 0x38, 0x28, 0x28, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xea, 0x2a, 0x4e, 0x8e, 0xee, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xea, 0x2a, 0x4e, 0x8e, 0xee, 0x00, 0xa2, 0xa2, 0xe2, 0xea, 0xa4, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xea, 0x2a, 0x4e, 0x8e, 0xee, 0x00, 0x08, 0x08, 0x08, 0x28, 0x10, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0x80, 0x80, 0x80, 0xf0, 0x28, 0x30, 0x28, 0x0a, 0x0e, 0x0e, 0x0a, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xc0, 0xa0, 0xc0, 0xa0, 0x20, 0x20, 0x38, 0x0a, 0x0e, 0x0e, 0x0a, 0x00, 0xfe, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x9c, 0xd2, 0xbc, 0x92, 0x9c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xfe, 0x00},
+	{0x00, 0x18, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00},
+	{0x00, 0x30, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x66, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00},
+	{0x00, 0xcc, 0xcc, 0xcc, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x38, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x6b, 0x6b, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x92, 0x44, 0x28, 0x92, 0x28, 0x44, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0xc3, 0xdb, 0x1b, 0x1e, 0x1c, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x7c, 0x00, 0x00},
+	{0x7c, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x38, 0x28, 0x00, 0x00, 0x44, 0xee, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7b, 0xcf, 0xcf, 0x1b, 0x33, 0x33, 0x33, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xde, 0xf3, 0xf3, 0xc6, 0xcc, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x06, 0x06, 0x0c, 0x0c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xdb, 0xdb, 0xdb, 0xde, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x3e, 0x72, 0xf2, 0xf2, 0xf2, 0x72, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x9c, 0x9e, 0x9e, 0x9e, 0x9c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x38, 0x78, 0xd8, 0xfc, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xf8, 0xc0, 0xf0, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x78, 0xc0, 0xf0, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xf8, 0xd8, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd8, 0x70, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd8, 0xd8, 0x78, 0x18, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x60, 0x30, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xb0, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0xd8, 0xfc, 0x18, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xc0, 0xf0, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xc0, 0xf0, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd8, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x70, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0xd8, 0x78, 0x18, 0xf0, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcf, 0xcc, 0xcc, 0x7f, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x04, 0x7c, 0xce, 0xc8, 0xc8, 0xd0, 0xd0, 0xd0, 0xe0, 0xe6, 0x7c, 0x40, 0x40, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xd6, 0xd8, 0xd8, 0xd8, 0xde, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0xc0, 0xc0, 0xc0, 0xf0, 0xcd, 0xce, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x60, 0xf8, 0x60, 0xf8, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x02, 0xec, 0xd6, 0xde, 0xd6, 0xd6, 0xf6, 0xd6, 0x40, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x76, 0xff, 0x76, 0x6e, 0xff, 0x6e, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xf8, 0xe0, 0xf3, 0xd6, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x81, 0x81, 0x81, 0x5a, 0xff, 0x5a, 0xff, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xf2, 0x8a, 0xaa, 0xaa, 0xaa, 0xaa, 0xa2, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x3e, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x36, 0x60, 0xfc, 0x60, 0xf8, 0x60, 0x60, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0xfe, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x1e, 0x78, 0x1e, 0x78, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x7c, 0xb6, 0x36, 0x33, 0x33, 0x33, 0x63, 0x66, 0xf6, 0xdc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd0, 0xd2, 0xd6, 0x7c, 0x18, 0x30, 0x6e, 0xd8, 0x98, 0x18, 0x0e, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd0, 0xd2, 0xd6, 0x7c, 0x18, 0x30, 0x6e, 0xd8, 0x8c, 0x06, 0x1c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x62, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x62, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x4e, 0xb9, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x7c, 0xda, 0xd8, 0xd8, 0xda, 0x7c, 0x19, 0x3f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xc0, 0xc2, 0xc6, 0x7c, 0x18, 0x30, 0x6e, 0xdb, 0x9b, 0x1b, 0x0e, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xc0, 0xc2, 0xc6, 0x7c, 0x18, 0x30, 0x7b, 0xdb, 0x9b, 0x1b, 0x0d, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc2, 0xc0, 0x78, 0xc0, 0xc0, 0xc2, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0x86, 0x26, 0x3e, 0x26, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7f, 0xb9, 0x58, 0x1a, 0x1e, 0x1a, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x66, 0x46, 0x87, 0x8c, 0x8c, 0x7c, 0x98, 0x98, 0x70, 0x00},
+	{0x00, 0x00, 0x52, 0xb5, 0x15, 0x16, 0x2c, 0x34, 0x68, 0xa9, 0xaa, 0x4c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x48, 0xb0, 0x80, 0x48, 0x7c, 0x66, 0x26, 0x26, 0xa6, 0x46, 0x06, 0x34, 0x48, 0x00},
+	{0x00, 0x00, 0xe2, 0xa2, 0xa2, 0xa2, 0xbe, 0xa2, 0xa2, 0xa2, 0xa2, 0xe2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x36, 0x3b, 0x3b, 0x33, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x1e, 0x18, 0x76, 0x3b, 0x3b, 0x33, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x33, 0x4e, 0x06, 0x06, 0x0c, 0x0c, 0x1f, 0x6c, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x71, 0x8e, 0x04, 0x0c, 0x06, 0x03, 0x63, 0xc3, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x46, 0x49, 0x39, 0x1e, 0x18, 0x30, 0x70, 0xb1, 0xba, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0e, 0x19, 0x31, 0x32, 0x64, 0x68, 0x70, 0xe1, 0x66, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd8, 0xff, 0xd8, 0xde, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe2, 0xa2, 0xb2, 0xb2, 0xaa, 0xaa, 0xa6, 0xa6, 0xa2, 0xe2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0xcf, 0xed, 0xff, 0xfc, 0xdf, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0xb9, 0xa5, 0xa5, 0xb9, 0xa1, 0xa1, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x40, 0x8e, 0x93, 0xa3, 0x63, 0x4b, 0x6a, 0xa4, 0xb0, 0xb0, 0x60, 0x00},
+	{0x00, 0x00, 0xfc, 0xa2, 0xa2, 0xa2, 0xa2, 0xbc, 0xa0, 0xa0, 0xa0, 0xe0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xaa, 0xa6, 0x7e, 0x01, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3e, 0x4d, 0x4d, 0x19, 0x1e, 0x1c, 0x34, 0x34, 0xb5, 0x62, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x58, 0xa6, 0xa3, 0x6c, 0xb8, 0x26, 0x26, 0x26, 0xa7, 0xc2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0xa2, 0xa2, 0xa2, 0xa2, 0xbc, 0xb0, 0xa8, 0xa4, 0xe2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x6d, 0x67, 0x66, 0xee, 0x08, 0x00, 0x00, 0x00},
+	{0x30, 0x0c, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xd8, 0xdc, 0xdc, 0xe6, 0xe6, 0x20, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x71, 0xdb, 0x35, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x52, 0x5a, 0x52, 0x5f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf1, 0x5b, 0x55, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x18, 0xce, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xe6, 0x6c, 0x38, 0x50, 0x40, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x0a, 0x14, 0x14, 0x28, 0x28, 0x50, 0x50, 0xa0, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x9c, 0x30, 0xfe, 0x0c, 0x18, 0x38, 0x0c, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xee, 0x6c, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x26, 0x03, 0x13, 0x0c, 0x13, 0x03, 0x03, 0x66, 0x98, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x38, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x2d, 0x2d, 0x1a, 0x1e, 0x1b, 0x31, 0x31, 0xb2, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x14, 0x6b, 0xc8, 0xcc, 0xc6, 0xc6, 0xcc, 0xc0, 0x63, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xe7, 0xff, 0xe0, 0x67, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x44, 0xf8, 0xc0, 0xc8, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x4c, 0x52, 0x3c, 0x10, 0x3c, 0x60, 0xc0, 0xc3, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x73, 0xce, 0x18, 0x3a, 0x5c, 0x18, 0x30, 0x30, 0xb0, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x2c, 0x3c, 0x2c, 0x8c, 0xcc, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x12, 0x12, 0x12, 0x16, 0x36, 0x3e, 0x3a, 0x5a, 0x52, 0x91, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x46, 0xc6, 0xc4, 0xc8, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x42, 0xc6, 0xe7, 0x7a, 0x38, 0x5c, 0xce, 0xe7, 0x63, 0xe2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xfc, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x7e, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x40, 0x78, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x7e, 0xf2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xfe, 0x7e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x38, 0x00, 0x78, 0x38, 0x38, 0x38, 0x38, 0x38, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xff, 0x83, 0x86, 0x82, 0xfe, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x1c, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0xe0, 0x30, 0x62, 0xc6, 0xfc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x1c, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0xe0, 0x30, 0x62, 0xc6, 0xfc, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0xe0, 0x30, 0x62, 0x36, 0xec, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0x30, 0x70, 0xb2, 0xf6, 0x3c, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0xb0, 0x3c, 0x36, 0x1c, 0x00, 0x00},
+	{0x00, 0xf0, 0xc0, 0xe2, 0x36, 0xec, 0x18, 0x30, 0x60, 0xdc, 0xb0, 0x3c, 0x36, 0x1c, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00},
+	{0x00, 0xe0, 0x30, 0x62, 0x36, 0xec, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00},
+	{0x00, 0xf0, 0x80, 0xe2, 0x36, 0xec, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00},
+	{0x00, 0xf0, 0x30, 0x62, 0x66, 0x6c, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0xce, 0xc4, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x73, 0x23, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x65, 0x65, 0x65, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xce, 0xce, 0xce, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0x73, 0x73, 0x73, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x95, 0x95, 0x95, 0x65, 0x65, 0x65, 0x95, 0x95, 0x95, 0x95, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0xc4, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x23, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x05, 0x05, 0x00, 0x95, 0x95, 0x95, 0x95, 0x95, 0x65, 0x65, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x15, 0x15, 0x00, 0xb5, 0xb5, 0xb5, 0xb5, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0x00, 0xdb, 0xdb, 0xce, 0xce, 0xce, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x00, 0xdb, 0xdb, 0x73, 0x73, 0x73, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x05, 0x05, 0x00, 0x95, 0x95, 0x65, 0x65, 0x95, 0x95, 0x95, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x5a, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0xcc, 0xe6, 0xd6, 0xd6, 0xd6, 0xd6, 0xe6, 0xcc, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x5a, 0x99, 0xbd, 0xdb, 0xdb, 0xbd, 0x99, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x06, 0x06, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xf0, 0xe0, 0xb0, 0x18, 0x0c, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x0f, 0x07, 0x0d, 0x18, 0x30, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x0d, 0x07, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x0c, 0x18, 0xb0, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x62, 0xff, 0x64, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x26, 0xff, 0x46, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xce, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x73, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xff, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x36, 0xff, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x66, 0xfc, 0x66, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x3f, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x63, 0xff, 0x63, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xc6, 0xff, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x33, 0x63, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0xc6, 0x7f, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x3b, 0x6b, 0xfe, 0x68, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x60, 0xdc, 0xd6, 0x7f, 0x16, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x5a, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x6e, 0xff, 0x76, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x60, 0x63, 0xff, 0xc6, 0x16, 0x1c, 0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x66, 0x36, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0xcc, 0xd8, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x36, 0x66, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xd8, 0xcc, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x36, 0x66, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x1e, 0x33, 0x33, 0x33, 0x30, 0xfc, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x0c, 0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x00, 0xf0, 0xe0, 0xb0, 0x18, 0x0c, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x98, 0xb0, 0xff, 0xb0, 0x98, 0x19, 0x0d, 0xff, 0x0d, 0x19, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x1e, 0x1c, 0x16, 0x03, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x78, 0x38, 0x68, 0xc0, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x1c, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x06, 0xff, 0x06, 0x0c, 0x30, 0x60, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x2e, 0x3f, 0x24, 0x24, 0x24, 0x24, 0xfc, 0x74, 0x24, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x60, 0xff, 0x60, 0x30, 0x0c, 0x06, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x7e, 0xff, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0xff, 0x7e, 0x24, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xff, 0x00, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xff, 0x00, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x7f, 0xc4, 0x7f, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x7e, 0xcb, 0x7e, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xfe, 0x23, 0xfe, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x7f, 0xc0, 0x7f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x7c, 0xee, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0x03, 0xfe, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x7e, 0xc3, 0x7e, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x7c, 0xee, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xf0, 0xe0, 0xb0, 0xd8, 0xec, 0xb6, 0x1b, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x0f, 0x07, 0x0d, 0x1b, 0x37, 0x6d, 0xd8, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x20, 0x30, 0xd8, 0x6d, 0x37, 0x1b, 0x0d, 0x07, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x0c, 0x1b, 0xb6, 0xec, 0xd8, 0xb0, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x3f, 0x60, 0xff, 0x60, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0xfc, 0x06, 0xff, 0x06, 0xfc, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x6a, 0xff, 0x65, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xa6, 0xff, 0x56, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x3c, 0x18, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x3c, 0x18, 0x3c, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xd5, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x66, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xab, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xb0, 0xff, 0xb0, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0d, 0xff, 0x0d, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x3f, 0x41, 0x81, 0x41, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x44, 0x44, 0x44, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0xfc, 0x82, 0x81, 0x82, 0xfc, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc6, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x7c, 0x00, 0x7c, 0x44, 0x7c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x44, 0xc6, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x7c, 0xc6, 0x44, 0x44, 0x44, 0xc6, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x54, 0xd6, 0x54, 0x54, 0x54, 0xd6, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x28, 0x54, 0xee, 0x44, 0xc6, 0x44, 0x44, 0x44, 0x44, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x28, 0x54, 0xee, 0x44, 0xc6, 0x44, 0x44, 0xc6, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xe8, 0xbc, 0x82, 0x81, 0x82, 0xbc, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x80, 0xbc, 0xb8, 0xac, 0x86, 0x83, 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x01, 0x81, 0xc1, 0x61, 0x35, 0x1d, 0x3d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x44, 0xc6, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xfe, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x06, 0x06, 0x3e, 0x66, 0xc6, 0xc6, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x7e, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0xfe, 0x16, 0x16, 0x16, 0x7e, 0x16, 0x26, 0x26, 0x26, 0xfe, 0x40, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x3e, 0x66, 0xcf, 0xdb, 0xdb, 0xf3, 0x66, 0x7c, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x3e, 0x60, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x3e, 0x64, 0xc8, 0xc8, 0xfe, 0xc8, 0xd0, 0x70, 0x3e, 0x20, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x3e, 0x60, 0xc0, 0xfe, 0xc0, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xf8, 0x0c, 0x06, 0x06, 0xfe, 0x06, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0xf8, 0x1c, 0x16, 0x26, 0xfe, 0x26, 0x26, 0x4c, 0xf8, 0x40, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x0c, 0x06, 0xfe, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe7, 0x00, 0x00},
+	{0x00, 0x00, 0xe7, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0xc1, 0x60, 0x30, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xff, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x7e, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x06, 0x06, 0x06, 0x0c, 0xcc, 0x6c, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe3, 0x33, 0x66, 0x36, 0xe6, 0x0c, 0xcc, 0x6c, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x33, 0x73, 0xb6, 0xf6, 0x36, 0x0c, 0xcc, 0x6c, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdb, 0xdb, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x16, 0x0c, 0x1c, 0x34, 0x62, 0xff, 0x02, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x1a, 0x1c, 0x38, 0x58, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6e, 0x7c, 0xec, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x1a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00},
+	{0x33, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00},
+	{0x2a, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0xa8, 0x00, 0x00},
+	{0x0c, 0x1a, 0x18, 0x18, 0x3c, 0x5a, 0x99, 0x99, 0x5a, 0x3c, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00},
+	{0x33, 0x66, 0x66, 0x66, 0x7e, 0xe7, 0xe7, 0xe7, 0xe7, 0x7e, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00},
+	{0x2a, 0x54, 0x54, 0x54, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x54, 0x54, 0x54, 0xa8, 0x00, 0x00},
+	{0x18, 0x34, 0x30, 0x30, 0x38, 0x35, 0x33, 0x37, 0x30, 0x30, 0x30, 0x30, 0xb0, 0x60, 0x00, 0x00},
+	{0x0c, 0x1a, 0x18, 0x18, 0x3c, 0x5a, 0xfa, 0x5a, 0x5a, 0x3c, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00},
+	{0x0c, 0x1a, 0x18, 0x18, 0x3c, 0x5a, 0x5f, 0x5a, 0x5a, 0x3c, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0xfc, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x7e, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x76, 0xdc, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0xdb, 0xdb, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0xdb, 0xdb, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x1c, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x76, 0xdc, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x76, 0xdc, 0x10, 0xfe, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x08, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x08, 0x76, 0xdc, 0x10, 0xfe, 0x20, 0xfe, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x76, 0xdc, 0x10, 0x76, 0xdc, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x00, 0x00, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x06, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf, 0x00, 0x00, 0xdf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x03, 0xfb, 0x00, 0x00, 0xfb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x28, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x10, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x44, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x44, 0x28, 0x10, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x10, 0x7c, 0x28, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x28, 0x44, 0x7c, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x26, 0x7c, 0xb4, 0x6c, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x68, 0x54, 0x54, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x08, 0x10, 0x00, 0x10, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x08, 0x7e, 0x08, 0x10, 0x7e, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x08, 0xfe, 0x08, 0x10, 0xfe, 0x10, 0x20, 0xfe, 0x20, 0x40, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x08, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x08, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x1b, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x1b, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0xce, 0x7c, 0x10, 0x7c, 0xe6, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x04, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0xe0, 0x38, 0x2e, 0x38, 0xe0, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x04, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0xe0, 0x38, 0x2e, 0x38, 0xe0, 0x40, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x04, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0x76, 0xdc, 0x20, 0x20, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0xe0, 0x38, 0x2e, 0x38, 0xe0, 0x40, 0x76, 0xdc, 0x80, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x0e, 0x38, 0xe8, 0x38, 0x1e, 0xf0, 0x38, 0x2e, 0x38, 0xe0, 0x20, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0xe8, 0x38, 0x0e, 0x38, 0xf0, 0x1e, 0x38, 0xe0, 0x38, 0x2e, 0x20, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0xf2, 0x1c, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x9e, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x06, 0x0c, 0x38, 0xe8, 0x38, 0x1c, 0x16, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0xd0, 0x70, 0x38, 0x2e, 0x38, 0x60, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x7e, 0xc8, 0xc8, 0xd0, 0xd0, 0x7e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0xfc, 0x16, 0x16, 0x26, 0x26, 0xfc, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x7e, 0xc8, 0xc8, 0xd0, 0xd0, 0x7e, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0xfc, 0x16, 0x16, 0x26, 0x26, 0xfc, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0x7e, 0x08, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x82, 0x92, 0xa2, 0xfa, 0xa2, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0xba, 0xba, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0xba, 0x92, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x54, 0x92, 0xfe, 0x92, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0xfe, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0xaa, 0x92, 0xaa, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x8a, 0x92, 0xa2, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x92, 0xba, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x92, 0xaa, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x54, 0xd6, 0xba, 0xd6, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0xba, 0x82, 0xba, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0xba, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x92, 0x92, 0xfe, 0x92, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0xfe, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xaa, 0x92, 0xaa, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x92, 0xba, 0x92, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x7e, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xd8, 0xdf, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xa8, 0xa8, 0xa8, 0xa8, 0xaf, 0xa8, 0xa8, 0xa8, 0xa8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xdf, 0xd8, 0xdf, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc2, 0xc4, 0xc4, 0xff, 0xc8, 0xc8, 0xd0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc4, 0xc4, 0xff, 0xc8, 0xff, 0xd0, 0xd0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xd8, 0xd9, 0xda, 0xda, 0xdf, 0xda, 0xda, 0xdc, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xd8, 0xd9, 0xda, 0xdf, 0xda, 0xdf, 0xda, 0xdc, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x0c, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x60, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x06, 0x1e, 0x76, 0xc6, 0x76, 0x1e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xf0, 0xdc, 0xc6, 0xdc, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x1e, 0x76, 0xc6, 0x76, 0x1e, 0x06, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xf0, 0xdc, 0xc6, 0xdc, 0xf0, 0xc0, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xbf, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0xc6, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xf0, 0xc8, 0xc4, 0xc4, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0b, 0x13, 0x23, 0x43, 0x83, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x38, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x92, 0x44, 0x28, 0x92, 0x28, 0x44, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x82, 0xc6, 0xaa, 0x92, 0xaa, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x82, 0xc4, 0xa8, 0x90, 0xa8, 0xc4, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x82, 0x46, 0x2a, 0x12, 0x2a, 0x46, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x3e, 0x60, 0xce, 0xd8, 0xd8, 0xce, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xf8, 0x0c, 0xe6, 0x36, 0x36, 0xe6, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x44, 0x92, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x38, 0x54, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x64, 0xce, 0x64, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x4c, 0xe6, 0x4c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x15, 0x2a, 0x54, 0xa8, 0x54, 0x2a, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xa8, 0x54, 0x2a, 0x15, 0x2a, 0x54, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0xfe, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x00},
+	{0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0xfe, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf2, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xc0, 0x70, 0x9e, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0a, 0x0e, 0x1c, 0xf0, 0x1c, 0x16, 0xf2, 0x1c, 0x26, 0x22, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x88, 0xc8, 0x70, 0x1e, 0x70, 0xd0, 0x9e, 0x70, 0xe0, 0xa0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0xfe, 0xc8, 0xc8, 0xd0, 0xd0, 0xfe, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0xfe, 0x16, 0x16, 0x26, 0x26, 0xfe, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x08, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x0e, 0x1e, 0x76, 0xd6, 0x76, 0x1e, 0x26, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0xc8, 0xf0, 0xdc, 0xd6, 0xdc, 0xf0, 0xe0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x0e, 0x1e, 0x76, 0xd6, 0x76, 0x1e, 0x26, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0xc8, 0xf0, 0xdc, 0xd6, 0xdc, 0xf0, 0xe0, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x3d, 0x66, 0xc7, 0xcb, 0xd3, 0xe3, 0x66, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x42, 0xa5, 0x7e, 0x24, 0x24, 0x7e, 0xa5, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x38, 0x54, 0x8a, 0xf6, 0x82, 0x54, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xfe, 0xfe, 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x00, 0x00},
+	{0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00},
+	{0x00, 0x03, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
+	{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
+	{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x03, 0x00, 0x00},
+	{0x00, 0xc0, 0x60, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
+	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
+	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x30, 0x30, 0x60, 0xc0, 0x00, 0x00},
+	{0x00, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
+	{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
+	{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3f, 0x00, 0x00},
+	{0x00, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
+	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
+	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xfc, 0x00, 0x00},
+	{0x00, 0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0},
+	{0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07},
+	{0x00, 0x00, 0xff, 0xc1, 0xc0, 0x60, 0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x60, 0x60, 0x60, 0x60, 0xc0, 0xc1, 0xff, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xff, 0x00, 0xff, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x78, 0x78, 0x38, 0x38, 0x18, 0x18, 0x00, 0x00},
+	{0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
+	{0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03},
+	{0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x07, 0x05, 0x05, 0x05, 0x05, 0x25, 0x79, 0xc2, 0x7c, 0x20, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd8, 0xd8, 0xf8, 0xd8, 0xd8, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0, 0x0f, 0x0c, 0x0e, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd8, 0xd8, 0xf8, 0x70, 0x20, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0xc0, 0xe0, 0xc0, 0xc0, 0x0f, 0x0c, 0x0e, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xc0, 0xc0, 0xc0, 0x70, 0x1e, 0x1b, 0x1e, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x98, 0xd8, 0xf8, 0xd8, 0xd8, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xfe, 0xc6, 0xc6, 0x60, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xfc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0e, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x70, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x70, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x0e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80},
+	{0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01},
+	{0x81, 0x81, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x42, 0x42, 0x81, 0x81},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe},
+	{0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc},
+	{0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8},
+	{0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0},
+	{0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0},
+	{0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
+	{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80},
+	{0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f},
+	{0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44},
+	{0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa},
+	{0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77},
+	{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+	{0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x82, 0xba, 0xba, 0xba, 0xba, 0xba, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x82, 0xfe, 0x82, 0xfe, 0x82, 0xfe, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0xaa, 0xfe, 0xaa, 0xfe, 0xaa, 0xfe, 0xaa, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x8a, 0xc6, 0xa2, 0x92, 0x8a, 0xc6, 0xa2, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0xa2, 0xc6, 0x8a, 0x92, 0xa2, 0xc6, 0x8a, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0xaa, 0xc6, 0xaa, 0x92, 0xaa, 0xc6, 0xaa, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x44, 0x44, 0x44, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x84, 0x84, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x44, 0x44, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x80, 0xc0, 0xa0, 0x90, 0x88, 0x84, 0x88, 0x90, 0xa0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, 0x78, 0x70, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, 0x48, 0x70, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x98, 0x86, 0x98, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x02, 0x06, 0x0a, 0x12, 0x22, 0x42, 0x22, 0x12, 0x0a, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x38, 0x78, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x38, 0x48, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x32, 0xc2, 0x32, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x82, 0x82, 0x44, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0x54, 0xba, 0xba, 0x54, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x99, 0xbd, 0xbd, 0xbd, 0xbd, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x28, 0x44, 0x82, 0x82, 0x44, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x14, 0x40, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x99, 0xa5, 0xa5, 0xa5, 0xa5, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x72, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0x72, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x4e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x4e, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x4e, 0x8f, 0x8f, 0x8f, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x4e, 0x8f, 0x8f, 0x8f, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x70, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x70, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0xff, 0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0xbd, 0xc3, 0xff, 0xff, 0xff, 0xff},
+	{0xff, 0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0xbd, 0xc3, 0xff, 0xff, 0xff, 0xff},
+	{0x00, 0x00, 0x30, 0x40, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x0f, 0x1f, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f, 0xff, 0xff},
+	{0x80, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfc, 0xfe, 0xfe, 0xff, 0xff},
+	{0xff, 0xff, 0xfe, 0xfe, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, 0xe0, 0xe0, 0xc0, 0xc0, 0x80, 0x80},
+	{0xff, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x07, 0x03, 0x03, 0x01, 0x01},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0xff, 0xfd, 0xf9, 0xf1, 0xf1, 0xe1, 0xc1, 0x81, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x81, 0x83, 0x87, 0x8f, 0x8f, 0x9f, 0xbf, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x28, 0x28, 0x44, 0x44, 0x92, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x74, 0x74, 0xf2, 0xf2, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x5c, 0x5c, 0x9e, 0x9e, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x92, 0x92, 0x92, 0xf2, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0xf2, 0x92, 0x92, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x9e, 0x92, 0x92, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x92, 0x92, 0x92, 0x9e, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x4a, 0x89, 0x89, 0x89, 0xf9, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0xf9, 0x89, 0x89, 0x89, 0x4a, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x9f, 0x91, 0x91, 0x91, 0x52, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x52, 0x91, 0x91, 0x91, 0x9f, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x30, 0x7c, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x7c, 0xfe, 0x10, 0x10, 0x10, 0x10, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0xfe, 0x7c, 0x38, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x28, 0xee, 0x44, 0x54, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x34, 0x1c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcd, 0xc7, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x92, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0xa5, 0xa5, 0x42, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x42, 0xa5, 0xa5, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x18, 0x30, 0x70, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x86, 0x8a, 0xba, 0x92, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0xee, 0xba, 0xba, 0xee, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x82, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x82, 0xaa, 0x82, 0x44, 0x7c, 0x44, 0x38, 0x00, 0x44, 0xc6, 0x38, 0xc6, 0x44, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x44, 0xee, 0xfe, 0x92, 0xba, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x7e, 0x18, 0x18, 0xff, 0x18, 0x1e, 0x78, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x7e, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x10, 0x10, 0x92, 0xfe, 0x92, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x72, 0xe0, 0xc4, 0xdf, 0xce, 0xca, 0xe0, 0x72, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x54, 0x28, 0x54, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x5a, 0x99, 0x99, 0x99, 0xbd, 0xff, 0xdb, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x85, 0xb1, 0xf9, 0xff, 0xdf, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0x81, 0x99, 0xa5, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xa5, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xdb, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x54, 0x28, 0xc6, 0x28, 0x54, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0x14, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x14, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x28, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x28, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x06, 0x0e, 0x1a, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x03, 0x03, 0x7b, 0xcf, 0xcf, 0xcf, 0x0f, 0x1b, 0x33, 0xff, 0x03, 0x03, 0x03, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0xf0, 0x60, 0x6e, 0x73, 0x63, 0x63, 0x66, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd6, 0x54, 0x54, 0x7c, 0x54, 0x54, 0xd6, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0xdb, 0xdb, 0xdb, 0xdb, 0x7e, 0x3c, 0x18, 0x3c, 0x18, 0x18, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xf8, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x42, 0xa5, 0xa5, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc3, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00},
+	{0x00, 0x00, 0xc3, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7e, 0xc3, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0xdb, 0xd8, 0x70, 0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x33, 0x33, 0x33, 0x33, 0x1b, 0x7b, 0xdb, 0xdb, 0x73, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x94, 0x7c, 0x55, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x06, 0x0b, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x24, 0xe7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x94, 0x7c, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x04, 0x03, 0x00, 0x00},
+	{0x00, 0x00, 0x1f, 0x07, 0x8f, 0xdb, 0x73, 0x70, 0xd8, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x90, 0x50, 0x70, 0x68, 0x48, 0x48, 0x4e, 0x49, 0x09, 0x0e, 0x10, 0x20, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x2a, 0x7e, 0xaa, 0x00, 0x00, 0x2a, 0x7e, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc3, 0x66, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x82, 0x82, 0x82, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x44, 0x82, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x81, 0x81, 0x66, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x24, 0x3c, 0xe7, 0xa5, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x3c, 0x3e, 0x32, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0x7f, 0x6f, 0x63, 0x63, 0x63, 0x63, 0xe3, 0xe7, 0xc7, 0x06, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x63, 0xe7, 0xe7, 0xc6, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xcc, 0xde, 0xe6, 0xc4, 0xd8, 0xe0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x40, 0x40, 0x44, 0x5c, 0x74, 0x44, 0x44, 0x5c, 0x74, 0x44, 0x04, 0x04, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x04, 0x46, 0x5c, 0x74, 0xc4, 0x46, 0x5c, 0x74, 0xc4, 0x40, 0x40, 0x00, 0x00},
+	{0x00, 0x00, 0x3b, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x6e, 0x66, 0x60, 0xfe, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3e, 0x6e, 0x66, 0x66, 0xfe, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6e, 0xdb, 0xdb, 0xd8, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6f, 0xdb, 0xdb, 0xdb, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x6c, 0x6f, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0xf6, 0x00, 0x00, 0x00, 0x00},
+	{0x06, 0x29, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x06, 0x29, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x14, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x89, 0x86, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0a, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0a, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x89, 0x86, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x88, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x88, 0x80, 0x88, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x94, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x94, 0x80, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x94, 0x80, 0x88, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x94, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x94, 0x80, 0x94, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x28, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x28, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x00, 0x28, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x00, 0x28, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x38, 0x28, 0x70, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x38, 0x28, 0x70, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x01, 0x02, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x01, 0x02, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x30, 0x46, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x30, 0x46, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00},
+	{0x0c, 0x30, 0x46, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00},
+	{0x0c, 0x30, 0x46, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0xa4, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xa4, 0x09, 0x12, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xa2, 0x0c, 0x13, 0x0c, 0x10, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xa2, 0x0c, 0x13, 0x0c, 0x10, 0x10, 0x08, 0x04, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x00, 0x01, 0x41, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x40, 0x38, 0x40, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x70, 0x80, 0x70, 0x80, 0x10, 0x68, 0x88, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xf0, 0x10, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xf7, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0x80, 0x70, 0x80, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x20, 0x1c, 0x20, 0x00, 0x00, 0x07, 0x18, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x00, 0x29, 0x01, 0x19, 0x21, 0x19, 0xa1, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x00, 0x2a, 0x02, 0x32, 0x42, 0x32, 0xc6, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0x00, 0xa3, 0x0c, 0x10, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0x00, 0xa3, 0x0c, 0x10, 0x10, 0x08, 0x04, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x28, 0x18, 0x10, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x28, 0x18, 0x10, 0x20, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x08, 0x08, 0x08, 0x08, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x23, 0x54, 0x33, 0x24, 0x40, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x3c, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x3c, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x10, 0x00, 0x10},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x10, 0x00, 0x10},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x20, 0x20, 0x20, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x10, 0x10, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x10, 0x10, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x24, 0x98, 0x60, 0xc2, 0x12, 0x92, 0x9c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x02, 0x92, 0x9c, 0x60, 0x0e, 0x70, 0x0e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x60, 0x04, 0x54, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x28, 0x10, 0x60, 0x04, 0x54, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x54, 0x58, 0x20, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x04, 0x54, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00},
+	{0x0e, 0xf0, 0x02, 0x92, 0x9c, 0x60, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x24, 0x18, 0x60, 0x02, 0x92, 0x9c, 0x60, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x02, 0x12, 0x9c, 0x60, 0x0e, 0x70, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x28, 0x50, 0x28, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x14, 0x28, 0x14, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x08, 0x10, 0x54, 0x38, 0x54, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x10, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x2a, 0x14, 0x00, 0x21, 0x69, 0xa9, 0x69, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x08, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x20, 0x10, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x04, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x7c, 0x28, 0x7c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x10, 0x2a, 0x24, 0x1a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x38, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x54, 0x30, 0x18, 0x54, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x08, 0x08, 0x10, 0x10, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x54, 0x58, 0x40, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x06, 0x18, 0x60, 0x06, 0x18, 0x60, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x12, 0xca, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00},
+	{0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x06, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x14, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x24, 0x14, 0x18, 0x60, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x06, 0x18, 0x60, 0x00, 0x00},
+	{0x0a, 0x2a, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x02, 0x12, 0x92, 0x9c, 0x60, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x20, 0x1e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x02, 0x3c, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x01, 0x3e, 0x40, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x20, 0x1c, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x10, 0x0e, 0x10, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x0c, 0x10, 0x0e, 0x10, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x0c, 0x10, 0x0e, 0x10, 0x00, 0x00},
+	{0x00, 0x30, 0x40, 0x38, 0x40, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x40, 0x38, 0x40, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00},
+	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x28, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x50, 0x00, 0x10, 0x10, 0x68, 0x88, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x14, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x14, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x88, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x88, 0x80, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x80, 0x80, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x20, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x80, 0x80, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x15, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0x2a, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0x22, 0x41, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x10, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x40, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0x22, 0x41, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x00, 0x00, 0x0e, 0x10, 0x10, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x89, 0x86, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0a, 0x00, 0x00, 0x06, 0x09, 0x49, 0x87, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x32, 0x42, 0x32, 0x42, 0x02, 0x86, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3c, 0x4b, 0x4a, 0x44, 0x40, 0x40, 0x40, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x32, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x41, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x68, 0x88, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x40, 0x30, 0x4e, 0x49, 0x39, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x24, 0x28, 0xf3, 0x24, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x24, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x24, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x68, 0x90, 0x02, 0x22, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x68, 0x90, 0x02, 0x32, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x80, 0x72, 0xa2, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x40, 0x3a, 0x52, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x42, 0x22, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x18, 0x20, 0x1c, 0x20, 0x00},
+	{0x00, 0x00, 0x22, 0x12, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x18, 0x20, 0x1c, 0x20, 0x00},
+	{0x00, 0x00, 0x42, 0x22, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x22, 0x12, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xf1, 0x35, 0x55, 0x8a, 0xe0, 0x06, 0x95, 0xd6, 0xb5, 0x97, 0x00, 0xee, 0x8a, 0xee, 0x28, 0xe8},
+	{0x00, 0x38, 0x7c, 0x7c, 0xc6, 0x92, 0xf2, 0xe6, 0xfe, 0xe6, 0x7c, 0x7c, 0x38, 0x00, 0x00, 0x00},
+	
+	/* Special glyph for unknown character */
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}
+};
+
+/** @}
+ */
Index: uspace/lib/draw/gfx/font-8x16.h
===================================================================
--- uspace/lib/draw/gfx/font-8x16.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/gfx/font-8x16.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005 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 genarch
+ * @{
+ */
+/** @file
+ */
+
+#ifndef FONT_8X16_H_
+#define FONT_8X16_H_
+
+#include <sys/types.h>
+
+#define FONT_GLYPHS     2899
+#define FONT_WIDTH      8
+#define FONT_SCANLINES  16
+
+extern uint16_t fb_font_glyph(const wchar_t);
+extern uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES];
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/draw/path.c
===================================================================
--- uspace/lib/draw/path.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/path.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <assert.h>
+#include <bool.h>
+#include <malloc.h>
+
+#include "path.h"
+
+struct path {
+	list_t list;
+	double cur_x;
+	double cur_y;
+};
+
+void path_init(path_t *path)
+{
+	list_initialize(&path->list);
+	path->cur_x = 0;
+	path->cur_y = 0;
+}
+
+void path_clear(path_t *path)
+{
+	while (!list_empty(&path->list)) {
+		path_step_t *step = (path_step_t *) list_last(&path->list);
+		list_remove(&step->link);
+		free(step);
+	}
+	path->cur_x = 0;
+	path->cur_y = 0;
+}
+
+void path_get_cursor(path_t *path, double *x, double *y)
+{
+	assert(x);
+	assert(y);
+
+	*x = path->cur_x;
+	*y = path->cur_y;
+}
+
+void path_move_to(path_t *path, double dx, double dy)
+{
+	path_step_t *step = (path_step_t *) malloc(sizeof(path_step_t));
+	if (step) {
+		path->cur_x += dx;
+		path->cur_y += dy;
+		link_initialize(&step->link);
+		step->type = PATH_STEP_MOVETO;
+		step->to_x = path->cur_x;
+		step->to_y = path->cur_y;
+		list_append(&step->link, &path->list);
+		
+	}
+}
+
+void path_line_to(path_t *path, double dx, double dy)
+{
+	path_step_t *step = (path_step_t *) malloc(sizeof(path_step_t));
+	if (step) {
+		path->cur_x += dx;
+		path->cur_y += dy;
+		link_initialize(&step->link);
+		step->type = PATH_STEP_LINETO;
+		step->to_x = path->cur_x;
+		step->to_y = path->cur_y;
+		list_append(&step->link, &path->list);
+	}
+}
+
+void path_rectangle(path_t *path, double x, double y, double width, double height)
+{
+	path_move_to(path, x, y);
+	path_line_to(path, width, 0);
+	path_line_to(path, 0, height);
+	path_line_to(path, -width, 0);
+	path_line_to(path, 0, -height);
+}
+
+/** @}
+ */
Index: uspace/lib/draw/path.h
===================================================================
--- uspace/lib/draw/path.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/path.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef DRAW_PATH_H_
+#define DRAW_PATH_H_
+
+#include <adt/list.h>
+
+typedef enum {
+	PATH_STEP_MOVETO,
+	PATH_STEP_LINETO
+} path_step_type_t;
+
+typedef struct {
+	link_t link;
+	path_step_type_t type;
+	double to_x;
+	double to_y;
+} path_step_t;
+
+struct path;
+typedef struct path path_t;
+
+extern void path_init(path_t *);
+extern void path_clear(path_t *);
+
+extern void path_get_cursor(path_t *, double *, double *);
+
+extern void path_move_to(path_t *, double, double);
+extern void path_line_to(path_t *, double, double);
+
+extern void path_rectangle(path_t *, double, double, double, double);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/draw/source.c
===================================================================
--- uspace/lib/draw/source.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/source.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <assert.h>
+
+#include "source.h"
+
+void source_init(source_t *source)
+{
+	transform_identity(&source->transform);
+	source->filter = filter_nearest;
+	
+	source->color = PIXEL(0, 0, 0, 0);
+	source->texture = NULL;
+	source->texture_tile = false;
+
+	source->alpha = PIXEL(255, 0, 0, 0);
+	source->mask = NULL;
+	source->mask_tile = false;
+}
+
+void source_set_transform(source_t *source, transform_t transform)
+{
+	source->transform = transform;
+	transform_invert(&source->transform);
+}
+
+void source_reset_transform(source_t *source)
+{
+	transform_identity(&source->transform);
+}
+
+void source_set_filter(source_t *source, filter_t filter)
+{
+	source->filter = filter;
+}
+
+void source_set_color(source_t *source, pixel_t color)
+{
+	source->color = color;
+}
+
+void source_set_texture(source_t *source, surface_t *texture, bool tile)
+{
+	source->texture = texture;
+	source->texture_tile = tile;
+}
+
+void source_set_alpha(source_t *source, pixel_t alpha)
+{
+	source->alpha = alpha;
+}
+
+void source_set_mask(source_t *source, surface_t *mask, bool tile)
+{
+	source->mask = mask;
+	source->mask_tile = tile;
+}
+
+pixel_t source_determine_pixel(source_t *source, double x, double y)
+{
+	if (source->mask || source->texture) {
+		transform_apply_affine(&source->transform, &x, &y);
+	}
+
+	pixel_t mask_pix;
+	if (source->mask) {
+		mask_pix = source->filter(
+		    surface_pixmap_access(source->mask),
+		    x, y, source->mask_tile);
+	} else {
+		mask_pix = source->alpha;
+	}
+
+	if (!ALPHA(mask_pix)) {
+		return 0;
+	}
+
+	pixel_t texture_pix;
+	if (source->texture) {
+		texture_pix = source->filter(
+		    surface_pixmap_access(source->texture),
+		    x, y, source->texture_tile);
+	} else {
+		texture_pix = source->color;
+	}
+
+	if (ALPHA(mask_pix) < 255) {
+		double ratio = ((double) ALPHA(mask_pix)) / 255.0;
+		double res_a = ratio * ((double) ALPHA(texture_pix));
+		return PIXEL((unsigned) res_a,
+		    RED(texture_pix), GREEN(texture_pix), BLUE(texture_pix));
+	} else {
+		return texture_pix;
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/draw/source.h
===================================================================
--- uspace/lib/draw/source.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/source.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef DRAW_SOURCE_H_
+#define DRAW_SOURCE_H_
+
+#include <sys/types.h>
+#include <bool.h>
+
+#include <transform.h>
+#include <filter.h>
+
+#include "surface.h"
+
+typedef struct source {
+	transform_t transform;
+	filter_t filter;
+
+	pixel_t color;
+	surface_t *texture;
+	bool texture_tile;
+
+	pixel_t alpha;
+	surface_t *mask;
+	bool mask_tile;
+} source_t;
+
+extern void source_init(source_t *);
+
+extern void source_set_transform(source_t *, transform_t);
+extern void source_reset_transform(source_t *);
+
+extern void source_set_filter(source_t *, filter_t);
+
+extern void source_set_color(source_t *, pixel_t);
+extern void source_set_texture(source_t *, surface_t *, bool);
+
+extern void source_set_alpha(source_t *, pixel_t);
+extern void source_set_mask(source_t *, surface_t *, bool);
+
+extern pixel_t source_determine_pixel(source_t *, double, double);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/draw/surface.c
===================================================================
--- uspace/lib/draw/surface.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/surface.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <malloc.h>
+#include <mem.h>
+#include <as.h>
+#include <assert.h>
+#include "surface.h"
+
+struct surface {
+	surface_flags_t flags;
+
+	surface_coord_t dirty_x_lo;
+	surface_coord_t dirty_x_hi;
+	surface_coord_t dirty_y_lo;
+	surface_coord_t dirty_y_hi;
+
+	pixelmap_t pixmap;
+};
+
+surface_t *surface_create(surface_coord_t width, surface_coord_t height,
+    pixel_t *pixbuf, surface_flags_t flags)
+{
+	surface_t *surface = (surface_t *) malloc(sizeof(surface_t));
+	if (!surface) {
+		return NULL;
+	}
+	
+	size_t pixbuf_size = width * height * sizeof(pixel_t);
+
+	if (!pixbuf) {
+		if ((flags & SURFACE_FLAG_SHARED) == SURFACE_FLAG_SHARED) {
+			pixbuf = (pixel_t *) as_area_create(AS_AREA_ANY, pixbuf_size,
+			    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
+			if (pixbuf == AS_MAP_FAILED) {
+				free(surface);
+				return NULL;
+			}
+		} else {
+			pixbuf = (pixel_t *) malloc(pixbuf_size);
+			if (pixbuf == NULL) {
+				free(surface);
+				return NULL;
+			}
+		}
+
+		memset(pixbuf, 0, pixbuf_size);
+	}
+
+	surface->flags = flags;
+	surface->pixmap.width = width;
+	surface->pixmap.height = height;
+	surface->pixmap.data = pixbuf;
+
+	surface_reset_damaged_region(surface);
+
+	return surface;
+}
+
+void surface_destroy(surface_t *surface)
+{
+	pixel_t *pixbuf = surface->pixmap.data;
+
+	if ((surface->flags & SURFACE_FLAG_SHARED) == SURFACE_FLAG_SHARED)
+		as_area_destroy((void *) pixbuf);
+	else
+		free(pixbuf);
+
+	free(surface);
+}
+
+bool surface_is_shared(surface_t *surface)
+{
+	return ((surface->flags & SURFACE_FLAG_SHARED) == SURFACE_FLAG_SHARED);
+}
+
+pixel_t *surface_direct_access(surface_t *surface)
+{
+	return surface->pixmap.data;
+}
+
+pixelmap_t *surface_pixmap_access(surface_t *surface)
+{
+	return &surface->pixmap;
+}
+
+void surface_get_resolution(surface_t *surface, surface_coord_t *width, surface_coord_t *height)
+{
+	assert(width);
+	assert(height);
+	
+	*width = surface->pixmap.width;
+	*height = surface->pixmap.height;
+}
+
+void surface_get_damaged_region(surface_t *surface, surface_coord_t *x, surface_coord_t *y,
+    surface_coord_t *width, surface_coord_t *height)
+{
+	assert(x);
+	assert(y);
+	assert(width);
+	assert(height);
+
+	*x = surface->dirty_x_lo;
+	*y = surface->dirty_y_lo;
+	*width = surface->dirty_x_lo <= surface->dirty_x_hi ?
+	    (surface->dirty_x_hi - surface->dirty_x_lo) + 1 : 0;
+	*height = surface->dirty_y_lo <= surface->dirty_y_hi ?
+	    (surface->dirty_y_hi - surface->dirty_y_lo) + 1 : 0;
+}
+
+void surface_reset_damaged_region(surface_t *surface)
+{
+	surface->dirty_x_lo = surface->pixmap.width - 1;
+	surface->dirty_x_hi = 0;
+	surface->dirty_y_lo = surface->pixmap.height - 1;
+	surface->dirty_y_hi = 0;
+}
+
+void surface_put_pixel(surface_t *surface, surface_coord_t x, surface_coord_t y, pixel_t pixel)
+{
+	surface->dirty_x_lo = surface->dirty_x_lo > x ? x : surface->dirty_x_lo;
+	surface->dirty_x_hi = surface->dirty_x_hi < x ? x : surface->dirty_x_hi;
+	surface->dirty_y_lo = surface->dirty_y_lo > y ? y : surface->dirty_y_lo;
+	surface->dirty_y_hi = surface->dirty_y_hi < y ? y : surface->dirty_y_hi;
+
+	if (x < surface->pixmap.width && y < surface->pixmap.height) {
+		pixelmap_put_pixel(&surface->pixmap, x, y, pixel);
+	}
+}
+
+pixel_t surface_get_pixel(surface_t *surface, surface_coord_t x, surface_coord_t y)
+{
+	if (x < surface->pixmap.width && y < surface->pixmap.height) {
+		return pixelmap_get_pixel(&surface->pixmap, x, y);
+	} else {
+		return 0;
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/draw/surface.h
===================================================================
--- uspace/lib/draw/surface.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/draw/surface.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * Copyright (c) 2012 Petr Koupy
+ * 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 draw
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef DRAW_SURFACE_H_
+#define DRAW_SURFACE_H_
+
+#include <sys/types.h>
+#include <bool.h>
+#include <io/pixelmap.h>
+
+struct surface;
+typedef struct surface surface_t;
+
+typedef sysarg_t surface_coord_t;
+
+typedef enum {
+	SURFACE_FLAG_NONE = 0,
+	SURFACE_FLAG_SHARED = 1
+} surface_flags_t;
+
+extern surface_t *surface_create(surface_coord_t, surface_coord_t, pixel_t *, surface_flags_t);
+extern void surface_destroy(surface_t *);
+
+extern bool surface_is_shared(surface_t *);
+extern pixel_t *surface_direct_access(surface_t *);
+extern pixelmap_t *surface_pixmap_access(surface_t *);
+extern void surface_get_resolution(surface_t *, surface_coord_t *, surface_coord_t *);
+extern void surface_get_damaged_region(surface_t *, surface_coord_t *, surface_coord_t *,
+    surface_coord_t *, surface_coord_t *);
+extern void surface_reset_damaged_region(surface_t *);
+
+extern void surface_put_pixel(surface_t *, surface_coord_t, surface_coord_t, pixel_t);
+extern pixel_t surface_get_pixel(surface_t *, surface_coord_t, surface_coord_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/drv/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,9 +40,13 @@
 	generic/remote_hw_res.c \
 	generic/remote_char_dev.c \
+	generic/remote_graph_dev.c \
 	generic/remote_nic.c \
 	generic/remote_usb.c \
 	generic/remote_pci.c \
 	generic/remote_usbhc.c \
-	generic/remote_usbhid.c
+	generic/remote_usbhid.c \
+	generic/remote_clock_dev.c \
+	generic/remote_battery_dev.c \
+	generic/remote_ahci.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/drv/generic/dev_iface.c
===================================================================
--- uspace/lib/drv/generic/dev_iface.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/drv/generic/dev_iface.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,4 +41,7 @@
 #include "remote_hw_res.h"
 #include "remote_char_dev.h"
+#include "remote_clock_dev.h"
+#include "remote_battery_dev.h"
+#include "remote_graph_dev.h"
 #include "remote_nic.h"
 #include "remote_usb.h"
@@ -46,4 +49,5 @@
 #include "remote_usbhid.h"
 #include "remote_pci.h"
+#include "remote_ahci.h"
 
 static iface_dipatch_table_t remote_ifaces = {
@@ -51,9 +55,13 @@
 		&remote_hw_res_iface,
 		&remote_char_dev_iface,
+		&remote_graph_dev_iface,
 		&remote_nic_iface,
 		&remote_pci_iface,
 		&remote_usb_iface,
 		&remote_usbhc_iface,
-		&remote_usbhid_iface
+		&remote_usbhid_iface,
+		&remote_clock_dev_iface,
+		&remote_battery_dev_iface,
+		&remote_ahci_iface
 	}
 };
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/drv/generic/driver.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,4 +36,6 @@
 /** @file
  */
+
+#define _DDF_DATA_IMPLANT
 
 #include <assert.h>
@@ -58,4 +60,5 @@
 #include "ddf/driver.h"
 #include "ddf/interrupt.h"
+#include "private/driver.h"
 
 /** Driver structure */
@@ -523,4 +526,6 @@
 static void delete_device(ddf_dev_t *dev)
 {
+	if (dev->parent_sess)
+		async_hangup(dev->parent_sess);
 	if (dev->driver_data != NULL)
 		free(dev->driver_data);
@@ -597,4 +602,96 @@
 }
 
+/** Implant foreign driver-specific device data.
+ *
+ * XXX This is used to transition USB to new interface. Do not use
+ * in new code. Use of this function must be removed.
+ */
+void ddf_fun_data_implant(ddf_fun_t *fun, void *data)
+{
+	assert(fun->driver_data == NULL);
+	fun->driver_data = data;
+}
+
+/** Return driver-specific device data. */
+void *ddf_dev_data_get(ddf_dev_t *dev)
+{
+	return dev->driver_data;
+}
+
+/** Get device handle. */
+devman_handle_t ddf_dev_get_handle(ddf_dev_t *dev)
+{
+	return dev->handle;
+}
+
+/** Return device name.
+ *
+ * @param dev	Device
+ * @return	Device name. Valid as long as @a dev is valid.
+ */
+const char *ddf_dev_get_name(ddf_dev_t *dev)
+{
+	return dev->name;
+}
+
+/** Create session with the parent function.
+ *
+ * The session will be automatically closed when @a dev is destroyed.
+ *
+ * @param dev	Device
+ * @param mgmt	Exchange management style
+ * @return	New session or NULL if session could not be created
+ */
+async_sess_t *ddf_dev_parent_sess_create(ddf_dev_t *dev, exch_mgmt_t mgmt)
+{
+	assert(dev->parent_sess == NULL);
+	dev->parent_sess = devman_parent_device_connect(mgmt, dev->handle,
+	    IPC_FLAG_BLOCKING);
+
+	return dev->parent_sess;
+}
+
+/** Return existing session with the parent function.
+ *
+ * @param dev	Device
+ * @return	Existing session or NULL if there is no session
+ */
+async_sess_t *ddf_dev_parent_sess_get(ddf_dev_t *dev)
+{
+	return dev->parent_sess;
+}
+
+/** Set function name (if it was not specified when node was created.)
+ *
+ * @param dev	Device whose name has not been set yet
+ * @param name	Name, will be copied
+ * @return	EOK on success, ENOMEM if out of memory
+ */
+int ddf_fun_set_name(ddf_fun_t *dev, const char *name)
+{
+	assert(dev->name == NULL);
+
+	dev->name = str_dup(name);
+	if (dev->name == NULL)
+		return ENOENT;
+
+	return EOK;
+}
+
+/** Get device to which function belongs. */
+ddf_dev_t *ddf_fun_get_dev(ddf_fun_t *fun)
+{
+	return fun->dev;
+}
+
+/** Get function handle.
+ *
+ * XXX USB uses this, but its use should be eliminated.
+ */
+devman_handle_t ddf_fun_get_handle(ddf_fun_t *fun)
+{
+	return fun->handle;
+}
+
 /** Create a DDF function node.
  *
@@ -608,5 +705,7 @@
  * This function should only fail if there is not enough free memory.
  * Specifically, this function succeeds even if @a dev already has
- * a (bound) function with the same name.
+ * a (bound) function with the same name. @a name can be NULL in which
+ * case the caller will set the name later using ddf_fun_set_name().
+ * He must do this before binding the function.
  *
  * Type: A function of type fun_inner indicates that DDF should attempt
@@ -616,5 +715,5 @@
  * @param dev		Device to which we are adding function
  * @param ftype		Type of function (fun_inner or fun_exposed)
- * @param name		Name of function
+ * @param name		Name of function or NULL
  *
  * @return		New function or @c NULL if memory is not available
@@ -633,8 +732,10 @@
 	fun->ftype = ftype;
 	
-	fun->name = str_dup(name);
-	if (fun->name == NULL) {
-		delete_function(fun);
-		return NULL;
+	if (name != NULL) {
+		fun->name = str_dup(name);
+		if (fun->name == NULL) {
+			delete_function(fun);
+			return NULL;
+		}
 	}
 	
@@ -654,4 +755,20 @@
 	fun->driver_data = data;
 	return data;
+}
+
+/** Return driver-specific function data. */
+void *ddf_fun_data_get(ddf_fun_t *fun)
+{
+	return fun->driver_data;
+}
+
+/** Return function name.
+ *
+ * @param fun	Function
+ * @return	Function name. Valid as long as @a fun is valid.
+ */
+const char *ddf_fun_get_name(ddf_fun_t *fun)
+{
+	return fun->name;
 }
 
@@ -805,4 +922,21 @@
 	add_match_id(&fun->match_ids, match_id);
 	return EOK;
+}
+
+/** Set function ops. */
+void ddf_fun_set_ops(ddf_fun_t *fun, ddf_dev_ops_t *dev_ops)
+{
+	assert(fun->conn_handler == NULL);
+	fun->ops = dev_ops;
+}
+
+/** Set user-defined connection handler.
+ *
+ * This allows handling connections the non-devman way.
+ */
+void ddf_fun_set_conn_handler(ddf_fun_t *fun, async_client_conn_t conn)
+{
+	assert(fun->ops == NULL);
+	fun->conn_handler = conn;
 }
 
Index: uspace/lib/drv/generic/interrupt.c
===================================================================
--- uspace/lib/drv/generic/interrupt.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/drv/generic/interrupt.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,4 +41,5 @@
 
 #include "ddf/interrupt.h"
+#include "private/driver.h"
 
 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall);
Index: uspace/lib/drv/generic/log.c
===================================================================
--- uspace/lib/drv/generic/log.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/drv/generic/log.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,10 +38,9 @@
  *
  * @param drv_name Driver name, will be printed as part of message
- * @param level    Minimum message level to print
  *
  */
-int ddf_log_init(const char *drv_name, log_level_t level)
+int ddf_log_init(const char *drv_name)
 {
-	return log_init(drv_name, level);
+	return log_init(drv_name);
 }
 
@@ -59,5 +58,5 @@
 	
 	va_start(args, fmt);
-	log_msgv(level, fmt, args);
+	log_msgv(LOG_DEFAULT, level, fmt, args);
 	va_end(args);
 }
Index: uspace/lib/drv/generic/private/driver.h
===================================================================
--- uspace/lib/drv/generic/private/driver.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/generic/private/driver.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2012 Jiri Svoboda
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef DDF_PRIVATE_DRIVER_H_
+#define DDF_PRIVATE_DRIVER_H_
+
+#include <async.h>
+#include <ipc/devman.h>
+#include <ipc/dev_iface.h>
+#include "dev_iface.h"
+
+/** Device structure */
+struct ddf_dev {
+	/**
+	 * Globally unique device identifier (assigned to the device by the
+	 * device manager).
+	 */
+	devman_handle_t handle;
+	
+	/** Reference count */
+	atomic_t refcnt;
+	
+	/** Session with the parent device driver */
+	async_sess_t *parent_sess;
+	
+	/** Device name */
+	const char *name;
+	
+	/** Driver-specific data associated with this device */
+	void *driver_data;
+	
+	/** Link in the list of devices handled by the driver */
+	link_t link;
+};
+
+/** Function structure */
+struct ddf_fun {
+	/** True if bound to the device manager */
+	bool bound;
+	
+	/** Function indentifier (asigned by device manager) */
+	devman_handle_t handle;
+	
+	/** Reference count */
+	atomic_t refcnt;
+	
+	/** Device which this function belogs to */
+	struct ddf_dev *dev;
+	
+	/** Function type */
+	fun_type_t ftype;
+	
+	/** Function name */
+	const char *name;
+	
+	/** List of device ids for driver matching */
+	match_id_list_t match_ids;
+	
+	/** Driver-specific data associated with this function */
+	void *driver_data;
+	
+	/** Implementation of operations provided by this function */
+	ddf_dev_ops_t *ops;
+	
+	/** Connection handler or @c NULL to use the DDF default handler. */
+	async_client_conn_t conn_handler;
+	
+	/** Link in the list of functions handled by the driver */
+	link_t link;
+};
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/generic/remote_ahci.c
===================================================================
--- uspace/lib/drv/generic/remote_ahci.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/generic/remote_ahci.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,208 @@
+/*
+  * Copyright (c) 2012 Petr Jerman
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <stdio.h>
+#include "ahci_iface.h"
+#include "ddf/driver.h"
+
+typedef enum {
+	IPC_M_AHCI_GET_SATA_DEVICE_NAME,
+	IPC_M_AHCI_GET_NUM_BLOCKS,
+	IPC_M_AHCI_GET_BLOCK_SIZE,
+	IPC_M_AHCI_READ_BLOCKS,
+	IPC_M_AHCI_WRITE_BLOCKS
+} ahci_iface_funcs_t;
+
+#define LO(ptr) \
+	((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) & 0xffffffff))
+
+#define HI(ptr) \
+	((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) >> 32))
+
+static void remote_ahci_get_sata_device_name(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+static void remote_ahci_get_num_blocks(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+static void remote_ahci_get_block_size(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+static void remote_ahci_read_blocks(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+static void remote_ahci_write_blocks(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+
+/** Remote AHCI interface operations. */
+static remote_iface_func_ptr_t remote_ahci_iface_ops [] = {
+	[IPC_M_AHCI_GET_SATA_DEVICE_NAME] = remote_ahci_get_sata_device_name,
+	[IPC_M_AHCI_GET_NUM_BLOCKS] = remote_ahci_get_num_blocks,
+	[IPC_M_AHCI_GET_BLOCK_SIZE] = remote_ahci_get_block_size,
+	[IPC_M_AHCI_READ_BLOCKS] = remote_ahci_read_blocks,
+	[IPC_M_AHCI_WRITE_BLOCKS] = remote_ahci_write_blocks
+};
+
+/** Remote AHCI interface structure.
+ */
+remote_iface_t remote_ahci_iface = {
+	.method_count = sizeof(remote_ahci_iface_ops) /
+	    sizeof(remote_ahci_iface_ops[0]),
+	.methods = remote_ahci_iface_ops
+};
+
+void remote_ahci_get_sata_device_name(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
+	
+	if (ahci_iface->get_sata_device_name == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	const size_t sata_dev_name_length =
+	    (size_t) DEV_IPC_GET_ARG1(*call);
+	
+	char* sata_dev_name = malloc(sata_dev_name_length);
+	
+	const int ret = ahci_iface->get_sata_device_name(fun,
+	    sata_dev_name_length, sata_dev_name);
+	
+	size_t real_size;
+	ipc_callid_t cid;
+	if ((async_data_read_receive(&cid, &real_size)) &&
+	    (real_size == sata_dev_name_length))
+		async_data_read_finalize(cid, sata_dev_name, sata_dev_name_length);
+	
+	async_answer_0(callid, ret);
+}
+
+static void remote_ahci_get_num_blocks(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
+	
+	if (ahci_iface->get_num_blocks == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	uint64_t blocks;
+	const int ret = ahci_iface->get_num_blocks(fun, &blocks);
+	
+	if (ret != EOK)
+		async_answer_0(callid, ret);
+	else
+		async_answer_2(callid, EOK, HI(blocks), LO(blocks));
+}
+
+static void remote_ahci_get_block_size(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
+	
+	if (ahci_iface->get_block_size == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	size_t blocks;
+	const int ret = ahci_iface->get_block_size(fun, &blocks);
+	
+	if (ret != EOK)
+		async_answer_0(callid, ret);
+	else
+		async_answer_1(callid, EOK, blocks);
+}
+
+void remote_ahci_read_blocks(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
+	
+	if (ahci_iface->read_blocks == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	size_t maxblock_size;
+	unsigned int flags;
+	
+	ipc_callid_t cid;
+	async_share_out_receive(&cid, &maxblock_size, &flags);
+	
+	void *buf;
+	async_share_out_finalize(cid, &buf);
+	
+	const uint64_t blocknum =
+	    (((uint64_t) (DEV_IPC_GET_ARG1(*call))) << 32) |
+	    (((uint64_t) (DEV_IPC_GET_ARG2(*call))) & 0xffffffff);
+	const size_t cnt = (size_t) DEV_IPC_GET_ARG3(*call);
+	
+	const int ret = ahci_iface->read_blocks(fun, blocknum, cnt, buf);
+	
+	async_answer_0(callid, ret);
+}
+
+void remote_ahci_write_blocks(ddf_fun_t *fun, void *iface, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
+	
+	if (ahci_iface->read_blocks == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	size_t maxblock_size;
+	unsigned int flags;
+	
+	ipc_callid_t cid;
+	async_share_out_receive(&cid, &maxblock_size, &flags);
+	
+	void *buf;
+	async_share_out_finalize(cid, &buf);
+	
+	const uint64_t blocknum =
+	    (((uint64_t)(DEV_IPC_GET_ARG1(*call))) << 32) |
+	    (((uint64_t)(DEV_IPC_GET_ARG2(*call))) & 0xffffffff);
+	const size_t cnt = (size_t) DEV_IPC_GET_ARG3(*call);
+	
+	const int ret = ahci_iface->write_blocks(fun, blocknum, cnt, buf);
+	
+	async_answer_0(callid, ret);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/generic/remote_battery_dev.c
===================================================================
--- uspace/lib/drv/generic/remote_battery_dev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/generic/remote_battery_dev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <ops/battery_dev.h>
+#include <device/battery_dev.h>
+#include <ddf/driver.h>
+
+static void remote_battery_status_get(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+static void remote_battery_charge_level_get(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+
+/** Remote battery interface operations */
+static remote_iface_func_ptr_t remote_battery_dev_iface_ops[] = {
+	&remote_battery_status_get,
+	&remote_battery_charge_level_get,
+};
+
+/** Remote battery interface structure
+ *
+ * Interface for processing request from remote clients
+ * addressed by the battery interface.
+ *
+ */
+remote_iface_t remote_battery_dev_iface = {
+	.method_count = sizeof(remote_battery_dev_iface_ops) /
+	    sizeof(remote_iface_func_ptr_t),
+	.methods = remote_battery_dev_iface_ops,
+};
+
+/** Process the status_get() request from the remote client
+ *
+ * @param fun    The function from which the battery status is read
+ * @param ops    The local ops structure
+ */
+static void
+remote_battery_status_get(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	const battery_dev_ops_t *bops = (battery_dev_ops_t *) ops;
+
+	if (bops->battery_status_get == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	battery_status_t batt_status;
+	const int rc = bops->battery_status_get(fun, &batt_status);
+
+	if (rc != EOK)
+		async_answer_0(callid, rc);
+	else
+		async_answer_1(callid, rc, batt_status);
+}
+
+/** Process the battery_charge_level_get() request from the remote client
+ *
+ * @param fun    The function from which the battery charge level is read
+ * @param ops    The local ops structure
+ *
+ */
+static void
+remote_battery_charge_level_get(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	const battery_dev_ops_t *bops = (battery_dev_ops_t *) ops;
+
+	if (bops->battery_charge_level_get == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	int battery_level;
+	const int rc = bops->battery_charge_level_get(fun, &battery_level);
+
+	if (rc != EOK)
+		async_answer_0(callid, rc);
+	else
+		async_answer_1(callid, rc, battery_level);
+}
+
Index: uspace/lib/drv/generic/remote_clock_dev.c
===================================================================
--- uspace/lib/drv/generic/remote_clock_dev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/generic/remote_clock_dev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <time.h>
+
+#include <ops/clock_dev.h>
+#include <ddf/driver.h>
+
+static void remote_clock_time_get(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+static void remote_clock_time_set(ddf_fun_t *, void *, ipc_callid_t,
+    ipc_call_t *);
+
+/** Remote clock interface operations */
+static remote_iface_func_ptr_t remote_clock_dev_iface_ops[] = {
+	&remote_clock_time_get,
+	&remote_clock_time_set,
+};
+
+/** Remote clock interface structure
+ *
+ * Interface for processing requests from remote clients
+ * addressed by the clock interface.
+ */
+remote_iface_t remote_clock_dev_iface = {
+	.method_count = sizeof(remote_clock_dev_iface_ops) /
+	    sizeof(remote_iface_func_ptr_t),
+	.methods = remote_clock_dev_iface_ops,
+};
+
+/** Process the time_get() request from the remote client
+ *
+ * @param fun   The function from which the time is read
+ * @param ops   The local ops structure
+ */
+static void
+remote_clock_time_get(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	clock_dev_ops_t *clock_dev_ops = (clock_dev_ops_t *) ops;
+	ipc_callid_t cid;
+	struct tm t;
+	int rc;
+	size_t len;
+
+	if (!async_data_read_receive(&cid, &len)) {
+		/* TODO: Handle protocol error */
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (!clock_dev_ops->time_get) {
+		/* The driver does not provide the time_get() functionality */
+		async_answer_0(cid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	rc = (*clock_dev_ops->time_get)(fun, &t);
+
+	if (rc != EOK) {
+		/* Some error occurred */
+		async_answer_0(cid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	/* The operation was successful */
+	async_data_read_finalize(cid, &t, sizeof(struct tm));
+	async_answer_0(callid, rc);
+}
+
+/** Process the time_set() request from the remote client
+ *
+ * @param fun   The function to which the data are written
+ * @param ops   The local ops structure
+ */
+static void remote_clock_time_set(ddf_fun_t *fun, void *ops,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	clock_dev_ops_t *clock_dev_ops = (clock_dev_ops_t *) ops;
+	int          rc;
+	struct tm    t;
+	ipc_callid_t cid;
+	size_t       len;
+
+	if (!async_data_write_receive(&cid, &len)) {
+		/* TODO: Handle protocol error */
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (!clock_dev_ops->time_set) {
+		/* The driver does not support the time_set() functionality */
+		async_answer_0(cid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	async_data_write_finalize(cid, &t, sizeof(struct tm));
+
+	rc = (*clock_dev_ops->time_set)(fun, &t);
+
+	async_answer_0(callid, rc);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/lib/drv/generic/remote_graph_dev.c
===================================================================
--- uspace/lib/drv/generic/remote_graph_dev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/generic/remote_graph_dev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#include <errno.h>
+#include <async.h>
+
+#include "ops/graph_dev.h"
+#include "ddf/driver.h"
+
+static void remote_graph_connect(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+
+static remote_iface_func_ptr_t remote_graph_dev_iface_ops[] = {
+	&remote_graph_connect
+};
+
+remote_iface_t remote_graph_dev_iface = {
+	.method_count = sizeof(remote_graph_dev_iface_ops) /
+	    sizeof(remote_iface_func_ptr_t),
+	.methods = remote_graph_dev_iface_ops
+};
+
+static void remote_graph_connect(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	graph_dev_ops_t *graph_dev_ops = (graph_dev_ops_t *) ops;
+
+	if (!graph_dev_ops->connect || !ddf_fun_data_get(fun)) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	(*graph_dev_ops->connect)(ddf_fun_data_get(fun), callid, call, NULL);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/generic/remote_usb.c
===================================================================
--- uspace/lib/drv/generic/remote_usb.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/drv/generic/remote_usb.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -56,5 +56,5 @@
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	sysarg_t addr;
 	const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
@@ -65,5 +65,5 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Tell interface number given device can use.
  * @param[in] exch IPC communication exchange
@@ -75,5 +75,5 @@
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	sysarg_t iface_no;
 	const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
@@ -83,5 +83,5 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Tell devman handle of device host controller.
  * @param[in] exch IPC communication exchange
@@ -92,5 +92,5 @@
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	devman_handle_t h;
 	const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
@@ -121,5 +121,5 @@
 };
 
-/*----------------------------------------------------------------------------*/
+
 void remote_usb_get_my_address(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -140,5 +140,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -159,5 +159,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usb_get_hc_handle(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -165,5 +165,5 @@
 {
 	if (!exch || !address)
-		return EINVAL;
+		return EBADMEM;
 	sysarg_t new_address;
 	const int ret = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
@@ -173,19 +173,19 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_bind_address(async_exch_t *exch, usb_address_t address,
     devman_handle_t handle)
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	return async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
 	    IPC_M_USBHC_BIND_ADDRESS, address, handle);
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_get_handle(async_exch_t *exch, usb_address_t address,
     devman_handle_t *handle)
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	sysarg_t h;
 	const int ret = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
@@ -195,13 +195,13 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_release_address(async_exch_t *exch, usb_address_t address)
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
 	    IPC_M_USBHC_RELEASE_ADDRESS, address);
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_register_endpoint(async_exch_t *exch, usb_address_t address,
     usb_endpoint_t endpoint, usb_transfer_type_t type,
@@ -209,5 +209,5 @@
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	const usb_target_t target =
 	    {{ .address = address, .endpoint = endpoint }};
@@ -220,23 +220,24 @@
 #undef _PACK2
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_unregister_endpoint(async_exch_t *exch, usb_address_t address,
     usb_endpoint_t endpoint, usb_direction_t direction)
 {
 	if (!exch)
-		return EINVAL;
+		return EBADMEM;
 	return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
 	    IPC_M_USBHC_UNREGISTER_ENDPOINT, address, endpoint, direction);
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_read(async_exch_t *exch, usb_address_t address,
     usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size,
     size_t *rec_size)
 {
+	if (!exch)
+		return EBADMEM;
+
 	if (size == 0 && setup == 0)
 		return EOK;
 
-	if (!exch)
-		return EINVAL;
 	const usb_target_t target =
 	    {{ .address = address, .endpoint = endpoint }};
@@ -284,13 +285,14 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 int usbhc_write(async_exch_t *exch, usb_address_t address,
     usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)
 {
+	if (!exch)
+		return EBADMEM;
+
 	if (size == 0 && setup == 0)
 		return EOK;
 
-	if (!exch)
-		return EINVAL;
 	const usb_target_t target =
 	    {{ .address = address, .endpoint = endpoint }};
@@ -319,5 +321,5 @@
 	return (int) opening_request_rc;
 }
-/*----------------------------------------------------------------------------*/
+
 
 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
@@ -384,5 +386,5 @@
 	return trans;
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -406,5 +408,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -423,5 +425,5 @@
 	async_answer_0(callid, ret);
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usbhc_get_handle(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -444,5 +446,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usbhc_release_address(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -460,5 +462,5 @@
 	async_answer_0(callid, ret);
 }
-/*----------------------------------------------------------------------------*/
+
 static void callback_out(ddf_fun_t *fun,
     int outcome, void *arg)
@@ -470,5 +472,5 @@
 	async_transaction_destroy(trans);
 }
-/*----------------------------------------------------------------------------*/
+
 static void callback_in(ddf_fun_t *fun,
     int outcome, size_t actual_size, void *arg)
@@ -494,5 +496,5 @@
 	async_transaction_destroy(trans);
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
@@ -594,5 +596,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 void remote_usbhc_write(
     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
Index: uspace/lib/drv/include/ahci_iface.h
===================================================================
--- uspace/lib/drv/include/ahci_iface.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/include/ahci_iface.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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 libdrv
+ * @addtogroup ahci
+ * @{
+ */
+/** @file
+ * @brief AHCI interface definition.
+ */
+
+#ifndef LIBDRV_AHCI_IFACE_H_
+#define LIBDRV_AHCI_IFACE_H_
+
+#include "ddf/driver.h"
+#include <async.h>
+
+/** AHCI device communication interface. */
+typedef struct {
+	int (*get_sata_device_name)(ddf_fun_t *, size_t, char *);
+	int (*get_num_blocks)(ddf_fun_t *, uint64_t *);
+	int (*get_block_size)(ddf_fun_t *, size_t *);
+	int (*read_blocks)(ddf_fun_t *, uint64_t, size_t, void *);
+	int (*write_blocks)(ddf_fun_t *, uint64_t, size_t, void *);
+} ahci_iface_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/drv/include/ddf/driver.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,10 +42,11 @@
 #include "../dev_iface.h"
 
-typedef struct ddf_dev ddf_dev_t;
-typedef struct ddf_fun ddf_fun_t;
 
 /*
  * Device
  */
+
+typedef struct ddf_dev ddf_dev_t;
+typedef struct ddf_fun ddf_fun_t;
 
 /** Devices operations */
@@ -75,65 +76,8 @@
 
 /** Device structure */
-struct ddf_dev {
-	/**
-	 * Globally unique device identifier (assigned to the device by the
-	 * device manager).
-	 */
-	devman_handle_t handle;
-	
-	/** Reference count */
-	atomic_t refcnt;
-	
-	/**
-	 * Session to the parent device driver (if it is different from this
-	 * driver)
-	 */
-	async_sess_t *parent_sess;
-	
-	/** Device name */
-	const char *name;
-	
-	/** Driver-specific data associated with this device */
-	void *driver_data;
-	
-	/** Link in the list of devices handled by the driver */
-	link_t link;
-};
+struct ddf_dev;
 
 /** Function structure */
-struct ddf_fun {
-	/** True if bound to the device manager */
-	bool bound;
-	
-	/** Function indentifier (asigned by device manager) */
-	devman_handle_t handle;
-	
-	/** Reference count */
-	atomic_t refcnt;
-	
-	/** Device which this function belogs to */
-	ddf_dev_t *dev;
-	
-	/** Function type */
-	fun_type_t ftype;
-	
-	/** Function name */
-	const char *name;
-	
-	/** List of device ids for driver matching */
-	match_id_list_t match_ids;
-	
-	/** Driver-specific data associated with this function */
-	void *driver_data;
-	
-	/** Implementation of operations provided by this function */
-	ddf_dev_ops_t *ops;
-	
-	/** Connection handler or @c NULL to use the DDF default handler. */
-	async_client_conn_t conn_handler;
-	
-	/** Link in the list of functions handled by the driver */
-	link_t link;
-};
+struct ddf_fun;
 
 /*
@@ -167,10 +111,25 @@
 } driver_t;
 
+/** XXX Only to transition USB */
+#ifdef _DDF_DATA_IMPLANT
+extern void ddf_fun_data_implant(ddf_fun_t *, void *);
+#endif
+
 extern int ddf_driver_main(driver_t *);
 
 extern void *ddf_dev_data_alloc(ddf_dev_t *, size_t);
+extern void *ddf_dev_data_get(ddf_dev_t *);
+extern devman_handle_t ddf_dev_get_handle(ddf_dev_t *);
+extern const char *ddf_dev_get_name(ddf_dev_t *);
+extern async_sess_t *ddf_dev_parent_sess_create(ddf_dev_t *, exch_mgmt_t);
+extern async_sess_t *ddf_dev_parent_sess_get(ddf_dev_t *);
 extern ddf_fun_t *ddf_fun_create(ddf_dev_t *, fun_type_t, const char *);
+extern devman_handle_t ddf_fun_get_handle(ddf_fun_t *);
 extern void ddf_fun_destroy(ddf_fun_t *);
 extern void *ddf_fun_data_alloc(ddf_fun_t *, size_t);
+extern void *ddf_fun_data_get(ddf_fun_t *);
+extern const char *ddf_fun_get_name(ddf_fun_t *);
+extern int ddf_fun_set_name(ddf_fun_t *, const char *);
+extern ddf_dev_t *ddf_fun_get_dev(ddf_fun_t *);
 extern int ddf_fun_bind(ddf_fun_t *);
 extern int ddf_fun_unbind(ddf_fun_t *);
@@ -178,5 +137,6 @@
 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_conn_handler(ddf_fun_t *, async_client_conn_t);
 extern int ddf_fun_add_to_category(ddf_fun_t *, const char *);
 
Index: uspace/lib/drv/include/ddf/log.h
===================================================================
--- uspace/lib/drv/include/ddf/log.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/drv/include/ddf/log.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,7 +35,9 @@
 
 #include <io/log.h>
+#include <io/verify.h>
 
-extern int ddf_log_init(const char *, log_level_t);
-extern void ddf_msg(log_level_t, const char *, ...);
+extern int ddf_log_init(const char *);
+extern void ddf_msg(log_level_t, const char *, ...)
+    PRINTF_ATTRIBUTE(2, 3);
 
 extern void ddf_dump_buffer(char *, size_t, const void *, size_t, size_t,
Index: uspace/lib/drv/include/ops/battery_dev.h
===================================================================
--- uspace/lib/drv/include/ops/battery_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/include/ops/battery_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_OPS_BATTERY_DEV_H_
+#define LIBDRV_OPS_BATTERY_DEV_H_
+
+#include "../ddf/driver.h"
+#include "device/battery_dev.h"
+
+typedef struct {
+	int (*battery_status_get)(ddf_fun_t *, battery_status_t *);
+	int (*battery_charge_level_get)(ddf_fun_t *, int *);
+} battery_dev_ops_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/ops/clock_dev.h
===================================================================
--- uspace/lib/drv/include/ops/clock_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/include/ops/clock_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_OPS_CLOCK_DEV_H_
+#define LIBDRV_OPS_CLOCK_DEV_H_
+
+#include <time.h>
+#include "../ddf/driver.h"
+
+typedef struct {
+	int (*time_get)(ddf_fun_t *, struct tm *);
+	int (*time_set)(ddf_fun_t *, struct tm *);
+} clock_dev_ops_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/ops/graph_dev.h
===================================================================
--- uspace/lib/drv/include/ops/graph_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/include/ops/graph_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_OPS_GRAPH_DEV_H_
+#define LIBDRV_OPS_GRAPH_DEV_H_
+
+#include <async.h>
+#include "../ddf/driver.h"
+
+typedef void (*connect_func)(void *, ipc_callid_t , ipc_call_t *, void *);
+
+typedef struct {
+	connect_func connect;
+} graph_dev_ops_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/remote_ahci.h
===================================================================
--- uspace/lib/drv/include/remote_ahci.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/include/remote_ahci.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_AHCI_H_
+#define LIBDRV_REMOTE_AHCI_H_
+
+extern remote_iface_t remote_ahci_iface;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/remote_battery_dev.h
===================================================================
--- uspace/lib/drv/include/remote_battery_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/include/remote_battery_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_BATTERY_DEV_H_
+#define LIBDRV_REMOTE_BATTERY_DEV_H_
+
+extern remote_iface_t remote_battery_dev_iface;
+
+#endif
+
+/**
+ * @}
+ */
+
Index: uspace/lib/drv/include/remote_clock_dev.h
===================================================================
--- uspace/lib/drv/include/remote_clock_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/include/remote_clock_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_CLOCK_DEV_H_
+#define LIBDRV_REMOTE_CLOCK_DEV_H_
+
+extern remote_iface_t remote_clock_dev_iface;
+
+#endif
+
+/**
+ * @}
+ */
+
Index: uspace/lib/drv/include/remote_graph_dev.h
===================================================================
--- uspace/lib/drv/include/remote_graph_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/drv/include/remote_graph_dev.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_GRAPH_DEV_H_
+#define LIBDRV_REMOTE_GRAPH_DEV_H_
+
+extern remote_iface_t remote_graph_dev_iface;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext2/libext2_block_group.h
===================================================================
--- uspace/lib/ext2/libext2_block_group.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/ext2/libext2_block_group.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,5 +37,5 @@
 #define LIBEXT2_LIBEXT2_BLOCK_GROUP_H_
 
-#include <libblock.h>
+#include <block.h>
 
 typedef struct ext2_block_group {
Index: uspace/lib/ext2/libext2_directory.h
===================================================================
--- uspace/lib/ext2/libext2_directory.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/ext2/libext2_directory.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,5 +37,5 @@
 #define LIBEXT2_LIBEXT2_DIRECTORY_H_
 
-#include <libblock.h>
+#include <block.h>
 #include "libext2_filesystem.h"
 #include "libext2_inode.h"
Index: uspace/lib/ext2/libext2_filesystem.c
===================================================================
--- uspace/lib/ext2/libext2_filesystem.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/ext2/libext2_filesystem.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -39,5 +39,5 @@
 #include "libext2_inode.h"
 #include <errno.h>
-#include <libblock.h>
+#include <block.h>
 #include <malloc.h>
 #include <assert.h>
Index: uspace/lib/ext2/libext2_filesystem.h
===================================================================
--- uspace/lib/ext2/libext2_filesystem.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/ext2/libext2_filesystem.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,5 +37,5 @@
 #define LIBEXT2_LIBEXT2_FILESYSTEM_H_
 
-#include <libblock.h>
+#include <block.h>
 #include "libext2_superblock.h"
 #include "libext2_block_group.h"
Index: uspace/lib/ext2/libext2_inode.h
===================================================================
--- uspace/lib/ext2/libext2_inode.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/ext2/libext2_inode.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,5 +37,5 @@
 #define LIBEXT2_LIBEXT2_INODE_H_
 
-#include <libblock.h>
+#include <block.h>
 #include "libext2_superblock.h"
 
Index: uspace/lib/ext2/libext2_superblock.c
===================================================================
--- uspace/lib/ext2/libext2_superblock.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/ext2/libext2_superblock.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,5 +37,5 @@
 #include <errno.h>
 #include <malloc.h>
-#include <libblock.h>
+#include <block.h>
 #include <byteorder.h>
 
Index: uspace/lib/ext2/libext2_superblock.h
===================================================================
--- uspace/lib/ext2/libext2_superblock.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/ext2/libext2_superblock.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,5 +37,5 @@
 #define LIBEXT2_LIBEXT2_SUPERBLOCK_H_
 
-#include <libblock.h>
+#include <block.h>
 
 typedef struct ext2_superblock {
Index: uspace/lib/ext4/Makefile
===================================================================
--- uspace/lib/ext4/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2012 Frantisek Princ
+# 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 = ../..
+LIBRARY = libext4
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX)
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a
+
+SOURCES = \
+	libext4_balloc.c \
+	libext4_bitmap.c \
+	libext4_block_group.c \
+	libext4_crc.c \
+	libext4_directory.c \
+	libext4_directory_index.c \
+	libext4_extent.c \
+	libext4_filesystem.c \
+	libext4_hash.c \
+	libext4_ialloc.c \
+	libext4_inode.c \
+	libext4_superblock.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/ext4/libext4.h
===================================================================
--- uspace/lib/ext4/libext4.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_H_
+#define LIBEXT4_LIBEXT4_H_
+
+#include "libext4_balloc.h"
+#include "libext4_bitmap.h"
+#include "libext4_block_group.h"
+#include "libext4_crc.h"
+#include "libext4_directory.h"
+#include "libext4_directory_index.h"
+#include "libext4_extent.h"
+#include "libext4_filesystem.h"
+#include "libext4_hash.h"
+#include "libext4_ialloc.h"
+#include "libext4_inode.h"
+#include "libext4_superblock.h"
+#include "libext4_types.h"
+
+#include <stdio.h>
+#define EXT4FS_DBG(format, ...) \
+	printf("ext4fs: %s: " format "\n", \
+	    __FUNCTION__, ##__VA_ARGS__) \
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_balloc.c
===================================================================
--- uspace/lib/ext4/libext4_balloc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_balloc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+/**
+ * @file  libext4_balloc.c
+ * @brief Physical block allocator.
+ */
+
+#include <errno.h>
+#include <sys/types.h>
+#include "libext4.h"
+
+/** Compute number of block group from block address.
+ *
+ * @param sb         Superblock pointer.
+ * @param block_addr Absolute address of block.
+ *
+ * @return Block group index
+ *
+ */
+static uint32_t ext4_balloc_get_bgid_of_block(ext4_superblock_t *sb,
+    uint32_t block_addr)
+{
+	uint32_t blocks_per_group =
+	    ext4_superblock_get_blocks_per_group(sb);
+	uint32_t first_block =
+	    ext4_superblock_get_first_data_block(sb);
+	
+	/* First block == 0 or 1 */
+	if (first_block == 0)
+		return block_addr / blocks_per_group;
+	else
+		return (block_addr - 1) / blocks_per_group;
+}
+
+/** Free block.
+ *
+ * @param inode_ref  Inode, where the block is allocated
+ * @param block_addr Absolute block address to free
+ *
+ * @return Error code
+ *
+ */
+int ext4_balloc_free_block(ext4_inode_ref_t *inode_ref, uint32_t block_addr)
+{
+	ext4_filesystem_t *fs = inode_ref->fs;
+	ext4_superblock_t *sb = fs->superblock;
+	
+	/* Compute indexes */
+	uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, block_addr);
+	uint32_t index_in_group =
+	    ext4_filesystem_blockaddr2_index_in_group(sb, block_addr);
+	
+	/* Load block group reference */
+	ext4_block_group_ref_t *bg_ref;
+	int rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
+	if (rc != EOK)
+		return rc;
+	
+	/* Load block with bitmap */
+	uint32_t bitmap_block_addr =
+	    ext4_block_group_get_block_bitmap(bg_ref->block_group, sb);
+	block_t *bitmap_block;
+	rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0);
+	if (rc != EOK)
+		return rc;
+	
+	/* Modify bitmap */
+	ext4_bitmap_free_bit(bitmap_block->data, index_in_group);
+	bitmap_block->dirty = true;
+	
+	/* Release block with bitmap */
+	rc = block_put(bitmap_block);
+	if (rc != EOK) {
+		/* Error in saving bitmap */
+		ext4_filesystem_put_block_group_ref(bg_ref);
+		return rc;
+	}
+	
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	
+	/* Update superblock free blocks count */
+	uint32_t sb_free_blocks =
+	    ext4_superblock_get_free_blocks_count(sb);
+	sb_free_blocks++;
+	ext4_superblock_set_free_blocks_count(sb, sb_free_blocks);
+	
+	/* Update inode blocks count */
+	uint64_t ino_blocks =
+	    ext4_inode_get_blocks_count(sb, inode_ref->inode);
+	ino_blocks -= block_size / EXT4_INODE_BLOCK_SIZE;
+	ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
+	inode_ref->dirty = true;
+	
+	/* Update block group free blocks count */
+	uint32_t free_blocks =
+	    ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb);
+	free_blocks++;
+	ext4_block_group_set_free_blocks_count(bg_ref->block_group,
+	    sb, free_blocks);
+	bg_ref->dirty = true;
+	
+	/* Release block group reference */
+	rc = ext4_filesystem_put_block_group_ref(bg_ref);
+	if (rc != EOK)
+		return rc;
+	
+	return EOK;
+}
+
+/** Free continuous set of blocks.
+ *
+ * @param inode_ref Inode, where the blocks are allocated
+ * @param first     First block to release
+ * @param count     Number of blocks to release
+ *
+ */
+int ext4_balloc_free_blocks(ext4_inode_ref_t *inode_ref,
+    uint32_t first, uint32_t count)
+{
+	ext4_filesystem_t *fs = inode_ref->fs;
+	ext4_superblock_t *sb = fs->superblock;
+	
+	/* Compute indexes */
+	uint32_t block_group_first =
+	    ext4_balloc_get_bgid_of_block(sb, first);
+	uint32_t block_group_last =
+	    ext4_balloc_get_bgid_of_block(sb, first + count - 1);
+	
+	assert(block_group_first == block_group_last);
+	
+	/* Load block group reference */
+	ext4_block_group_ref_t *bg_ref;
+	int rc = ext4_filesystem_get_block_group_ref(fs, block_group_first, &bg_ref);
+	if (rc != EOK)
+		return rc;
+	
+	uint32_t index_in_group_first =
+	    ext4_filesystem_blockaddr2_index_in_group(sb, first);
+	
+	/* Load block with bitmap */
+	uint32_t bitmap_block_addr =
+	    ext4_block_group_get_block_bitmap(bg_ref->block_group, sb);
+	
+	block_t *bitmap_block;
+	rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0);
+	if (rc != EOK)
+		return rc;
+	
+	/* Modify bitmap */
+	ext4_bitmap_free_bits(bitmap_block->data, index_in_group_first, count);
+	bitmap_block->dirty = true;
+	
+	/* Release block with bitmap */
+	rc = block_put(bitmap_block);
+	if (rc != EOK) {
+		/* Error in saving bitmap */
+		ext4_filesystem_put_block_group_ref(bg_ref);
+		return rc;
+	}
+	
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	
+	/* Update superblock free blocks count */
+	uint32_t sb_free_blocks =
+	    ext4_superblock_get_free_blocks_count(sb);
+	sb_free_blocks += count;
+	ext4_superblock_set_free_blocks_count(sb, sb_free_blocks);
+	
+	/* Update inode blocks count */
+	uint64_t ino_blocks =
+	    ext4_inode_get_blocks_count(sb, inode_ref->inode);
+	ino_blocks -= count * (block_size / EXT4_INODE_BLOCK_SIZE);
+	ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
+	inode_ref->dirty = true;
+	
+	/* Update block group free blocks count */
+	uint32_t free_blocks =
+	    ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb);
+	free_blocks += count;
+	ext4_block_group_set_free_blocks_count(bg_ref->block_group,
+	    sb, free_blocks);
+	bg_ref->dirty = true;
+	
+	/* Release block group reference */
+	rc = ext4_filesystem_put_block_group_ref(bg_ref);
+	if (rc != EOK)
+		return rc;
+	
+	return EOK;
+}
+
+/** Compute first block for data in block group.
+ *
+ * @param sb   Pointer to superblock
+ * @param bg   Pointer to block group
+ * @param bgid Index of block group
+ *
+ * @return Absolute block index of first block
+ *
+ */
+uint32_t ext4_balloc_get_first_data_block_in_group(ext4_superblock_t *sb,
+    ext4_block_group_ref_t *bg_ref)
+{
+	uint32_t block_group_count = ext4_superblock_get_block_group_count(sb);
+	uint32_t inode_table_first_block =
+	    ext4_block_group_get_inode_table_first_block(bg_ref->block_group, sb);
+	uint16_t inode_table_item_size = ext4_superblock_get_inode_size(sb);
+	uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb);
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	uint32_t inode_table_bytes;
+	
+	if (bg_ref->index < block_group_count - 1) {
+		inode_table_bytes = inodes_per_group * inode_table_item_size;
+	} else {
+		/* Last block group could be smaller */
+		uint32_t inodes_count_total = ext4_superblock_get_inodes_count(sb);
+		inode_table_bytes =
+		    (inodes_count_total - ((block_group_count - 1) * inodes_per_group)) *
+		    inode_table_item_size;
+	}
+	
+	uint32_t inode_table_blocks = inode_table_bytes / block_size;
+	
+	if (inode_table_bytes % block_size)
+		inode_table_blocks++;
+	
+	return inode_table_first_block + inode_table_blocks;
+}
+
+/** Compute 'goal' for allocation algorithm.
+ *
+ * @param inode_ref Reference to inode, to allocate block for
+ *
+ * @return Goal block number
+ *
+ */
+static uint32_t ext4_balloc_find_goal(ext4_inode_ref_t *inode_ref)
+{
+	uint32_t goal = 0;
+	
+	ext4_superblock_t *sb = inode_ref->fs->superblock;
+	
+	uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	uint32_t inode_block_count = inode_size / block_size;
+	
+	if (inode_size % block_size != 0)
+		inode_block_count++;
+	
+	/* If inode has some blocks, get last block address + 1 */
+	if (inode_block_count > 0) {
+		int rc = ext4_filesystem_get_inode_data_block_index(inode_ref,
+		    inode_block_count - 1, &goal);
+		if (rc != EOK)
+			return 0;
+		
+		if (goal != 0) {
+			goal++;
+			return goal;
+		}
+		
+		/* If goal == 0, sparse file -> continue */
+	}
+	
+	/* Identify block group of inode */
+	uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb);
+	uint32_t block_group = (inode_ref->index - 1) / inodes_per_group;
+	block_size = ext4_superblock_get_block_size(sb);
+	
+	/* Load block group reference */
+	ext4_block_group_ref_t *bg_ref;
+	int rc = ext4_filesystem_get_block_group_ref(inode_ref->fs,
+	    block_group, &bg_ref);
+	if (rc != EOK)
+		return 0;
+	
+	/* Compute indexes */
+	uint32_t block_group_count = ext4_superblock_get_block_group_count(sb);
+	uint32_t inode_table_first_block =
+	    ext4_block_group_get_inode_table_first_block(bg_ref->block_group, sb);
+	uint16_t inode_table_item_size = ext4_superblock_get_inode_size(sb);
+	uint32_t inode_table_bytes;
+	
+	/* Check for last block group */
+	if (block_group < block_group_count - 1) {
+		inode_table_bytes = inodes_per_group * inode_table_item_size;
+	} else {
+		/* Last block group could be smaller */
+		uint32_t inodes_count_total = ext4_superblock_get_inodes_count(sb);
+		inode_table_bytes =
+		    (inodes_count_total - ((block_group_count - 1) * inodes_per_group)) *
+		    inode_table_item_size;
+	}
+	
+	uint32_t inode_table_blocks = inode_table_bytes / block_size;
+	
+	if (inode_table_bytes % block_size)
+		inode_table_blocks++;
+	
+	goal = inode_table_first_block + inode_table_blocks;
+	
+	ext4_filesystem_put_block_group_ref(bg_ref);
+	
+	return goal;
+}
+
+/** Data block allocation algorithm.
+ *
+ * @param inode_ref Inode to allocate block for
+ * @param fblock    Allocated block address
+ *
+ * @return Error code
+ *
+ */
+int ext4_balloc_alloc_block(ext4_inode_ref_t *inode_ref, uint32_t *fblock)
+{
+	uint32_t allocated_block = 0;
+	
+	uint32_t bitmap_block_addr;
+	block_t *bitmap_block;
+	uint32_t rel_block_idx = 0;
+	
+	/* Find GOAL */
+	uint32_t goal = ext4_balloc_find_goal(inode_ref);
+	if (goal == 0) {
+		/* no goal found => partition is full */
+		return ENOSPC;
+	}
+	
+	ext4_superblock_t *sb = inode_ref->fs->superblock;
+	
+	/* Load block group number for goal and relative index */
+	uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, goal);
+	uint32_t index_in_group =
+	    ext4_filesystem_blockaddr2_index_in_group(sb, goal);
+	
+	/* Load block group reference */
+	ext4_block_group_ref_t *bg_ref;
+	int rc = ext4_filesystem_get_block_group_ref(inode_ref->fs,
+	    block_group, &bg_ref);
+	if (rc != EOK)
+		return rc;
+	
+	/* Compute indexes */
+	uint32_t first_in_group =
+	    ext4_balloc_get_first_data_block_in_group(sb, bg_ref);
+	
+	uint32_t first_in_group_index =
+	    ext4_filesystem_blockaddr2_index_in_group(sb, first_in_group);
+	
+	if (index_in_group < first_in_group_index)
+		index_in_group = first_in_group_index;
+	
+	/* Load block with bitmap */
+	bitmap_block_addr =
+	    ext4_block_group_get_block_bitmap(bg_ref->block_group, sb);
+	
+	rc = block_get(&bitmap_block, inode_ref->fs->device,
+	    bitmap_block_addr, BLOCK_FLAGS_NONE);
+	if (rc != EOK) {
+		ext4_filesystem_put_block_group_ref(bg_ref);
+		return rc;
+	}
+	
+	/* Check if goal is free */
+	if (ext4_bitmap_is_free_bit(bitmap_block->data, index_in_group)) {
+		ext4_bitmap_set_bit(bitmap_block->data, index_in_group);
+		bitmap_block->dirty = true;
+		rc = block_put(bitmap_block);
+		if (rc != EOK) {
+			ext4_filesystem_put_block_group_ref(bg_ref);
+			return rc;
+		}
+		
+		allocated_block =
+		    ext4_filesystem_index_in_group2blockaddr(sb, index_in_group,
+		    block_group);
+		
+		goto success;
+	}
+	
+	uint32_t blocks_in_group =
+	    ext4_superblock_get_blocks_in_group(sb, block_group);
+	
+	uint32_t end_idx = (index_in_group + 63) & ~63;
+	if (end_idx > blocks_in_group)
+		end_idx = blocks_in_group;
+	
+	/* Try to find free block near to goal */
+	for (uint32_t tmp_idx = index_in_group + 1; tmp_idx < end_idx;
+	    ++tmp_idx) {
+		if (ext4_bitmap_is_free_bit(bitmap_block->data, tmp_idx)) {
+			ext4_bitmap_set_bit(bitmap_block->data, tmp_idx);
+			bitmap_block->dirty = true;
+			rc = block_put(bitmap_block);
+			if (rc != EOK)
+				return rc;
+			
+			allocated_block =
+			    ext4_filesystem_index_in_group2blockaddr(sb, tmp_idx,
+			    block_group);
+			
+			goto success;
+		}
+	}
+	
+	/* Find free BYTE in bitmap */
+	rc = ext4_bitmap_find_free_byte_and_set_bit(bitmap_block->data,
+	    index_in_group, &rel_block_idx, blocks_in_group);
+	if (rc == EOK) {
+		bitmap_block->dirty = true;
+		rc = block_put(bitmap_block);
+		if (rc != EOK)
+			return rc;
+		
+		allocated_block =
+		    ext4_filesystem_index_in_group2blockaddr(sb, rel_block_idx,
+		    block_group);
+		
+		goto success;
+	}
+	
+	/* Find free bit in bitmap */
+	rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data,
+	    index_in_group, &rel_block_idx, blocks_in_group);
+	if (rc == EOK) {
+		bitmap_block->dirty = true;
+		rc = block_put(bitmap_block);
+		if (rc != EOK)
+			return rc;
+		
+		allocated_block =
+		    ext4_filesystem_index_in_group2blockaddr(sb, rel_block_idx,
+		    block_group);
+		
+		goto success;
+	}
+	
+	/* No free block found yet */
+	block_put(bitmap_block);
+	ext4_filesystem_put_block_group_ref(bg_ref);
+	
+	/* Try other block groups */
+	uint32_t block_group_count = ext4_superblock_get_block_group_count(sb);
+	
+	uint32_t bgid = (block_group + 1) % block_group_count;
+	uint32_t count = block_group_count;
+	
+	while (count > 0) {
+		rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, bgid,
+		    &bg_ref);
+		if (rc != EOK)
+			return rc;
+		
+		/* Load block with bitmap */
+		bitmap_block_addr =
+		    ext4_block_group_get_block_bitmap(bg_ref->block_group, sb);
+		
+		rc = block_get(&bitmap_block, inode_ref->fs->device,
+		    bitmap_block_addr, 0);
+		if (rc != EOK) {
+			ext4_filesystem_put_block_group_ref(bg_ref);
+			return rc;
+		}
+		
+		/* Compute indexes */
+		first_in_group =
+		    ext4_balloc_get_first_data_block_in_group(sb, bg_ref);
+		index_in_group =
+		    ext4_filesystem_blockaddr2_index_in_group(sb, first_in_group);
+		blocks_in_group = ext4_superblock_get_blocks_in_group(sb, bgid);
+		
+		first_in_group_index =
+		    ext4_filesystem_blockaddr2_index_in_group(sb, first_in_group);
+		
+		if (index_in_group < first_in_group_index)
+			index_in_group = first_in_group_index;
+		
+		/* Try to find free byte in bitmap */
+		rc = ext4_bitmap_find_free_byte_and_set_bit(bitmap_block->data,
+		    index_in_group, &rel_block_idx, blocks_in_group);
+		if (rc == EOK) {
+			bitmap_block->dirty = true;
+			rc = block_put(bitmap_block);
+			if (rc != EOK)
+				return rc;
+			
+			allocated_block =
+			    ext4_filesystem_index_in_group2blockaddr(sb, rel_block_idx,
+			    bgid);
+			
+			goto success;
+		}
+		
+		/* Try to find free bit in bitmap */
+		rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data,
+		    index_in_group, &rel_block_idx, blocks_in_group);
+		if (rc == EOK) {
+			bitmap_block->dirty = true;
+			rc = block_put(bitmap_block);
+			if (rc != EOK)
+				return rc;
+			
+			allocated_block =
+			    ext4_filesystem_index_in_group2blockaddr(sb, rel_block_idx,
+			    bgid);
+			
+			goto success;
+		}
+		
+		block_put(bitmap_block);
+		ext4_filesystem_put_block_group_ref(bg_ref);
+		
+		/* Goto next group */
+		bgid = (bgid + 1) % block_group_count;
+		count--;
+	}
+	
+	return ENOSPC;
+	
+success:
+	/* Empty command - because of syntax */
+	;
+	
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	
+	/* Update superblock free blocks count */
+	uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb);
+	sb_free_blocks--;
+	ext4_superblock_set_free_blocks_count(sb, sb_free_blocks);
+	
+	/* Update inode blocks (different block size!) count */
+	uint64_t ino_blocks =
+	    ext4_inode_get_blocks_count(sb, inode_ref->inode);
+	ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE;
+	ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
+	inode_ref->dirty = true;
+	
+	/* Update block group free blocks count */
+	uint32_t bg_free_blocks =
+	    ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb);
+	bg_free_blocks--;
+	ext4_block_group_set_free_blocks_count(bg_ref->block_group, sb,
+	    bg_free_blocks);
+	bg_ref->dirty = true;
+	
+	ext4_filesystem_put_block_group_ref(bg_ref);
+	
+	*fblock = allocated_block;
+	return EOK;
+}
+
+/** Try to allocate concrete block.
+ *
+ * @param inode_ref Inode to allocate block for
+ * @param fblock    Block address to allocate
+ * @param free      Output value - if target block is free
+ *
+ * @return Error code
+ *
+ */
+int ext4_balloc_try_alloc_block(ext4_inode_ref_t *inode_ref, uint32_t fblock,
+    bool *free)
+{
+	int rc = EOK;
+	
+	ext4_filesystem_t *fs = inode_ref->fs;
+	ext4_superblock_t *sb = fs->superblock;
+	
+	/* Compute indexes */
+	uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, fblock);
+	uint32_t index_in_group =
+	    ext4_filesystem_blockaddr2_index_in_group(sb, fblock);
+	
+	/* Load block group reference */
+	ext4_block_group_ref_t *bg_ref;
+	rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
+	if (rc != EOK)
+		return rc;
+	
+	/* Load block with bitmap */
+	uint32_t bitmap_block_addr =
+	    ext4_block_group_get_block_bitmap(bg_ref->block_group, sb);
+	block_t *bitmap_block;
+	rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0);
+	if (rc != EOK)
+		return rc;
+	
+	/* Check if block is free */
+	*free = ext4_bitmap_is_free_bit(bitmap_block->data, index_in_group);
+	
+	/* Allocate block if possible */
+	if (*free) {
+		ext4_bitmap_set_bit(bitmap_block->data, index_in_group);
+		bitmap_block->dirty = true;
+	}
+	
+	/* Release block with bitmap */
+	rc = block_put(bitmap_block);
+	if (rc != EOK) {
+		/* Error in saving bitmap */
+		ext4_filesystem_put_block_group_ref(bg_ref);
+		return rc;
+	}
+	
+	/* If block is not free, return */
+	if (!(*free))
+		goto terminate;
+	
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	
+	/* Update superblock free blocks count */
+	uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb);
+	sb_free_blocks--;
+	ext4_superblock_set_free_blocks_count(sb, sb_free_blocks);
+	
+	/* Update inode blocks count */
+	uint64_t ino_blocks =
+	    ext4_inode_get_blocks_count(sb, inode_ref->inode);
+	ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE;
+	ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
+	inode_ref->dirty = true;
+	
+	/* Update block group free blocks count */
+	uint32_t free_blocks =
+	    ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb);
+	free_blocks--;
+	ext4_block_group_set_free_blocks_count(bg_ref->block_group,
+	    sb, free_blocks);
+	bg_ref->dirty = true;
+	
+terminate:
+	return ext4_filesystem_put_block_group_ref(bg_ref);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_balloc.h
===================================================================
--- uspace/lib/ext4/libext4_balloc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_balloc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_BALLOC_H_
+#define LIBEXT4_LIBEXT4_BALLOC_H_
+
+#include <sys/types.h>
+#include "libext4_types.h"
+
+extern int ext4_balloc_free_block(ext4_inode_ref_t *, uint32_t);
+extern int ext4_balloc_free_blocks(ext4_inode_ref_t *, uint32_t, uint32_t);
+extern uint32_t ext4_balloc_get_first_data_block_in_group(ext4_superblock_t *,
+    ext4_block_group_ref_t *);
+extern int ext4_balloc_alloc_block(ext4_inode_ref_t *, uint32_t *);
+extern int ext4_balloc_try_alloc_block(ext4_inode_ref_t *, uint32_t, bool *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_bitmap.c
===================================================================
--- uspace/lib/ext4/libext4_bitmap.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_bitmap.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+/**
+ * @file  libext4_bitmap.c
+ * @brief Ext4 bitmap operations.
+ */
+
+#include <errno.h>
+#include <block.h>
+#include <sys/types.h>
+#include "libext4.h"
+
+/** Set bit in bitmap to 0 (free).
+ *
+ * Index must be checked by caller, if it's not out of bounds.
+ *
+ * @param bitmap Pointer to bitmap
+ * @param index  Index of bit in bitmap
+ *
+ */
+void ext4_bitmap_free_bit(uint8_t *bitmap, uint32_t index)
+{
+	uint32_t byte_index = index / 8;
+	uint32_t bit_index = index % 8;
+	
+	uint8_t *target = bitmap + byte_index;
+	
+	*target &= ~ (1 << bit_index);
+}
+
+/** Free continous set of bits (set to 0).
+ *
+ * Index and count must be checked by caller, if they aren't out of bounds.
+ *
+ * @param bitmap Pointer to bitmap
+ * @param index  Index of first bit to zeroed
+ * @param count  Number of bits to be zeroed
+ *
+ */
+void ext4_bitmap_free_bits(uint8_t *bitmap, uint32_t index, uint32_t count)
+{
+	uint8_t *target;
+	uint32_t idx = index;
+	uint32_t remaining = count;
+	uint32_t byte_index;
+	
+	/* Align index to multiple of 8 */
+	while (((idx % 8) != 0) && (remaining > 0)) {
+		byte_index = idx / 8;
+		uint32_t bit_index = idx % 8;
+		
+		target = bitmap + byte_index;
+		*target &= ~ (1 << bit_index);
+		
+		idx++;
+		remaining--;
+	}
+	
+	/* For < 8 bits this check necessary */
+	if (remaining == 0)
+		return;
+	
+	assert((idx % 8) == 0);
+	
+	byte_index = idx / 8;
+	target = bitmap + byte_index;
+	
+	/* Zero the whole bytes */
+	while (remaining >= 8) {
+		*target = 0;
+		
+		idx += 8;
+		remaining -= 8;
+		target++;
+	}
+	
+	assert(remaining < 8);
+	
+	/* Zero remaining bytes */
+	while (remaining != 0) {
+		byte_index = idx / 8;
+		uint32_t bit_index = idx % 8;
+		
+		target = bitmap + byte_index;
+		*target &= ~ (1 << bit_index);
+		
+		idx++;
+		remaining--;
+	}
+}
+
+/** Set bit in bitmap to 1 (used).
+ *
+ * @param bitmap Pointer to bitmap
+ * @param index  Index of bit to set
+ *
+ */
+void ext4_bitmap_set_bit(uint8_t *bitmap, uint32_t index)
+{
+	uint32_t byte_index = index / 8;
+	uint32_t bit_index = index % 8;
+	
+	uint8_t *target = bitmap + byte_index;
+	
+	*target |= 1 << bit_index;
+}
+
+/** Check if requested bit is free.
+ *
+ * @param bitmap Pointer to bitmap
+ * @param index  Index of bit to be checked
+ *
+ * @return True if bit is free, else false
+ *
+ */
+bool ext4_bitmap_is_free_bit(uint8_t *bitmap, uint32_t index)
+{
+	uint32_t byte_index = index / 8;
+	uint32_t bit_index = index % 8;
+	
+	uint8_t *target = bitmap + byte_index;
+	
+	if (*target & (1 << bit_index))
+		return false;
+	else
+		return true;
+}
+
+/** Try to find free byte and set the first bit as used.
+ *
+ * Walk through bitmap and try to find free byte (equal to 0).
+ * If byte found, set the first bit as used.
+ *
+ * @param bitmap Pointer to bitmap
+ * @param start  Index of bit, where the algorithm will begin
+ * @param index  Output value - index of bit (if found free byte)
+ * @param max    Maximum index of bit in bitmap
+ *
+ * @return Error code
+ *
+ */
+int ext4_bitmap_find_free_byte_and_set_bit(uint8_t *bitmap, uint32_t start,
+    uint32_t *index, uint32_t max)
+{
+	uint32_t idx;
+	
+	/* Align idx */
+	if (start % 8)
+		idx = start + (8 - (start % 8));
+	else
+		idx = start;
+	
+	uint8_t *pos = bitmap + (idx / 8);
+	
+	/* Try to find free byte */
+	while (idx < max) {
+		if (*pos == 0) {
+			*pos |= 1;
+			
+			*index = idx;
+			return EOK;
+		}
+		
+		idx += 8;
+		++pos;
+	}
+	
+	/* Free byte not found */
+	return ENOSPC;
+}
+
+/** Try to find free bit and set it as used (1).
+ *
+ * Walk through bitmap and try to find any free bit.
+ *
+ * @param bitmap    Pointer to bitmap
+ * @param start_idx Index of bit, where algorithm will begin
+ * @param index     Output value - index of set bit (if found)
+ * @param max       Maximum index of bit in bitmap
+ *
+ * @return Error code
+ *
+ */
+int ext4_bitmap_find_free_bit_and_set(uint8_t *bitmap, uint32_t start_idx,
+    uint32_t *index, uint32_t max)
+{
+	uint8_t *pos = bitmap + (start_idx / 8);
+	uint32_t idx = start_idx;
+	bool byte_part = false;
+	
+	/* Check the rest of first byte */
+	while ((idx % 8) != 0) {
+		byte_part = true;
+		
+		if ((*pos & (1 << (idx % 8))) == 0) {
+			*pos |= (1 << (idx % 8));
+			*index = idx;
+			return EOK;
+		}
+		
+		++idx;
+	}
+	
+	if (byte_part)
+		++pos;
+	
+	/* Check the whole bytes (255 = 11111111 binary) */
+	while (idx < max) {
+		if ((*pos & 255) != 255) {
+			/* Free bit found */
+			break;
+		}
+		
+		idx += 8;
+		++pos;
+	}
+	
+	/* If idx < max, some free bit found */
+	if (idx < max) {
+		/* Check which bit from byte is free */
+		for (uint8_t i = 0; i < 8; ++i) {
+			if ((*pos & (1 << i)) == 0) {
+				/* Free bit found */
+				*pos |= (1 << i);
+				
+				*index = idx;
+				return EOK;
+			}
+			
+			idx++;
+		}
+	}
+	
+	/* Free bit not found */
+	return ENOSPC;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_bitmap.h
===================================================================
--- uspace/lib/ext4/libext4_bitmap.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_bitmap.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_BITMAP_H_
+#define LIBEXT4_LIBEXT4_BITMAP_H_
+
+#include <sys/types.h>
+
+extern void ext4_bitmap_free_bit(uint8_t *, uint32_t);
+extern void ext4_bitmap_free_bits(uint8_t *, uint32_t, uint32_t);
+extern void ext4_bitmap_set_bit(uint8_t *, uint32_t);
+extern bool ext4_bitmap_is_free_bit(uint8_t *, uint32_t);
+extern int ext4_bitmap_find_free_byte_and_set_bit(uint8_t *, uint32_t,
+    uint32_t *, uint32_t);
+extern int ext4_bitmap_find_free_bit_and_set(uint8_t *, uint32_t, uint32_t *,
+    uint32_t);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_block_group.c
===================================================================
--- uspace/lib/ext4/libext4_block_group.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_block_group.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+/**
+ * @file  libext4_block_group.c
+ * @brief Ext4 block group structure operations.
+ */
+
+#include <byteorder.h>
+#include "libext4.h"
+
+/** Get address of block with data block bitmap.
+ *
+ * @param bg Pointer to block group
+ * @param sb Pointer to superblock
+ *
+ * @return Address of block with block bitmap
+ *
+ */
+uint64_t ext4_block_group_get_block_bitmap(ext4_block_group_t *bg,
+    ext4_superblock_t *sb)
+{
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		return ((uint64_t) uint32_t_le2host(bg->block_bitmap_hi) << 32) |
+		    uint32_t_le2host(bg->block_bitmap_lo);
+	else
+		return uint32_t_le2host(bg->block_bitmap_lo);
+}
+
+/** Set address of block with data block bitmap.
+ *
+ * @param bg           Pointer to block group
+ * @param sb           Pointer to superblock
+ * @param block_bitmap Address of block with block bitmap
+ *
+ */
+void ext4_block_group_set_block_bitmap(ext4_block_group_t *bg,
+    ext4_superblock_t *sb, uint64_t block_bitmap)
+{
+	bg->block_bitmap_lo = host2uint32_t_le((block_bitmap << 32) >> 32);
+	
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		bg->block_bitmap_hi = host2uint32_t_le(block_bitmap >> 32);
+}
+
+/** Get address of block with i-node bitmap.
+ *
+ * @param bg Pointer to block group
+ * @param sb Pointer to superblock
+ *
+ * @return Address of block with i-node bitmap
+ *
+ */
+uint64_t ext4_block_group_get_inode_bitmap(ext4_block_group_t *bg,
+    ext4_superblock_t *sb)
+{
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		return ((uint64_t) uint32_t_le2host(bg->inode_bitmap_hi) << 32) |
+		    uint32_t_le2host(bg->inode_bitmap_lo);
+	else
+		return uint32_t_le2host(bg->inode_bitmap_lo);
+}
+
+/** Set address of block with i-node bitmap.
+ *
+ * @param bg           Pointer to block group
+ * @param sb           Pointer to superblock
+ * @param inode_bitmap Address of block with i-node bitmap
+ *
+ */
+void ext4_block_group_set_inode_bitmap(ext4_block_group_t *bg,
+    ext4_superblock_t *sb, uint64_t inode_bitmap)
+{
+	bg->inode_bitmap_lo = host2uint32_t_le((inode_bitmap << 32) >> 32);
+	
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		bg->inode_bitmap_hi = host2uint32_t_le(inode_bitmap >> 32);
+}
+
+/** Get address of the first block of the i-node table.
+ *
+ * @param bg Pointer to block group
+ * @param sb Pointer to superblock
+ *
+ * @return Address of first block of i-node table
+ *
+ */
+uint64_t ext4_block_group_get_inode_table_first_block(ext4_block_group_t *bg,
+    ext4_superblock_t *sb)
+{
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		return ((uint64_t)
+		    uint32_t_le2host(bg->inode_table_first_block_hi) << 32) |
+		    uint32_t_le2host(bg->inode_table_first_block_lo);
+	else
+		return uint32_t_le2host(bg->inode_table_first_block_lo);
+}
+
+/** Set address of the first block of the i-node table.
+ *
+ * @param bg                Pointer to block group
+ * @param sb                Pointer to superblock
+ * @param inode_table_first Address of first block of i-node table
+ *
+ */
+void ext4_block_group_set_inode_table_first_block(ext4_block_group_t *bg,
+    ext4_superblock_t *sb, uint64_t inode_table_first)
+{
+	bg->inode_table_first_block_lo =
+	    host2uint32_t_le((inode_table_first << 32) >> 32);
+	
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		bg->inode_table_first_block_hi =
+		    host2uint32_t_le(inode_table_first >> 32);
+}
+
+/** Get number of free blocks in block group.
+ *
+ * @param bg Pointer to block group
+ * @param sb Pointer to superblock
+ *
+ * @return Number of free blocks in block group
+ *
+ */
+uint32_t ext4_block_group_get_free_blocks_count(ext4_block_group_t *bg,
+    ext4_superblock_t *sb)
+{
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		return ((uint32_t)
+		    uint16_t_le2host(bg->free_blocks_count_hi) << 16) |
+		    uint16_t_le2host(bg->free_blocks_count_lo);
+	else
+		return uint16_t_le2host(bg->free_blocks_count_lo);
+}
+
+/** Set number of free blocks in block group.
+ *
+ * @param bg    Pointer to block group
+ * @param sb    Pointer to superblock
+ * @param value Number of free blocks in block group
+ *
+ */
+void ext4_block_group_set_free_blocks_count(ext4_block_group_t *bg,
+    ext4_superblock_t *sb, uint32_t value)
+{
+	bg->free_blocks_count_lo = host2uint16_t_le((value << 16) >> 16);
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		bg->free_blocks_count_hi = host2uint16_t_le(value >> 16);
+}
+
+/** Get number of free i-nodes in block group.
+ *
+ * @param bg Pointer to block group
+ * @param sb Pointer to superblock
+ *
+ * @return Number of free i-nodes in block group
+ *
+ */
+uint32_t ext4_block_group_get_free_inodes_count(ext4_block_group_t *bg,
+    ext4_superblock_t *sb)
+{
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		return ((uint32_t)
+		    uint16_t_le2host(bg->free_inodes_count_hi) << 16) |
+		    uint16_t_le2host(bg->free_inodes_count_lo);
+	else
+		return uint16_t_le2host(bg->free_inodes_count_lo);
+}
+
+/** Set number of free i-nodes in block group.
+ *
+ * @param bg    Pointer to block group
+ * @param sb    Pointer to superblock
+ * @param value Number of free i-nodes in block group
+ *
+ */
+void ext4_block_group_set_free_inodes_count(ext4_block_group_t *bg,
+    ext4_superblock_t *sb, uint32_t value)
+{
+	bg->free_inodes_count_lo = host2uint16_t_le((value << 16) >> 16);
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		bg->free_inodes_count_hi = host2uint16_t_le(value >> 16);
+}
+
+/** Get number of used directories in block group.
+ *
+ * @param bg Pointer to block group
+ * @param sb Pointer to superblock
+ *
+ * @return Number of used directories in block group
+ *
+ */
+uint32_t ext4_block_group_get_used_dirs_count(ext4_block_group_t *bg,
+    ext4_superblock_t *sb)
+{
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		return ((uint32_t)
+		    uint16_t_le2host(bg->used_dirs_count_hi) << 16) |
+		    uint16_t_le2host(bg->used_dirs_count_lo);
+	else
+		return uint16_t_le2host(bg->used_dirs_count_lo);
+}
+
+/** Set number of used directories in block group.
+ *
+ * @param bg    Pointer to block group
+ * @param sb    Pointer to superblock
+ * @param value Number of used directories in block group
+ *
+ */
+void ext4_block_group_set_used_dirs_count(ext4_block_group_t *bg,
+    ext4_superblock_t *sb, uint32_t count)
+{
+	bg->used_dirs_count_lo = host2uint16_t_le((count << 16) >> 16);
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		bg->used_dirs_count_hi = host2uint16_t_le(count >> 16);
+}
+
+/** Get flags of block group.
+ *
+ * @param bg Pointer to block group
+ *
+ * @return Flags of block group
+ *
+ */
+uint16_t ext4_block_group_get_flags(ext4_block_group_t *bg)
+{
+	return uint16_t_le2host(bg->flags);
+}
+
+/** Set flags for block group.
+ *
+ * @param bg    Pointer to block group
+ * @param flags Flags for block group
+ *
+ */
+void ext4_block_group_set_flags(ext4_block_group_t *bg, uint16_t flags)
+{
+	bg->flags = host2uint16_t_le(flags);
+}
+
+/** Get number of unused i-nodes.
+ *
+ * @param bg Pointer to block group
+ * @param sb Pointer to superblock
+ *
+ * @return Number of unused i-nodes
+ *
+ */
+uint32_t ext4_block_group_get_itable_unused(ext4_block_group_t *bg,
+    ext4_superblock_t *sb)
+{
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		return ((uint32_t)
+		    uint16_t_le2host(bg->itable_unused_hi) << 16) |
+		    uint16_t_le2host(bg->itable_unused_lo);
+	else
+		return uint16_t_le2host(bg->itable_unused_lo);
+}
+
+/** Set number of unused i-nodes.
+ *
+ * @param bg    Pointer to block group
+ * @param sb    Pointer to superblock
+ * @param value Number of unused i-nodes
+ *
+ */
+void ext4_block_group_set_itable_unused(ext4_block_group_t *bg,
+    ext4_superblock_t *sb, uint32_t value)
+{
+	bg->itable_unused_lo = host2uint16_t_le((value << 16) >> 16);
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		bg->itable_unused_hi = host2uint16_t_le(value >> 16);
+}
+
+/** Get checksum of block group.
+ *
+ * @param bg Pointer to block group
+ *
+ * @return checksum of block group
+ *
+ */
+uint16_t ext4_block_group_get_checksum(ext4_block_group_t *bg)
+{
+	return uint16_t_le2host(bg->checksum);
+}
+
+/** Set checksum of block group.
+ *
+ * @param bg       Pointer to block group
+ * @param checksum Cheksum of block group
+ *
+ */
+void ext4_block_group_set_checksum(ext4_block_group_t *bg, uint16_t checksum)
+{
+	bg->checksum = host2uint16_t_le(checksum);
+}
+
+/** Check if block group has a flag.
+ *
+ * @param bg   Pointer to block group
+ * @param flag Flag to be checked
+ *
+ * @return True if flag is set to 1
+ *
+ */
+bool ext4_block_group_has_flag(ext4_block_group_t *bg, uint32_t flag)
+{
+	if (ext4_block_group_get_flags(bg) & flag)
+		return true;
+	
+	return false;
+}
+
+/** Set (add) flag of block group.
+ *
+ * @param bg   Pointer to block group
+ * @param flag Flag to be set
+ *
+ */
+void ext4_block_group_set_flag(ext4_block_group_t *bg, uint32_t set_flag)
+{
+	uint32_t flags = ext4_block_group_get_flags(bg);
+	flags = flags | set_flag;
+	ext4_block_group_set_flags(bg, flags);
+}
+
+/** Clear (remove) flag of block group.
+ *
+ * @param bg   Pointer to block group
+ * @param flag Flag to be cleared
+ *
+ */
+void ext4_block_group_clear_flag(ext4_block_group_t *bg, uint32_t clear_flag)
+{
+	uint32_t flags = ext4_block_group_get_flags(bg);
+	flags = flags & (~clear_flag);
+	ext4_block_group_set_flags(bg, flags);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_block_group.h
===================================================================
--- uspace/lib/ext4/libext4_block_group.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_block_group.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_BLOCK_GROUP_H_
+#define LIBEXT4_LIBEXT4_BLOCK_GROUP_H_
+
+#include <block.h>
+#include <sys/types.h>
+#include "libext4_types.h"
+
+extern uint64_t ext4_block_group_get_block_bitmap(ext4_block_group_t *,
+    ext4_superblock_t *);
+extern void ext4_block_group_set_block_bitmap(ext4_block_group_t *,
+    ext4_superblock_t *, uint64_t);
+extern uint64_t ext4_block_group_get_inode_bitmap(ext4_block_group_t *,
+    ext4_superblock_t *);
+extern void ext4_block_group_set_inode_bitmap(ext4_block_group_t *,
+    ext4_superblock_t *, uint64_t);
+extern uint64_t ext4_block_group_get_inode_table_first_block(
+    ext4_block_group_t *, ext4_superblock_t *);
+extern void ext4_block_group_set_inode_table_first_block(ext4_block_group_t *,
+    ext4_superblock_t *, uint64_t);
+extern uint32_t ext4_block_group_get_free_blocks_count(ext4_block_group_t *,
+    ext4_superblock_t *);
+extern void ext4_block_group_set_free_blocks_count(ext4_block_group_t *,
+    ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_block_group_get_free_inodes_count(ext4_block_group_t *,
+    ext4_superblock_t *);
+extern void ext4_block_group_set_free_inodes_count(ext4_block_group_t *,
+    ext4_superblock_t *, uint32_t);
+extern void ext4_block_group_set_free_inodes_count(ext4_block_group_t *,
+    ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_block_group_get_used_dirs_count(ext4_block_group_t *,
+    ext4_superblock_t *);
+extern void ext4_block_group_set_used_dirs_count(ext4_block_group_t *,
+    ext4_superblock_t *, uint32_t);
+extern uint16_t ext4_block_group_get_flags(ext4_block_group_t *);
+extern void ext4_block_group_set_flags(ext4_block_group_t *, uint16_t);
+extern uint32_t ext4_block_group_get_itable_unused(ext4_block_group_t *,
+    ext4_superblock_t *);
+extern void ext4_block_group_set_itable_unused(ext4_block_group_t *,
+    ext4_superblock_t *, uint32_t);
+extern uint16_t ext4_block_group_get_checksum(ext4_block_group_t *);
+extern void ext4_block_group_set_checksum(ext4_block_group_t *, uint16_t);
+
+extern bool ext4_block_group_has_flag(ext4_block_group_t *, uint32_t);
+extern void ext4_block_group_set_flag(ext4_block_group_t *, uint32_t);
+extern void ext4_block_group_clear_flag(ext4_block_group_t *, uint32_t);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_crc.c
===================================================================
--- uspace/lib/ext4/libext4_crc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_crc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+/**
+ * @file  libext4_crc.c
+ */
+
+#include "libext4.h"
+
+uint16_t crc16(uint16_t crc, const uint8_t *buffer, size_t len)
+{
+	// TODO
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_crc.h
===================================================================
--- uspace/lib/ext4/libext4_crc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_crc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_CRC_H_
+#define LIBEXT4_LIBEXT4_CRC_H_
+
+extern uint16_t crc16(uint16_t, const uint8_t *, size_t);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_directory.c
===================================================================
--- uspace/lib/ext4/libext4_directory.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_directory.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,766 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+/**
+ * @file  libext4_directory.c
+ * @brief Ext4 directory structure operations.
+ */
+
+#include <byteorder.h>
+#include <errno.h>
+#include <malloc.h>
+#include "libext4.h"
+
+/** Get i-node number from directory entry.
+ *
+ * @param de Directory entry
+ *
+ * @return I-node number
+ *
+ */
+uint32_t ext4_directory_entry_ll_get_inode(ext4_directory_entry_ll_t *de)
+{
+	return uint32_t_le2host(de->inode);
+}
+
+/** Set i-node number to directory entry.
+ *
+ * @param de    Directory entry
+ * @param inode I-node number
+ *
+ */
+void ext4_directory_entry_ll_set_inode(ext4_directory_entry_ll_t *de,
+    uint32_t inode)
+{
+	de->inode = host2uint32_t_le(inode);
+}
+
+/** Get directory entry length.
+ *
+ * @param de Directory entry
+ *
+ * @return Entry length
+ *
+ */
+uint16_t ext4_directory_entry_ll_get_entry_length(ext4_directory_entry_ll_t *de)
+{
+	return uint16_t_le2host(de->entry_length);
+}
+
+/** Set directory entry length.
+ *
+ * @param de     Directory entry
+ * @param length Entry length
+ *
+ */
+void ext4_directory_entry_ll_set_entry_length(ext4_directory_entry_ll_t *de,
+    uint16_t length)
+{
+	de->entry_length = host2uint16_t_le(length);
+}
+
+/** Get directory entry name length.
+ *
+ * @param sb Superblock
+ * @param de Directory entry
+ *
+ * @return Entry name length
+ *
+ */
+uint16_t ext4_directory_entry_ll_get_name_length(ext4_superblock_t *sb,
+    ext4_directory_entry_ll_t *de)
+{
+	if ((ext4_superblock_get_rev_level(sb) == 0) &&
+	    (ext4_superblock_get_minor_rev_level(sb) < 5))
+		return ((uint16_t)de->name_length_high) << 8 |
+		    ((uint16_t)de->name_length);
+	
+	return de->name_length;
+
+}
+
+/** Set directory entry name length.
+ *
+ * @param sb     Superblock
+ * @param de     Directory entry
+ * @param length Entry name length
+ *
+ */
+void ext4_directory_entry_ll_set_name_length(ext4_superblock_t *sb,
+    ext4_directory_entry_ll_t *de, uint16_t length)
+{
+	de->name_length = (length << 8) >> 8;
+	
+	if ((ext4_superblock_get_rev_level(sb) == 0) &&
+	    (ext4_superblock_get_minor_rev_level(sb) < 5))
+		de->name_length_high = length >> 8;
+	
+	/* Else do nothing */
+}
+
+/** Get i-node type of directory entry.
+ *
+ * @param sb Superblock
+ * @param de Directory entry
+ *
+ * @return I-node type (file, dir, etc.)
+ *
+ */
+uint8_t ext4_directory_entry_ll_get_inode_type(ext4_superblock_t *sb,
+    ext4_directory_entry_ll_t *de)
+{
+	if ((ext4_superblock_get_rev_level(sb) > 0) ||
+	    (ext4_superblock_get_minor_rev_level(sb) >= 5))
+		return de->inode_type;
+	
+	return EXT4_DIRECTORY_FILETYPE_UNKNOWN;
+}
+
+/** Set i-node type of directory entry.
+ *
+ * @param sb   Superblock
+ * @param de   Directory entry
+ * @param type I-node type (file, dir, etc.)
+ *
+ */
+void ext4_directory_entry_ll_set_inode_type(ext4_superblock_t *sb,
+    ext4_directory_entry_ll_t *de, uint8_t type)
+{
+	if ((ext4_superblock_get_rev_level(sb) > 0) ||
+	    (ext4_superblock_get_minor_rev_level(sb) >= 5))
+		de->inode_type = type;
+	
+	/* Else do nothing */
+}
+
+static int ext4_directory_iterator_seek(ext4_directory_iterator_t *, aoff64_t);
+static int ext4_directory_iterator_set(ext4_directory_iterator_t *, uint32_t);
+
+/** Initialize directory iterator.
+ *
+ * Set position to the first valid entry from the required position.
+ *
+ * @param it        Pointer to iterator to be initialized
+ * @param inode_ref Directory i-node
+ * @param pos       Position to start reading entries from
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_iterator_init(ext4_directory_iterator_t *it,
+    ext4_inode_ref_t *inode_ref, aoff64_t pos)
+{
+	it->inode_ref = inode_ref;
+	it->current = NULL;
+	it->current_offset = 0;
+	it->current_block = NULL;
+	
+	return ext4_directory_iterator_seek(it, pos);
+}
+
+/** Jump to the next valid entry
+ *
+ * @param it Initialized iterator
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_iterator_next(ext4_directory_iterator_t *it)
+{
+	assert(it->current != NULL);
+	
+	uint16_t skip = ext4_directory_entry_ll_get_entry_length(it->current);
+	
+	return ext4_directory_iterator_seek(it, it->current_offset + skip);
+}
+
+/** Seek to next valid directory entry.
+ *
+ * Here can be jumped to the next data block.
+ *
+ * @param it  Initialized iterator
+ * @param pos Position of the next entry
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_iterator_seek(ext4_directory_iterator_t *it, aoff64_t pos)
+{
+	uint64_t size = ext4_inode_get_size(it->inode_ref->fs->superblock,
+	    it->inode_ref->inode);
+	
+	/* The iterator is not valid until we seek to the desired position */
+	it->current = NULL;
+	
+	/* Are we at the end? */
+	if (pos >= size) {
+		if (it->current_block) {
+			int rc = block_put(it->current_block);
+			it->current_block = NULL;
+			
+			if (rc != EOK)
+				return rc;
+		}
+		
+		it->current_offset = pos;
+		return EOK;
+	}
+	
+	/* Compute next block address */
+	uint32_t block_size =
+	    ext4_superblock_get_block_size(it->inode_ref->fs->superblock);
+	aoff64_t current_block_idx = it->current_offset / block_size;
+	aoff64_t next_block_idx = pos / block_size;
+	
+	/*
+	 * If we don't have a block or are moving accross block boundary,
+	 * we need to get another block
+	 */
+	if ((it->current_block == NULL) ||
+	    (current_block_idx != next_block_idx)) {
+		if (it->current_block) {
+			int rc = block_put(it->current_block);
+			it->current_block = NULL;
+			
+			if (rc != EOK)
+				return rc;
+		}
+		
+		uint32_t next_block_phys_idx;
+		int rc = ext4_filesystem_get_inode_data_block_index(it->inode_ref,
+		    next_block_idx, &next_block_phys_idx);
+		if (rc != EOK)
+			return rc;
+		
+		rc = block_get(&it->current_block, it->inode_ref->fs->device,
+		    next_block_phys_idx, BLOCK_FLAGS_NONE);
+		if (rc != EOK) {
+			it->current_block = NULL;
+			return rc;
+		}
+	}
+	
+	it->current_offset = pos;
+	
+	return ext4_directory_iterator_set(it, block_size);
+}
+
+/** Do some checks before returning iterator.
+ *
+ * @param it         Iterator to be checked
+ * @param block_size Size of data block
+ *
+ * @return Error code
+ *
+ */
+static int ext4_directory_iterator_set(ext4_directory_iterator_t *it,
+    uint32_t block_size)
+{
+	it->current = NULL;
+	
+	uint32_t offset_in_block = it->current_offset % block_size;
+	
+	/* Ensure proper alignment */
+	if ((offset_in_block % 4) != 0)
+		return EIO;
+	
+	/* Ensure that the core of the entry does not overflow the block */
+	if (offset_in_block > block_size - 8)
+		return EIO;
+	
+	ext4_directory_entry_ll_t *entry =
+	    it->current_block->data + offset_in_block;
+	
+	/* Ensure that the whole entry does not overflow the block */
+	uint16_t length = ext4_directory_entry_ll_get_entry_length(entry);
+	if (offset_in_block + length > block_size)
+		return EIO;
+	
+	/* Ensure the name length is not too large */
+	if (ext4_directory_entry_ll_get_name_length(
+	    it->inode_ref->fs->superblock, entry) > length-8)
+		return EIO;
+	
+	/* Everything OK - "publish" the entry */
+	it->current = entry;
+	return EOK;
+}
+
+/** Uninitialize directory iterator.
+ *
+ * Release all allocated structures.
+ *
+ * @param it Iterator to be finished
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_iterator_fini(ext4_directory_iterator_t *it)
+{
+	it->inode_ref = NULL;
+	it->current = NULL;
+	
+	if (it->current_block)
+		return block_put(it->current_block);
+	
+	return EOK;
+}
+
+/** Write directory entry to concrete data block.
+ *
+ * @param sb        Superblock
+ * @param entry     Pointer to entry to be written
+ * @param entry_len Length of new entry
+ * @param child     Child i-node to be written to new entry
+ * @param name      Name of the new entry
+ * @param name_len  Length of entry name
+ *
+ */
+void ext4_directory_write_entry(ext4_superblock_t *sb,
+    ext4_directory_entry_ll_t *entry, uint16_t entry_len,
+    ext4_inode_ref_t *child, const char *name, size_t name_len)
+{
+	/* Check maximum entry length */
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	assert(entry_len <= block_size);
+	
+	/* Set basic attributes */
+	ext4_directory_entry_ll_set_inode(entry, child->index);
+	ext4_directory_entry_ll_set_entry_length(entry, entry_len);
+	ext4_directory_entry_ll_set_name_length(sb, entry, name_len);
+	
+	/* Write name */
+	memcpy(entry->name, name, name_len);
+	
+	/* Set type of entry */
+	if (ext4_inode_is_type(sb, child->inode, EXT4_INODE_MODE_DIRECTORY))
+		ext4_directory_entry_ll_set_inode_type(sb, entry,
+		    EXT4_DIRECTORY_FILETYPE_DIR);
+	else
+		ext4_directory_entry_ll_set_inode_type(sb, entry,
+		    EXT4_DIRECTORY_FILETYPE_REG_FILE);
+}
+
+/** Add new entry to the directory.
+ *
+ * @param parent Directory i-node
+ * @param name   Name of new entry
+ * @param child  I-node to be referenced from new entry
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_add_entry(ext4_inode_ref_t *parent, const char *name,
+    ext4_inode_ref_t *child)
+{
+	ext4_filesystem_t *fs = parent->fs;
+	
+	/* Index adding (if allowed) */
+	if ((ext4_superblock_has_feature_compatible(fs->superblock,
+	    EXT4_FEATURE_COMPAT_DIR_INDEX)) &&
+	    (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {
+		int rc = ext4_directory_dx_add_entry(parent, child, name);
+		
+		/* Check if index is not corrupted */
+		if (rc != EXT4_ERR_BAD_DX_DIR) {
+			if (rc != EOK)
+				return rc;
+			
+			return EOK;
+		}
+		
+		/* Needed to clear dir index flag if corrupted */
+		ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);
+		parent->dirty = true;
+	}
+	
+	/* Linear algorithm */
+	
+	uint32_t iblock = 0;
+	uint32_t fblock = 0;
+	uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
+	uint32_t inode_size = ext4_inode_get_size(fs->superblock, parent->inode);
+	uint32_t total_blocks = inode_size / block_size;
+	
+	uint32_t name_len = str_size(name);
+	
+	/* Find block, where is space for new entry and try to add */
+	bool success = false;
+	for (iblock = 0; iblock < total_blocks; ++iblock) {
+		int rc = ext4_filesystem_get_inode_data_block_index(parent,
+		    iblock, &fblock);
+		if (rc != EOK)
+			return rc;
+		
+		block_t *block;
+		rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
+		if (rc != EOK)
+			return rc;
+		
+		/* If adding is successful, function can finish */
+		rc = ext4_directory_try_insert_entry(fs->superblock, block,
+		    child, name, name_len);
+		if (rc == EOK)
+			success = true;
+		
+		rc = block_put(block);
+		if (rc != EOK)
+			return rc;
+		
+		if (success)
+			return EOK;
+	}
+	
+	/* No free block found - needed to allocate next data block */
+	
+	iblock = 0;
+	fblock = 0;
+	int rc = ext4_filesystem_append_inode_block(parent, &fblock, &iblock);
+	if (rc != EOK)
+		return rc;
+	
+	/* Load new block */
+	block_t *new_block;
+	rc = block_get(&new_block, fs->device, fblock, BLOCK_FLAGS_NOREAD);
+	if (rc != EOK)
+		return rc;
+	
+	/* Fill block with zeroes */
+	memset(new_block->data, 0, block_size);
+	ext4_directory_entry_ll_t *block_entry = new_block->data;
+	ext4_directory_write_entry(fs->superblock, block_entry, block_size,
+	    child, name, name_len);
+	
+	/* Save new block */
+	new_block->dirty = true;
+	rc = block_put(new_block);
+	
+	return rc;
+}
+
+/** Find directory entry with passed name.
+ *
+ * @param result Result structure to be returned if entry found
+ * @param parent Directory i-node
+ * @param name   Name of entry to be found
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_find_entry(ext4_directory_search_result_t *result,
+    ext4_inode_ref_t *parent, const char *name)
+{
+	uint32_t name_len = str_size(name);
+	
+	ext4_superblock_t *sb = parent->fs->superblock;
+	
+	/* Index search */
+	if ((ext4_superblock_has_feature_compatible(sb,
+	    EXT4_FEATURE_COMPAT_DIR_INDEX)) &&
+	    (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {
+		int rc = ext4_directory_dx_find_entry(result, parent, name_len,
+		    name);
+		
+		/* Check if index is not corrupted */
+		if (rc != EXT4_ERR_BAD_DX_DIR) {
+			if (rc != EOK)
+				return rc;
+			
+			return EOK;
+		}
+		
+		/* Needed to clear dir index flag if corrupted */
+		ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);
+		parent->dirty = true;
+	}
+	
+	/* Linear algorithm */
+	
+	uint32_t iblock;
+	uint32_t fblock;
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	uint32_t inode_size = ext4_inode_get_size(sb, parent->inode);
+	uint32_t total_blocks = inode_size / block_size;
+	
+	/* Walk through all data blocks */
+	for (iblock = 0; iblock < total_blocks; ++iblock) {
+		/* Load block address */
+		int rc = ext4_filesystem_get_inode_data_block_index(parent, iblock,
+		    &fblock);
+		if (rc != EOK)
+			return rc;
+		
+		/* Load data block */
+		block_t *block;
+		rc = block_get(&block, parent->fs->device, fblock, BLOCK_FLAGS_NONE);
+		if (rc != EOK)
+			return rc;
+		
+		/* Try to find entry in block */
+		ext4_directory_entry_ll_t *res_entry;
+		rc = ext4_directory_find_in_block(block, sb, name_len, name,
+		    &res_entry);
+		if (rc == EOK) {
+			result->block = block;
+			result->dentry = res_entry;
+			return EOK;
+		}
+		
+		/* Entry not found - put block and continue to the next block */
+		
+		rc = block_put(block);
+		if (rc != EOK)
+			return rc;
+	}
+	
+	/* Entry was not found */
+	
+	result->block = NULL;
+	result->dentry =  NULL;
+	
+	return ENOENT;
+}
+
+/** Remove directory entry.
+ *
+ * @param parent Directory i-node
+ * @param name   Name of the entry to be removed
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_remove_entry(ext4_inode_ref_t *parent, const char *name)
+{
+	/* Check if removing from directory */
+	if (!ext4_inode_is_type(parent->fs->superblock, parent->inode,
+	    EXT4_INODE_MODE_DIRECTORY))
+		return ENOTDIR;
+	
+	/* Try to find entry */
+	ext4_directory_search_result_t result;
+	int rc = ext4_directory_find_entry(&result, parent, name);
+	if (rc != EOK)
+		return rc;
+	
+	/* Invalidate entry */
+	ext4_directory_entry_ll_set_inode(result.dentry, 0);
+	
+	/* Store entry position in block */
+	uint32_t pos = (void *) result.dentry - result.block->data;
+	
+	/*
+	 * If entry is not the first in block, it must be merged
+	 * with previous entry
+	 */
+	if (pos != 0) {
+		uint32_t offset = 0;
+		
+		/* Start from the first entry in block */
+		ext4_directory_entry_ll_t *tmp_dentry = result.block->data;
+		uint16_t tmp_dentry_length =
+		    ext4_directory_entry_ll_get_entry_length(tmp_dentry);
+		
+		/* Find direct predecessor of removed entry */
+		while ((offset + tmp_dentry_length) < pos) {
+			offset +=
+			    ext4_directory_entry_ll_get_entry_length(tmp_dentry);
+			tmp_dentry = result.block->data + offset;
+			tmp_dentry_length =
+			    ext4_directory_entry_ll_get_entry_length(tmp_dentry);
+		}
+		
+		assert(tmp_dentry_length + offset == pos);
+		
+		/* Add to removed entry length to predecessor's length */
+		uint16_t del_entry_length =
+		    ext4_directory_entry_ll_get_entry_length(result.dentry);
+		ext4_directory_entry_ll_set_entry_length(tmp_dentry,
+		    tmp_dentry_length + del_entry_length);
+	}
+	
+	result.block->dirty = true;
+	
+	return ext4_directory_destroy_result(&result);
+}
+
+/** Try to insert entry to concrete data block.
+ *
+ * @param sb           Superblock
+ * @param target_block Block to try to insert entry to
+ * @param child        Child i-node to be inserted by new entry
+ * @param name         Name of the new entry
+ * @param name_len     Length of the new entry name
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_try_insert_entry(ext4_superblock_t *sb,
+    block_t *target_block, ext4_inode_ref_t *child, const char *name,
+    uint32_t name_len)
+{
+	/* Compute required length entry and align it to 4 bytes */
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	uint16_t required_len = sizeof(ext4_fake_directory_entry_t) + name_len;
+	
+	if ((required_len % 4) != 0)
+		required_len += 4 - (required_len % 4);
+	
+	/* Initialize pointers, stop means to upper bound */
+	ext4_directory_entry_ll_t *dentry = target_block->data;
+	ext4_directory_entry_ll_t *stop = target_block->data + block_size;
+	
+	/*
+	 * Walk through the block and check for invalid entries
+	 * or entries with free space for new entry
+	 */
+	while (dentry < stop) {
+		uint32_t inode = ext4_directory_entry_ll_get_inode(dentry);
+		uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(dentry);
+		
+		/* If invalid and large enough entry, use it */
+		if ((inode == 0) && (rec_len >= required_len)) {
+			ext4_directory_write_entry(sb, dentry, rec_len, child,
+			    name, name_len);
+			target_block->dirty = true;
+			
+			return EOK;
+		}
+		
+		/* Valid entry, try to split it */
+		if (inode != 0) {
+			uint16_t used_name_len =
+			    ext4_directory_entry_ll_get_name_length(sb, dentry);
+			
+			uint16_t used_space =
+			    sizeof(ext4_fake_directory_entry_t) + used_name_len;
+			
+			if ((used_name_len % 4) != 0)
+				used_space += 4 - (used_name_len % 4);
+			
+			uint16_t free_space = rec_len - used_space;
+			
+			/* There is free space for new entry */
+			if (free_space >= required_len) {
+				/* Cut tail of current entry */
+				ext4_directory_entry_ll_set_entry_length(dentry, used_space);
+				ext4_directory_entry_ll_t *new_entry =
+				    (void *) dentry + used_space;
+				ext4_directory_write_entry(sb, new_entry,
+				    free_space, child, name, name_len);
+				
+				target_block->dirty = true;
+				
+				return EOK;
+			}
+		}
+		
+		/* Jump to the next entry */
+		dentry = (void *) dentry + rec_len;
+	}
+	
+	/* No free space found for new entry */
+	return ENOSPC;
+}
+
+/** Try to find entry in block by name.
+ *
+ * @param block     Block containing entries
+ * @param sb        Superblock
+ * @param name_len  Length of entry name
+ * @param name      Name of entry to be found
+ * @param res_entry Output pointer to found entry, NULL if not found
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_find_in_block(block_t *block, ext4_superblock_t *sb,
+    size_t name_len, const char *name, ext4_directory_entry_ll_t **res_entry)
+{
+	/* Start from the first entry in block */
+	ext4_directory_entry_ll_t *dentry =
+	    (ext4_directory_entry_ll_t *) block->data;
+	
+	/* Set upper bound for cycling */
+	uint8_t *addr_limit = block->data + ext4_superblock_get_block_size(sb);
+	
+	/* Walk through the block and check entries */
+	while ((uint8_t *) dentry < addr_limit) {
+		/* Termination condition */
+		if ((uint8_t *) dentry + name_len > addr_limit)
+			break;
+		
+		/* Valid entry - check it */
+		if (dentry->inode != 0) {
+			/* For more effectivity compare firstly only lengths */
+			if (ext4_directory_entry_ll_get_name_length(sb, dentry) ==
+			    name_len) {
+				/* Compare names */
+				if (bcmp((uint8_t *) name, dentry->name, name_len) == 0) {
+					*res_entry = dentry;
+					return EOK;
+				}
+			}
+		}
+		
+		uint16_t dentry_len =
+		    ext4_directory_entry_ll_get_entry_length(dentry);
+		
+		/* Corrupted entry */
+		if (dentry_len == 0)
+			return EINVAL;
+		
+		/* Jump to next entry */
+		dentry = (ext4_directory_entry_ll_t *) ((uint8_t *) dentry + dentry_len);
+	}
+	
+	/* Entry not found */
+	return ENOENT;
+}
+
+/** Simple function to release allocated data from result.
+ *
+ * @param result Search result to destroy
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_destroy_result(ext4_directory_search_result_t *result)
+{
+	if (result->block)
+		return block_put(result->block);
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_directory.h
===================================================================
--- uspace/lib/ext4/libext4_directory.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_directory.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_DIRECTORY_H_
+#define LIBEXT4_LIBEXT4_DIRECTORY_H_
+
+#include "libext4_types.h"
+
+extern uint32_t ext4_directory_entry_ll_get_inode(ext4_directory_entry_ll_t *);
+extern void ext4_directory_entry_ll_set_inode(ext4_directory_entry_ll_t *,
+    uint32_t);
+extern uint16_t ext4_directory_entry_ll_get_entry_length(
+    ext4_directory_entry_ll_t *);
+extern void ext4_directory_entry_ll_set_entry_length(ext4_directory_entry_ll_t *,
+    uint16_t);
+extern uint16_t ext4_directory_entry_ll_get_name_length(ext4_superblock_t *,
+    ext4_directory_entry_ll_t *);
+extern void ext4_directory_entry_ll_set_name_length(ext4_superblock_t *,
+    ext4_directory_entry_ll_t *, uint16_t);
+extern uint8_t ext4_directory_entry_ll_get_inode_type(ext4_superblock_t *,
+    ext4_directory_entry_ll_t *);
+extern void ext4_directory_entry_ll_set_inode_type(ext4_superblock_t *,
+    ext4_directory_entry_ll_t *, uint8_t);
+
+extern int ext4_directory_iterator_init(ext4_directory_iterator_t *,
+    ext4_inode_ref_t *, aoff64_t);
+extern int ext4_directory_iterator_next(ext4_directory_iterator_t *);
+extern int ext4_directory_iterator_fini(ext4_directory_iterator_t *);
+
+extern void ext4_directory_write_entry(ext4_superblock_t *,
+    ext4_directory_entry_ll_t *, uint16_t, ext4_inode_ref_t *,
+    const char *, size_t);
+extern int ext4_directory_add_entry(ext4_inode_ref_t *, const char *,
+    ext4_inode_ref_t *);
+extern int ext4_directory_find_entry(ext4_directory_search_result_t *,
+    ext4_inode_ref_t *, const char *);
+extern int ext4_directory_remove_entry(ext4_inode_ref_t *, const char *);
+
+extern int ext4_directory_try_insert_entry(ext4_superblock_t *, block_t *,
+    ext4_inode_ref_t *, const char *, uint32_t);
+
+extern int ext4_directory_find_in_block(block_t *, ext4_superblock_t *, size_t,
+    const char *, ext4_directory_entry_ll_t **);
+
+extern int ext4_directory_destroy_result(ext4_directory_search_result_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_directory_index.c
===================================================================
--- uspace/lib/ext4/libext4_directory_index.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_directory_index.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1159 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+/**
+ * @file  libext4_directory_index.c
+ * @brief Ext4 directory index operations.
+ */
+
+#include <byteorder.h>
+#include <errno.h>
+#include <malloc.h>
+#include <sort.h>
+#include "libext4.h"
+
+/** Type entry to pass to sorting algorithm.
+ *
+ */
+typedef struct ext4_dx_sort_entry {
+	uint32_t hash;
+	uint32_t rec_len;
+	void *dentry;
+} ext4_dx_sort_entry_t;
+
+/** Get hash version used in directory index.
+ *
+ * @param root_info Pointer to root info structure of index
+ *
+ * @return Hash algorithm version
+ *
+ */
+uint8_t ext4_directory_dx_root_info_get_hash_version(
+    ext4_directory_dx_root_info_t *root_info)
+{
+	return root_info->hash_version;
+}
+
+/** Set hash version, that will be used in directory index.
+ *
+ * @param root_info Pointer to root info structure of index
+ * @param version   Hash algorithm version
+ *
+ */
+void ext4_directory_dx_root_info_set_hash_version(
+    ext4_directory_dx_root_info_t *root_info, uint8_t version)
+{
+	root_info->hash_version = version;
+}
+
+/** Get length of root_info structure in bytes.
+ *
+ * @param root_info Pointer to root info structure of index
+ *
+ * @return Length of the structure
+ *
+ */
+uint8_t ext4_directory_dx_root_info_get_info_length(
+    ext4_directory_dx_root_info_t *root_info)
+{
+	return root_info->info_length;
+}
+
+/** Set length of root_info structure in bytes.
+ *
+ * @param root_info   Pointer to root info structure of index
+ * @param info_length Length of the structure
+ *
+ */
+void ext4_directory_dx_root_info_set_info_length(
+    ext4_directory_dx_root_info_t *root_info, uint8_t info_length)
+{
+	root_info->info_length = info_length;
+}
+
+/** Get number of indirect levels of HTree.
+ *
+ * @param root_info Pointer to root info structure of index
+ *
+ * @return Height of HTree (actually only 0 or 1)
+ *
+ */
+uint8_t ext4_directory_dx_root_info_get_indirect_levels(
+    ext4_directory_dx_root_info_t *root_info)
+{
+	return root_info->indirect_levels;
+}
+
+/** Set number of indirect levels of HTree.
+ *
+ * @param root_info Pointer to root info structure of index
+ * @param levels    Height of HTree (actually only 0 or 1)
+ *
+ */
+void ext4_directory_dx_root_info_set_indirect_levels(
+    ext4_directory_dx_root_info_t *root_info, uint8_t levels)
+{
+	root_info->indirect_levels = levels;
+}
+
+/** Get maximum number of index node entries.
+ *
+ * @param countlimit Pointer to counlimit structure
+ *
+ * @return Maximum of entries in node
+ *
+ */
+uint16_t ext4_directory_dx_countlimit_get_limit(
+    ext4_directory_dx_countlimit_t *countlimit)
+{
+	return uint16_t_le2host(countlimit->limit);
+}
+
+/** Set maximum number of index node entries.
+ *
+ * @param countlimit Pointer to counlimit structure
+ * @param limit      Maximum of entries in node
+ *
+ */
+void ext4_directory_dx_countlimit_set_limit(
+    ext4_directory_dx_countlimit_t *countlimit, uint16_t limit)
+{
+	countlimit->limit = host2uint16_t_le(limit);
+}
+
+/** Get current number of index node entries.
+ *
+ * @param countlimit Pointer to counlimit structure
+ *
+ * @return Number of entries in node
+ *
+ */
+uint16_t ext4_directory_dx_countlimit_get_count(
+    ext4_directory_dx_countlimit_t *countlimit)
+{
+	return uint16_t_le2host(countlimit->count);
+}
+
+/** Set current number of index node entries.
+ *
+ * @param countlimit Pointer to counlimit structure
+ * @param count      Number of entries in node
+ *
+ */
+void ext4_directory_dx_countlimit_set_count(
+    ext4_directory_dx_countlimit_t *countlimit, uint16_t count)
+{
+	countlimit->count = host2uint16_t_le(count);
+}
+
+/** Get hash value of index entry.
+ *
+ * @param entry Pointer to index entry
+ *
+ * @return Hash value
+ *
+ */
+uint32_t ext4_directory_dx_entry_get_hash(ext4_directory_dx_entry_t *entry)
+{
+	return uint32_t_le2host(entry->hash);
+}
+
+/** Set hash value of index entry.
+ *
+ * @param entry Pointer to index entry
+ * @param hash  Hash value
+ *
+ */
+void ext4_directory_dx_entry_set_hash(ext4_directory_dx_entry_t *entry,
+    uint32_t hash)
+{
+	entry->hash = host2uint32_t_le(hash);
+}
+
+/** Get block address where child node is located.
+ *
+ * @param entry Pointer to index entry
+ *
+ * @return Block address of child node
+ *
+ */
+uint32_t ext4_directory_dx_entry_get_block(ext4_directory_dx_entry_t *entry)
+{
+	return uint32_t_le2host(entry->block);
+}
+
+/** Set block address where child node is located.
+ *
+ * @param entry Pointer to index entry
+ * @param block Block address of child node
+ *
+ */
+void ext4_directory_dx_entry_set_block(ext4_directory_dx_entry_t *entry,
+    uint32_t block)
+{
+	entry->block = host2uint32_t_le(block);
+}
+
+/** Initialize index structure of new directory.
+ *
+ * @param dir Pointer to directory i-node
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_dx_init(ext4_inode_ref_t *dir)
+{
+	/* Load block 0, where will be index root located */
+	uint32_t fblock;
+	int rc = ext4_filesystem_get_inode_data_block_index(dir, 0,
+	    &fblock);
+	if (rc != EOK)
+		return rc;
+	
+	block_t *block;
+	rc = block_get(&block, dir->fs->device, fblock, BLOCK_FLAGS_NONE);
+	if (rc != EOK)
+		return rc;
+	
+	/* Initialize pointers to data structures */
+	ext4_directory_dx_root_t *root = block->data;
+	ext4_directory_dx_root_info_t *info = &(root->info);
+	
+	/* Initialize root info structure */
+	uint8_t hash_version =
+	    ext4_superblock_get_default_hash_version(dir->fs->superblock);
+	
+	ext4_directory_dx_root_info_set_hash_version(info, hash_version);
+	ext4_directory_dx_root_info_set_indirect_levels(info, 0);
+	ext4_directory_dx_root_info_set_info_length(info, 8);
+	
+	/* Set limit and current number of entries */
+	ext4_directory_dx_countlimit_t *countlimit =
+	    (ext4_directory_dx_countlimit_t *) &root->entries;
+	ext4_directory_dx_countlimit_set_count(countlimit, 1);
+	
+	uint32_t block_size =
+	    ext4_superblock_get_block_size(dir->fs->superblock);
+	uint32_t entry_space =
+	    block_size - 2 * sizeof(ext4_directory_dx_dot_entry_t) -
+	    sizeof(ext4_directory_dx_root_info_t);
+	uint16_t root_limit = entry_space / sizeof(ext4_directory_dx_entry_t);
+	ext4_directory_dx_countlimit_set_limit(countlimit, root_limit);
+	
+	/* Append new block, where will be new entries inserted in the future */
+	uint32_t iblock;
+	rc = ext4_filesystem_append_inode_block(dir, &fblock, &iblock);
+	if (rc != EOK) {
+		block_put(block);
+		return rc;
+	}
+	
+	block_t *new_block;
+	rc = block_get(&new_block, dir->fs->device, fblock, BLOCK_FLAGS_NOREAD);
+	if (rc != EOK) {
+		block_put(block);
+		return rc;
+	}
+	
+	/* Fill the whole block with empty entry */
+	ext4_directory_entry_ll_t *block_entry = new_block->data;
+	ext4_directory_entry_ll_set_entry_length(block_entry, block_size);
+	ext4_directory_entry_ll_set_inode(block_entry, 0);
+	
+	new_block->dirty = true;
+	rc = block_put(new_block);
+	if (rc != EOK) {
+		block_put(block);
+		return rc;
+	}
+	
+	/* Connect new block to the only entry in index */
+	ext4_directory_dx_entry_t *entry = root->entries;
+	ext4_directory_dx_entry_set_block(entry, iblock);
+	
+	block->dirty = true;
+	
+	return block_put(block);
+}
+
+/** Initialize hash info structure necessary for index operations.
+ *
+ * @param hinfo      Pointer to hinfo to be initialized
+ * @param root_block Root block (number 0) of index
+ * @param sb         Pointer to superblock
+ * @param name_len   Length of name to be computed hash value from
+ * @param name       Name to be computed hash value from
+ *
+ * @return Error code
+ *
+ */
+static int ext4_directory_hinfo_init(ext4_hash_info_t *hinfo,
+    block_t *root_block, ext4_superblock_t *sb, size_t name_len,
+    const char *name)
+{
+	ext4_directory_dx_root_t *root =
+	    (ext4_directory_dx_root_t *) root_block->data;
+	
+	if ((root->info.hash_version != EXT4_HASH_VERSION_TEA) &&
+	    (root->info.hash_version != EXT4_HASH_VERSION_HALF_MD4) &&
+	    (root->info.hash_version != EXT4_HASH_VERSION_LEGACY))
+		return EXT4_ERR_BAD_DX_DIR;
+	
+	/* Check unused flags */
+	if (root->info.unused_flags != 0)
+		return EXT4_ERR_BAD_DX_DIR;
+	
+	/* Check indirect levels */
+	if (root->info.indirect_levels > 1)
+		return EXT4_ERR_BAD_DX_DIR;
+	
+	/* Check if node limit is correct */
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	uint32_t entry_space = block_size;
+	entry_space -= 2 * sizeof(ext4_directory_dx_dot_entry_t);
+	entry_space -= sizeof(ext4_directory_dx_root_info_t);
+	entry_space = entry_space / sizeof(ext4_directory_dx_entry_t);
+	
+	uint16_t limit = ext4_directory_dx_countlimit_get_limit(
+	    (ext4_directory_dx_countlimit_t *) &root->entries);
+	if (limit != entry_space)
+		return EXT4_ERR_BAD_DX_DIR;
+	
+	/* Check hash version and modify if necessary */
+	hinfo->hash_version =
+	    ext4_directory_dx_root_info_get_hash_version(&root->info);
+	if ((hinfo->hash_version <= EXT4_HASH_VERSION_TEA) &&
+	    (ext4_superblock_has_flag(sb, EXT4_SUPERBLOCK_FLAGS_UNSIGNED_HASH))) {
+		/* 3 is magic from ext4 linux implementation */
+		hinfo->hash_version += 3;
+	}
+	
+	/* Load hash seed from superblock */
+	hinfo->seed = ext4_superblock_get_hash_seed(sb);
+	
+	/* Compute hash value of name */
+	if (name)
+		ext4_hash_string(hinfo, name_len, name);
+	
+	return EOK;
+}
+
+/** Walk through index tree and load leaf with corresponding hash value.
+ *
+ * @param hinfo      Initialized hash info structure
+ * @param inode_ref  Current i-node
+ * @param root_block Root block (iblock 0), where is root node located
+ * @param dx_block   Pointer to leaf node in dx_blocks array
+ * @param dx_blocks  Array with the whole path from root to leaf
+ *
+ * @return Error code
+ *
+ */
+static int ext4_directory_dx_get_leaf(ext4_hash_info_t *hinfo,
+    ext4_inode_ref_t *inode_ref, block_t *root_block,
+    ext4_directory_dx_block_t **dx_block, ext4_directory_dx_block_t *dx_blocks)
+{
+	ext4_directory_dx_block_t *tmp_dx_block = dx_blocks;
+	ext4_directory_dx_root_t *root =
+	    (ext4_directory_dx_root_t *) root_block->data;
+	ext4_directory_dx_entry_t *entries =
+	    (ext4_directory_dx_entry_t *) &root->entries;
+	
+	uint16_t limit = ext4_directory_dx_countlimit_get_limit(
+	    (ext4_directory_dx_countlimit_t *) entries);
+	uint8_t indirect_level =
+	    ext4_directory_dx_root_info_get_indirect_levels(&root->info);
+	
+	block_t *tmp_block = root_block;
+	ext4_directory_dx_entry_t *p;
+	ext4_directory_dx_entry_t *q;
+	ext4_directory_dx_entry_t *m;
+	ext4_directory_dx_entry_t *at;
+	
+	/* Walk through the index tree */
+	while (true) {
+		uint16_t count = ext4_directory_dx_countlimit_get_count(
+		    (ext4_directory_dx_countlimit_t *) entries);
+		if ((count == 0) || (count > limit))
+			return EXT4_ERR_BAD_DX_DIR;
+		
+		/* Do binary search in every node */
+		p = entries + 1;
+		q = entries + count - 1;
+		
+		while (p <= q) {
+			m = p + (q - p) / 2;
+			if (ext4_directory_dx_entry_get_hash(m) > hinfo->hash)
+				q = m - 1;
+			else
+				p = m + 1;
+		}
+		
+		at = p - 1;
+		
+		/* Write results */
+		tmp_dx_block->block = tmp_block;
+		tmp_dx_block->entries = entries;
+		tmp_dx_block->position = at;
+		
+		/* Is algorithm in the leaf? */
+		if (indirect_level == 0) {
+			*dx_block = tmp_dx_block;
+			return EOK;
+		}
+		
+		/* Goto child node */
+		uint32_t next_block = ext4_directory_dx_entry_get_block(at);
+		
+		indirect_level--;
+		
+		uint32_t fblock;
+		int rc = ext4_filesystem_get_inode_data_block_index(inode_ref,
+		    next_block, &fblock);
+		if (rc != EOK)
+			return rc;
+		
+		rc = block_get(&tmp_block, inode_ref->fs->device, fblock,
+		    BLOCK_FLAGS_NONE);
+		if (rc != EOK)
+			return rc;
+		
+		entries = ((ext4_directory_dx_node_t *) tmp_block->data)->entries;
+		limit = ext4_directory_dx_countlimit_get_limit(
+		    (ext4_directory_dx_countlimit_t *) entries);
+		
+		uint16_t entry_space =
+		    ext4_superblock_get_block_size(inode_ref->fs->superblock) -
+		    sizeof(ext4_directory_dx_dot_entry_t);
+		entry_space = entry_space / sizeof(ext4_directory_dx_entry_t);
+		
+		if (limit != entry_space) {
+			block_put(tmp_block);
+			return EXT4_ERR_BAD_DX_DIR;
+		}
+		
+		++tmp_dx_block;
+	}
+	
+	/* Unreachable */
+	return EOK;
+}
+
+/** Check if the the next block would be checked during entry search.
+ *
+ * @param inode_ref Directory i-node
+ * @param hash      Hash value to check
+ * @param dx_block  Current block
+ * @param dx_blocks Array with path from root to leaf node
+ *
+ * @return Error code
+ *
+ */
+static int ext4_directory_dx_next_block(ext4_inode_ref_t *inode_ref,
+    uint32_t hash, ext4_directory_dx_block_t *dx_block,
+    ext4_directory_dx_block_t *dx_blocks)
+{
+	uint32_t num_handles = 0;
+	ext4_directory_dx_block_t *p = dx_block;
+	
+	/* Try to find data block with next bunch of entries */
+	while (true) {
+		p->position++;
+		uint16_t count = ext4_directory_dx_countlimit_get_count(
+		    (ext4_directory_dx_countlimit_t *) p->entries);
+		
+		if (p->position < p->entries + count)
+			break;
+		
+		if (p == dx_blocks)
+			return EOK;
+		
+		num_handles++;
+		p--;
+	}
+	
+	/* Check hash collision (if not occured - no next block cannot be used) */
+	uint32_t current_hash = ext4_directory_dx_entry_get_hash(p->position);
+	if ((hash & 1) == 0) {
+		if ((current_hash & ~1) != hash)
+			return 0;
+	}
+	
+	/* Fill new path */
+	while (num_handles--) {
+		uint32_t block_idx =
+		    ext4_directory_dx_entry_get_block(p->position);
+		uint32_t block_addr;
+		
+		int rc = ext4_filesystem_get_inode_data_block_index(inode_ref,
+		    block_idx, &block_addr);
+		if (rc != EOK)
+			return rc;
+		
+		block_t *block;
+		rc = block_get(&block, inode_ref->fs->device, block_addr, BLOCK_FLAGS_NONE);
+		if (rc != EOK)
+			return rc;
+		
+		p++;
+		
+		/* Don't forget to put old block (prevent memory leak) */
+		block_put(p->block);
+		
+		p->block = block;
+		p->entries = ((ext4_directory_dx_node_t *) block->data)->entries;
+		p->position = p->entries;
+	}
+	
+	return ENOENT;
+}
+
+/** Try to find directory entry using directory index.
+ *
+ * @param result    Output value - if entry will be found,
+ *                  than will be passed through this parameter
+ * @param inode_ref Directory i-node
+ * @param name_len  Length of name to be found
+ * @param name      Name to be found
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_dx_find_entry(ext4_directory_search_result_t *result,
+    ext4_inode_ref_t *inode_ref, size_t name_len, const char *name)
+{
+	/* Load direct block 0 (index root) */
+	uint32_t root_block_addr;
+	int rc = ext4_filesystem_get_inode_data_block_index(inode_ref, 0,
+	    &root_block_addr);
+	if (rc != EOK)
+		return rc;
+	
+	ext4_filesystem_t *fs = inode_ref->fs;
+	
+	block_t *root_block;
+	rc = block_get(&root_block, fs->device, root_block_addr,
+	    BLOCK_FLAGS_NONE);
+	if (rc != EOK)
+		return rc;
+	
+	/* Initialize hash info (compute hash value) */
+	ext4_hash_info_t hinfo;
+	rc = ext4_directory_hinfo_init(&hinfo, root_block, fs->superblock,
+	    name_len, name);
+	if (rc != EOK) {
+		block_put(root_block);
+		return EXT4_ERR_BAD_DX_DIR;
+	}
+	
+	/*
+	 * Hardcoded number 2 means maximum height of index tree,
+	 * specified in the Linux driver.
+	 */
+	ext4_directory_dx_block_t dx_blocks[2];
+	ext4_directory_dx_block_t *dx_block;
+	ext4_directory_dx_block_t *tmp;
+	
+	rc = ext4_directory_dx_get_leaf(&hinfo, inode_ref, root_block,
+	    &dx_block, dx_blocks);
+	if (rc != EOK) {
+		block_put(root_block);
+		return EXT4_ERR_BAD_DX_DIR;
+	}
+	
+	do {
+		/* Load leaf block */
+		uint32_t leaf_block_idx =
+		    ext4_directory_dx_entry_get_block(dx_block->position);
+		uint32_t leaf_block_addr;
+		
+		rc = ext4_filesystem_get_inode_data_block_index(inode_ref,
+		    leaf_block_idx, &leaf_block_addr);
+		if (rc != EOK)
+			goto cleanup;
+		
+		block_t *leaf_block;
+		rc = block_get(&leaf_block, fs->device, leaf_block_addr,
+		    BLOCK_FLAGS_NONE);
+		if (rc != EOK)
+			goto cleanup;
+		
+		/* Linear search inside block */
+		ext4_directory_entry_ll_t *res_dentry;
+		rc = ext4_directory_find_in_block(leaf_block, fs->superblock,
+		    name_len, name, &res_dentry);
+		
+		/* Found => return it */
+		if (rc == EOK) {
+			result->block = leaf_block;
+			result->dentry = res_dentry;
+			goto cleanup;
+		}
+		
+		/* Not found, leave untouched */
+		block_put(leaf_block);
+		
+		if (rc != ENOENT)
+			goto cleanup;
+		
+		/* check if the next block could be checked */
+		rc = ext4_directory_dx_next_block(inode_ref, hinfo.hash,
+		    dx_block, &dx_blocks[0]);
+		if (rc < 0)
+			goto cleanup;
+	} while (rc == ENOENT);
+	
+	/* Entry not found */
+	rc = ENOENT;
+	
+cleanup:
+	/* The whole path must be released (preventing memory leak) */
+	tmp = dx_blocks;
+	
+	while (tmp <= dx_block) {
+		block_put(tmp->block);
+		++tmp;
+	}
+	
+	return rc;
+}
+
+/** Compare function used to pass in quicksort implementation.
+ *
+ * It can compare two entries by hash value.
+ *
+ * @param arg1  First entry
+ * @param arg2  Second entry
+ * @param dummy Unused parameter, can be NULL
+ *
+ * @return Classic compare result
+ *         (0: equal, -1: arg1 < arg2, 1: arg1 > arg2)
+ *
+ */
+static int ext4_directory_dx_entry_comparator(void *arg1, void *arg2, void *dummy)
+{
+	ext4_dx_sort_entry_t *entry1 = arg1;
+	ext4_dx_sort_entry_t *entry2 = arg2;
+	
+	if (entry1->hash == entry2->hash)
+		return 0;
+	
+	if (entry1->hash < entry2->hash)
+		return -1;
+	else
+		return 1;
+}
+
+/** Insert new index entry to block.
+ *
+ * Note that space for new entry must be checked by caller.
+ *
+ * @param index_block Block where to insert new entry
+ * @param hash        Hash value covered by child node
+ * @param iblock      Logical number of child block
+ *
+ */
+static void ext4_directory_dx_insert_entry(
+    ext4_directory_dx_block_t *index_block, uint32_t hash, uint32_t iblock)
+{
+	ext4_directory_dx_entry_t *old_index_entry = index_block->position;
+	ext4_directory_dx_entry_t *new_index_entry = old_index_entry + 1;
+	
+	ext4_directory_dx_countlimit_t *countlimit =
+	    (ext4_directory_dx_countlimit_t *) index_block->entries;
+	uint32_t count = ext4_directory_dx_countlimit_get_count(countlimit);
+	
+	ext4_directory_dx_entry_t *start_index = index_block->entries;
+	size_t bytes = (void *) (start_index + count) - (void *) (new_index_entry);
+	
+	memmove(new_index_entry + 1, new_index_entry, bytes);
+	
+	ext4_directory_dx_entry_set_block(new_index_entry, iblock);
+	ext4_directory_dx_entry_set_hash(new_index_entry, hash);
+	
+	ext4_directory_dx_countlimit_set_count(countlimit, count + 1);
+	
+	index_block->block->dirty = true;
+}
+
+/** Split directory entries to two parts preventing node overflow.
+ *
+ * @param inode_ref      Directory i-node
+ * @param hinfo          Hash info
+ * @param old_data_block Block with data to be split
+ * @param index_block    Block where index entries are located
+ * @param new_data_block Output value for newly allocated data block
+ *
+ */
+static int ext4_directory_dx_split_data(ext4_inode_ref_t *inode_ref,
+    ext4_hash_info_t *hinfo, block_t *old_data_block,
+    ext4_directory_dx_block_t *index_block, block_t **new_data_block)
+{
+	int rc = EOK;
+	
+	/* Allocate buffer for directory entries */
+	uint32_t block_size =
+	    ext4_superblock_get_block_size(inode_ref->fs->superblock);
+	void *entry_buffer = malloc(block_size);
+	if (entry_buffer == NULL)
+		return ENOMEM;
+	
+	/* dot entry has the smallest size available */
+	uint32_t max_entry_count =
+	    block_size / sizeof(ext4_directory_dx_dot_entry_t);
+	
+	/* Allocate sort entry */
+	ext4_dx_sort_entry_t *sort_array =
+	    malloc(max_entry_count * sizeof(ext4_dx_sort_entry_t));
+	if (sort_array == NULL) {
+		free(entry_buffer);
+		return ENOMEM;
+	}
+	
+	uint32_t idx = 0;
+	uint32_t real_size = 0;
+	
+	/* Initialize hinfo */
+	ext4_hash_info_t tmp_hinfo;
+	memcpy(&tmp_hinfo, hinfo, sizeof(ext4_hash_info_t));
+	
+	/* Load all valid entries to the buffer */
+	ext4_directory_entry_ll_t *dentry = old_data_block->data;
+	void *entry_buffer_ptr = entry_buffer;
+	while ((void *)dentry < old_data_block->data + block_size) {
+		/* Read only valid entries */
+		if (ext4_directory_entry_ll_get_inode(dentry) != 0) {
+			uint8_t len = ext4_directory_entry_ll_get_name_length(
+			    inode_ref->fs->superblock, dentry);
+			ext4_hash_string(&tmp_hinfo, len, (char *) dentry->name);
+			
+			uint32_t rec_len = 8 + len;
+			
+			if ((rec_len % 4) != 0)
+				rec_len += 4 - (rec_len % 4);
+			
+			memcpy(entry_buffer_ptr, dentry, rec_len);
+			
+			sort_array[idx].dentry = entry_buffer_ptr;
+			sort_array[idx].rec_len = rec_len;
+			sort_array[idx].hash = tmp_hinfo.hash;
+			
+			entry_buffer_ptr += rec_len;
+			real_size += rec_len;
+			idx++;
+		}
+		
+		dentry = (void *) dentry +
+		    ext4_directory_entry_ll_get_entry_length(dentry);
+	}
+	
+	/* Sort all entries */
+	qsort(sort_array, idx, sizeof(ext4_dx_sort_entry_t),
+	    ext4_directory_dx_entry_comparator, NULL);
+	
+	/* Allocate new block for store the second part of entries */
+	uint32_t new_fblock;
+	uint32_t new_iblock;
+	rc = ext4_filesystem_append_inode_block(inode_ref, &new_fblock,
+	    &new_iblock);
+	if (rc != EOK) {
+		free(sort_array);
+		free(entry_buffer);
+		return rc;
+	}
+	
+	/* Load new block */
+	block_t *new_data_block_tmp;
+	rc = block_get(&new_data_block_tmp, inode_ref->fs->device,
+	    new_fblock, BLOCK_FLAGS_NOREAD);
+	if (rc != EOK) {
+		free(sort_array);
+		free(entry_buffer);
+		return rc;
+	}
+	
+	/*
+	 * Distribute entries to two blocks (by size)
+	 * - compute the half
+	 */
+	uint32_t new_hash = 0;
+	uint32_t current_size = 0;
+	uint32_t mid = 0;
+	for (uint32_t i = 0; i < idx; ++i) {
+		if ((current_size + sort_array[i].rec_len) > (real_size / 2)) {
+			new_hash = sort_array[i].hash;
+			mid = i;
+			break;
+		}
+		
+		current_size += sort_array[i].rec_len;
+	}
+	
+	/* Check hash collision */
+	uint32_t continued = 0;
+	if (new_hash == sort_array[mid-1].hash)
+		continued = 1;
+	
+	uint32_t offset = 0;
+	void *ptr;
+	
+	/* First part - to the old block */
+	for (uint32_t i = 0; i < mid; ++i) {
+		ptr = old_data_block->data + offset;
+		memcpy(ptr, sort_array[i].dentry, sort_array[i].rec_len);
+		
+		ext4_directory_entry_ll_t *tmp = ptr;
+		if (i < (mid - 1))
+			ext4_directory_entry_ll_set_entry_length(tmp,
+			    sort_array[i].rec_len);
+		else
+			ext4_directory_entry_ll_set_entry_length(tmp,
+			    block_size - offset);
+		
+		offset += sort_array[i].rec_len;
+	}
+	
+	/* Second part - to the new block */
+	offset = 0;
+	for (uint32_t i = mid; i < idx; ++i) {
+		ptr = new_data_block_tmp->data + offset;
+		memcpy(ptr, sort_array[i].dentry, sort_array[i].rec_len);
+		
+		ext4_directory_entry_ll_t *tmp = ptr;
+		if (i < (idx - 1))
+			ext4_directory_entry_ll_set_entry_length(tmp,
+			    sort_array[i].rec_len);
+		else
+			ext4_directory_entry_ll_set_entry_length(tmp,
+			    block_size - offset);
+		
+		offset += sort_array[i].rec_len;
+	}
+	
+	/* Do some steps to finish operation */
+	old_data_block->dirty = true;
+	new_data_block_tmp->dirty = true;
+	
+	free(sort_array);
+	free(entry_buffer);
+	
+	ext4_directory_dx_insert_entry(index_block, new_hash + continued,
+	    new_iblock);
+	
+	*new_data_block = new_data_block_tmp;
+	
+	return EOK;
+}
+
+/** Split index node and maybe some parent nodes in the tree hierarchy.
+ *
+ * @param inode_ref Directory i-node
+ * @param dx_blocks Array with path from root to leaf node
+ * @param dx_block  Leaf block to be split if needed
+ *
+ * @return Error code
+ *
+ */
+static int ext4_directory_dx_split_index(ext4_inode_ref_t *inode_ref,
+		ext4_directory_dx_block_t *dx_blocks, ext4_directory_dx_block_t *dx_block)
+{
+	ext4_directory_dx_entry_t *entries;
+	if (dx_block == dx_blocks)
+		entries =
+		    ((ext4_directory_dx_root_t *) dx_block->block->data)->entries;
+	else
+		entries =
+		    ((ext4_directory_dx_node_t *) dx_block->block->data)->entries;
+	
+	ext4_directory_dx_countlimit_t *countlimit =
+	    (ext4_directory_dx_countlimit_t *) entries;
+	
+	uint16_t leaf_limit =
+	    ext4_directory_dx_countlimit_get_limit(countlimit);
+	uint16_t leaf_count =
+	    ext4_directory_dx_countlimit_get_count(countlimit);
+	
+	/* Check if is necessary to split index block */
+	if (leaf_limit == leaf_count) {
+		size_t levels = dx_block - dx_blocks;
+		
+		ext4_directory_dx_entry_t *root_entries =
+		    ((ext4_directory_dx_root_t *) dx_blocks[0].block->data)->entries;
+		
+		ext4_directory_dx_countlimit_t *root_countlimit =
+		    (ext4_directory_dx_countlimit_t *) root_entries;
+		uint16_t root_limit =
+		    ext4_directory_dx_countlimit_get_limit(root_countlimit);
+		uint16_t root_count =
+		    ext4_directory_dx_countlimit_get_count(root_countlimit);
+		
+		/* Linux limitation */
+		if ((levels > 0) && (root_limit == root_count))
+			return ENOSPC;
+		
+		/* Add new block to directory */
+		uint32_t new_fblock;
+		uint32_t new_iblock;
+		int rc = ext4_filesystem_append_inode_block(inode_ref,
+		    &new_fblock, &new_iblock);
+		if (rc != EOK)
+			return rc;
+		
+		/* load new block */
+		block_t *new_block;
+		rc = block_get(&new_block, inode_ref->fs->device,
+		    new_fblock, BLOCK_FLAGS_NOREAD);
+		if (rc != EOK)
+			return rc;
+		
+		ext4_directory_dx_node_t *new_node = new_block->data;
+		ext4_directory_dx_entry_t *new_entries = new_node->entries;
+		
+		uint32_t block_size =
+		    ext4_superblock_get_block_size(inode_ref->fs->superblock);
+		
+		/* Split leaf node */
+		if (levels > 0) {
+			uint32_t count_left = leaf_count / 2;
+			uint32_t count_right = leaf_count - count_left;
+			uint32_t hash_right =
+			    ext4_directory_dx_entry_get_hash(entries + count_left);
+			
+			/* Copy data to new node */
+			memcpy((void *) new_entries, (void *) (entries + count_left),
+			    count_right * sizeof(ext4_directory_dx_entry_t));
+			
+			/* Initialize new node */
+			ext4_directory_dx_countlimit_t *left_countlimit =
+			    (ext4_directory_dx_countlimit_t *) entries;
+			ext4_directory_dx_countlimit_t *right_countlimit =
+			    (ext4_directory_dx_countlimit_t *) new_entries;
+			
+			ext4_directory_dx_countlimit_set_count(left_countlimit, count_left);
+			ext4_directory_dx_countlimit_set_count(right_countlimit, count_right);
+			
+			uint32_t entry_space =
+			    block_size - sizeof(ext4_fake_directory_entry_t);
+			uint32_t node_limit =
+			    entry_space / sizeof(ext4_directory_dx_entry_t);
+			ext4_directory_dx_countlimit_set_limit(right_countlimit, node_limit);
+			
+			/* Which index block is target for new entry */
+			uint32_t position_index = (dx_block->position - dx_block->entries);
+			if (position_index >= count_left) {
+				dx_block->block->dirty = true;
+				
+				block_t *block_tmp = dx_block->block;
+				dx_block->block = new_block;
+				dx_block->position =
+				    new_entries + position_index - count_left;
+				dx_block->entries = new_entries;
+				
+				new_block = block_tmp;
+			}
+			
+			/* Finally insert new entry */
+			ext4_directory_dx_insert_entry(dx_blocks, hash_right, new_iblock);
+			
+			return block_put(new_block);
+		} else {
+			/* Create second level index */
+			
+			/* Copy data from root to child block */
+			memcpy((void *) new_entries, (void *) entries,
+			    leaf_count * sizeof(ext4_directory_dx_entry_t));
+			
+			ext4_directory_dx_countlimit_t *new_countlimit =
+			    (ext4_directory_dx_countlimit_t *) new_entries;
+			
+			uint32_t entry_space =
+			    block_size - sizeof(ext4_fake_directory_entry_t);
+			uint32_t node_limit =
+			    entry_space / sizeof(ext4_directory_dx_entry_t);
+			ext4_directory_dx_countlimit_set_limit(new_countlimit, node_limit);
+			
+			/* Set values in root node */
+			ext4_directory_dx_countlimit_t *new_root_countlimit =
+			    (ext4_directory_dx_countlimit_t *) entries;
+			
+			ext4_directory_dx_countlimit_set_count(new_root_countlimit, 1);
+			ext4_directory_dx_entry_set_block(entries, new_iblock);
+			
+			((ext4_directory_dx_root_t *)
+			    dx_blocks[0].block->data)->info.indirect_levels = 1;
+			
+			/* Add new entry to the path */
+			dx_block = dx_blocks + 1;
+			dx_block->position = dx_block->position - entries + new_entries;
+			dx_block->entries = new_entries;
+			dx_block->block = new_block;
+		}
+	}
+	
+	return EOK;
+}
+
+/** Add new entry to indexed directory
+ *
+ * @param parent Directory i-node
+ * @param child  I-node to be referenced from directory entry
+ * @param name   Name of new directory entry
+ *
+ * @return Error code
+ *
+ */
+int ext4_directory_dx_add_entry(ext4_inode_ref_t *parent,
+    ext4_inode_ref_t *child, const char *name)
+{
+	int rc2 = EOK;
+	
+	/* Get direct block 0 (index root) */
+	uint32_t root_block_addr;
+	int rc = ext4_filesystem_get_inode_data_block_index(parent, 0,
+	    &root_block_addr);
+	if (rc != EOK)
+		return rc;
+	
+	ext4_filesystem_t *fs = parent->fs;
+	
+	block_t *root_block;
+	rc = block_get(&root_block, fs->device, root_block_addr,
+	    BLOCK_FLAGS_NONE);
+	if (rc != EOK)
+		return rc;
+	
+	/* Initialize hinfo structure (mainly compute hash) */
+	uint32_t name_len = str_size(name);
+	ext4_hash_info_t hinfo;
+	rc = ext4_directory_hinfo_init(&hinfo, root_block, fs->superblock,
+	    name_len, name);
+	if (rc != EOK) {
+		block_put(root_block);
+		return EXT4_ERR_BAD_DX_DIR;
+	}
+	
+	/*
+	 * Hardcoded number 2 means maximum height of index
+	 * tree defined in Linux.
+	 */
+	ext4_directory_dx_block_t dx_blocks[2];
+	ext4_directory_dx_block_t *dx_block;
+	ext4_directory_dx_block_t *dx_it;
+	
+	rc = ext4_directory_dx_get_leaf(&hinfo, parent, root_block,
+	    &dx_block, dx_blocks);
+	if (rc != EOK) {
+		rc = EXT4_ERR_BAD_DX_DIR;
+		goto release_index;
+	}
+	
+	/* Try to insert to existing data block */
+	uint32_t leaf_block_idx =
+	    ext4_directory_dx_entry_get_block(dx_block->position);
+	uint32_t leaf_block_addr;
+	rc = ext4_filesystem_get_inode_data_block_index(parent, leaf_block_idx,
+	    &leaf_block_addr);
+	if (rc != EOK)
+		goto release_index;
+	
+	block_t *target_block;
+	rc = block_get(&target_block, fs->device, leaf_block_addr,
+	    BLOCK_FLAGS_NONE);
+	if (rc != EOK)
+		goto release_index;
+	
+	/* Check if insert operation passed */
+	rc = ext4_directory_try_insert_entry(fs->superblock, target_block, child,
+	    name, name_len);
+	if (rc == EOK)
+		goto release_target_index;
+	
+	/*
+	 * Check if there is needed to split index node
+	 * (and recursively also parent nodes)
+	 */
+	rc = ext4_directory_dx_split_index(parent, dx_blocks, dx_block);
+	if (rc != EOK)
+		goto release_target_index;
+	
+	/* Split entries to two blocks (includes sorting by hash value) */
+	block_t *new_block = NULL;
+	rc = ext4_directory_dx_split_data(parent, &hinfo, target_block,
+	    dx_block, &new_block);
+	if (rc != EOK) {
+		rc2 = rc;
+		goto release_target_index;
+	}
+	
+	/* Where to save new entry */
+	uint32_t new_block_hash =
+	    ext4_directory_dx_entry_get_hash(dx_block->position + 1);
+	if (hinfo.hash >= new_block_hash)
+		rc = ext4_directory_try_insert_entry(fs->superblock, new_block,
+		    child, name, name_len);
+	else
+		rc = ext4_directory_try_insert_entry(fs->superblock, target_block,
+		    child, name, name_len);
+	
+	/* Cleanup */
+	rc = block_put(new_block);
+	if (rc != EOK)
+		return rc;
+	
+	/* Cleanup operations */
+	
+release_target_index:
+	rc2 = rc;
+	
+	rc = block_put(target_block);
+	if (rc != EOK)
+		return rc;
+	
+release_index:
+	if (rc != EOK)
+		rc2 = rc;
+	
+	dx_it = dx_blocks;
+	
+	while (dx_it <= dx_block) {
+		rc = block_put(dx_it->block);
+		if (rc != EOK)
+			return rc;
+		
+		dx_it++;
+	}
+	
+	return rc2;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_directory_index.h
===================================================================
--- uspace/lib/ext4/libext4_directory_index.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_directory_index.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_DIRECTORY_INDEX_H_
+#define LIBEXT4_LIBEXT4_DIRECTORY_INDEX_H_
+
+#include "libext4_types.h"
+
+extern uint8_t ext4_directory_dx_root_info_get_hash_version(
+    ext4_directory_dx_root_info_t *);
+extern void ext4_directory_dx_root_info_set_hash_version(
+    ext4_directory_dx_root_info_t *, uint8_t);
+extern uint8_t ext4_directory_dx_root_info_get_info_length(
+    ext4_directory_dx_root_info_t *);
+extern void ext4_directory_dx_root_info_set_info_length(
+    ext4_directory_dx_root_info_t *, uint8_t);
+extern uint8_t ext4_directory_dx_root_info_get_indirect_levels(
+    ext4_directory_dx_root_info_t *);
+extern void ext4_directory_dx_root_info_set_indirect_levels(
+    ext4_directory_dx_root_info_t *, uint8_t);
+
+extern uint16_t ext4_directory_dx_countlimit_get_limit(
+    ext4_directory_dx_countlimit_t *);
+extern void ext4_directory_dx_countlimit_set_limit(
+    ext4_directory_dx_countlimit_t *, uint16_t);
+extern uint16_t ext4_directory_dx_countlimit_get_count(
+    ext4_directory_dx_countlimit_t *);
+extern void ext4_directory_dx_countlimit_set_count(
+    ext4_directory_dx_countlimit_t *, uint16_t);
+
+extern uint32_t ext4_directory_dx_entry_get_hash(ext4_directory_dx_entry_t *);
+extern void ext4_directory_dx_entry_set_hash(ext4_directory_dx_entry_t *,
+    uint32_t);
+extern uint32_t ext4_directory_dx_entry_get_block(ext4_directory_dx_entry_t *);
+extern void ext4_directory_dx_entry_set_block(ext4_directory_dx_entry_t *,
+    uint32_t);
+
+extern int ext4_directory_dx_init(ext4_inode_ref_t *);
+extern int ext4_directory_dx_find_entry(ext4_directory_search_result_t *,
+    ext4_inode_ref_t *, size_t, const char *);
+extern int ext4_directory_dx_add_entry(ext4_inode_ref_t *, ext4_inode_ref_t *,
+    const char *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_extent.c
===================================================================
--- uspace/lib/ext4/libext4_extent.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_extent.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1084 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+/**
+ * @file  libext4_extent.c
+ * @brief Ext4 extent structures operations.
+ */
+
+#include <byteorder.h>
+#include <errno.h>
+#include <malloc.h>
+#include "libext4.h"
+
+/** Get logical number of the block covered by extent.
+ *
+ * @param extent Extent to load number from
+ *
+ * @return Logical number of the first block covered by extent
+ *
+ */
+uint32_t ext4_extent_get_first_block(ext4_extent_t *extent)
+{
+	return uint32_t_le2host(extent->first_block);
+}
+
+/** Set logical number of the first block covered by extent.
+ *
+ * @param extent Extent to set number to
+ * @param iblock Logical number of the first block covered by extent
+ *
+ */
+void ext4_extent_set_first_block(ext4_extent_t *extent, uint32_t iblock)
+{
+	extent->first_block = host2uint32_t_le(iblock);
+}
+
+/** Get number of blocks covered by extent.
+ *
+ * @param extent Extent to load count from
+ *
+ * @return Number of blocks covered by extent
+ *
+ */
+uint16_t ext4_extent_get_block_count(ext4_extent_t *extent)
+{
+	return uint16_t_le2host(extent->block_count);
+}
+
+/** Set number of blocks covered by extent.
+ *
+ * @param extent Extent to load count from
+ * @param count  Number of blocks covered by extent
+ *
+ */
+void ext4_extent_set_block_count(ext4_extent_t *extent, uint16_t count)
+{
+	extent->block_count = host2uint16_t_le(count);
+}
+
+/** Get physical number of the first block covered by extent.
+ *
+ * @param extent Extent to load number
+ *
+ * @return Physical number of the first block covered by extent
+ *
+ */
+uint64_t ext4_extent_get_start(ext4_extent_t *extent)
+{
+	return ((uint64_t)uint16_t_le2host(extent->start_hi)) << 32 |
+	    ((uint64_t)uint32_t_le2host(extent->start_lo));
+}
+
+/** Set physical number of the first block covered by extent.
+ *
+ * @param extent Extent to load number
+ * @param fblock Physical number of the first block covered by extent
+ *
+ */
+void ext4_extent_set_start(ext4_extent_t *extent, uint64_t fblock)
+{
+	extent->start_lo = host2uint32_t_le((fblock << 32) >> 32);
+	extent->start_hi = host2uint16_t_le((uint16_t)(fblock >> 32));
+}
+
+/** Get logical number of the block covered by extent index.
+ *
+ * @param index Extent index to load number from
+ *
+ * @return Logical number of the first block covered by extent index
+ *
+ */
+uint32_t ext4_extent_index_get_first_block(ext4_extent_index_t *index)
+{
+	return uint32_t_le2host(index->first_block);
+}
+
+/** Set logical number of the block covered by extent index.
+ *
+ * @param index  Extent index to set number to
+ * @param iblock Logical number of the first block covered by extent index
+ *
+ */
+void ext4_extent_index_set_first_block(ext4_extent_index_t *index,
+    uint32_t iblock)
+{
+	index->first_block = host2uint32_t_le(iblock);
+}
+
+/** Get physical number of block where the child node is located.
+ *
+ * @param index Extent index to load number from
+ *
+ * @return Physical number of the block with child node
+ *
+ */
+uint64_t ext4_extent_index_get_leaf(ext4_extent_index_t *index)
+{
+	return ((uint64_t) uint16_t_le2host(index->leaf_hi)) << 32 |
+	    ((uint64_t)uint32_t_le2host(index->leaf_lo));
+}
+
+/** Set physical number of block where the child node is located.
+ *
+ * @param index  Extent index to set number to
+ * @param fblock Ohysical number of the block with child node
+ *
+ */
+void ext4_extent_index_set_leaf(ext4_extent_index_t *index, uint64_t fblock)
+{
+	index->leaf_lo = host2uint32_t_le((fblock << 32) >> 32);
+	index->leaf_hi = host2uint16_t_le((uint16_t) (fblock >> 32));
+}
+
+/** Get magic value from extent header.
+ *
+ * @param header Extent header to load value from
+ *
+ * @return Magic value of extent header
+ *
+ */
+uint16_t ext4_extent_header_get_magic(ext4_extent_header_t *header)
+{
+	return uint16_t_le2host(header->magic);
+}
+
+/** Set magic value to extent header.
+ *
+ * @param header Extent header to set value to
+ * @param magic  Magic value of extent header
+ *
+ */
+void ext4_extent_header_set_magic(ext4_extent_header_t *header, uint16_t magic)
+{
+	header->magic = host2uint16_t_le(magic);
+}
+
+/** Get number of entries from extent header
+ *
+ * @param header Extent header to get value from
+ *
+ * @return Number of entries covered by extent header
+ *
+ */
+uint16_t ext4_extent_header_get_entries_count(ext4_extent_header_t *header)
+{
+	return uint16_t_le2host(header->entries_count);
+}
+
+/** Set number of entries to extent header
+ *
+ * @param header Extent header to set value to
+ * @param count  Number of entries covered by extent header
+ *
+ */
+void ext4_extent_header_set_entries_count(ext4_extent_header_t *header,
+    uint16_t count)
+{
+	header->entries_count = host2uint16_t_le(count);
+}
+
+/** Get maximum number of entries from extent header
+ *
+ * @param header Extent header to get value from
+ *
+ * @return Maximum number of entries covered by extent header
+ *
+ */
+uint16_t ext4_extent_header_get_max_entries_count(ext4_extent_header_t *header)
+{
+	return uint16_t_le2host(header->max_entries_count);
+}
+
+/** Set maximum number of entries to extent header
+ *
+ * @param header    Extent header to set value to
+ * @param max_count Maximum number of entries covered by extent header
+ *
+ */
+void ext4_extent_header_set_max_entries_count(ext4_extent_header_t *header,
+    uint16_t max_count)
+{
+	header->max_entries_count = host2uint16_t_le(max_count);
+}
+
+/** Get depth of extent subtree.
+ *
+ * @param header Extent header to get value from
+ *
+ * @return Depth of extent subtree
+ *
+ */
+uint16_t ext4_extent_header_get_depth(ext4_extent_header_t *header)
+{
+	return uint16_t_le2host(header->depth);
+}
+
+/** Set depth of extent subtree.
+ *
+ * @param header Extent header to set value to
+ * @param depth  Depth of extent subtree
+ *
+ */
+void ext4_extent_header_set_depth(ext4_extent_header_t *header, uint16_t depth)
+{
+	header->depth = host2uint16_t_le(depth);
+}
+
+/** Get generation from extent header
+ *
+ * @param header Extent header to get value from
+ *
+ * @return Generation
+ *
+ */
+uint32_t ext4_extent_header_get_generation(ext4_extent_header_t *header)
+{
+	return uint32_t_le2host(header->generation);
+}
+
+/** Set generation to extent header
+ *
+ * @param header     Extent header to set value to
+ * @param generation Generation
+ *
+ */
+void ext4_extent_header_set_generation(ext4_extent_header_t *header,
+    uint32_t generation)
+{
+	header->generation = host2uint32_t_le(generation);
+}
+
+/** Binary search in extent index node.
+ *
+ * @param header Extent header of index node
+ * @param index  Output value - found index will be set here
+ * @param iblock Logical block number to find in index node
+ *
+ */
+static void ext4_extent_binsearch_idx(ext4_extent_header_t *header,
+    ext4_extent_index_t **index, uint32_t iblock)
+{
+	ext4_extent_index_t *r;
+	ext4_extent_index_t *l;
+	ext4_extent_index_t *m;
+	
+	uint16_t entries_count =
+	    ext4_extent_header_get_entries_count(header);
+	
+	/* Initialize bounds */
+	l = EXT4_EXTENT_FIRST_INDEX(header) + 1;
+	r = EXT4_EXTENT_FIRST_INDEX(header) + entries_count - 1;
+	
+	/* Do binary search */
+	while (l <= r) {
+		m = l + (r - l) / 2;
+		uint32_t first_block = ext4_extent_index_get_first_block(m);
+		
+		if (iblock < first_block)
+			r = m - 1;
+		else
+			l = m + 1;
+	}
+	
+	/* Set output value */
+	*index = l - 1;
+}
+
+/** Binary search in extent leaf node.
+ *
+ * @param header Extent header of leaf node
+ * @param extent Output value - found extent will be set here,
+ *               or NULL if node is empty
+ * @param iblock Logical block number to find in leaf node
+ *
+ */
+static void ext4_extent_binsearch(ext4_extent_header_t *header,
+    ext4_extent_t **extent, uint32_t iblock)
+{
+	ext4_extent_t *r;
+	ext4_extent_t *l;
+	ext4_extent_t *m;
+	
+	uint16_t entries_count =
+	    ext4_extent_header_get_entries_count(header);
+	
+	if (entries_count == 0) {
+		/* this leaf is empty */
+		*extent = NULL;
+		return;
+	}
+	
+	/* Initialize bounds */
+	l = EXT4_EXTENT_FIRST(header) + 1;
+	r = EXT4_EXTENT_FIRST(header) + entries_count - 1;
+	
+	/* Do binary search */
+	while (l <= r) {
+		m = l + (r - l) / 2;
+		uint32_t first_block = ext4_extent_get_first_block(m);
+		
+		if (iblock < first_block)
+			r = m - 1;
+		else
+			l = m + 1;
+	}
+	
+	/* Set output value */
+	*extent = l - 1;
+}
+
+/** Find physical block in the extent tree by logical block number.
+ *
+ * There is no need to save path in the tree during this algorithm.
+ *
+ * @param inode_ref I-node to load block from
+ * @param iblock    Logical block number to find
+ * @param fblock    Output value for physical block number
+ *
+ * @return Error code
+ *
+ */
+int ext4_extent_find_block(ext4_inode_ref_t *inode_ref, uint32_t iblock,
+    uint32_t *fblock)
+{
+	/* Compute bound defined by i-node size */
+	uint64_t inode_size =
+	    ext4_inode_get_size(inode_ref->fs->superblock, inode_ref->inode);
+	
+	uint32_t block_size =
+	    ext4_superblock_get_block_size(inode_ref->fs->superblock);
+	
+	uint32_t last_idx = (inode_size - 1) / block_size;
+	
+	/* Check if requested iblock is not over size of i-node */
+	if (iblock > last_idx) {
+		*fblock = 0;
+		return EOK;
+	}
+	
+	block_t *block = NULL;
+	
+	/* Walk through extent tree */
+	ext4_extent_header_t *header =
+	    ext4_inode_get_extent_header(inode_ref->inode);
+	
+	while (ext4_extent_header_get_depth(header) != 0) {
+		/* Search index in node */
+		ext4_extent_index_t *index;
+		ext4_extent_binsearch_idx(header, &index, iblock);
+		
+		/* Load child node and set values for the next iteration */
+		uint64_t child = ext4_extent_index_get_leaf(index);
+		
+		if (block != NULL)
+			block_put(block);
+		
+		int rc = block_get(&block, inode_ref->fs->device, child,
+		    BLOCK_FLAGS_NONE);
+		if (rc != EOK)
+			return rc;
+		
+		header = (ext4_extent_header_t *)block->data;
+	}
+	
+	/* Search extent in the leaf block */
+	ext4_extent_t* extent = NULL;
+	ext4_extent_binsearch(header, &extent, iblock);
+	
+	/* Prevent empty leaf */
+	if (extent == NULL) {
+		*fblock = 0;
+	} else {
+		/* Compute requested physical block address */
+		uint32_t phys_block;
+		uint32_t first = ext4_extent_get_first_block(extent);
+		phys_block = ext4_extent_get_start(extent) + iblock - first;
+		
+		*fblock = phys_block;
+	}
+	
+	/* Cleanup */
+	if (block != NULL)
+		block_put(block);
+	
+	return EOK;
+}
+
+/** Find extent for specified iblock.
+ *
+ * This function is used for finding block in the extent tree with
+ * saving the path through the tree for possible future modifications.
+ *
+ * @param inode_ref I-node to read extent tree from
+ * @param iblock    Iblock to find extent for
+ * @param ret_path  Output value for loaded path from extent tree
+ *
+ * @return Error code
+ *
+ */
+static int ext4_extent_find_extent(ext4_inode_ref_t *inode_ref, uint32_t iblock,
+    ext4_extent_path_t **ret_path)
+{
+	ext4_extent_header_t *eh =
+	    ext4_inode_get_extent_header(inode_ref->inode);
+	
+	uint16_t depth = ext4_extent_header_get_depth(eh);
+	
+	ext4_extent_path_t *tmp_path;
+	
+	/* Added 2 for possible tree growing */
+	tmp_path = malloc(sizeof(ext4_extent_path_t) * (depth + 2));
+	if (tmp_path == NULL)
+		return ENOMEM;
+	
+	/* Initialize structure for algorithm start */
+	tmp_path[0].block = inode_ref->block;
+	tmp_path[0].header = eh;
+	
+	/* Walk through the extent tree */
+	uint16_t pos = 0;
+	int rc;
+	while (ext4_extent_header_get_depth(eh) != 0) {
+		/* Search index in index node by iblock */
+		ext4_extent_binsearch_idx(tmp_path[pos].header,
+		    &tmp_path[pos].index, iblock);
+		
+		tmp_path[pos].depth = depth;
+		tmp_path[pos].extent = NULL;
+		
+		assert(tmp_path[pos].index != NULL);
+		
+		/* Load information for the next iteration */
+		uint64_t fblock = ext4_extent_index_get_leaf(tmp_path[pos].index);
+		
+		block_t *block;
+		rc = block_get(&block, inode_ref->fs->device, fblock,
+		    BLOCK_FLAGS_NONE);
+		if (rc != EOK)
+			goto cleanup;
+		
+		pos++;
+		
+		eh = (ext4_extent_header_t *)block->data;
+		tmp_path[pos].block = block;
+		tmp_path[pos].header = eh;
+	}
+	
+	tmp_path[pos].depth = 0;
+	tmp_path[pos].extent = NULL;
+	tmp_path[pos].index = NULL;
+	
+	/* Find extent in the leaf node */
+	ext4_extent_binsearch(tmp_path[pos].header, &tmp_path[pos].extent, iblock);
+	*ret_path = tmp_path;
+	
+	return EOK;
+	
+cleanup:
+	/*
+	 * Put loaded blocks
+	 * From 1: 0 is a block with inode data
+	 */
+	for (uint16_t i = 1; i < tmp_path->depth; ++i) {
+		if (tmp_path[i].block)
+			block_put(tmp_path[i].block);
+	}
+	
+	/* Destroy temporary data structure */
+	free(tmp_path);
+	
+	return rc;
+}
+
+/** Release extent and all data blocks covered by the extent.
+ *
+ * @param inode_ref I-node to release extent and block from
+ * @param extent    Extent to release
+ *
+ * @return Error code
+ *
+ */
+static int ext4_extent_release(ext4_inode_ref_t *inode_ref,
+    ext4_extent_t *extent)
+{
+	/* Compute number of the first physical block to release */
+	uint64_t start = ext4_extent_get_start(extent);
+	uint16_t block_count = ext4_extent_get_block_count(extent);
+	
+	return ext4_balloc_free_blocks(inode_ref, start, block_count);
+}
+
+/** Recursively release the whole branch of the extent tree.
+ *
+ * For each entry of the node release the subbranch and finally release
+ * the node. In the leaf node all extents will be released.
+ *
+ * @param inode_ref I-node where the branch is released
+ * @param index     Index in the non-leaf node to be released
+ *                  with the whole subtree
+ *
+ * @return Error code
+ *
+ */
+static int ext4_extent_release_branch(ext4_inode_ref_t *inode_ref,
+		ext4_extent_index_t *index)
+{
+	uint32_t fblock = ext4_extent_index_get_leaf(index);
+	
+	block_t* block;
+	int rc = block_get(&block, inode_ref->fs->device, fblock, BLOCK_FLAGS_NONE);
+	if (rc != EOK)
+		return rc;
+	
+	ext4_extent_header_t *header = block->data;
+	
+	if (ext4_extent_header_get_depth(header)) {
+		/* The node is non-leaf, do recursion */
+		ext4_extent_index_t *idx = EXT4_EXTENT_FIRST_INDEX(header);
+		
+		/* Release all subbranches */
+		for (uint32_t i = 0;
+		    i < ext4_extent_header_get_entries_count(header);
+		    ++i, ++idx) {
+			rc = ext4_extent_release_branch(inode_ref, idx);
+			if (rc != EOK)
+				return rc;
+		}
+	} else {
+		/* Leaf node reached */
+		ext4_extent_t *ext = EXT4_EXTENT_FIRST(header);
+		
+		/* Release all extents and stop recursion */
+		for (uint32_t i = 0;
+		    i < ext4_extent_header_get_entries_count(header);
+		    ++i, ++ext) {
+			rc = ext4_extent_release(inode_ref, ext);
+			if (rc != EOK)
+				return rc;
+		}
+	}
+	
+	/* Release data block where the node was stored */
+	
+	rc = block_put(block);
+	if (rc != EOK)
+		return rc;
+	
+	ext4_balloc_free_block(inode_ref, fblock);
+	
+	return EOK;
+}
+
+/** Release all data blocks starting from specified logical block.
+ *
+ * @param inode_ref   I-node to release blocks from
+ * @param iblock_from First logical block to release
+ *
+ */
+int ext4_extent_release_blocks_from(ext4_inode_ref_t *inode_ref,
+    uint32_t iblock_from)
+{
+	/* Find the first extent to modify */
+	ext4_extent_path_t *path;
+	int rc = ext4_extent_find_extent(inode_ref, iblock_from, &path);
+	if (rc != EOK)
+		return rc;
+	
+	/* Jump to last item of the path (extent) */
+	ext4_extent_path_t *path_ptr = path;
+	while (path_ptr->depth != 0)
+		path_ptr++;
+	
+	assert(path_ptr->extent != NULL);
+	
+	/* First extent maybe released partially */
+	uint32_t first_iblock =
+	    ext4_extent_get_first_block(path_ptr->extent);
+	uint32_t first_fblock =
+	    ext4_extent_get_start(path_ptr->extent) + iblock_from - first_iblock;
+	
+	uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent);
+	
+	uint16_t delete_count = block_count -
+	    (ext4_extent_get_start(path_ptr->extent) - first_fblock);
+	
+	/* Release all blocks */
+	rc = ext4_balloc_free_blocks(inode_ref, first_fblock, delete_count);
+	if (rc != EOK)
+		goto cleanup;
+	
+	/* Correct counter */
+	block_count -= delete_count;
+	ext4_extent_set_block_count(path_ptr->extent, block_count);
+	
+	/* Initialize the following loop */
+	uint16_t entries =
+	    ext4_extent_header_get_entries_count(path_ptr->header);
+	ext4_extent_t *tmp_ext = path_ptr->extent + 1;
+	ext4_extent_t *stop_ext = EXT4_EXTENT_FIRST(path_ptr->header) + entries;
+	
+	/* If first extent empty, release it */
+	if (block_count == 0)
+		entries--;
+	
+	/* Release all successors of the first extent in the same node */
+	while (tmp_ext < stop_ext) {
+		first_fblock = ext4_extent_get_start(tmp_ext);
+		delete_count = ext4_extent_get_block_count(tmp_ext);
+		
+		rc = ext4_balloc_free_blocks(inode_ref, first_fblock, delete_count);
+		if (rc != EOK)
+			goto cleanup;
+		
+		entries--;
+		tmp_ext++;
+	}
+	
+	ext4_extent_header_set_entries_count(path_ptr->header, entries);
+	path_ptr->block->dirty = true;
+	
+	/* If leaf node is empty, parent entry must be modified */
+	bool remove_parent_record = false;
+	
+	/* Don't release root block (including inode data) !!! */
+	if ((path_ptr != path) && (entries == 0)) {
+		rc = ext4_balloc_free_block(inode_ref, path_ptr->block->lba);
+		if (rc != EOK)
+			goto cleanup;
+		
+		remove_parent_record = true;
+	}
+	
+	/* Jump to the parent */
+	--path_ptr;
+	
+	/* Release all successors in all tree levels */
+	while (path_ptr >= path) {
+		entries = ext4_extent_header_get_entries_count(path_ptr->header);
+		ext4_extent_index_t *index = path_ptr->index + 1;
+		ext4_extent_index_t *stop =
+		    EXT4_EXTENT_FIRST_INDEX(path_ptr->header) + entries;
+		
+		/* Correct entries count because of changes in the previous iteration */
+		if (remove_parent_record)
+			entries--;
+		
+		/* Iterate over all entries and release the whole subtrees */
+		while (index < stop) {
+			rc = ext4_extent_release_branch(inode_ref, index);
+			if (rc != EOK)
+				goto cleanup;
+			
+			++index;
+			--entries;
+		}
+		
+		ext4_extent_header_set_entries_count(path_ptr->header, entries);
+		path_ptr->block->dirty = true;
+		
+		/* Free the node if it is empty */
+		if ((entries == 0) && (path_ptr != path)) {
+			rc = ext4_balloc_free_block(inode_ref, path_ptr->block->lba);
+			if (rc != EOK)
+				goto cleanup;
+			
+			/* Mark parent to be checked */
+			remove_parent_record = true;
+		} else
+			remove_parent_record = false;
+		
+		--path_ptr;
+	}
+	
+cleanup:
+	/*
+	 * Put loaded blocks
+	 * starting from 1: 0 is a block with inode data
+	 */
+	for (uint16_t i = 1; i <= path->depth; ++i) {
+		if (path[i].block)
+			block_put(path[i].block);
+	}
+	
+	/* Destroy temporary data structure */
+	free(path);
+	
+	return rc;
+}
+
+/** Append new extent to the i-node and do some splitting if necessary.
+ *
+ * @param inode_ref      I-node to append extent to
+ * @param path           Path in the extent tree for possible splitting
+ * @param last_path_item Input/output parameter for pointer to the last
+ *                       valid item in the extent tree path
+ * @param iblock         Logical index of block to append extent for
+ *
+ * @return Error code
+ *
+ */
+static int ext4_extent_append_extent(ext4_inode_ref_t *inode_ref,
+    ext4_extent_path_t *path, uint32_t iblock)
+{
+	ext4_extent_path_t *path_ptr = path + path->depth;
+	
+	uint32_t block_size =
+	    ext4_superblock_get_block_size(inode_ref->fs->superblock);
+	
+	/* Start splitting */
+	while (path_ptr > path) {
+		uint16_t entries =
+		    ext4_extent_header_get_entries_count(path_ptr->header);
+		uint16_t limit =
+		    ext4_extent_header_get_max_entries_count(path_ptr->header);
+		
+		if (entries == limit) {
+			/* Full node - allocate block for new one */
+			uint32_t fblock;
+			int rc = ext4_balloc_alloc_block(inode_ref, &fblock);
+			if (rc != EOK)
+				return rc;
+			
+			block_t *block;
+			rc = block_get(&block, inode_ref->fs->device, fblock,
+			    BLOCK_FLAGS_NOREAD);
+			if (rc != EOK) {
+				ext4_balloc_free_block(inode_ref, fblock);
+				return rc;
+			}
+			
+			/* Put back not modified old block */
+			block_put(path_ptr->block);
+			
+			/* Initialize newly allocated block and remember it */
+			memset(block->data, 0, block_size);
+			path_ptr->block = block;
+			
+			/* Update pointers in extent path structure */
+			path_ptr->header = block->data;
+			if (path_ptr->depth) {
+				path_ptr->index = EXT4_EXTENT_FIRST_INDEX(path_ptr->header);
+				ext4_extent_index_set_first_block(path_ptr->index, iblock);
+				ext4_extent_index_set_leaf(path_ptr->index, (path_ptr + 1)->block->lba);
+				limit = (block_size - sizeof(ext4_extent_header_t)) /
+				    sizeof(ext4_extent_index_t);
+			} else {
+				path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header);
+				ext4_extent_set_first_block(path_ptr->extent, iblock);
+				limit = (block_size - sizeof(ext4_extent_header_t)) /
+				    sizeof(ext4_extent_t);
+			}
+			
+			/* Initialize on-disk structure (header) */
+			ext4_extent_header_set_entries_count(path_ptr->header, 1);
+			ext4_extent_header_set_max_entries_count(path_ptr->header, limit);
+			ext4_extent_header_set_magic(path_ptr->header, EXT4_EXTENT_MAGIC);
+			ext4_extent_header_set_depth(path_ptr->header, path_ptr->depth);
+			ext4_extent_header_set_generation(path_ptr->header, 0);
+			
+			path_ptr->block->dirty = true;
+			
+			/* Jump to the preceeding item */
+			path_ptr--;
+		} else {
+			/* Node with free space */
+			if (path_ptr->depth) {
+				path_ptr->index = EXT4_EXTENT_FIRST_INDEX(path_ptr->header) + entries;
+				ext4_extent_index_set_first_block(path_ptr->index, iblock);
+				ext4_extent_index_set_leaf(path_ptr->index, (path_ptr + 1)->block->lba);
+			} else {
+				path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries;
+				ext4_extent_set_first_block(path_ptr->extent, iblock);
+			}
+			
+			ext4_extent_header_set_entries_count(path_ptr->header, entries + 1);
+			path_ptr->block->dirty = true;
+			
+			/* No more splitting needed */
+			return EOK;
+		}
+	}
+	
+	assert(path_ptr == path);
+	
+	/* Should be the root split too? */
+	
+	uint16_t entries = ext4_extent_header_get_entries_count(path->header);
+	uint16_t limit = ext4_extent_header_get_max_entries_count(path->header);
+	
+	if (entries == limit) {
+		uint32_t new_fblock;
+		int rc = ext4_balloc_alloc_block(inode_ref, &new_fblock);
+		if (rc != EOK)
+			return rc;
+		
+		block_t *block;
+		rc = block_get(&block, inode_ref->fs->device, new_fblock,
+		    BLOCK_FLAGS_NOREAD);
+		if (rc != EOK)
+			return rc;
+		
+		/* Initialize newly allocated block */
+		memset(block->data, 0, block_size);
+		
+		/* Move data from root to the new block */
+		memcpy(block->data, inode_ref->inode->blocks,
+		    EXT4_INODE_BLOCKS * sizeof(uint32_t));
+		
+		/* Data block is initialized */
+		
+		block_t *root_block = path->block;
+		uint16_t root_depth = path->depth;
+		ext4_extent_header_t *root_header = path->header;
+		
+		/* Make space for tree growing */
+		ext4_extent_path_t *new_root = path;
+		ext4_extent_path_t *old_root = path + 1;
+		
+		size_t nbytes = sizeof(ext4_extent_path_t) * (path->depth + 1);
+		memmove(old_root, new_root, nbytes);
+		memset(new_root, 0, sizeof(ext4_extent_path_t));
+		
+		/* Update old root structure */
+		old_root->block = block;
+		old_root->header = (ext4_extent_header_t *)block->data;
+		
+		/* Add new entry and update limit for entries */
+		if (old_root->depth) {
+			limit = (block_size - sizeof(ext4_extent_header_t)) /
+			    sizeof(ext4_extent_index_t);
+			old_root->index = EXT4_EXTENT_FIRST_INDEX(old_root->header) + entries;
+			ext4_extent_index_set_first_block(old_root->index, iblock);
+			ext4_extent_index_set_leaf(old_root->index, (old_root + 1)->block->lba);
+			old_root->extent = NULL;
+		} else {
+			limit = (block_size - sizeof(ext4_extent_header_t)) /
+			    sizeof(ext4_extent_t);
+			old_root->extent = EXT4_EXTENT_FIRST(old_root->header) + entries;
+			ext4_extent_set_first_block(old_root->extent, iblock);
+			old_root->index = NULL;
+		}
+		
+		ext4_extent_header_set_entries_count(old_root->header, entries + 1);
+		ext4_extent_header_set_max_entries_count(old_root->header, limit);
+		
+		old_root->block->dirty = true;
+		
+		/* Re-initialize new root metadata */
+		new_root->depth = root_depth + 1;
+		new_root->block = root_block;
+		new_root->header = root_header;
+		new_root->extent = NULL;
+		new_root->index = EXT4_EXTENT_FIRST_INDEX(new_root->header);
+		
+		ext4_extent_header_set_depth(new_root->header, new_root->depth);
+		
+		/* Create new entry in root */
+		ext4_extent_header_set_entries_count(new_root->header, 1);
+		ext4_extent_index_set_first_block(new_root->index, 0);
+		ext4_extent_index_set_leaf(new_root->index, new_fblock);
+		
+		new_root->block->dirty = true;
+	} else {
+		if (path->depth) {
+			path->index = EXT4_EXTENT_FIRST_INDEX(path->header) + entries;
+			ext4_extent_index_set_first_block(path->index, iblock);
+			ext4_extent_index_set_leaf(path->index, (path + 1)->block->lba);
+		} else {
+			path->extent = EXT4_EXTENT_FIRST(path->header) + entries;
+			ext4_extent_set_first_block(path->extent, iblock);
+		}
+		
+		ext4_extent_header_set_entries_count(path->header, entries + 1);
+		path->block->dirty = true;
+	}
+	
+	return EOK;
+}
+
+/** Append data block to the i-node.
+ *
+ * This function allocates data block, tries to append it
+ * to some existing extent or creates new extents.
+ * It includes possible extent tree modifications (splitting).
+ *<
+ * @param inode_ref I-node to append block to
+ * @param iblock    Output logical number of newly allocated block
+ * @param fblock    Output physical block address of newly allocated block
+ *
+ * @return Error code
+ *
+ */
+int ext4_extent_append_block(ext4_inode_ref_t *inode_ref, uint32_t *iblock,
+    uint32_t *fblock, bool update_size)
+{
+	ext4_superblock_t *sb = inode_ref->fs->superblock;
+	uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	
+	/* Calculate number of new logical block */
+	uint32_t new_block_idx = 0;
+	if (inode_size > 0) {
+		if ((inode_size % block_size) != 0)
+			inode_size += block_size - (inode_size % block_size);
+		
+		new_block_idx = inode_size / block_size;
+	}
+	
+	/* Load the nearest leaf (with extent) */
+	ext4_extent_path_t *path;
+	int rc = ext4_extent_find_extent(inode_ref, new_block_idx, &path);
+	if (rc != EOK)
+		return rc;
+	
+	/* Jump to last item of the path (extent) */
+	ext4_extent_path_t *path_ptr = path;
+	while (path_ptr->depth != 0)
+		path_ptr++;
+	
+	/* Add new extent to the node if not present */
+	if (path_ptr->extent == NULL)
+		goto append_extent;
+	
+	uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent);
+	uint16_t block_limit = (1 << 15);
+	
+	uint32_t phys_block = 0;
+	if (block_count < block_limit) {
+		/* There is space for new block in the extent */
+		if (block_count == 0) {
+			/* Existing extent is empty */
+			rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
+			if (rc != EOK)
+				goto finish;
+			
+			/* Initialize extent */
+			ext4_extent_set_first_block(path_ptr->extent, new_block_idx);
+			ext4_extent_set_start(path_ptr->extent, phys_block);
+			ext4_extent_set_block_count(path_ptr->extent, 1);
+			
+			/* Update i-node */
+			if (update_size) {
+				ext4_inode_set_size(inode_ref->inode, inode_size + block_size);
+				inode_ref->dirty = true;
+			}
+			
+			path_ptr->block->dirty = true;
+			
+			goto finish;
+		} else {
+			/* Existing extent contains some blocks */
+			phys_block = ext4_extent_get_start(path_ptr->extent);
+			phys_block += ext4_extent_get_block_count(path_ptr->extent);
+			
+			/* Check if the following block is free for allocation */
+			bool free;
+			rc = ext4_balloc_try_alloc_block(inode_ref, phys_block, &free);
+			if (rc != EOK)
+				goto finish;
+			
+			if (!free) {
+				/* Target is not free, new block must be appended to new extent */
+				goto append_extent;
+			}
+			
+			/* Update extent */
+			ext4_extent_set_block_count(path_ptr->extent, block_count + 1);
+			
+			/* Update i-node */
+			if (update_size) {
+				ext4_inode_set_size(inode_ref->inode, inode_size + block_size);
+				inode_ref->dirty = true;
+			}
+			
+			path_ptr->block->dirty = true;
+			
+			goto finish;
+		}
+	}
+	
+	
+append_extent:
+	/* Append new extent to the tree */
+	phys_block = 0;
+	
+	/* Allocate new data block */
+	rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
+	if (rc != EOK)
+		goto finish;
+	
+	/* Append extent for new block (includes tree splitting if needed) */
+	rc = ext4_extent_append_extent(inode_ref, path, new_block_idx);
+	if (rc != EOK) {
+		ext4_balloc_free_block(inode_ref, phys_block);
+		goto finish;
+	}
+	
+	uint32_t tree_depth = ext4_extent_header_get_depth(path->header);
+	path_ptr = path + tree_depth;
+	
+	/* Initialize newly created extent */
+	ext4_extent_set_block_count(path_ptr->extent, 1);
+	ext4_extent_set_first_block(path_ptr->extent, new_block_idx);
+	ext4_extent_set_start(path_ptr->extent, phys_block);
+	
+	/* Update i-node */
+	if (update_size) {
+		ext4_inode_set_size(inode_ref->inode, inode_size + block_size);
+		inode_ref->dirty = true;
+	}
+	
+	path_ptr->block->dirty = true;
+	
+finish:
+	/* Set return values */
+	*iblock = new_block_idx;
+	*fblock = phys_block;
+	
+	/*
+	 * Put loaded blocks
+	 * starting from 1: 0 is a block with inode data
+	 */
+	for (uint16_t i = 1; i <= path->depth; ++i) {
+		if (path[i].block)
+			block_put(path[i].block);
+	}
+	
+	/* Destroy temporary data structure */
+	free(path);
+	
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_extent.h
===================================================================
--- uspace/lib/ext4/libext4_extent.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_extent.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_EXTENT_H_
+#define LIBEXT4_LIBEXT4_EXTENT_H_
+
+#include "libext4_types.h"
+
+extern uint32_t ext4_extent_get_first_block(ext4_extent_t *);
+extern void ext4_extent_set_first_block(ext4_extent_t *, uint32_t);
+extern uint16_t ext4_extent_get_block_count(ext4_extent_t *);
+extern void ext4_extent_set_block_count(ext4_extent_t *, uint16_t);
+extern uint64_t ext4_extent_get_start(ext4_extent_t *);
+extern void ext4_extent_set_start(ext4_extent_t *, uint64_t);
+
+extern uint32_t ext4_extent_index_get_first_block(ext4_extent_index_t *);
+extern void ext4_extent_index_set_first_block(ext4_extent_index_t *, uint32_t);
+extern uint64_t ext4_extent_index_get_leaf(ext4_extent_index_t *);
+extern void ext4_extent_index_set_leaf(ext4_extent_index_t *, uint64_t);
+
+extern uint16_t ext4_extent_header_get_magic(ext4_extent_header_t *);
+extern void ext4_extent_header_set_magic(ext4_extent_header_t *, uint16_t);
+extern uint16_t ext4_extent_header_get_entries_count(ext4_extent_header_t *);
+extern void ext4_extent_header_set_entries_count(ext4_extent_header_t *,
+    uint16_t);
+extern uint16_t ext4_extent_header_get_max_entries_count(ext4_extent_header_t *);
+extern void ext4_extent_header_set_max_entries_count(ext4_extent_header_t *,
+    uint16_t);
+extern uint16_t ext4_extent_header_get_depth(ext4_extent_header_t *);
+extern void ext4_extent_header_set_depth(ext4_extent_header_t *, uint16_t);
+extern uint32_t ext4_extent_header_get_generation(ext4_extent_header_t *);
+extern void ext4_extent_header_set_generation(ext4_extent_header_t *, uint32_t);
+
+extern int ext4_extent_find_block(ext4_inode_ref_t *, uint32_t, uint32_t *);
+extern int ext4_extent_release_blocks_from(ext4_inode_ref_t *, uint32_t);
+
+extern int ext4_extent_append_block(ext4_inode_ref_t *, uint32_t *, uint32_t *,
+    bool);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_filesystem.c
===================================================================
--- uspace/lib/ext4/libext4_filesystem.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_filesystem.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1388 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+/**
+ * @file  libext4_filesystem.c
+ * @brief More complex filesystem operations.
+ */
+
+#include <byteorder.h>
+#include <errno.h>
+#include <malloc.h>
+#include "libext4.h"
+
+/** Initialize filesystem and read all needed data.
+ *
+ * @param fs         Filesystem instance to be initialized
+ * @param service_id Identifier if device with the filesystem
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_init(ext4_filesystem_t *fs, service_id_t service_id,
+    enum cache_mode cmode)
+{
+	fs->device = service_id;
+	
+	/* Initialize block library (4096 is size of communication channel) */
+	int rc = block_init(EXCHANGE_SERIALIZE, fs->device, 4096);
+	if (rc != EOK)
+		return rc;
+	
+	/* Read superblock from device to memory */
+	ext4_superblock_t *temp_superblock;
+	rc = ext4_superblock_read_direct(fs->device, &temp_superblock);
+	if (rc != EOK) {
+		block_fini(fs->device);
+		return rc;
+	}
+	
+	/* Read block size from superblock and check */
+	uint32_t block_size = ext4_superblock_get_block_size(temp_superblock);
+	if (block_size > EXT4_MAX_BLOCK_SIZE) {
+		block_fini(fs->device);
+		return ENOTSUP;
+	}
+	
+	/* Initialize block caching by libblock */
+	rc = block_cache_init(service_id, block_size, 0, cmode);
+	if (rc != EOK) {
+		block_fini(fs->device);
+		return rc;
+	}
+	
+	/* Compute limits for indirect block levels */
+	uint32_t block_ids_per_block = block_size / sizeof(uint32_t);
+	fs->inode_block_limits[0] = EXT4_INODE_DIRECT_BLOCK_COUNT;
+	fs->inode_blocks_per_level[0] = 1;
+	for (unsigned int i = 1; i < 4; i++) {
+		fs->inode_blocks_per_level[i] = fs->inode_blocks_per_level[i - 1] *
+		    block_ids_per_block;
+		fs->inode_block_limits[i] = fs->inode_block_limits[i - 1] +
+		    fs->inode_blocks_per_level[i];
+	}
+	
+	/* Return loaded superblock */
+	fs->superblock = temp_superblock;
+	
+	uint16_t state = ext4_superblock_get_state(fs->superblock);
+	
+	if (((state & EXT4_SUPERBLOCK_STATE_VALID_FS) !=
+	    EXT4_SUPERBLOCK_STATE_VALID_FS) ||
+	    ((state & EXT4_SUPERBLOCK_STATE_ERROR_FS) ==
+	    EXT4_SUPERBLOCK_STATE_ERROR_FS)) {
+		block_cache_fini(fs->device);
+		block_fini(fs->device);
+		return ENOTSUP;
+	}
+	
+	/* Mark system as mounted */
+	ext4_superblock_set_state(fs->superblock, EXT4_SUPERBLOCK_STATE_ERROR_FS);
+	rc = ext4_superblock_write_direct(fs->device, fs->superblock);
+	if (rc != EOK) {
+		block_cache_fini(fs->device);
+		block_fini(fs->device);
+		return rc;
+	}
+	
+	uint16_t mnt_count = ext4_superblock_get_mount_count(fs->superblock);
+	ext4_superblock_set_mount_count(fs->superblock, mnt_count + 1);
+	
+	return EOK;
+}
+
+/** Destroy filesystem instance (used by unmount operation).
+ *
+ * @param fs Filesystem to be destroyed
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_fini(ext4_filesystem_t *fs)
+{
+	/* Write the superblock to the device */
+	ext4_superblock_set_state(fs->superblock, EXT4_SUPERBLOCK_STATE_VALID_FS);
+	int rc = ext4_superblock_write_direct(fs->device, fs->superblock);
+	
+	/* Release memory space for superblock */
+	free(fs->superblock);
+	
+	/* Finish work with block library */
+	block_cache_fini(fs->device);
+	block_fini(fs->device);
+	
+	return rc;
+}
+
+/** Check sanity of the filesystem.
+ *
+ * Main is the check of the superblock structure.
+ *
+ * @param fs Filesystem to be checked
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_check_sanity(ext4_filesystem_t *fs)
+{
+	/* Check superblock */
+	return ext4_superblock_check_sanity(fs->superblock);
+}
+
+/** Check filesystem's features, if supported by this driver
+ *
+ * Function can return EOK and set read_only flag. It mean's that
+ * there are some not-supported features, that can cause problems
+ * during some write operations.
+ *
+ * @param fs        Filesystem to be checked
+ * @param read_only Flag if filesystem should be mounted only for reading
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_check_features(ext4_filesystem_t *fs, bool *read_only)
+{
+	/* Feature flags are present only in higher revisions */
+	if (ext4_superblock_get_rev_level(fs->superblock) == 0) {
+		*read_only = false;
+		return EOK;
+	}
+	
+	/*
+	 * Check incompatible features - if filesystem has some,
+	 * volume can't be mounted
+	 */
+	uint32_t incompatible_features;
+	incompatible_features =
+	    ext4_superblock_get_features_incompatible(fs->superblock);
+	incompatible_features &= ~EXT4_FEATURE_INCOMPAT_SUPP;
+	if (incompatible_features > 0)
+		return ENOTSUP;
+	
+	/*
+	 * Check read-only features, if filesystem has some,
+	 * volume can be mount only in read-only mode
+	 */
+	uint32_t compatible_read_only;
+	compatible_read_only =
+	    ext4_superblock_get_features_read_only(fs->superblock);
+	compatible_read_only &= ~EXT4_FEATURE_RO_COMPAT_SUPP;
+	if (compatible_read_only > 0) {
+		*read_only = true;
+		return EOK;
+	}
+	
+	return EOK;
+}
+
+
+/** Convert block address to relative index in block group.
+ *
+ * @param sb         Superblock pointer
+ * @param block_addr Block number to convert
+ *
+ * @return Relative number of block
+ *
+ */
+uint32_t ext4_filesystem_blockaddr2_index_in_group(ext4_superblock_t *sb,
+    uint32_t block_addr)
+{
+	uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb);
+	uint32_t first_block = ext4_superblock_get_first_data_block(sb);
+	
+	/* First block == 0 or 1 */
+	if (first_block == 0)
+		return block_addr % blocks_per_group;
+	else
+		return (block_addr - 1) % blocks_per_group;
+}
+
+
+/** Convert relative block address in group to absolute address.
+ *
+ * @param sb Superblock pointer
+ *
+ * @return Absolute block address
+ *
+ */
+uint32_t ext4_filesystem_index_in_group2blockaddr(ext4_superblock_t *sb,
+    uint32_t index, uint32_t bgid)
+{
+	uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb);
+	
+	if (ext4_superblock_get_first_data_block(sb) == 0)
+		return bgid * blocks_per_group + index;
+	else
+		return bgid * blocks_per_group + index + 1;
+}
+
+/** Initialize block bitmap in block group.
+ *
+ * @param bg_ref Reference to block group
+ *
+ * @return Error code
+ *
+ */
+static int ext4_filesystem_init_block_bitmap(ext4_block_group_ref_t *bg_ref)
+{
+	/* Load bitmap */
+	uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap(
+	    bg_ref->block_group, bg_ref->fs->superblock);
+	
+	block_t *bitmap_block;
+	int rc = block_get(&bitmap_block, bg_ref->fs->device,
+	    bitmap_block_addr, BLOCK_FLAGS_NOREAD);
+	if (rc != EOK)
+		return rc;
+	
+	uint8_t *bitmap = bitmap_block->data;
+	
+	/* Initialize all bitmap bits to zero */
+	uint32_t block_size = ext4_superblock_get_block_size(bg_ref->fs->superblock);
+	memset(bitmap, 0, block_size);
+	
+	/* Determine first block and first data block in group */
+	uint32_t first_idx = 0;
+	
+	uint32_t first_data = ext4_balloc_get_first_data_block_in_group(
+	    bg_ref->fs->superblock, bg_ref);
+	uint32_t first_data_idx = ext4_filesystem_blockaddr2_index_in_group(
+	    bg_ref->fs->superblock, first_data);
+	
+	/* Set bits from to first block to first data block - 1 to one (allocated) */
+	for (uint32_t block = first_idx; block < first_data_idx; ++block)
+		ext4_bitmap_set_bit(bitmap, block);
+	
+	bitmap_block->dirty = true;
+	
+	/* Save bitmap */
+	return block_put(bitmap_block);
+}
+
+/** Initialize i-node bitmap in block group.
+ *
+ * @param bg_ref Reference to block group
+ *
+ * @return Error code
+ *
+ */
+static int ext4_filesystem_init_inode_bitmap(ext4_block_group_ref_t *bg_ref)
+{
+	/* Load bitmap */
+	uint32_t bitmap_block_addr = ext4_block_group_get_inode_bitmap(
+	    bg_ref->block_group, bg_ref->fs->superblock);
+	block_t *bitmap_block;
+	
+	int rc = block_get(&bitmap_block, bg_ref->fs->device,
+	    bitmap_block_addr, BLOCK_FLAGS_NOREAD);
+	if (rc != EOK)
+		return rc;
+	
+	uint8_t *bitmap = bitmap_block->data;
+	
+	/* Initialize all bitmap bits to zero */
+	uint32_t block_size = ext4_superblock_get_block_size(bg_ref->fs->superblock);
+	uint32_t inodes_per_group =
+	    ext4_superblock_get_inodes_per_group(bg_ref->fs->superblock);
+	memset(bitmap, 0, (inodes_per_group + 7) / 8);
+	
+	uint32_t start_bit = inodes_per_group;
+	uint32_t end_bit = block_size * 8;
+	
+	uint32_t i;
+	for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++)
+		ext4_bitmap_set_bit(bitmap, i);
+	
+	if (i < end_bit)
+		memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
+	
+	bitmap_block->dirty = true;
+	
+	/* Save bitmap */
+	return block_put(bitmap_block);
+}
+
+/** Initialize i-node table in block group.
+ *
+ * @param bg_ref Reference to block group
+ *
+ * @return Error code
+ *
+ */
+static int ext4_filesystem_init_inode_table(ext4_block_group_ref_t *bg_ref)
+{
+	ext4_superblock_t *sb = bg_ref->fs->superblock;
+	
+	uint32_t inode_size = ext4_superblock_get_inode_size(sb);
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	uint32_t inodes_per_block = block_size / inode_size;
+	
+	uint32_t inodes_in_group =
+	    ext4_superblock_get_inodes_in_group(sb, bg_ref->index);
+	
+	uint32_t table_blocks = inodes_in_group / inodes_per_block;
+	
+	if (inodes_in_group % inodes_per_block)
+		table_blocks++;
+	
+	/* Compute initialization bounds */
+	uint32_t first_block = ext4_block_group_get_inode_table_first_block(
+	    bg_ref->block_group, sb);
+	
+	uint32_t last_block = first_block + table_blocks - 1;
+	
+	/* Initialization of all itable blocks */
+	for (uint32_t fblock = first_block; fblock <= last_block; ++fblock) {
+		block_t *block;
+		int rc = block_get(&block, bg_ref->fs->device, fblock,
+		    BLOCK_FLAGS_NOREAD);
+		if (rc != EOK)
+			return rc;
+		
+		memset(block->data, 0, block_size);
+		block->dirty = true;
+		
+		rc = block_put(block);
+		if (rc != EOK)
+			return rc;
+	}
+	
+	return EOK;
+}
+
+/** Get reference to block group specified by index.
+ *
+ * @param fs   Filesystem to find block group on
+ * @param bgid Index of block group to load
+ * @param ref  Output pointer for reference
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_get_block_group_ref(ext4_filesystem_t *fs, uint32_t bgid,
+    ext4_block_group_ref_t **ref)
+{
+	/* Allocate memory for new structure */
+	ext4_block_group_ref_t *newref =
+	    malloc(sizeof(ext4_block_group_ref_t));
+	if (newref == NULL)
+		return ENOMEM;
+	
+	/* Compute number of descriptors, that fits in one data block */
+	uint32_t descriptors_per_block =
+	    ext4_superblock_get_block_size(fs->superblock) /
+	    ext4_superblock_get_desc_size(fs->superblock);
+	
+	/* Block group descriptor table starts at the next block after superblock */
+	aoff64_t block_id =
+	    ext4_superblock_get_first_data_block(fs->superblock) + 1;
+	
+	/* Find the block containing the descriptor we are looking for */
+	block_id += bgid / descriptors_per_block;
+	uint32_t offset = (bgid % descriptors_per_block) *
+	    ext4_superblock_get_desc_size(fs->superblock);
+	
+	/* Load block with descriptors */
+	int rc = block_get(&newref->block, fs->device, block_id, 0);
+	if (rc != EOK) {
+		free(newref);
+		return rc;
+	}
+	
+	/* Inititialize in-memory representation */
+	newref->block_group = newref->block->data + offset;
+	newref->fs = fs;
+	newref->index = bgid;
+	newref->dirty = false;
+	
+	*ref = newref;
+	
+	if (ext4_block_group_has_flag(newref->block_group,
+	    EXT4_BLOCK_GROUP_BLOCK_UNINIT)) {
+		rc = ext4_filesystem_init_block_bitmap(newref);
+		if (rc != EOK) {
+			block_put(newref->block);
+			free(newref);
+			return rc;
+		}
+		
+		ext4_block_group_clear_flag(newref->block_group,
+		    EXT4_BLOCK_GROUP_BLOCK_UNINIT);
+		
+		newref->dirty = true;
+	}
+	
+	if (ext4_block_group_has_flag(newref->block_group,
+	    EXT4_BLOCK_GROUP_INODE_UNINIT)) {
+		rc = ext4_filesystem_init_inode_bitmap(newref);
+		if (rc != EOK) {
+			block_put(newref->block);
+			free(newref);
+			return rc;
+		}
+		
+		ext4_block_group_clear_flag(newref->block_group,
+		    EXT4_BLOCK_GROUP_INODE_UNINIT);
+		
+		if (!ext4_block_group_has_flag(newref->block_group,
+		    EXT4_BLOCK_GROUP_ITABLE_ZEROED)) {
+			rc = ext4_filesystem_init_inode_table(newref);
+			if (rc != EOK)
+				return rc;
+			
+			ext4_block_group_set_flag(newref->block_group,
+			    EXT4_BLOCK_GROUP_ITABLE_ZEROED);
+		}
+		
+		newref->dirty = true;
+	}
+	
+	return EOK;
+}
+
+/** Compute checksum of block group descriptor.
+ *
+ * @param sb   Superblock
+ * @param bgid Index of block group in the filesystem
+ * @param bg   Block group to compute checksum for
+ *
+ * @return Checksum value
+ *
+ */
+static uint16_t ext4_filesystem_bg_checksum(ext4_superblock_t *sb, uint32_t bgid,
+    ext4_block_group_t *bg)
+{
+	/* If checksum not supported, 0 will be returned */
+	uint16_t crc = 0;
+	
+	/* Compute the checksum only if the filesystem supports it */
+	if (ext4_superblock_has_feature_read_only(sb,
+	    EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+		void *base = bg;
+		void *checksum = &bg->checksum;
+		
+		uint32_t offset = (uint32_t) (checksum - base);
+		
+		/* Convert block group index to little endian */
+		uint32_t le_group = host2uint32_t_le(bgid);
+		
+		/* Initialization */
+		crc = crc16(~0, sb->uuid, sizeof(sb->uuid));
+		
+		/* Include index of block group */
+		crc = crc16(crc, (uint8_t *) &le_group, sizeof(le_group));
+		
+		/* Compute crc from the first part (stop before checksum field) */
+		crc = crc16(crc, (uint8_t *) bg, offset);
+		
+		/* Skip checksum */
+		offset += sizeof(bg->checksum);
+		
+		/* Checksum of the rest of block group descriptor */
+		if ((ext4_superblock_has_feature_incompatible(sb,
+		    EXT4_FEATURE_INCOMPAT_64BIT)) &&
+		    (offset < ext4_superblock_get_desc_size(sb)))
+			crc = crc16(crc, ((uint8_t *) bg) + offset,
+			    ext4_superblock_get_desc_size(sb) - offset);
+	}
+	
+	return crc;
+}
+
+/** Put reference to block group.
+ *
+ * @oaram ref Pointer for reference to be put back
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_put_block_group_ref(ext4_block_group_ref_t *ref)
+{
+	/* Check if reference modified */
+	if (ref->dirty) {
+		/* Compute new checksum of block group */
+		uint16_t checksum =
+		    ext4_filesystem_bg_checksum(ref->fs->superblock, ref->index,
+		    ref->block_group);
+		ext4_block_group_set_checksum(ref->block_group, checksum);
+		
+		/* Mark block dirty for writing changes to physical device */
+		ref->block->dirty = true;
+	}
+	
+	/* Put back block, that contains block group descriptor */
+	int rc = block_put(ref->block);
+	free(ref);
+	
+	return rc;
+}
+
+/** Get reference to i-node specified by index.
+ *
+ * @param fs    Filesystem to find i-node on
+ * @param index Index of i-node to load
+ * @oaram ref   Output pointer for reference
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_get_inode_ref(ext4_filesystem_t *fs, uint32_t index,
+    ext4_inode_ref_t **ref)
+{
+	/* Allocate memory for new structure */
+	ext4_inode_ref_t *newref =
+	    malloc(sizeof(ext4_inode_ref_t));
+	if (newref == NULL)
+		return ENOMEM;
+	
+	/* Compute number of i-nodes, that fits in one data block */
+	uint32_t inodes_per_group =
+	    ext4_superblock_get_inodes_per_group(fs->superblock);
+	
+	/*
+	 * Inode numbers are 1-based, but it is simpler to work with 0-based
+	 * when computing indices
+	 */
+	index -= 1;
+	uint32_t block_group = index / inodes_per_group;
+	uint32_t offset_in_group = index % inodes_per_group;
+	
+	/* Load block group, where i-node is located */
+	ext4_block_group_ref_t *bg_ref;
+	int rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
+	if (rc != EOK) {
+		free(newref);
+		return rc;
+	}
+	
+	/* Load block address, where i-node table is located */
+	uint32_t inode_table_start =
+	    ext4_block_group_get_inode_table_first_block(bg_ref->block_group,
+	    fs->superblock);
+	
+	/* Put back block group reference (not needed more) */
+	rc = ext4_filesystem_put_block_group_ref(bg_ref);
+	if (rc != EOK) {
+		free(newref);
+		return rc;
+	}
+	
+	/* Compute position of i-node in the block group */
+	uint16_t inode_size = ext4_superblock_get_inode_size(fs->superblock);
+	uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
+	uint32_t byte_offset_in_group = offset_in_group * inode_size;
+	
+	/* Compute block address */
+	aoff64_t block_id = inode_table_start + (byte_offset_in_group / block_size);
+	rc = block_get(&newref->block, fs->device, block_id, 0);
+	if (rc != EOK) {
+		free(newref);
+		return rc;
+	}
+	
+	/* Compute position of i-node in the data block */
+	uint32_t offset_in_block = byte_offset_in_group % block_size;
+	newref->inode = newref->block->data + offset_in_block;
+	
+	/* We need to store the original value of index in the reference */
+	newref->index = index + 1;
+	newref->fs = fs;
+	newref->dirty = false;
+	
+	*ref = newref;
+	
+	return EOK;
+}
+
+/** Put reference to i-node.
+ *
+ * @param ref Pointer for reference to be put back
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_put_inode_ref(ext4_inode_ref_t *ref)
+{
+	/* Check if reference modified */
+	if (ref->dirty) {
+		/* Mark block dirty for writing changes to physical device */
+		ref->block->dirty = true;
+	}
+	
+	/* Put back block, that contains i-node */
+	int rc = block_put(ref->block);
+	free(ref);
+	
+	return rc;
+}
+
+/** Allocate new i-node in the filesystem.
+ *
+ * @param fs        Filesystem to allocated i-node on
+ * @param inode_ref Output pointer to return reference to allocated i-node
+ * @param flags     Flags to be set for newly created i-node
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_alloc_inode(ext4_filesystem_t *fs,
+    ext4_inode_ref_t **inode_ref, int flags)
+{
+	/* Check if newly allocated i-node will be a directory */
+	bool is_dir = false;
+	if (flags & L_DIRECTORY)
+		is_dir = true;
+	
+	/* Allocate inode by allocation algorithm */
+	uint32_t index;
+	int rc = ext4_ialloc_alloc_inode(fs, &index, is_dir);
+	if (rc != EOK)
+		return rc;
+	
+	/* Load i-node from on-disk i-node table */
+	rc = ext4_filesystem_get_inode_ref(fs, index, inode_ref);
+	if (rc != EOK) {
+		ext4_ialloc_free_inode(fs, index, is_dir);
+		return rc;
+	}
+	
+	/* Initialize i-node */
+	ext4_inode_t *inode = (*inode_ref)->inode;
+	
+	uint16_t mode;
+	if (is_dir) {
+		/*
+		 * Default directory permissions to be compatible with other systems
+		 * 0777 (octal) == rwxrwxrwx
+		 */
+		
+		mode = 0777;
+		mode |= EXT4_INODE_MODE_DIRECTORY;
+		ext4_inode_set_mode(fs->superblock, inode, mode);
+		ext4_inode_set_links_count(inode, 1);  /* '.' entry */
+	} else {
+		/*
+		 * Default file permissions to be compatible with other systems
+		 * 0666 (octal) == rw-rw-rw-
+		 */
+		
+		mode = 0666;
+		mode |= EXT4_INODE_MODE_FILE;
+		ext4_inode_set_mode(fs->superblock, inode, mode);
+		ext4_inode_set_links_count(inode, 0);
+	}
+	
+	ext4_inode_set_uid(inode, 0);
+	ext4_inode_set_gid(inode, 0);
+	ext4_inode_set_size(inode, 0);
+	ext4_inode_set_access_time(inode, 0);
+	ext4_inode_set_change_inode_time(inode, 0);
+	ext4_inode_set_modification_time(inode, 0);
+	ext4_inode_set_deletion_time(inode, 0);
+	ext4_inode_set_blocks_count(fs->superblock, inode, 0);
+	ext4_inode_set_flags(inode, 0);
+	ext4_inode_set_generation(inode, 0);
+	
+	/* Reset blocks array */
+	for (uint32_t i = 0; i < EXT4_INODE_BLOCKS; i++)
+		inode->blocks[i] = 0;
+	
+	/* Initialize extents if needed */
+	if (ext4_superblock_has_feature_incompatible(
+	    fs->superblock, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+		ext4_inode_set_flag(inode, EXT4_INODE_FLAG_EXTENTS);
+		
+		/* Initialize extent root header */
+		ext4_extent_header_t *header = ext4_inode_get_extent_header(inode);
+		ext4_extent_header_set_depth(header, 0);
+		ext4_extent_header_set_entries_count(header, 0);
+		ext4_extent_header_set_generation(header, 0);
+		ext4_extent_header_set_magic(header, EXT4_EXTENT_MAGIC);
+		
+		uint16_t max_entries = (EXT4_INODE_BLOCKS * sizeof(uint32_t) -
+		    sizeof(ext4_extent_header_t)) / sizeof(ext4_extent_t);
+		
+		ext4_extent_header_set_max_entries_count(header, max_entries);
+	}
+	
+	(*inode_ref)->dirty = true;
+	
+	return EOK;
+}
+
+/** Release i-node and mark it as free.
+ *
+ * @param inode_ref I-node to be released
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_free_inode(ext4_inode_ref_t *inode_ref)
+{
+	ext4_filesystem_t *fs = inode_ref->fs;
+	
+	/* For extents must be data block destroyed by other way */
+	if ((ext4_superblock_has_feature_incompatible(fs->superblock,
+	    EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
+	    (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
+		/* Data structures are released during truncate operation... */
+		goto finish;
+	}
+	
+	/* Release all indirect (no data) blocks */
+	
+	/* 1) Single indirect */
+	uint32_t fblock = ext4_inode_get_indirect_block(inode_ref->inode, 0);
+	if (fblock != 0) {
+		int rc = ext4_balloc_free_block(inode_ref, fblock);
+		if (rc != EOK)
+			return rc;
+		
+		ext4_inode_set_indirect_block(inode_ref->inode, 0, 0);
+	}
+	
+	block_t *block;
+	uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
+	uint32_t count = block_size / sizeof(uint32_t);
+	
+	/* 2) Double indirect */
+	fblock = ext4_inode_get_indirect_block(inode_ref->inode, 1);
+	if (fblock != 0) {
+		int rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
+		if (rc != EOK)
+			return rc;
+		
+		uint32_t ind_block;
+		for (uint32_t offset = 0; offset < count; ++offset) {
+			ind_block = uint32_t_le2host(((uint32_t *) block->data)[offset]);
+			
+			if (ind_block != 0) {
+				rc = ext4_balloc_free_block(inode_ref, ind_block);
+				if (rc != EOK) {
+					block_put(block);
+					return rc;
+				}
+			}
+		}
+		
+		block_put(block);
+		rc = ext4_balloc_free_block(inode_ref, fblock);
+		if (rc != EOK)
+			return rc;
+		
+		ext4_inode_set_indirect_block(inode_ref->inode, 1, 0);
+	}
+	
+	/* 3) Tripple indirect */
+	block_t *subblock;
+	fblock = ext4_inode_get_indirect_block(inode_ref->inode, 2);
+	if (fblock != 0) {
+		int rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
+		if (rc != EOK)
+			return rc;
+		
+		uint32_t ind_block;
+		for (uint32_t offset = 0; offset < count; ++offset) {
+			ind_block = uint32_t_le2host(((uint32_t *) block->data)[offset]);
+			
+			if (ind_block != 0) {
+				rc = block_get(&subblock, fs->device, ind_block,
+				    BLOCK_FLAGS_NONE);
+				if (rc != EOK) {
+					block_put(block);
+					return rc;
+				}
+				
+				uint32_t ind_subblock;
+				for (uint32_t suboffset = 0; suboffset < count;
+				    ++suboffset) {
+					ind_subblock = uint32_t_le2host(((uint32_t *)
+					    subblock->data)[suboffset]);
+					
+					if (ind_subblock != 0) {
+						rc = ext4_balloc_free_block(inode_ref, ind_subblock);
+						if (rc != EOK) {
+							block_put(subblock);
+							block_put(block);
+							return rc;
+						}
+					}
+				}
+				
+				block_put(subblock);
+			}
+			
+			rc = ext4_balloc_free_block(inode_ref, ind_block);
+			if (rc != EOK) {
+				block_put(block);
+				return rc;
+			}
+		}
+		
+		block_put(block);
+		rc = ext4_balloc_free_block(inode_ref, fblock);
+		if (rc != EOK)
+			return rc;
+		
+		ext4_inode_set_indirect_block(inode_ref->inode, 2, 0);
+	}
+	
+finish:
+	/* Mark inode dirty for writing to the physical device */
+	inode_ref->dirty = true;
+	
+	/* Free block with extended attributes if present */
+	uint32_t xattr_block = ext4_inode_get_file_acl(
+	    inode_ref->inode, fs->superblock);
+	if (xattr_block) {
+		int rc = ext4_balloc_free_block(inode_ref, xattr_block);
+		if (rc != EOK)
+			return rc;
+		
+		ext4_inode_set_file_acl(inode_ref->inode, fs->superblock, 0);
+	}
+	
+	/* Free inode by allocator */
+	int rc;
+	if (ext4_inode_is_type(fs->superblock, inode_ref->inode,
+	    EXT4_INODE_MODE_DIRECTORY))
+		rc = ext4_ialloc_free_inode(fs, inode_ref->index, true);
+	else
+		rc = ext4_ialloc_free_inode(fs, inode_ref->index, false);
+	
+	return rc;
+}
+
+/** Truncate i-node data blocks.
+ *
+ * @param inode_ref I-node to be truncated
+ * @param new_size  New size of inode (must be < current size)
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_truncate_inode(ext4_inode_ref_t *inode_ref,
+    aoff64_t new_size)
+{
+	ext4_superblock_t *sb = inode_ref->fs->superblock;
+	
+	/* Check flags, if i-node can be truncated */
+	if (!ext4_inode_can_truncate(sb, inode_ref->inode))
+		return EINVAL;
+	
+	/* If sizes are equal, nothing has to be done. */
+	aoff64_t old_size = ext4_inode_get_size(sb, inode_ref->inode);
+	if (old_size == new_size)
+		return EOK;
+	
+	/* It's not suppported to make the larger file by truncate operation */
+	if (old_size < new_size)
+		return EINVAL;
+	
+	/* Compute how many blocks will be released */
+	aoff64_t size_diff = old_size - new_size;
+	uint32_t block_size  = ext4_superblock_get_block_size(sb);
+	uint32_t diff_blocks_count = size_diff / block_size;
+	if (size_diff % block_size != 0)
+		diff_blocks_count++;
+	
+	uint32_t old_blocks_count = old_size / block_size;
+	if (old_size % block_size != 0)
+		old_blocks_count++;
+	
+	if ((ext4_superblock_has_feature_incompatible(inode_ref->fs->superblock,
+	    EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
+	    (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
+		/* Extents require special operation */
+		int rc = ext4_extent_release_blocks_from(inode_ref,
+		    old_blocks_count - diff_blocks_count);
+		if (rc != EOK)
+			return rc;
+	} else {
+		/* Release data blocks from the end of file */
+		
+		/* Starting from 1 because of logical blocks are numbered from 0 */
+		for (uint32_t i = 1; i <= diff_blocks_count; ++i) {
+			int rc = ext4_filesystem_release_inode_block(inode_ref,
+			    old_blocks_count - i);
+			if (rc != EOK)
+				return rc;
+		}
+	}
+	
+	/* Update i-node */
+	ext4_inode_set_size(inode_ref->inode, new_size);
+	inode_ref->dirty = true;
+	
+	return EOK;
+}
+
+/** Get physical block address by logical index of the block.
+ *
+ * @param inode_ref I-node to read block address from
+ * @param iblock    Logical index of block
+ * @param fblock    Output pointer for return physical block address
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_get_inode_data_block_index(ext4_inode_ref_t *inode_ref,
+    aoff64_t iblock, uint32_t *fblock)
+{
+	ext4_filesystem_t *fs = inode_ref->fs;
+	
+	/* For empty file is situation simple */
+	if (ext4_inode_get_size(fs->superblock, inode_ref->inode) == 0) {
+		*fblock = 0;
+		return EOK;
+	}
+	
+	uint32_t current_block;
+	
+	/* Handle i-node using extents */
+	if ((ext4_superblock_has_feature_incompatible(fs->superblock,
+	    EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
+	    (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
+		int rc = ext4_extent_find_block(inode_ref, iblock, &current_block);
+		if (rc != EOK)
+			return rc;
+		
+		*fblock = current_block;
+		return EOK;
+	}
+	
+	ext4_inode_t *inode = inode_ref->inode;
+	
+	/* Direct block are read directly from array in i-node structure */
+	if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
+		current_block = ext4_inode_get_direct_block(inode, (uint32_t) iblock);
+		*fblock = current_block;
+		return EOK;
+	}
+	
+	/* Determine indirection level of the target block */
+	unsigned int level = 0;
+	for (unsigned int i = 1; i < 4; i++) {
+		if (iblock < fs->inode_block_limits[i]) {
+			level = i;
+			break;
+		}
+	}
+	
+	if (level == 0)
+		return EIO;
+	
+	/* Compute offsets for the topmost level */
+	aoff64_t block_offset_in_level =
+	    iblock - fs->inode_block_limits[level - 1];
+	current_block = ext4_inode_get_indirect_block(inode, level - 1);
+	uint32_t offset_in_block =
+	    block_offset_in_level / fs->inode_blocks_per_level[level - 1];
+	
+	/* Sparse file */
+	if (current_block == 0) {
+		*fblock = 0;
+		return EOK;
+	}
+	
+	block_t *block;
+	
+	/*
+	 * Navigate through other levels, until we find the block number
+	 * or find null reference meaning we are dealing with sparse file
+	 */
+	while (level > 0) {
+		/* Load indirect block */
+		int rc = block_get(&block, fs->device, current_block, 0);
+		if (rc != EOK)
+			return rc;
+		
+		/* Read block address from indirect block */
+		current_block =
+		    uint32_t_le2host(((uint32_t *) block->data)[offset_in_block]);
+		
+		/* Put back indirect block untouched */
+		rc = block_put(block);
+		if (rc != EOK)
+			return rc;
+		
+		/* Check for sparse file */
+		if (current_block == 0) {
+			*fblock = 0;
+			return EOK;
+		}
+		
+		/* Jump to the next level */
+		level--;
+		
+		/* Termination condition - we have address of data block loaded */
+		if (level == 0)
+			break;
+		
+		/* Visit the next level */
+		block_offset_in_level %= fs->inode_blocks_per_level[level];
+		offset_in_block =
+		    block_offset_in_level / fs->inode_blocks_per_level[level - 1];
+	}
+	
+	*fblock = current_block;
+	
+	return EOK;
+}
+
+/** Set physical block address for the block logical address into the i-node.
+ *
+ * @param inode_ref I-node to set block address to
+ * @param iblock    Logical index of block
+ * @param fblock    Physical block address
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_set_inode_data_block_index(ext4_inode_ref_t *inode_ref,
+    aoff64_t iblock, uint32_t fblock)
+{
+	ext4_filesystem_t *fs = inode_ref->fs;
+	
+	/* Handle inode using extents */
+	if ((ext4_superblock_has_feature_compatible(fs->superblock,
+	    EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
+	    (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
+		/* Not reachable */
+		return ENOTSUP;
+	}
+	
+	/* Handle simple case when we are dealing with direct reference */
+	if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
+		ext4_inode_set_direct_block(inode_ref->inode, (uint32_t) iblock, fblock);
+		inode_ref->dirty = true;
+		
+		return EOK;
+	}
+	
+	/* Determine the indirection level needed to get the desired block */
+	unsigned int level = 0;
+	for (unsigned int i = 1; i < 4; i++) {
+		if (iblock < fs->inode_block_limits[i]) {
+			level = i;
+			break;
+		}
+	}
+	
+	if (level == 0)
+		return EIO;
+	
+	uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
+	
+	/* Compute offsets for the topmost level */
+	aoff64_t block_offset_in_level =
+	    iblock - fs->inode_block_limits[level - 1];
+	uint32_t current_block =
+	    ext4_inode_get_indirect_block(inode_ref->inode, level - 1);
+	uint32_t offset_in_block =
+	    block_offset_in_level / fs->inode_blocks_per_level[level - 1];
+	
+	uint32_t new_block_addr;
+	block_t *block;
+	block_t *new_block;
+	
+	/* Is needed to allocate indirect block on the i-node level */
+	if (current_block == 0) {
+		/* Allocate new indirect block */
+		int rc = ext4_balloc_alloc_block(inode_ref, &new_block_addr);
+		if (rc != EOK)
+			return rc;
+		
+		/* Update i-node */
+		ext4_inode_set_indirect_block(inode_ref->inode, level - 1,
+		    new_block_addr);
+		inode_ref->dirty = true;
+		
+		/* Load newly allocated block */
+		rc = block_get(&new_block, fs->device, new_block_addr,
+		    BLOCK_FLAGS_NOREAD);
+		if (rc != EOK) {
+			ext4_balloc_free_block(inode_ref, new_block_addr);
+			return rc;
+		}
+		
+		/* Initialize new block */
+		memset(new_block->data, 0, block_size);
+		new_block->dirty = true;
+		
+		/* Put back the allocated block */
+		rc = block_put(new_block);
+		if (rc != EOK)
+			return rc;
+		
+		current_block = new_block_addr;
+	}
+	
+	/*
+	 * Navigate through other levels, until we find the block number
+	 * or find null reference meaning we are dealing with sparse file
+	 */
+	while (level > 0) {
+		int rc = block_get(&block, fs->device, current_block, 0);
+		if (rc != EOK)
+			return rc;
+		
+		current_block =
+		    uint32_t_le2host(((uint32_t *) block->data)[offset_in_block]);
+		
+		if ((level > 1) && (current_block == 0)) {
+			/* Allocate new block */
+			rc = ext4_balloc_alloc_block(inode_ref, &new_block_addr);
+			if (rc != EOK) {
+				block_put(block);
+				return rc;
+			}
+			
+			/* Load newly allocated block */
+			rc = block_get(&new_block, fs->device, new_block_addr,
+			    BLOCK_FLAGS_NOREAD);
+			if (rc != EOK) {
+				block_put(block);
+				return rc;
+			}
+			
+			/* Initialize allocated block */
+			memset(new_block->data, 0, block_size);
+			new_block->dirty = true;
+			
+			rc = block_put(new_block);
+			if (rc != EOK) {
+				block_put(block);
+				return rc;
+			}
+			
+			/* Write block address to the parent */
+			((uint32_t *) block->data)[offset_in_block] =
+			    host2uint32_t_le(new_block_addr);
+			block->dirty = true;
+			current_block = new_block_addr;
+		}
+		
+		/* Will be finished, write the fblock address */
+		if (level == 1) {
+			((uint32_t *) block->data)[offset_in_block] =
+			    host2uint32_t_le(fblock);
+			block->dirty = true;
+		}
+		
+		rc = block_put(block);
+		if (rc != EOK)
+			return rc;
+		
+		level--;
+		
+		/*
+		 * If we are on the last level, break here as
+		 * there is no next level to visit
+		 */
+		if (level == 0)
+			break;
+		
+		/* Visit the next level */
+		block_offset_in_level %= fs->inode_blocks_per_level[level];
+		offset_in_block =
+		    block_offset_in_level / fs->inode_blocks_per_level[level - 1];
+	}
+	
+	return EOK;
+}
+
+/** Release data block from i-node
+ *
+ * @param inode_ref I-node to release block from
+ * @param iblock    Logical block to be released
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_release_inode_block(ext4_inode_ref_t *inode_ref,
+    uint32_t iblock)
+{
+	uint32_t fblock;
+	
+	ext4_filesystem_t *fs = inode_ref->fs;
+	
+	/* Extents are handled otherwise = there is not support in this function */
+	assert(!(ext4_superblock_has_feature_incompatible(fs->superblock,
+	    EXT4_FEATURE_INCOMPAT_EXTENTS) &&
+	    (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))));
+	
+	ext4_inode_t *inode = inode_ref->inode;
+	
+	/* Handle simple case when we are dealing with direct reference */
+	if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
+		fblock = ext4_inode_get_direct_block(inode, iblock);
+		
+		/* Sparse file */
+		if (fblock == 0)
+			return EOK;
+		
+		ext4_inode_set_direct_block(inode, iblock, 0);
+		return ext4_balloc_free_block(inode_ref, fblock);
+	}
+	
+	/* Determine the indirection level needed to get the desired block */
+	unsigned int level = 0;
+	for (unsigned int i = 1; i < 4; i++) {
+		if (iblock < fs->inode_block_limits[i]) {
+			level = i;
+			break;
+		}
+	}
+	
+	if (level == 0)
+		return EIO;
+	
+	/* Compute offsets for the topmost level */
+	aoff64_t block_offset_in_level =
+	    iblock - fs->inode_block_limits[level - 1];
+	uint32_t current_block =
+	    ext4_inode_get_indirect_block(inode, level - 1);
+	uint32_t offset_in_block =
+	    block_offset_in_level / fs->inode_blocks_per_level[level - 1];
+	
+	/*
+	 * Navigate through other levels, until we find the block number
+	 * or find null reference meaning we are dealing with sparse file
+	 */
+	block_t *block;
+	while (level > 0) {
+		
+		/* Sparse check */
+		if (current_block == 0)
+			return EOK;
+		
+		int rc = block_get(&block, fs->device, current_block, 0);
+		if (rc != EOK)
+			return rc;
+		
+		current_block =
+		    uint32_t_le2host(((uint32_t *) block->data)[offset_in_block]);
+		
+		/* Set zero if physical data block address found */
+		if (level == 1) {
+			((uint32_t *) block->data)[offset_in_block] =
+			    host2uint32_t_le(0);
+			block->dirty = true;
+		}
+		
+		rc = block_put(block);
+		if (rc != EOK)
+			return rc;
+		
+		level--;
+		
+		/*
+		 * If we are on the last level, break here as
+		 * there is no next level to visit
+		 */
+		if (level == 0)
+			break;
+		
+		/* Visit the next level */
+		block_offset_in_level %= fs->inode_blocks_per_level[level];
+		offset_in_block =
+		    block_offset_in_level / fs->inode_blocks_per_level[level - 1];
+	}
+	
+	fblock = current_block;
+	if (fblock == 0)
+		return EOK;
+	
+	/* Physical block is not referenced, it can be released */
+	return ext4_balloc_free_block(inode_ref, fblock);
+}
+
+/** Append following logical block to the i-node.
+ *
+ * @param inode_ref I-node to append block to
+ * @param fblock    Output physical block address of newly allocated block
+ * @param iblock    Output logical number of newly allocated block
+ *
+ * @return Error code
+ *
+ */
+int ext4_filesystem_append_inode_block(ext4_inode_ref_t *inode_ref,
+    uint32_t *fblock, uint32_t *iblock)
+{
+	/* Handle extents separately */
+	if ((ext4_superblock_has_feature_incompatible(inode_ref->fs->superblock,
+	    EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
+	    (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS)))
+		return ext4_extent_append_block(inode_ref, iblock, fblock, true);
+	
+	ext4_superblock_t *sb = inode_ref->fs->superblock;
+	
+	/* Compute next block index and allocate data block */
+	uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	
+	/* Align size i-node size */
+	if ((inode_size % block_size) != 0)
+		inode_size += block_size - (inode_size % block_size);
+	
+	/* Logical blocks are numbered from 0 */
+	uint32_t new_block_idx = inode_size / block_size;
+	
+	/* Allocate new physical block */
+	uint32_t phys_block;
+	int rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
+	if (rc != EOK)
+		return rc;
+	
+	/* Add physical block address to the i-node */
+	rc = ext4_filesystem_set_inode_data_block_index(inode_ref,
+	    new_block_idx, phys_block);
+	if (rc != EOK) {
+		ext4_balloc_free_block(inode_ref, phys_block);
+		return rc;
+	}
+	
+	/* Update i-node */
+	ext4_inode_set_size(inode_ref->inode, inode_size + block_size);
+	inode_ref->dirty = true;
+	
+	*fblock = phys_block;
+	*iblock = new_block_idx;
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_filesystem.h
===================================================================
--- uspace/lib/ext4/libext4_filesystem.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_filesystem.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_FILESYSTEM_H_
+#define LIBEXT4_LIBEXT4_FILESYSTEM_H_
+
+#include <block.h>
+#include "libext4_types.h"
+
+extern int ext4_filesystem_init(ext4_filesystem_t *, service_id_t,
+    enum cache_mode);
+extern int ext4_filesystem_fini(ext4_filesystem_t *);
+extern int ext4_filesystem_check_sanity(ext4_filesystem_t *);
+extern int ext4_filesystem_check_features(ext4_filesystem_t *, bool *);
+extern uint32_t ext4_filesystem_blockaddr2_index_in_group(ext4_superblock_t *,
+    uint32_t);
+extern uint32_t ext4_filesystem_index_in_group2blockaddr(ext4_superblock_t *,
+    uint32_t, uint32_t);
+extern int ext4_filesystem_get_block_group_ref(ext4_filesystem_t *, uint32_t,
+    ext4_block_group_ref_t **);
+extern int ext4_filesystem_put_block_group_ref(ext4_block_group_ref_t *);
+extern int ext4_filesystem_get_inode_ref(ext4_filesystem_t *, uint32_t,
+    ext4_inode_ref_t **);
+extern int ext4_filesystem_put_inode_ref(ext4_inode_ref_t *);
+extern int ext4_filesystem_alloc_inode(ext4_filesystem_t *, ext4_inode_ref_t **,
+    int);
+extern int ext4_filesystem_free_inode(ext4_inode_ref_t *);
+extern int ext4_filesystem_truncate_inode(ext4_inode_ref_t *, aoff64_t);
+extern int ext4_filesystem_get_inode_data_block_index(ext4_inode_ref_t *,
+    aoff64_t iblock, uint32_t *);
+extern int ext4_filesystem_set_inode_data_block_index(ext4_inode_ref_t *,
+    aoff64_t, uint32_t);
+extern int ext4_filesystem_release_inode_block(ext4_inode_ref_t *, uint32_t);
+extern int ext4_filesystem_append_inode_block(ext4_inode_ref_t *, uint32_t *,
+    uint32_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_hash.c
===================================================================
--- uspace/lib/ext4/libext4_hash.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_hash.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+/**
+ * @file  libext4_hash.c
+ * @brief Hashing algorithms for ext4 HTree.
+ */
+
+#include "libext4.h"
+#include <errno.h>
+
+int ext4_hash_string(ext4_hash_info_t *hinfo, int len, const char *name)
+{
+	// TODO
+	hinfo->hash = 0;
+	return ENOTSUP;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_hash.h
===================================================================
--- uspace/lib/ext4/libext4_hash.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_hash.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_HASH_H_
+#define LIBEXT4_LIBEXT4_HASH_H_
+
+#include <sys/types.h>
+#include "libext4_types.h"
+
+extern int ext4_hash_string(ext4_hash_info_t *, int, const char *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_ialloc.c
===================================================================
--- uspace/lib/ext4/libext4_ialloc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_ialloc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+/**
+ * @file  libext4_ialloc.c
+ * @brief I-node (de)allocation operations.
+ */
+
+#include <errno.h>
+#include <time.h>
+#include "libext4.h"
+
+
+/** Convert i-node number to relative index in block group.
+ *
+ * @param sb    Superblock
+ * @param inode I-node number to be converted
+ *
+ * @return Index of the i-node in the block group
+ *
+ */
+static uint32_t ext4_ialloc_inode2index_in_group(ext4_superblock_t *sb,
+    uint32_t inode)
+{
+	uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb);
+	return (inode - 1) % inodes_per_group;
+}
+
+/** Convert relative index of i-node to absolute i-node number.
+ *
+ * @param sb    Superblock
+ * @param inode Index to be converted
+ *
+ * @return Absolute number of the i-node
+ *
+ */
+static uint32_t ext4_ialloc_index_in_group2inode(ext4_superblock_t *sb,
+    uint32_t index, uint32_t bgid)
+{
+	uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb);
+	return bgid * inodes_per_group + (index + 1);
+}
+
+/** Compute block group number from the i-node number.
+ *
+ * @param sb    Superblock
+ * @param inode I-node number to be found the block group for
+ *
+ * @return Block group number computed from i-node number
+ *
+ */
+static uint32_t ext4_ialloc_get_bgid_of_inode(ext4_superblock_t *sb,
+    uint32_t inode)
+{
+	uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb);
+	return (inode - 1) / inodes_per_group;
+}
+
+
+/** Free i-node number and modify filesystem data structers.
+ *
+ * @param fs     Filesystem, where the i-node is located
+ * @param index  Index of i-node to be release
+ * @param is_dir Flag us for information whether i-node is directory or not
+ *
+ */
+int ext4_ialloc_free_inode(ext4_filesystem_t *fs, uint32_t index, bool is_dir)
+{
+	ext4_superblock_t *sb = fs->superblock;
+	
+	/* Compute index of block group and load it */
+	uint32_t block_group = ext4_ialloc_get_bgid_of_inode(sb, index);
+	
+	ext4_block_group_ref_t *bg_ref;
+	int rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
+	if (rc != EOK)
+		return rc;
+	
+	/* Load i-node bitmap */
+	uint32_t bitmap_block_addr = ext4_block_group_get_inode_bitmap(
+	    bg_ref->block_group, sb);
+	block_t *bitmap_block;
+	rc = block_get(&bitmap_block, fs->device, bitmap_block_addr,
+	    BLOCK_FLAGS_NONE);
+	if (rc != EOK)
+		return rc;
+	
+	/* Free i-node in the bitmap */
+	uint32_t index_in_group = ext4_ialloc_inode2index_in_group(sb, index);
+	ext4_bitmap_free_bit(bitmap_block->data, index_in_group);
+	bitmap_block->dirty = true;
+	
+	/* Put back the block with bitmap */
+	rc = block_put(bitmap_block);
+	if (rc != EOK) {
+		/* Error in saving bitmap */
+		ext4_filesystem_put_block_group_ref(bg_ref);
+		return rc;
+	}
+	
+	/* If released i-node is a directory, decrement used directories count */
+	if (is_dir) {
+		uint32_t bg_used_dirs = ext4_block_group_get_used_dirs_count(
+		    bg_ref->block_group, sb);
+		bg_used_dirs--;
+		ext4_block_group_set_used_dirs_count(bg_ref->block_group, sb,
+		    bg_used_dirs);
+	}
+	
+	/* Update block group free inodes count */
+	uint32_t free_inodes = ext4_block_group_get_free_inodes_count(
+	    bg_ref->block_group, sb);
+	free_inodes++;
+	ext4_block_group_set_free_inodes_count(bg_ref->block_group, sb,
+	    free_inodes);
+	
+	bg_ref->dirty = true;
+	
+	/* Put back the modified block group */
+	rc = ext4_filesystem_put_block_group_ref(bg_ref);
+	if (rc != EOK)
+		return rc;
+	
+	/* Update superblock free inodes count */
+	uint32_t sb_free_inodes =
+	    ext4_superblock_get_free_inodes_count(sb);
+	sb_free_inodes++;
+	ext4_superblock_set_free_inodes_count(sb, sb_free_inodes);
+	
+	return EOK;
+}
+
+/** I-node allocation algorithm.
+ *
+ * This is more simple algorithm, than Orlov allocator used
+ * in the Linux kernel.
+ *
+ * @param fs     Filesystem to allocate i-node on
+ * @param index  Output value - allocated i-node number
+ * @param is_dir Flag if allocated i-node will be file or directory
+ *
+ * @return Error code
+ *
+ */
+int ext4_ialloc_alloc_inode(ext4_filesystem_t *fs, uint32_t *index, bool is_dir)
+{
+	ext4_superblock_t *sb = fs->superblock;
+	
+	uint32_t bgid = 0;
+	uint32_t bg_count = ext4_superblock_get_block_group_count(sb);
+	uint32_t sb_free_inodes = ext4_superblock_get_free_inodes_count(sb);
+	uint32_t avg_free_inodes = sb_free_inodes / bg_count;
+	
+	/* Try to find free i-node in all block groups */
+	while (bgid < bg_count) {
+		/* Load block group to check */
+		ext4_block_group_ref_t *bg_ref;
+		int rc = ext4_filesystem_get_block_group_ref(fs, bgid, &bg_ref);
+		if (rc != EOK)
+			return rc;
+		
+		ext4_block_group_t *bg = bg_ref->block_group;
+		
+		/* Read necessary values for algorithm */
+		uint32_t free_blocks = ext4_block_group_get_free_blocks_count(bg, sb);
+		uint32_t free_inodes = ext4_block_group_get_free_inodes_count(bg, sb);
+		uint32_t used_dirs = ext4_block_group_get_used_dirs_count(bg, sb);
+		
+		/* Check if this block group is good candidate for allocation */
+		if ((free_inodes >= avg_free_inodes) && (free_blocks > 0)) {
+			/* Load block with bitmap */
+			uint32_t bitmap_block_addr = ext4_block_group_get_inode_bitmap(
+			    bg_ref->block_group, sb);
+			
+			block_t *bitmap_block;
+			rc = block_get(&bitmap_block, fs->device, bitmap_block_addr,
+			    BLOCK_FLAGS_NONE);
+			if (rc != EOK)
+				return rc;
+			
+			/* Try to allocate i-node in the bitmap */
+			uint32_t inodes_in_group = ext4_superblock_get_inodes_in_group(sb, bgid);
+			uint32_t index_in_group;
+			rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data,
+			    0, &index_in_group, inodes_in_group);
+			
+			/* Block group has not any free i-node */
+			if (rc == ENOSPC) {
+				block_put(bitmap_block);
+				ext4_filesystem_put_block_group_ref(bg_ref);
+				continue;
+			}
+			
+			/* Free i-node found, save the bitmap */
+			bitmap_block->dirty = true;
+			
+			rc = block_put(bitmap_block);
+			if (rc != EOK)
+				return rc;
+			
+			/* Modify filesystem counters */
+			free_inodes--;
+			ext4_block_group_set_free_inodes_count(bg, sb, free_inodes);
+			
+			/* Increment used directories counter */
+			if (is_dir) {
+				used_dirs++;
+				ext4_block_group_set_used_dirs_count(bg, sb, used_dirs);
+			}
+			
+			/* Decrease unused inodes count */
+			if (ext4_block_group_has_flag(bg,
+			    EXT4_BLOCK_GROUP_ITABLE_ZEROED)) {
+				uint32_t unused =
+				    ext4_block_group_get_itable_unused(bg, sb);
+				
+				uint32_t inodes_in_group =
+				    ext4_superblock_get_inodes_in_group(sb, bgid);
+				
+				uint32_t free = inodes_in_group - unused;
+				
+				if (index_in_group >= free) {
+					unused = inodes_in_group - (index_in_group + 1);
+					ext4_block_group_set_itable_unused(bg, sb, unused);
+				}
+			}
+			
+			/* Save modified block group */
+			bg_ref->dirty = true;
+			
+			rc = ext4_filesystem_put_block_group_ref(bg_ref);
+			if (rc != EOK)
+				return rc;
+			
+			/* Update superblock */
+			sb_free_inodes--;
+			ext4_superblock_set_free_inodes_count(sb, sb_free_inodes);
+			
+			/* Compute the absolute i-nodex number */
+			*index = ext4_ialloc_index_in_group2inode(sb, index_in_group, bgid);
+			
+			return EOK;
+		}
+		
+		/* Block group not modified, put it and jump to the next block group */
+		ext4_filesystem_put_block_group_ref(bg_ref);
+		++bgid;
+	}
+	
+	return ENOSPC;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_ialloc.h
===================================================================
--- uspace/lib/ext4/libext4_ialloc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_ialloc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_IALLOC_H_
+#define LIBEXT4_LIBEXT4_IALLOC_H_
+
+#include "libext4_types.h"
+
+extern int ext4_ialloc_free_inode(ext4_filesystem_t *, uint32_t, bool);
+extern int ext4_ialloc_alloc_inode(ext4_filesystem_t *, uint32_t *, bool);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_inode.c
===================================================================
--- uspace/lib/ext4/libext4_inode.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_inode.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,594 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+/**
+ * @file  libext4_inode.c
+ * @brief Ext4 i-node structure operations.
+ */
+
+#include <byteorder.h>
+#include <errno.h>
+#include <block.h>
+#include "libext4.h"
+
+/** Compute number of bits for block count.
+ *
+ *  @param block_size Filesystem block_size
+ *
+ *  @return Number of bits
+ *
+ */
+static uint32_t ext4_inode_block_bits_count(uint32_t block_size)
+{
+	uint32_t bits = 8;
+	uint32_t size = block_size;
+	
+	do {
+		bits++;
+		size = size >> 1;
+	} while (size > 256);
+	
+	return bits;
+}
+
+/** Get mode of the i-node.
+ *
+ * @param sb    Superblock
+ * @param inode I-node to load mode from
+ *
+ * @return Mode of the i-node
+ *
+ */
+uint32_t ext4_inode_get_mode(ext4_superblock_t *sb, ext4_inode_t *inode)
+{
+	if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_HURD) {
+		return ((uint32_t) uint16_t_le2host(inode->osd2.hurd2.mode_high)) << 16 |
+		    ((uint32_t) uint16_t_le2host(inode->mode));
+	}
+	
+	return uint16_t_le2host(inode->mode);
+}
+
+/** Set mode of the i-node.
+ *
+ * @param sb    Superblock
+ * @param inode I-node to set mode to
+ * @param mode  Mode to set to i-node
+ *
+ */
+void ext4_inode_set_mode(ext4_superblock_t *sb, ext4_inode_t *inode, uint32_t mode)
+{
+	inode->mode = host2uint16_t_le((mode << 16) >> 16);
+	
+	if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_HURD)
+		inode->osd2.hurd2.mode_high = host2uint16_t_le(mode >> 16);
+}
+
+/** Get ID of the i-node owner (user id).
+ *
+ * @param inode I-node to load uid from
+ *
+ * @return User ID of the i-node owner
+ *
+ */
+uint32_t ext4_inode_get_uid(ext4_inode_t *inode)
+{
+	return uint32_t_le2host(inode->uid);
+}
+
+/** Set ID of the i-node owner.
+ *
+ * @param inode I-node to set uid to
+ * @param uid   ID of the i-node owner
+ *
+ */
+void ext4_inode_set_uid(ext4_inode_t *inode, uint32_t uid)
+{
+	inode->uid = host2uint32_t_le(uid);
+}
+
+/** Get real i-node size.
+ *
+ * @param sb    Superblock
+ * @param inode I-node to load size from
+ *
+ * @return Real size of i-node
+ *
+ */
+uint64_t ext4_inode_get_size(ext4_superblock_t *sb, ext4_inode_t *inode)
+{
+	uint32_t major_rev = ext4_superblock_get_rev_level(sb);
+	
+	if ((major_rev > 0) &&
+	    (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)))
+		return ((uint64_t)uint32_t_le2host(inode->size_hi)) << 32 |
+		    ((uint64_t)uint32_t_le2host(inode->size_lo));
+	
+	return uint32_t_le2host(inode->size_lo);
+}
+
+/** Set real i-node size.
+ *
+ * @param inode I-node to set size to
+ * @param size  Size of the i-node
+ *
+ */
+void ext4_inode_set_size(ext4_inode_t *inode, uint64_t size)
+{
+	inode->size_lo = host2uint32_t_le((size << 32) >> 32);
+	inode->size_hi = host2uint32_t_le(size >> 32);
+}
+
+/** Get time, when i-node was last accessed.
+ *
+ * @param inode I-node
+ *
+ * @return Time of the last access (POSIX)
+ *
+ */
+uint32_t ext4_inode_get_access_time(ext4_inode_t *inode)
+{
+	return uint32_t_le2host(inode->access_time);
+}
+
+/** Set time, when i-node was last accessed.
+ *
+ * @param inode I-node
+ * @param time  Time of the last access (POSIX)
+ *
+ */
+void ext4_inode_set_access_time(ext4_inode_t *inode, uint32_t time)
+{
+	inode->access_time = host2uint32_t_le(time);
+}
+
+/** Get time, when i-node was last changed.
+ *
+ * @param inode I-node
+ *
+ * @return Time of the last change (POSIX)
+ *
+ */
+uint32_t ext4_inode_get_change_inode_time(ext4_inode_t *inode)
+{
+	return uint32_t_le2host(inode->change_inode_time);
+}
+
+/** Set time, when i-node was last changed.
+ *
+ * @param inode I-node
+ * @param time  Time of the last change (POSIX)
+ *
+ */
+void ext4_inode_set_change_inode_time(ext4_inode_t *inode, uint32_t time)
+{
+	inode->change_inode_time = host2uint32_t_le(time);
+}
+
+/** Get time, when i-node content was last modified.
+ *
+ * @param inode I-node
+ *
+ * @return Time of the last content modification (POSIX)
+ *
+ */
+uint32_t ext4_inode_get_modification_time(ext4_inode_t *inode)
+{
+	return uint32_t_le2host(inode->modification_time);
+}
+
+/** Set time, when i-node content was last modified.
+ *
+ * @param inode I-node
+ * @param time  Time of the last content modification (POSIX)
+ *
+ */
+void ext4_inode_set_modification_time(ext4_inode_t *inode, uint32_t time)
+{
+	inode->modification_time = host2uint32_t_le(time);
+}
+
+/** Get time, when i-node was deleted.
+ *
+ * @param inode I-node
+ *
+ * @return Time of the delete action (POSIX)
+ *
+ */
+uint32_t ext4_inode_get_deletion_time(ext4_inode_t *inode)
+{
+	return uint32_t_le2host(inode->deletion_time);
+}
+
+/** Set time, when i-node was deleted.
+ *
+ * @param inode I-node
+ * @param time  Time of the delete action (POSIX)
+ *
+ */
+void ext4_inode_set_deletion_time(ext4_inode_t *inode, uint32_t time)
+{
+	inode->deletion_time = host2uint32_t_le(time);
+}
+
+/** Get ID of the i-node owner's group.
+ *
+ * @param inode I-node to load gid from
+ *
+ * @return Group ID of the i-node owner
+ *
+ */
+uint32_t ext4_inode_get_gid(ext4_inode_t *inode)
+{
+	return uint32_t_le2host(inode->gid);
+}
+
+/** Set ID ot the i-node owner's group.
+ *
+ * @param inode I-node to set gid to
+ * @param gid   Group ID of the i-node owner
+ *
+ */
+void ext4_inode_set_gid(ext4_inode_t *inode, uint32_t gid)
+{
+	inode->gid = host2uint32_t_le(gid);
+}
+
+/** Get number of links to i-node.
+ *
+ * @param inode I-node to load number of links from
+ *
+ * @return Number of links to i-node
+ *
+ */
+uint16_t ext4_inode_get_links_count(ext4_inode_t *inode)
+{
+	return uint16_t_le2host(inode->links_count);
+}
+
+/** Set number of links to i-node.
+ *
+ * @param inode I-node to set number of links to
+ * @param count Number of links to i-node
+ *
+ */
+void ext4_inode_set_links_count(ext4_inode_t *inode, uint16_t count)
+{
+	inode->links_count = host2uint16_t_le(count);
+}
+
+/** Get number of 512-bytes blocks used for i-node.
+ *
+ * @param sb    Superblock
+ * @param inode I-node
+ *
+ * @return Number of 512-bytes blocks
+ *
+ */
+uint64_t ext4_inode_get_blocks_count(ext4_superblock_t *sb, ext4_inode_t *inode)
+{
+	if (ext4_superblock_has_feature_read_only(sb,
+	    EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
+		/* 48-bit field */
+		uint64_t count = ((uint64_t)
+		    uint16_t_le2host(inode->osd2.linux2.blocks_high)) << 32 |
+		    uint32_t_le2host(inode->blocks_count_lo);
+		
+		if (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_HUGE_FILE)) {
+			uint32_t block_size = ext4_superblock_get_block_size(sb);
+			uint32_t block_bits = ext4_inode_block_bits_count(block_size);
+			return count << (block_bits - 9);
+		} else
+			return count;
+	} else
+		return uint32_t_le2host(inode->blocks_count_lo);
+}
+
+/** Set number of 512-bytes blocks used for i-node.
+ *
+ * @param sb    Superblock
+ * @param inode I-node
+ * @param count Number of 512-bytes blocks
+ *
+ * @return Error code
+ *
+ */
+int ext4_inode_set_blocks_count(ext4_superblock_t *sb, ext4_inode_t *inode,
+    uint64_t count)
+{
+	/* 32-bit maximum */
+	uint64_t max = 0;
+	max = ~max >> 32;
+	
+	if (count <= max) {
+		inode->blocks_count_lo = host2uint32_t_le(count);
+		inode->osd2.linux2.blocks_high = 0;
+		ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
+		
+		return EOK;
+	}
+	
+	/* Check if there can be used huge files (many blocks) */
+	if (!ext4_superblock_has_feature_read_only(sb,
+	    EXT4_FEATURE_RO_COMPAT_HUGE_FILE))
+		return EINVAL;
+	
+	/* 48-bit maximum */
+	max = 0;
+	max = ~max >> 16;
+	
+	if (count <= max) {
+		inode->blocks_count_lo = host2uint32_t_le(count);
+		inode->osd2.linux2.blocks_high = host2uint16_t_le(count >> 32);
+		ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
+	} else {
+		uint32_t block_size = ext4_superblock_get_block_size(sb);
+		uint32_t block_bits = ext4_inode_block_bits_count(block_size);
+		ext4_inode_set_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
+		count = count >> (block_bits - 9);
+		inode->blocks_count_lo = host2uint32_t_le(count);
+		inode->osd2.linux2.blocks_high = host2uint16_t_le(count >> 32);
+	}
+	
+	return EOK;
+}
+
+/** Get flags (features) of i-node.
+ *
+ * @param inode I-node to get flags from
+ *
+ * @return Flags (bitmap)
+ *
+ */
+uint32_t ext4_inode_get_flags(ext4_inode_t *inode)
+{
+	return uint32_t_le2host(inode->flags);
+}
+
+/** Set flags (features) of i-node.
+ *
+ * @param inode I-node to set flags to
+ * @param flags Flags to set to i-node
+ *
+ */
+void ext4_inode_set_flags(ext4_inode_t *inode, uint32_t flags)
+{
+	inode->flags = host2uint32_t_le(flags);
+}
+
+/** Get file generation (used by NFS).
+ *
+ * @param inode I-node
+ *
+ * @return File generation
+ *
+ */
+uint32_t ext4_inode_get_generation(ext4_inode_t *inode)
+{
+	return uint32_t_le2host(inode->generation);
+}
+
+/** Set file generation (used by NFS).
+ *
+ * @param inode      I-node
+ * @param generation File generation
+ *
+ */
+void ext4_inode_set_generation(ext4_inode_t *inode, uint32_t generation)
+{
+	inode->generation = host2uint32_t_le(generation);
+}
+
+/** Get address of block, where are extended attributes located.
+ *
+ * @param inode I-node
+ * @param sb    Superblock
+ *
+ * @return Block address
+ *
+ */
+uint64_t ext4_inode_get_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb)
+{
+	if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_LINUX)
+		return ((uint32_t)
+		    uint16_t_le2host(inode->osd2.linux2.file_acl_high)) << 16 |
+		    (uint32_t_le2host(inode->file_acl_lo));
+	
+	return uint32_t_le2host(inode->file_acl_lo);
+}
+
+/** Set address of block, where are extended attributes located.
+ *
+ * @param inode    I-node
+ * @param sb       Superblock
+ * @param file_acl Block address
+ *
+ */
+void ext4_inode_set_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb,
+    uint64_t file_acl)
+{
+	inode->file_acl_lo = host2uint32_t_le((file_acl << 32) >> 32);
+	
+	if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_LINUX)
+		inode->osd2.linux2.file_acl_high = host2uint16_t_le(file_acl >> 32);
+}
+
+/** Get block address of specified direct block.
+ *
+ * @param inode I-node to load block from
+ * @param idx   Index of logical block
+ *
+ * @return Physical block address
+ *
+ */
+uint32_t ext4_inode_get_direct_block(ext4_inode_t *inode, uint32_t idx)
+{
+	assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
+	
+	return uint32_t_le2host(inode->blocks[idx]);
+}
+
+/** Set block address of specified direct block.
+ *
+ * @param inode  I-node to set block address to
+ * @param idx    Index of logical block
+ * @param fblock Physical block address
+ *
+ */
+void ext4_inode_set_direct_block(ext4_inode_t *inode, uint32_t idx, uint32_t fblock)
+{
+	assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
+	
+	inode->blocks[idx] = host2uint32_t_le(fblock);
+}
+
+/** Get block address of specified indirect block.
+ *
+ * @param inode I-node to get block address from
+ * @param idx   Index of indirect block 
+ *
+ * @return Physical block address
+ *
+ */
+uint32_t ext4_inode_get_indirect_block(ext4_inode_t *inode, uint32_t idx)
+{
+	return uint32_t_le2host(inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK]);
+}
+
+/** Set block address of specified indirect block.
+ *
+ * @param inode  I-node to set block address to
+ * @param idx    Index of indirect block
+ * @param fblock Physical block address
+ *
+ */
+void ext4_inode_set_indirect_block(ext4_inode_t *inode, uint32_t idx,
+    uint32_t fblock)
+{
+	inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK] =
+	    host2uint32_t_le(fblock);
+}
+
+/** Check if i-node has specified type.
+ *
+ * @param sb    Superblock
+ * @param inode I-node to check type of
+ * @param type  Type to check
+ *
+ * @return Result of check operation
+ *
+ */
+bool ext4_inode_is_type(ext4_superblock_t *sb, ext4_inode_t *inode,
+    uint32_t type)
+{
+	uint32_t mode = ext4_inode_get_mode(sb, inode);
+	return (mode & EXT4_INODE_MODE_TYPE_MASK) == type;
+}
+
+/** Get extent header from the root of the extent tree.
+ *
+ * @param inode I-node to get extent header from
+ *
+ * @return Pointer to extent header of the root node
+ *
+ */
+ext4_extent_header_t * ext4_inode_get_extent_header(ext4_inode_t *inode)
+{
+	return (ext4_extent_header_t *) inode->blocks;
+}
+
+/** Check if i-node has specified flag.
+ *
+ * @param inode I-node to check flags of
+ * @param flag  Flag to check
+ *
+ * @return Result of check operation
+ *
+ */
+bool ext4_inode_has_flag(ext4_inode_t *inode, uint32_t flag)
+{
+	if (ext4_inode_get_flags(inode) & flag)
+		return true;
+	
+	return false;
+}
+
+/** Remove specified flag from i-node.
+ *
+ * @param inode      I-node to clear flag on
+ * @param clear_flag Flag to be cleared
+ *
+ */
+void ext4_inode_clear_flag(ext4_inode_t *inode, uint32_t clear_flag)
+{
+	uint32_t flags = ext4_inode_get_flags(inode);
+	flags = flags & (~clear_flag);
+	ext4_inode_set_flags(inode, flags);
+}
+
+/** Set specified flag to i-node.
+ *
+ * @param inode    I-node to set flag on
+ * @param set_flag Flag to be set
+ *
+ */
+void ext4_inode_set_flag(ext4_inode_t *inode, uint32_t set_flag)
+{
+	uint32_t flags = ext4_inode_get_flags(inode);
+	flags = flags | set_flag;
+	ext4_inode_set_flags(inode, flags);
+}
+
+/** Check if i-node can be truncated.
+ *
+ * @param sb    Superblock
+ * @param inode I-node to check
+ *
+ * @return Result of the check operation
+ *
+ */
+bool ext4_inode_can_truncate(ext4_superblock_t *sb, ext4_inode_t *inode)
+{
+	if ((ext4_inode_has_flag(inode, EXT4_INODE_FLAG_APPEND)) ||
+	    (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_IMMUTABLE)))
+		return false;
+	
+	if ((ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)) ||
+	    (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_DIRECTORY)))
+		return true;
+	
+	return false;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_inode.h
===================================================================
--- uspace/lib/ext4/libext4_inode.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_inode.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_INODE_H_
+#define LIBEXT4_LIBEXT4_INODE_H_
+
+#include <block.h>
+#include <sys/types.h>
+#include "libext4_types.h"
+
+extern uint32_t ext4_inode_get_mode(ext4_superblock_t *, ext4_inode_t *);
+extern void ext4_inode_set_mode(ext4_superblock_t *, ext4_inode_t *, uint32_t);
+extern uint32_t ext4_inode_get_uid(ext4_inode_t *);
+extern void ext4_inode_set_uid(ext4_inode_t *, uint32_t);
+extern uint64_t ext4_inode_get_size(ext4_superblock_t *, ext4_inode_t *);
+extern void ext4_inode_set_size(ext4_inode_t *, uint64_t);
+extern uint32_t ext4_inode_get_access_time(ext4_inode_t *);
+extern void ext4_inode_set_access_time(ext4_inode_t *, uint32_t);
+extern uint32_t ext4_inode_get_change_inode_time(ext4_inode_t *);
+extern void ext4_inode_set_change_inode_time(ext4_inode_t *, uint32_t);
+extern uint32_t ext4_inode_get_modification_time(ext4_inode_t *);
+extern void ext4_inode_set_modification_time(ext4_inode_t *, uint32_t);
+extern uint32_t ext4_inode_get_deletion_time(ext4_inode_t *);
+extern void ext4_inode_set_deletion_time(ext4_inode_t *, uint32_t);
+extern uint32_t ext4_inode_get_gid(ext4_inode_t *);
+extern void ext4_inode_set_gid(ext4_inode_t *, uint32_t);
+extern uint16_t ext4_inode_get_links_count(ext4_inode_t *);
+extern void ext4_inode_set_links_count(ext4_inode_t *, uint16_t);
+extern uint64_t ext4_inode_get_blocks_count(ext4_superblock_t *,
+    ext4_inode_t *);
+extern int ext4_inode_set_blocks_count(ext4_superblock_t *, ext4_inode_t *,
+    uint64_t);
+extern uint32_t ext4_inode_get_flags(ext4_inode_t *);
+extern void ext4_inode_set_flags(ext4_inode_t *, uint32_t);
+extern uint32_t ext4_inode_get_generation(ext4_inode_t *);
+extern void ext4_inode_set_generation(ext4_inode_t *, uint32_t);
+extern uint64_t ext4_inode_get_file_acl(ext4_inode_t *, ext4_superblock_t *);
+extern void ext4_inode_set_file_acl(ext4_inode_t *, ext4_superblock_t *,
+    uint64_t);
+
+extern uint32_t ext4_inode_get_direct_block(ext4_inode_t *, uint32_t);
+extern void ext4_inode_set_direct_block(ext4_inode_t *, uint32_t, uint32_t);
+extern uint32_t ext4_inode_get_indirect_block(ext4_inode_t *, uint32_t);
+extern void ext4_inode_set_indirect_block(ext4_inode_t *, uint32_t, uint32_t);
+extern ext4_extent_header_t * ext4_inode_get_extent_header(ext4_inode_t *);
+extern bool ext4_inode_is_type(ext4_superblock_t *, ext4_inode_t *, uint32_t);
+extern bool ext4_inode_has_flag(ext4_inode_t *, uint32_t);
+extern void ext4_inode_clear_flag(ext4_inode_t *, uint32_t);
+extern void ext4_inode_set_flag(ext4_inode_t *, uint32_t);
+extern bool ext4_inode_can_truncate(ext4_superblock_t *, ext4_inode_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_superblock.c
===================================================================
--- uspace/lib/ext4/libext4_superblock.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_superblock.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1292 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+/**
+ * @file  libext4_superblock.c
+ * @brief Ext4 superblock operations.
+ */
+
+#include <byteorder.h>
+#include <errno.h>
+#include <block.h>
+#include <malloc.h>
+#include "libext4.h"
+
+/** Get number of i-nodes in the whole filesystem.
+ *
+ * @param sb Superblock
+ *
+ * @return Number of i-nodes
+ *
+ */
+uint32_t ext4_superblock_get_inodes_count(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->inodes_count);
+}
+
+/** Set number of i-nodes in the whole filesystem.
+ *
+ * @param sb    Superblock
+ * @param count Number of i-nodes
+ *
+ */
+void ext4_superblock_set_inodes_count(ext4_superblock_t *sb, uint32_t count)
+{
+	sb->inodes_count = host2uint32_t_le(count);
+}
+
+/** Get number of data blocks in the whole filesystem.
+ *
+ * @param sb Superblock
+ *
+ * @return Number of data blocks
+ *
+ */
+uint64_t ext4_superblock_get_blocks_count(ext4_superblock_t *sb)
+{
+	return ((uint64_t) uint32_t_le2host(sb->blocks_count_hi) << 32) |
+	    uint32_t_le2host(sb->blocks_count_lo);
+}
+
+/** Set number of data blocks in the whole filesystem.
+ *
+ * @param sb    Superblock
+ * @param count Number of data blocks
+ *
+ */
+void ext4_superblock_set_blocks_count(ext4_superblock_t *sb, uint64_t count)
+{
+	sb->blocks_count_lo = host2uint32_t_le((count << 32) >> 32);
+	sb->blocks_count_hi = host2uint32_t_le(count >> 32);
+}
+
+/** Get number of reserved data blocks in the whole filesystem.
+ *
+ * @param sb Superblock
+ *
+ * @return Number of reserved data blocks
+ *
+ */
+uint64_t ext4_superblock_get_reserved_blocks_count(ext4_superblock_t *sb)
+{
+	return ((uint64_t)
+	    uint32_t_le2host(sb->reserved_blocks_count_hi) << 32) |
+	    uint32_t_le2host(sb->reserved_blocks_count_lo);
+}
+
+/** Set number of reserved data blocks in the whole filesystem.
+ *
+ * @param sb    Superblock
+ * @param count Number of reserved data blocks
+ *
+ */
+void ext4_superblock_set_reserved_blocks_count(ext4_superblock_t *sb,
+    uint64_t count)
+{
+	sb->reserved_blocks_count_lo = host2uint32_t_le((count << 32) >> 32);
+	sb->reserved_blocks_count_hi = host2uint32_t_le(count >> 32);
+}
+
+/** Get number of free data blocks in the whole filesystem.
+ *
+ * @param sb Superblock
+ *
+ * @return Number of free data blocks
+ *
+ */
+uint64_t ext4_superblock_get_free_blocks_count(ext4_superblock_t *sb)
+{
+	return ((uint64_t)
+	    uint32_t_le2host(sb->free_blocks_count_hi) << 32) |
+	    uint32_t_le2host(sb->free_blocks_count_lo);
+}
+
+/** Set number of free data blocks in the whole filesystem.
+ *
+ * @param sb    Superblock
+ * @param count Number of free data blocks
+ *
+ */
+void ext4_superblock_set_free_blocks_count(ext4_superblock_t *sb,
+    uint64_t count)
+{
+	sb->free_blocks_count_lo = host2uint32_t_le((count << 32) >> 32);
+	sb->free_blocks_count_hi = host2uint32_t_le(count >> 32);
+}
+
+/** Get number of free i-nodes in the whole filesystem.
+ *
+ * @param sb Superblock
+ *
+ * @return Number of free i-nodes
+ *
+ */
+uint32_t ext4_superblock_get_free_inodes_count(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->free_inodes_count);
+}
+
+/** Set number of free i-nodes in the whole filesystem.
+ *
+ * @param sb    Superblock
+ * @param count Number of free i-nodes
+ *
+ */
+void ext4_superblock_set_free_inodes_count(ext4_superblock_t *sb,
+    uint32_t count)
+{
+	sb->free_inodes_count = host2uint32_t_le(count);
+}
+
+/** Get index of first data block (block where the superblock is located)
+ *
+ * @param sb Superblock
+ *
+ * @return Index of the first data block
+ *
+ */
+uint32_t ext4_superblock_get_first_data_block(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->first_data_block);
+}
+
+/** Set index of first data block (block where the superblock is located)
+ *
+ * @param sb    Superblock
+ * @param first Index of the first data block
+ *
+ */
+void ext4_superblock_set_first_data_block(ext4_superblock_t *sb,
+    uint32_t first)
+{
+	sb->first_data_block = host2uint32_t_le(first);
+}
+
+/** Get logarithmic block size (1024 << size == block_size)
+ *
+ * @param sb Superblock
+ *
+ * @return Logarithmic block size
+ *
+ */
+uint32_t ext4_superblock_get_log_block_size(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->log_block_size);
+}
+
+/** Set logarithmic block size (1024 << size == block_size)
+ *
+ * @param sb Superblock
+ *
+ * @return Logarithmic block size
+ *
+ */
+void ext4_superblock_set_log_block_size(ext4_superblock_t *sb,
+    uint32_t log_size)
+{
+	sb->log_block_size = host2uint32_t_le(log_size);
+}
+
+/** Get size of data block (in bytes).
+ *
+ * @param sb Superblock
+ *
+ * @return Size of data block
+ *
+ */
+uint32_t ext4_superblock_get_block_size(ext4_superblock_t *sb)
+{
+	return 1024 << ext4_superblock_get_log_block_size(sb);
+}
+
+/** Set size of data block (in bytes).
+ *
+ * @param sb   Superblock
+ * @param size Size of data block (must be power of 2, at least 1024)
+ *
+ */
+void ext4_superblock_set_block_size(ext4_superblock_t *sb, uint32_t size)
+{
+	uint32_t log = 0;
+	uint32_t tmp = size / EXT4_MIN_BLOCK_SIZE;
+	
+	tmp >>= 1;
+	while (tmp) {
+		log++;
+		tmp >>= 1;
+	}
+	
+	ext4_superblock_set_log_block_size(sb, log);
+}
+
+/** Get logarithmic fragment size (1024 << size)
+ *
+ * @param sb Superblock
+ *
+ * @return Logarithmic fragment size
+ *
+ */
+uint32_t ext4_superblock_get_log_frag_size(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->log_frag_size);
+}
+
+/** Set logarithmic fragment size (1024 << size)
+ *
+ * @param sb        Superblock
+ * @param frag_size Logarithmic fragment size
+ *
+ */
+void ext4_superblock_set_log_frag_size(ext4_superblock_t *sb,
+    uint32_t frag_size)
+{
+	sb->log_frag_size = host2uint32_t_le(frag_size);
+}
+
+/** Get size of fragment (in bytes).
+ *
+ * @param sb Superblock
+ *
+ * @return Size of fragment
+ *
+ */
+uint32_t ext4_superblock_get_frag_size(ext4_superblock_t *sb)
+{
+	return 1024 << ext4_superblock_get_log_frag_size(sb);
+}
+
+/** Set size of fragment (in bytes).
+ *
+ * @param sb   Superblock
+ * @param size Size of fragment (must be power of 2, at least 1024)
+ *
+ */
+void ext4_superblock_set_frag_size(ext4_superblock_t *sb, uint32_t size)
+{
+	uint32_t log = 0;
+	uint32_t tmp = size / EXT4_MIN_BLOCK_SIZE;
+	
+	tmp >>= 1;
+	while (tmp) {
+		log++;
+		tmp >>= 1;
+	}
+	
+	ext4_superblock_set_log_frag_size(sb, log);
+}
+
+/** Get number of data blocks per block group (except last BG)
+ *
+ * @param sb Superblock
+ *
+ * @return Data blocks per block group
+ *
+ */
+uint32_t ext4_superblock_get_blocks_per_group(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->blocks_per_group);
+}
+
+/** Set number of data blocks per block group (except last BG)
+ *
+ * @param sb     Superblock
+ * @param blocks Data blocks per block group
+ *
+ */
+void ext4_superblock_set_blocks_per_group(ext4_superblock_t *sb,
+    uint32_t blocks)
+{
+	sb->blocks_per_group = host2uint32_t_le(blocks);
+}
+
+/** Get number of fragments per block group (except last BG)
+ *
+ * @param sb Superblock
+ *
+ * @return Fragments per block group
+ *
+ */
+uint32_t ext4_superblock_get_frags_per_group(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->frags_per_group);
+}
+
+/** Set number of fragment per block group (except last BG)
+ *
+ * @param sb    Superblock
+ * @param frags Fragments per block group
+ */
+void ext4_superblock_set_frags_per_group(ext4_superblock_t *sb, uint32_t frags)
+{
+	sb->frags_per_group = host2uint32_t_le(frags);
+}
+
+/** Get number of i-nodes per block group (except last BG)
+ *
+ * @param sb Superblock
+ *
+ * @return I-nodes per block group
+ *
+ */
+uint32_t ext4_superblock_get_inodes_per_group(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->inodes_per_group);
+}
+
+/** Set number of i-nodes per block group (except last BG)
+ *
+ * @param sb     Superblock
+ * @param inodes I-nodes per block group
+ *
+ */
+void ext4_superblock_set_inodes_per_group(ext4_superblock_t *sb,
+    uint32_t inodes)
+{
+	sb->inodes_per_group = host2uint32_t_le(inodes);
+}
+
+/** Get time when filesystem was mounted (POSIX time).
+ *
+ * @param sb Superblock
+ *
+ * @return Mount time
+ *
+ */
+uint32_t ext4_superblock_get_mount_time(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->mount_time);
+}
+
+/** Set time when filesystem was mounted (POSIX time).
+ *
+ * @param sb   Superblock
+ * @param time Mount time
+ *
+ */
+void ext4_superblock_set_mount_time(ext4_superblock_t *sb, uint32_t time)
+{
+	sb->mount_time = host2uint32_t_le(time);
+}
+
+/** Get time when filesystem was last accesed by write operation (POSIX time).
+ *
+ * @param sb Superblock
+ *
+ * @return Write time
+ *
+ */
+uint32_t ext4_superblock_get_write_time(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->write_time);
+}
+
+/** Set time when filesystem was last accesed by write operation (POSIX time).
+ *
+ * @param sb   Superblock
+ * @param time Write time
+ *
+ */
+void ext4_superblock_set_write_time(ext4_superblock_t *sb, uint32_t time)
+{
+	sb->write_time = host2uint32_t_le(time);
+}
+
+/** Get number of mount from last filesystem check.
+ *
+ * @param sb Superblock
+ *
+ * @return Number of mounts
+ *
+ */
+uint16_t ext4_superblock_get_mount_count(ext4_superblock_t *sb)
+{
+	return uint16_t_le2host(sb->mount_count);
+}
+
+/** Set number of mount from last filesystem check.
+ *
+ * @param sb    Superblock
+ * @param count Number of mounts
+ *
+ */
+void ext4_superblock_set_mount_count(ext4_superblock_t *sb, uint16_t count)
+{
+	sb->mount_count = host2uint16_t_le(count);
+}
+
+/** Get maximum number of mount from last filesystem check.
+ *
+ * @param sb Superblock
+ *
+ * @return Maximum number of mounts
+ *
+ */
+uint16_t ext4_superblock_get_max_mount_count(ext4_superblock_t *sb)
+{
+	return uint16_t_le2host(sb->max_mount_count);
+}
+
+/** Set maximum number of mount from last filesystem check.
+ *
+ * @param sb    Superblock
+ * @param count Maximum number of mounts
+ *
+ */
+void ext4_superblock_set_max_mount_count(ext4_superblock_t *sb, uint16_t count)
+{
+	sb->max_mount_count = host2uint16_t_le(count);
+}
+
+/** Get superblock magic value.
+ *
+ * @param sb Superblock
+ *
+ * @return Magic value
+ *
+ */
+uint16_t ext4_superblock_get_magic(ext4_superblock_t *sb)
+{
+	return uint16_t_le2host(sb->magic);
+}
+
+/** Set superblock magic value.
+ *
+ * @param sb    Superblock
+ * @param magic Magic value
+ *
+ */
+void ext4_superblock_set_magic(ext4_superblock_t *sb, uint16_t magic)
+{
+	sb->magic = host2uint16_t_le(magic);
+}
+
+/** Get filesystem state.
+ *
+ * @param sb Superblock
+ *
+ * @return Filesystem state
+ *
+ */
+uint16_t ext4_superblock_get_state(ext4_superblock_t *sb)
+{
+	return uint16_t_le2host(sb->state);
+}
+
+/** Set filesystem state.
+ *
+ * @param sb    Superblock
+ * @param state Filesystem state
+ *
+ */
+void ext4_superblock_set_state(ext4_superblock_t *sb, uint16_t state)
+{
+	sb->state = host2uint16_t_le(state);
+}
+
+/** Get behavior code when errors detected.
+ *
+ * @param sb Superblock
+ *
+ * @return Behavior code
+ *
+ */
+uint16_t ext4_superblock_get_errors(ext4_superblock_t *sb)
+{
+	return uint16_t_le2host(sb->errors);
+}
+
+/** Set behavior code when errors detected.
+ *
+ * @param sb     Superblock
+ * @param errors Behavior code
+ *
+ */
+void ext4_superblock_set_errors(ext4_superblock_t *sb, uint16_t errors)
+{
+	sb->errors = host2uint16_t_le(errors);
+}
+
+/** Get minor revision level of the filesystem.
+ *
+ * @param sb Superblock
+ *
+ * @return Minor revision level
+ *
+ */
+uint16_t ext4_superblock_get_minor_rev_level(ext4_superblock_t *sb)
+{
+	return uint16_t_le2host(sb->minor_rev_level);
+}
+
+/** Set minor revision level of the filesystem.
+ *
+ * @param sb    Superblock
+ * @param level Minor revision level
+ *
+ */
+void ext4_superblock_set_minor_rev_level(ext4_superblock_t *sb, uint16_t level)
+{
+	sb->minor_rev_level = host2uint16_t_le(level);
+}
+
+/** Get time of the last filesystem check.
+ *
+ * @param sb Superblock
+ *
+ * @return Time of the last check (POSIX)
+ *
+ */
+uint32_t ext4_superblock_get_last_check_time(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->last_check_time);
+}
+
+/** Set time of the last filesystem check.
+ *
+ * @param sb   Superblock
+ * @param time Time of the last check (POSIX)
+ *
+ */
+void ext4_superblock_set_last_check_time(ext4_superblock_t *sb, uint32_t time)
+{
+	sb->state = host2uint32_t_le(time);
+}
+
+/** Get maximum time interval between two filesystem checks.
+ *
+ * @param sb Superblock
+ *
+ * @return Time interval between two check (POSIX)
+ *
+ */
+uint32_t ext4_superblock_get_check_interval(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->check_interval);
+}
+
+/** Set maximum time interval between two filesystem checks.
+ *
+ * @param sb       Superblock
+ * @param interval Time interval between two check (POSIX)
+ *
+ */
+void ext4_superblock_set_check_interval(ext4_superblock_t *sb, uint32_t interval)
+{
+	sb->check_interval = host2uint32_t_le(interval);
+}
+
+/** Get operation system identifier, on which the filesystem was created.
+ *
+ * @param sb Superblock
+ *
+ * @return Operation system identifier
+ *
+ */
+uint32_t ext4_superblock_get_creator_os(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->creator_os);
+}
+
+/** Set operation system identifier, on which the filesystem was created.
+ *
+ * @param sb Superblock
+ * @param os Operation system identifier
+ *
+ */
+void ext4_superblock_set_creator_os(ext4_superblock_t *sb, uint32_t os)
+{
+	sb->creator_os = host2uint32_t_le(os);
+}
+
+/** Get revision level of the filesystem.
+ *
+ * @param sb Superblock
+ *
+ * @return Revision level
+ *
+ */
+uint32_t ext4_superblock_get_rev_level(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->rev_level);
+}
+
+/** Set revision level of the filesystem.
+ *
+ * @param sb    Superblock
+ * @param level Revision level
+ *
+ */
+void ext4_superblock_set_rev_level(ext4_superblock_t *sb, uint32_t level)
+{
+	sb->rev_level = host2uint32_t_le(level);
+}
+
+/** Get default user id for reserved blocks.
+ *
+ * @param sb Superblock
+ *
+ * @return Default user id for reserved blocks.
+ *
+ */
+uint16_t ext4_superblock_get_def_resuid(ext4_superblock_t *sb)
+{
+	return uint16_t_le2host(sb->def_resuid);
+}
+
+/** Set default user id for reserved blocks.
+ *
+ * @param sb  Superblock
+ * @param uid Default user id for reserved blocks.
+ *
+ */
+void ext4_superblock_set_def_resuid(ext4_superblock_t *sb, uint16_t uid)
+{
+	sb->def_resuid = host2uint16_t_le(uid);
+}
+
+/** Get default group id for reserved blocks.
+ *
+ * @param sb Superblock
+ *
+ * @return Default group id for reserved blocks.
+ *
+ */
+uint16_t ext4_superblock_get_def_resgid(ext4_superblock_t *sb)
+{
+	return uint16_t_le2host(sb->def_resgid);
+}
+
+/** Set default group id for reserved blocks.
+ *
+ * @param sb  Superblock
+ * @param gid Default group id for reserved blocks.
+ *
+ */
+void ext4_superblock_set_def_resgid(ext4_superblock_t *sb, uint16_t gid)
+{
+	sb->def_resgid = host2uint16_t_le(gid);
+}
+
+/** Get index of the first i-node, which can be used for allocation.
+ *
+ * @param sb Superblock
+ *
+ * @return I-node index
+ *
+ */
+uint32_t ext4_superblock_get_first_inode(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->first_inode);
+}
+
+/** Set index of the first i-node, which can be used for allocation.
+ *
+ * @param sb          Superblock
+ * @param first_inode I-node index
+ *
+ */
+void ext4_superblock_set_first_inode(ext4_superblock_t *sb,
+    uint32_t first_inode)
+{
+	sb->first_inode = host2uint32_t_le(first_inode);
+}
+
+/** Get size of i-node structure.
+ *
+ * For the oldest revision return constant number.
+ *
+ * @param sb Superblock
+ *
+ * @return Size of i-node structure
+ *
+ */
+uint16_t ext4_superblock_get_inode_size(ext4_superblock_t *sb)
+{
+	if (ext4_superblock_get_rev_level(sb) == 0)
+		return EXT4_REV0_INODE_SIZE;
+	
+	return uint16_t_le2host(sb->inode_size);
+}
+
+/** Set size of i-node structure.
+ *
+ * @param sb   Superblock
+ * @param size Size of i-node structure
+ *
+ */
+void ext4_superblock_set_inode_size(ext4_superblock_t *sb, uint16_t size)
+{
+	sb->inode_size = host2uint16_t_le(size);
+}
+
+/** Get index of block group, where superblock copy is located.
+ *
+ * @param sb Superblock
+ *
+ * @return Block group index
+ *
+ */
+uint16_t ext4_superblock_get_block_group_index(ext4_superblock_t *sb)
+{
+	return uint16_t_le2host(sb->block_group_index);
+}
+
+/** Set index of block group, where superblock copy is located.
+ *
+ * @param sb   Superblock
+ * @param bgid Block group index
+ *
+ */
+void ext4_superblock_set_block_group_index(ext4_superblock_t *sb, uint16_t bgid)
+{
+	sb->block_group_index = host2uint16_t_le(bgid);
+}
+
+/** Get compatible features supported by the filesystem.
+ *
+ * @param sb Superblock
+ *
+ * @return Compatible features bitmap
+ *
+ */
+uint32_t ext4_superblock_get_features_compatible(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->features_compatible);
+}
+
+/** Set compatible features supported by the filesystem.
+ *
+ * @param sb       Superblock
+ * @param features Compatible features bitmap
+ *
+ */
+void ext4_superblock_set_features_compatible(ext4_superblock_t *sb,
+    uint32_t features)
+{
+	sb->features_compatible = host2uint32_t_le(features);
+}
+
+/** Get incompatible features supported by the filesystem.
+ *
+ * @param sb Superblock
+ *
+ * @return Incompatible features bitmap
+ *
+ */
+uint32_t ext4_superblock_get_features_incompatible(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->features_incompatible);
+}
+
+/** Set incompatible features supported by the filesystem.
+ *
+ * @param sb       Superblock
+ * @param features Incompatible features bitmap
+ *
+ */
+void ext4_superblock_set_features_incompatible(ext4_superblock_t *sb,
+    uint32_t features)
+{
+	sb->features_incompatible = host2uint32_t_le(features);
+}
+
+/** Get compatible features supported by the filesystem.
+ *
+ * @param sb Superblock
+ *
+ * @return Read-only compatible features bitmap
+ *
+ */
+uint32_t ext4_superblock_get_features_read_only(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->features_read_only);
+}
+
+/** Set compatible features supported by the filesystem.
+ *
+ * @param sb      Superblock
+ * @param feature Read-only compatible features bitmap
+ *
+ */
+void ext4_superblock_set_features_read_only(ext4_superblock_t *sb,
+    uint32_t features)
+{
+	sb->features_read_only = host2uint32_t_le(features);
+}
+
+/** Get UUID of the filesystem.
+ *
+ * @param sb superblock
+ *
+ * @return Pointer to UUID array
+ *
+ */
+const uint8_t *ext4_superblock_get_uuid(ext4_superblock_t *sb)
+{
+	return sb->uuid;
+}
+
+/** Set UUID of the filesystem.
+ *
+ * @param sb   Superblock
+ * @param uuid Pointer to UUID array
+ *
+ */
+void ext4_superblock_set_uuid(ext4_superblock_t *sb, const uint8_t *uuid)
+{
+	memcpy(sb->uuid, uuid, sizeof(sb->uuid));
+}
+
+/** Get name of the filesystem volume.
+ *
+ * @param sb Superblock
+ *
+ * @return Name of the volume
+ *
+ */
+const char *ext4_superblock_get_volume_name(ext4_superblock_t *sb)
+{
+	return sb->volume_name;
+}
+
+/** Set name of the filesystem volume.
+ *
+ * @param sb   Superblock
+ * @param name New name of the volume
+ */
+void ext4_superblock_set_volume_name(ext4_superblock_t *sb, const char *name)
+{
+	memcpy(sb->volume_name, name, sizeof(sb->volume_name));
+}
+
+/** Get name of the directory, where this filesystem was mounted at last.
+ *
+ * @param sb Superblock
+ *
+ * @return Directory name
+ *
+ */
+const char *ext4_superblock_get_last_mounted(ext4_superblock_t *sb)
+{
+	return sb->last_mounted;
+}
+
+/** Set name of the directory, where this filesystem was mounted at last.
+ *
+ * @param sb   Superblock
+ * @param last Directory name
+ *
+ */
+void ext4_superblock_set_last_mounted(ext4_superblock_t *sb, const char *last)
+{
+	memcpy(sb->last_mounted, last, sizeof(sb->last_mounted));
+}
+
+/** Get last orphaned i-node index.
+ *
+ * Orphans are stored in linked list.
+ *
+ * @param sb Superblock
+ *
+ * @return Last orphaned i-node index
+ *
+ */
+uint32_t ext4_superblock_get_last_orphan(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->last_orphan);
+}
+
+/** Set last orphaned i-node index.
+ *
+ * Orphans are stored in linked list.
+ *
+ * @param sb          Superblock
+ * @param last_orphan Last orphaned i-node index
+ *
+ */
+void ext4_superblock_set_last_orphan(ext4_superblock_t *sb,
+    uint32_t last_orphan)
+{
+	sb->last_orphan = host2uint32_t_le(last_orphan);
+}
+
+/** Get hash seed for directory index hash function.
+ *
+ * @param sb Superblock
+ *
+ * @return Hash seed pointer
+ *
+ */
+const uint32_t *ext4_superblock_get_hash_seed(ext4_superblock_t *sb)
+{
+	return sb->hash_seed;
+}
+
+/** Set hash seed for directory index hash function.
+ *
+ * @param sb   Superblock
+ * @param seed Hash seed pointer
+ *
+ */
+void ext4_superblock_set_hash_seed(ext4_superblock_t *sb, const uint32_t *seed)
+{
+	memcpy(sb->hash_seed, seed, sizeof(sb->hash_seed));
+}
+
+/** Get default version of the hash algorithm version for directory index.
+ *
+ * @param sb Superblock
+ *
+ * @return Default hash version
+ *
+ */
+uint8_t ext4_superblock_get_default_hash_version(ext4_superblock_t *sb)
+{
+	return sb->default_hash_version;
+}
+
+/** Set default version of the hash algorithm version for directory index.
+ *
+ * @param sb      Superblock
+ * @param version Default hash version
+ *
+ */
+void ext4_superblock_set_default_hash_version(ext4_superblock_t *sb,
+    uint8_t version)
+{
+	sb->default_hash_version = version;
+}
+
+/** Get size of block group descriptor structure.
+ *
+ * Output value is checked for minimal size.
+ *
+ * @param sb Superblock
+ *
+ * @return Size of block group descriptor
+ *
+ */
+uint16_t ext4_superblock_get_desc_size(ext4_superblock_t *sb)
+{
+	uint16_t size = uint16_t_le2host(sb->desc_size);
+	
+	if (size < EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		size = EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE;
+	
+	return size;
+}
+
+/** Set size of block group descriptor structure.
+ *
+ * Input value is checked for minimal size.
+ *
+ * @param sb   Superblock
+ * @param size Size of block group descriptor
+ *
+ */
+void ext4_superblock_set_desc_size(ext4_superblock_t *sb, uint16_t size)
+{
+	if (size < EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		sb->desc_size =
+		    host2uint16_t_le(EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE);
+	
+	sb->desc_size = host2uint16_t_le(size);
+}
+
+/** Get superblock flags.
+ *
+ * @param sb Superblock
+ *
+ * @return Flags from the superblock
+ *
+ */
+uint32_t ext4_superblock_get_flags(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->flags);
+}
+
+/** Set superblock flags.
+ *
+ * @param sb    Superblock
+ * @param flags Flags for the superblock
+ *
+ */
+void ext4_superblock_set_flags(ext4_superblock_t *sb, uint32_t flags)
+{
+	sb->flags = host2uint32_t_le(flags);
+}
+
+/*
+ * More complex superblock operations
+ */
+
+/** Check if superblock has specified flag.
+ *
+ * @param sb   Superblock
+ * @param flag Flag to be checked
+ *
+ * @return True, if superblock has the flag
+ *
+ */
+bool ext4_superblock_has_flag(ext4_superblock_t *sb, uint32_t flag)
+{
+	if (ext4_superblock_get_flags(sb) & flag)
+		return true;
+	
+	return false;
+}
+
+/** Check if filesystem supports compatible feature.
+ *
+ * @param sb      Superblock
+ * @param feature Feature to be checked
+ *
+ * @return True, if filesystem supports the feature
+ *
+ */
+bool ext4_superblock_has_feature_compatible(ext4_superblock_t *sb,
+    uint32_t feature)
+{
+	if (ext4_superblock_get_features_compatible(sb) & feature)
+		return true;
+	
+	return false;
+}
+
+/** Check if filesystem supports incompatible feature.
+ *
+ * @param sb      Superblock
+ * @param feature Feature to be checked
+ *
+ * @return True, if filesystem supports the feature
+ *
+ */
+bool ext4_superblock_has_feature_incompatible(ext4_superblock_t *sb,
+    uint32_t feature)
+{
+	if (ext4_superblock_get_features_incompatible(sb) & feature)
+		return true;
+	
+	return false;
+}
+
+/** Check if filesystem supports read-only compatible feature.
+ *
+ * @param sb      Superblock
+ * @param feature Feature to be checked
+ *
+ * @return True, if filesystem supports the feature
+ *
+ */
+bool ext4_superblock_has_feature_read_only(ext4_superblock_t *sb,
+    uint32_t feature)
+{
+	if (ext4_superblock_get_features_read_only(sb) & feature)
+		return true;
+	
+	return false;
+}
+
+/** Read superblock directly from block device.
+ *
+ * @param service_id Block device identifier
+ * @param sb         Output pointer to memory structure
+ *
+ * @return Eerror code.
+ *
+ */
+int ext4_superblock_read_direct(service_id_t service_id, ext4_superblock_t **sb)
+{
+	/* Allocated memory for superblock structure */
+	void *data = malloc(EXT4_SUPERBLOCK_SIZE);
+	if (data == NULL)
+		return ENOMEM;
+	
+	/* Read data from block device */
+	int rc = block_read_bytes_direct(service_id, EXT4_SUPERBLOCK_OFFSET,
+	    EXT4_SUPERBLOCK_SIZE, data);
+	
+	if (rc != EOK) {
+		free(data);
+		return rc;
+	}
+	
+	/* Set output value */
+	(*sb) = data;
+	
+	return EOK;
+}
+
+/** Write superblock structure directly to block device.
+ *
+ * @param service_id Block device identifier
+ * @param sb         Superblock to be written
+ *
+ * @return Error code
+ *
+ */
+int ext4_superblock_write_direct(service_id_t service_id, ext4_superblock_t *sb)
+{
+	/* Load physical block size from block device */
+	size_t phys_block_size;
+	int rc = block_get_bsize(service_id, &phys_block_size);
+	if (rc != EOK)
+		return rc;
+	
+	/* Compute address of the first block */
+	uint64_t first_block = EXT4_SUPERBLOCK_OFFSET / phys_block_size;
+	
+	/* Compute number of block to write */
+	size_t block_count = EXT4_SUPERBLOCK_SIZE / phys_block_size;
+	
+	/* Check alignment */
+	if (EXT4_SUPERBLOCK_SIZE % phys_block_size)
+		block_count++;
+	
+	/* Write data */
+	return block_write_direct(service_id, first_block, block_count, sb);
+}
+
+/** Check sanity of the superblock.
+ *
+ * This check is performed at mount time.
+ * Checks are described by one-line comments in the code.
+ *
+ * @param sb Superblock to check
+ *
+ * @return Error code
+ *
+ */
+int ext4_superblock_check_sanity(ext4_superblock_t *sb)
+{
+	if (ext4_superblock_get_magic(sb) != EXT4_SUPERBLOCK_MAGIC)
+		return ENOTSUP;
+	
+	if (ext4_superblock_get_inodes_count(sb) == 0)
+		return ENOTSUP;
+	
+	if (ext4_superblock_get_blocks_count(sb) == 0)
+		return ENOTSUP;
+	
+	if (ext4_superblock_get_blocks_per_group(sb) == 0)
+		return ENOTSUP;
+	
+	if (ext4_superblock_get_inodes_per_group(sb) == 0)
+		return ENOTSUP;
+	
+	if (ext4_superblock_get_inode_size(sb) < 128)
+		return ENOTSUP;
+	
+	if (ext4_superblock_get_first_inode(sb) < 11)
+		return ENOTSUP;
+	
+	if (ext4_superblock_get_desc_size(sb) <
+	    EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		return ENOTSUP;
+	
+	if (ext4_superblock_get_desc_size(sb) >
+	    EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE)
+		return ENOTSUP;
+	
+	return EOK;
+}
+
+/** Compute number of block groups in the filesystem.
+ *
+ * @param sb Superblock
+ *
+ * @return Number of block groups
+ *
+ */
+uint32_t ext4_superblock_get_block_group_count(ext4_superblock_t *sb)
+{
+	uint64_t blocks_count = ext4_superblock_get_blocks_count(sb);
+	uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb);
+	
+	uint32_t block_groups_count = blocks_count / blocks_per_group;
+	
+	if (blocks_count % blocks_per_group)
+		block_groups_count++;
+	
+	return block_groups_count;
+}
+
+/** Compute number of blocks in specified block group.
+ *
+ * @param sb   Superblock
+ * @param bgid Block group index
+ *
+ * @return Number of blocks
+ *
+ */
+uint32_t ext4_superblock_get_blocks_in_group(ext4_superblock_t *sb, uint32_t bgid)
+{
+	uint32_t block_group_count =
+	    ext4_superblock_get_block_group_count(sb);
+	uint32_t blocks_per_group =
+	    ext4_superblock_get_blocks_per_group(sb);
+	uint64_t total_blocks =
+	    ext4_superblock_get_blocks_count(sb);
+	
+	if (bgid < block_group_count - 1)
+		return blocks_per_group;
+	else
+		return (total_blocks - ((block_group_count - 1) * blocks_per_group));
+}
+
+/** Compute number of i-nodes in specified block group.
+ *
+ * @param sb   Superblock
+ * @param bgid Block group index
+ *
+ * @return Number of i-nodes
+ *
+ */
+uint32_t ext4_superblock_get_inodes_in_group(ext4_superblock_t *sb, uint32_t bgid)
+{
+	uint32_t block_group_count =
+	    ext4_superblock_get_block_group_count(sb);
+	uint32_t inodes_per_group =
+	    ext4_superblock_get_inodes_per_group(sb);
+	uint32_t total_inodes =
+	    ext4_superblock_get_inodes_count(sb);
+	
+	if (bgid < block_group_count - 1)
+		return inodes_per_group;
+	else
+		return (total_inodes - ((block_group_count - 1) * inodes_per_group));
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_superblock.h
===================================================================
--- uspace/lib/ext4/libext4_superblock.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_superblock.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_SUPERBLOCK_H_
+#define LIBEXT4_LIBEXT4_SUPERBLOCK_H_
+
+#include <block.h>
+#include <sys/types.h>
+#include "libext4_types.h"
+
+extern uint32_t ext4_superblock_get_inodes_count(ext4_superblock_t *);
+extern void ext4_superblock_set_inodes_count(ext4_superblock_t *, uint32_t);
+extern uint64_t ext4_superblock_get_blocks_count(ext4_superblock_t *);
+extern void ext4_superblock_set_blocks_count(ext4_superblock_t *, uint64_t);
+extern uint64_t ext4_superblock_get_reserved_blocks_count(ext4_superblock_t *);
+extern void ext4_superblock_set_reserved_blocks_count(ext4_superblock_t *,
+    uint64_t);
+extern uint64_t ext4_superblock_get_free_blocks_count(ext4_superblock_t *);
+extern void ext4_superblock_set_free_blocks_count(ext4_superblock_t *,
+    uint64_t);
+extern uint32_t ext4_superblock_get_free_inodes_count(ext4_superblock_t *);
+extern void ext4_superblock_set_free_inodes_count(ext4_superblock_t *,
+    uint32_t);
+extern uint32_t ext4_superblock_get_first_data_block(ext4_superblock_t *);
+extern void ext4_superblock_set_first_data_block(ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_superblock_get_log_block_size(ext4_superblock_t *);
+extern void ext4_superblock_set_log_block_size(ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_superblock_get_block_size(ext4_superblock_t *);
+extern void ext4_superblock_set_block_size(ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_superblock_get_log_frag_size(ext4_superblock_t *);
+extern void ext4_superblock_set_log_frag_size(ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_superblock_get_frag_size(ext4_superblock_t *);
+extern void ext4_superblock_set_frag_size(ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_superblock_get_blocks_per_group(ext4_superblock_t *);
+extern void ext4_superblock_set_blocks_per_group(ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_superblock_get_frags_per_group(ext4_superblock_t *);
+extern void ext4_superblock_set_frags_per_group(ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_superblock_get_inodes_per_group(ext4_superblock_t *);
+extern void ext4_superblock_set_inodes_per_group(ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_superblock_get_mount_time(ext4_superblock_t *);
+extern void ext4_superblock_set_mount_time(ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_superblock_get_write_time(ext4_superblock_t *);
+extern void ext4_superblock_set_write_time(ext4_superblock_t *, uint32_t);
+extern uint16_t ext4_superblock_get_mount_count(ext4_superblock_t *);
+extern void ext4_superblock_set_mount_count(ext4_superblock_t *, uint16_t);
+extern uint16_t ext4_superblock_get_max_mount_count(ext4_superblock_t *);
+extern void ext4_superblock_set_max_mount_count(ext4_superblock_t *, uint16_t);
+extern uint16_t ext4_superblock_get_magic(ext4_superblock_t *);
+extern void ext4_superblock_set_magic(ext4_superblock_t *sb, uint16_t magic);
+extern uint16_t ext4_superblock_get_state(ext4_superblock_t *);
+extern void ext4_superblock_set_state(ext4_superblock_t *, uint16_t);
+extern uint16_t ext4_superblock_get_errors(ext4_superblock_t *);
+extern void ext4_superblock_set_errors(ext4_superblock_t *, uint16_t);
+extern uint16_t ext4_superblock_get_minor_rev_level(ext4_superblock_t *);
+extern void ext4_superblock_set_minor_rev_level(ext4_superblock_t *, uint16_t);
+extern uint32_t ext4_superblock_get_last_check_time(ext4_superblock_t *);
+extern void ext4_superblock_set_last_check_time(ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_superblock_get_check_interval(ext4_superblock_t *);
+extern void ext4_superblock_set_check_interval(ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_superblock_get_creator_os(ext4_superblock_t *);
+extern void ext4_superblock_set_creator_os(ext4_superblock_t *, uint32_t);
+extern uint32_t ext4_superblock_get_rev_level(ext4_superblock_t *);
+extern void ext4_superblock_set_rev_level(ext4_superblock_t *, uint32_t);
+extern uint16_t ext4_superblock_get_def_resuid(ext4_superblock_t *);
+extern void ext4_superblock_set_def_resuid(ext4_superblock_t *, uint16_t);
+extern uint16_t ext4_superblock_get_def_resgid(ext4_superblock_t *);
+extern void ext4_superblock_set_def_resgid(ext4_superblock_t *, uint16_t);
+extern uint32_t ext4_superblock_get_first_inode(ext4_superblock_t *);
+extern void ext4_superblock_set_first_inode(ext4_superblock_t *, uint32_t);
+extern uint16_t ext4_superblock_get_inode_size(ext4_superblock_t *);
+extern void ext4_superblock_set_inode_size(ext4_superblock_t *, uint16_t);
+extern uint16_t ext4_superblock_get_block_group_index(ext4_superblock_t *);
+extern void ext4_superblock_set_block_group_index(ext4_superblock_t *,
+    uint16_t);
+extern uint32_t ext4_superblock_get_features_compatible(ext4_superblock_t *);
+extern void ext4_superblock_set_features_compatible(ext4_superblock_t *,
+    uint32_t);
+extern uint32_t ext4_superblock_get_features_incompatible(ext4_superblock_t *);
+extern void ext4_superblock_set_features_incompatible(ext4_superblock_t *,
+    uint32_t);
+extern uint32_t ext4_superblock_get_features_read_only(ext4_superblock_t *);
+extern void ext4_superblock_set_features_read_only(ext4_superblock_t *,
+    uint32_t);
+
+extern const uint8_t * ext4_superblock_get_uuid(ext4_superblock_t *);
+extern void ext4_superblock_set_uuid(ext4_superblock_t *, const uint8_t *);
+extern const char * ext4_superblock_get_volume_name(ext4_superblock_t *);
+extern void ext4_superblock_set_volume_name(ext4_superblock_t *, const char *);
+extern const char * ext4_superblock_get_last_mounted(ext4_superblock_t *);
+extern void ext4_superblock_set_last_mounted(ext4_superblock_t *, const char *);
+
+extern uint32_t ext4_superblock_get_last_orphan(ext4_superblock_t *);
+extern void ext4_superblock_set_last_orphan(ext4_superblock_t *, uint32_t);
+extern const uint32_t * ext4_superblock_get_hash_seed(ext4_superblock_t *);
+extern void ext4_superblock_set_hash_seed(ext4_superblock_t *,
+    const uint32_t *);
+extern uint8_t ext4_superblock_get_default_hash_version(ext4_superblock_t *);
+extern void ext4_superblock_set_default_hash_version(ext4_superblock_t *,
+    uint8_t);
+
+extern uint16_t ext4_superblock_get_desc_size(ext4_superblock_t *);
+extern void ext4_superblock_set_desc_size(ext4_superblock_t *, uint16_t);
+
+extern uint32_t ext4_superblock_get_flags(ext4_superblock_t *);
+extern void ext4_superblock_set_flags(ext4_superblock_t *, uint32_t);
+
+/* More complex superblock functions */
+extern bool ext4_superblock_has_flag(ext4_superblock_t *, uint32_t);
+extern bool ext4_superblock_has_feature_compatible(ext4_superblock_t *,
+    uint32_t);
+extern bool ext4_superblock_has_feature_incompatible(ext4_superblock_t *,
+    uint32_t);
+extern bool ext4_superblock_has_feature_read_only(ext4_superblock_t *,
+    uint32_t);
+extern int ext4_superblock_read_direct(service_id_t, ext4_superblock_t **);
+extern int ext4_superblock_write_direct(service_id_t, ext4_superblock_t *);
+extern int ext4_superblock_check_sanity(ext4_superblock_t *);
+
+extern uint32_t ext4_superblock_get_block_group_count(ext4_superblock_t *);
+extern uint32_t ext4_superblock_get_blocks_in_group(ext4_superblock_t *,
+    uint32_t);
+extern uint32_t ext4_superblock_get_inodes_in_group(ext4_superblock_t *,
+    uint32_t);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/ext4/libext4_types.h
===================================================================
--- uspace/lib/ext4/libext4_types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/ext4/libext4_types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 libext4
+ * @{
+ */
+
+#ifndef LIBEXT4_LIBEXT4_TYPES_H_
+#define LIBEXT4_LIBEXT4_TYPES_H_
+
+#include <block.h>
+
+/*
+ * Structure of the super block
+ */
+typedef struct ext4_superblock {
+	uint32_t inodes_count;              /* I-nodes count */
+	uint32_t blocks_count_lo;           /* Blocks count */
+	uint32_t reserved_blocks_count_lo;  /* Reserved blocks count */
+	uint32_t free_blocks_count_lo;      /* Free blocks count */
+	uint32_t free_inodes_count;         /* Free inodes count */
+	uint32_t first_data_block;          /* First Data Block */
+	uint32_t log_block_size;            /* Block size */
+	uint32_t log_frag_size;             /* Obsoleted fragment size */
+	uint32_t blocks_per_group;          /* Number of blocks per group */
+	uint32_t frags_per_group;           /* Obsoleted fragments per group */
+	uint32_t inodes_per_group;          /* Number of inodes per group */
+	uint32_t mount_time;                /* Mount time */
+	uint32_t write_time;                /* Write time */
+	uint16_t mount_count;               /* Mount count */
+	uint16_t max_mount_count;           /* Maximal mount count */
+	uint16_t magic;                     /* Magic signature */
+	uint16_t state;                     /* File system state */
+	uint16_t errors;                    /* Behaviour when detecting errors */
+	uint16_t minor_rev_level;           /* Minor revision level */
+	uint32_t last_check_time;           /* Time of last check */
+	uint32_t check_interval;            /* Maximum time between checks */
+	uint32_t creator_os;                /* Creator OS */
+	uint32_t rev_level;                 /* Revision level */
+	uint16_t def_resuid;                /* Default uid for reserved blocks */
+	uint16_t def_resgid;                /* Default gid for reserved blocks */
+	
+	/* Fields for EXT4_DYNAMIC_REV superblocks only. */
+	uint32_t first_inode;             /* First non-reserved inode */
+	uint16_t inode_size;              /* Size of inode structure */
+	uint16_t block_group_index;       /* Block group index of this superblock */
+	uint32_t features_compatible;     /* Compatible feature set */
+	uint32_t features_incompatible;   /* Incompatible feature set */
+	uint32_t features_read_only;      /* Readonly-compatible feature set */
+	uint8_t uuid[16];                 /* 128-bit uuid for volume */
+	char volume_name[16];             /* Volume name */
+	char last_mounted[64];            /* Directory where last mounted */
+	uint32_t algorithm_usage_bitmap;  /* For compression */
+	
+	/*
+	 * Performance hints. Directory preallocation should only
+	 * happen if the EXT4_FEATURE_COMPAT_DIR_PREALLOC flag is on.
+	 */
+	uint8_t s_prealloc_blocks;       /* Number of blocks to try to preallocate */
+	uint8_t s_prealloc_dir_blocks;   /* Number to preallocate for dirs */
+	uint16_t s_reserved_gdt_blocks;  /* Per group desc for online growth */
+	
+	/*
+	 * Journaling support valid if EXT4_FEATURE_COMPAT_HAS_JOURNAL set.
+	 */
+	uint8_t journal_uuid[16];       /* UUID of journal superblock */
+	uint32_t journal_inode_number;  /* Inode number of journal file */
+	uint32_t journal_dev;           /* Device number of journal file */
+	uint32_t last_orphan;           /* Head of list of inodes to delete */
+	uint32_t hash_seed[4];          /* HTREE hash seed */
+	uint8_t default_hash_version;   /* Default hash version to use */
+	uint8_t journal_backup_type;
+	uint16_t desc_size;             /* Size of group descriptor */
+	uint32_t default_mount_opts;    /* Default mount options */
+	uint32_t first_meta_bg;         /* First metablock block group */
+	uint32_t mkfs_time;             /* When the filesystem was created */
+	uint32_t journal_blocks[17];    /* Backup of the journal inode */
+
+	/* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */
+	uint32_t blocks_count_hi;           /* Blocks count */
+	uint32_t reserved_blocks_count_hi;  /* Reserved blocks count */
+	uint32_t free_blocks_count_hi;      /* Free blocks count */
+	uint16_t min_extra_isize;           /* All inodes have at least # bytes */
+	uint16_t want_extra_isize;          /* New inodes should reserve # bytes */
+	uint32_t flags;                     /* Miscellaneous flags */
+	uint16_t raid_stride;               /* RAID stride */
+	uint16_t mmp_interval;              /* # seconds to wait in MMP checking */
+	uint64_t mmp_block;                 /* Block for multi-mount protection */
+	uint32_t raid_stripe_width;         /* Blocks on all data disks (N * stride) */
+	uint8_t log_groups_per_flex;        /* FLEX_BG group size */
+	uint8_t reserved_char_pad;
+	uint16_t reserved_pad;
+	uint64_t kbytes_written;            /* Number of lifetime kilobytes written */
+	uint32_t snapshot_inum;             /* I-node number of active snapshot */
+	uint32_t snapshot_id;               /* Sequential ID of active snapshot */
+	uint64_t snapshot_r_blocks_count;   /* Reserved blocks for active snapshot's future use */
+	uint32_t snapshot_list;             /* I-node number of the head of the on-disk snapshot list */
+	uint32_t error_count;               /* Number of file system errors */
+	uint32_t first_error_time;          /* First time an error happened */
+	uint32_t first_error_ino;           /* I-node involved in first error */
+	uint64_t first_error_block;         /* Block involved of first error */
+	uint8_t first_error_func[32];       /* Function where the error happened */
+	uint32_t first_error_line;          /* Line number where error happened */
+	uint32_t last_error_time;           /* Most recent time of an error */
+	uint32_t last_error_ino;            /* I-node involved in last error */
+	uint32_t last_error_line;           /* Line number where error happened */
+	uint64_t last_error_block;          /* Block involved of last error */
+	uint8_t last_error_func[32];        /* Function where the error happened */
+	uint8_t mount_opts[64];
+	uint32_t padding[112];              /* Padding to the end of the block */
+} __attribute__((packed)) ext4_superblock_t;
+
+
+#define EXT4_SUPERBLOCK_MAGIC   0xEF53
+#define EXT4_SUPERBLOCK_SIZE    1024
+#define EXT4_SUPERBLOCK_OFFSET  1024
+
+#define EXT4_SUPERBLOCK_OS_LINUX  0
+#define EXT4_SUPERBLOCK_OS_HURD   1
+
+/*
+ * Misc. filesystem flags
+ */
+#define EXT4_SUPERBLOCK_FLAGS_SIGNED_HASH    0x0001  /* Signed dirhash in use */
+#define EXT4_SUPERBLOCK_FLAGS_UNSIGNED_HASH  0x0002  /* Unsigned dirhash in use */
+#define EXT4_SUPERBLOCK_FLAGS_TEST_FILESYS   0x0004  /* to test development code */
+
+/*
+ * Filesystem states
+ */
+#define EXT4_SUPERBLOCK_STATE_VALID_FS   0x0001  /* Unmounted cleanly */
+#define EXT4_SUPERBLOCK_STATE_ERROR_FS   0x0002  /* Errors detected */
+#define EXT4_SUPERBLOCK_STATE_ORPHAN_FS  0x0004  /* Orphans being recovered */
+
+/*
+ * Behaviour when errors detected
+ */
+#define EXT4_SUPERBLOCK_ERRORS_CONTINUE  1  /* Continue execution */
+#define EXT4_SUPERBLOCK_ERRORS_RO        2  /* Remount fs read-only */
+#define EXT4_SUPERBLOCK_ERRORS_PANIC     3  /* Panic */
+#define EXT4_SUPERBLOCK_ERRORS_DEFAULT   EXT4_ERRORS_CONTINUE
+
+/*
+ * Compatible features
+ */
+#define EXT4_FEATURE_COMPAT_DIR_PREALLOC   0x0001
+#define EXT4_FEATURE_COMPAT_IMAGIC_INODES  0x0002
+#define EXT4_FEATURE_COMPAT_HAS_JOURNAL    0x0004
+#define EXT4_FEATURE_COMPAT_EXT_ATTR       0x0008
+#define EXT4_FEATURE_COMPAT_RESIZE_INODE   0x0010
+#define EXT4_FEATURE_COMPAT_DIR_INDEX      0x0020
+
+/*
+ * Read-only compatible features
+ */
+#define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER  0x0001
+#define EXT4_FEATURE_RO_COMPAT_LARGE_FILE    0x0002
+#define EXT4_FEATURE_RO_COMPAT_BTREE_DIR     0x0004
+#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE     0x0008
+#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM      0x0010
+#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK     0x0020
+#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE   0x0040
+
+/*
+ * Incompatible features
+ */
+#define EXT4_FEATURE_INCOMPAT_COMPRESSION  0x0001
+#define EXT4_FEATURE_INCOMPAT_FILETYPE     0x0002
+#define EXT4_FEATURE_INCOMPAT_RECOVER      0x0004  /* Needs recovery */
+#define EXT4_FEATURE_INCOMPAT_JOURNAL_DEV  0x0008  /* Journal device */
+#define EXT4_FEATURE_INCOMPAT_META_BG      0x0010
+#define EXT4_FEATURE_INCOMPAT_EXTENTS      0x0040  /* extents support */
+#define EXT4_FEATURE_INCOMPAT_64BIT        0x0080
+#define EXT4_FEATURE_INCOMPAT_MMP          0x0100
+#define EXT4_FEATURE_INCOMPAT_FLEX_BG      0x0200
+#define EXT4_FEATURE_INCOMPAT_EA_INODE     0x0400  /* EA in inode */
+#define EXT4_FEATURE_INCOMPAT_DIRDATA      0x1000  /* data in dirent */
+
+#define EXT4_FEATURE_COMPAT_SUPP  (EXT4_FEATURE_COMPAT_DIR_INDEX)
+
+#define EXT4_FEATURE_INCOMPAT_SUPP \
+	(EXT4_FEATURE_INCOMPAT_FILETYPE | \
+	EXT4_FEATURE_INCOMPAT_EXTENTS | \
+	EXT4_FEATURE_INCOMPAT_64BIT)
+
+#define EXT4_FEATURE_RO_COMPAT_SUPP \
+	(EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER | \
+	EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
+	EXT4_FEATURE_RO_COMPAT_HUGE_FILE | \
+	EXT4_FEATURE_RO_COMPAT_LARGE_FILE | \
+	EXT4_FEATURE_RO_COMPAT_GDT_CSUM | \
+	EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)
+
+typedef struct ext4_filesystem {
+	service_id_t device;
+	ext4_superblock_t *superblock;
+	aoff64_t inode_block_limits[4];
+	aoff64_t inode_blocks_per_level[4];
+} ext4_filesystem_t;
+
+
+#define EXT4_BLOCK_GROUP_INODE_UNINIT   0x0001  /* Inode table/bitmap not in use */
+#define EXT4_BLOCK_GROUP_BLOCK_UNINIT   0x0002  /* Block bitmap not in use */
+#define EXT4_BLOCK_GROUP_ITABLE_ZEROED  0x0004  /* On-disk itable initialized to zero */
+
+/*
+ * Structure of a blocks group descriptor
+ */
+typedef struct ext4_block_group {
+	uint32_t block_bitmap_lo;             /* Blocks bitmap block */
+	uint32_t inode_bitmap_lo;             /* Inodes bitmap block */
+	uint32_t inode_table_first_block_lo;  /* Inodes table block */
+	uint16_t free_blocks_count_lo;        /* Free blocks count */
+	uint16_t free_inodes_count_lo;        /* Free inodes count */
+	uint16_t used_dirs_count_lo;          /* Directories count */
+	uint16_t flags;                       /* EXT4_BG_flags (INODE_UNINIT, etc) */
+	uint32_t reserved[2];                 /* Likely block/inode bitmap checksum */
+	uint16_t itable_unused_lo;            /* Unused inodes count */
+	uint16_t checksum;                    /* crc16(sb_uuid+group+desc) */
+	
+	uint32_t block_bitmap_hi;             /* Blocks bitmap block MSB */
+	uint32_t inode_bitmap_hi;             /* I-nodes bitmap block MSB */
+	uint32_t inode_table_first_block_hi;  /* I-nodes table block MSB */
+	uint16_t free_blocks_count_hi;        /* Free blocks count MSB */
+	uint16_t free_inodes_count_hi;        /* Free i-nodes count MSB */
+	uint16_t used_dirs_count_hi;          /* Directories count MSB */
+	uint16_t itable_unused_hi;            /* Unused inodes count MSB */
+	uint32_t reserved2[3];                /* Padding */
+} ext4_block_group_t;
+
+typedef struct ext4_block_group_ref {
+	block_t *block;                   /* Reference to a block containing this block group descr */
+	ext4_block_group_t *block_group;
+	ext4_filesystem_t *fs;
+	uint32_t index;
+	bool dirty;
+} ext4_block_group_ref_t;
+
+#define EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE  32
+#define EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE  64
+
+#define EXT4_MIN_BLOCK_SIZE   1024   /* 1 KiB */
+#define EXT4_MAX_BLOCK_SIZE   65536  /* 64 KiB */
+#define EXT4_REV0_INODE_SIZE  128
+
+#define EXT4_INODE_BLOCK_SIZE  512
+
+#define EXT4_INODE_DIRECT_BLOCK_COUNT      12
+#define EXT4_INODE_INDIRECT_BLOCK          EXT4_INODE_DIRECT_BLOCK_COUNT
+#define EXT4_INODE_DOUBLE_INDIRECT_BLOCK   (EXT4_INODE_INDIRECT_BLOCK + 1)
+#define EXT4_INODE_TRIPPLE_INDIRECT_BLOCK  (EXT4_INODE_DOUBLE_INDIRECT_BLOCK + 1)
+#define EXT4_INODE_BLOCKS                  (EXT4_INODE_TRIPPLE_INDIRECT_BLOCK + 1)
+#define EXT4_INODE_INDIRECT_BLOCK_COUNT    (EXT4_INODE_BLOCKS - EXT4_INODE_DIRECT_BLOCK_COUNT)
+
+/*
+ * Structure of an inode on the disk
+ */
+typedef struct ext4_inode {
+	uint16_t mode;                       /* File mode */
+	uint16_t uid;                        /* Low 16 bits of owner uid */
+	uint32_t size_lo;                    /* Size in bytes */
+	uint32_t access_time;                /* Access time */
+	uint32_t change_inode_time;          /* I-node change time */
+	uint32_t modification_time;          /* Modification time */
+	uint32_t deletion_time;              /* Deletion time */
+	uint16_t gid;                        /* Low 16 bits of group id */
+	uint16_t links_count;                /* Links count */
+	uint32_t blocks_count_lo;            /* Blocks count */
+	uint32_t flags;                      /* File flags */
+	uint32_t unused_osd1;                /* OS dependent - not used in HelenOS */
+	uint32_t blocks[EXT4_INODE_BLOCKS];  /* Pointers to blocks */
+	uint32_t generation;                 /* File version (for NFS) */
+	uint32_t file_acl_lo;                /* File ACL */
+	uint32_t size_hi;
+	uint32_t obso_faddr;                 /* Obsoleted fragment address */
+	
+	union {
+		struct {
+			uint16_t blocks_high;
+			uint16_t file_acl_high;
+			uint16_t uid_high;
+			uint16_t gid_high;
+			uint32_t reserved2;
+		} linux2;
+		struct {
+			uint16_t reserved1;
+			uint16_t mode_high;
+			uint16_t uid_high;
+			uint16_t gid_high;
+			uint32_t author;
+		} hurd2;
+	} __attribute__ ((packed)) osd2;
+	
+	uint16_t extra_isize;
+	uint16_t pad1;
+	uint32_t ctime_extra;   /* Extra change time (nsec << 2 | epoch) */
+	uint32_t mtime_extra;   /* Extra Modification time (nsec << 2 | epoch) */
+	uint32_t atime_extra;   /* Extra Access time (nsec << 2 | epoch) */
+	uint32_t crtime;        /* File creation time */
+	uint32_t crtime_extra;  /* Extra file creation time (nsec << 2 | epoch) */
+	uint32_t version_hi;    /* High 32 bits for 64-bit version */
+} __attribute__ ((packed)) ext4_inode_t;
+
+#define EXT4_INODE_MODE_FIFO       0x1000
+#define EXT4_INODE_MODE_CHARDEV    0x2000
+#define EXT4_INODE_MODE_DIRECTORY  0x4000
+#define EXT4_INODE_MODE_BLOCKDEV   0x6000
+#define EXT4_INODE_MODE_FILE       0x8000
+#define EXT4_INODE_MODE_SOFTLINK   0xA000
+#define EXT4_INODE_MODE_SOCKET     0xC000
+#define EXT4_INODE_MODE_TYPE_MASK  0xF000
+
+/*
+ * Inode flags
+ */
+#define EXT4_INODE_FLAG_SECRM      0x00000001  /* Secure deletion */
+#define EXT4_INODE_FLAG_UNRM       0x00000002  /* Undelete */
+#define EXT4_INODE_FLAG_COMPR      0x00000004  /* Compress file */
+#define EXT4_INODE_FLAG_SYNC       0x00000008  /* Synchronous updates */
+#define EXT4_INODE_FLAG_IMMUTABLE  0x00000010  /* Immutable file */
+#define EXT4_INODE_FLAG_APPEND     0x00000020  /* writes to file may only append */
+#define EXT4_INODE_FLAG_NODUMP     0x00000040  /* do not dump file */
+#define EXT4_INODE_FLAG_NOATIME    0x00000080  /* do not update atime */
+
+/* Compression flags */
+#define EXT4_INODE_FLAG_DIRTY     0x00000100
+#define EXT4_INODE_FLAG_COMPRBLK  0x00000200  /* One or more compressed clusters */
+#define EXT4_INODE_FLAG_NOCOMPR   0x00000400  /* Don't compress */
+#define EXT4_INODE_FLAG_ECOMPR    0x00000800  /* Compression error */
+
+#define EXT4_INODE_FLAG_INDEX         0x00001000  /* hash-indexed directory */
+#define EXT4_INODE_FLAG_IMAGIC        0x00002000  /* AFS directory */
+#define EXT4_INODE_FLAG_JOURNAL_DATA  0x00004000  /* File data should be journaled */
+#define EXT4_INODE_FLAG_NOTAIL        0x00008000  /* File tail should not be merged */
+#define EXT4_INODE_FLAG_DIRSYNC       0x00010000  /* Dirsync behaviour (directories only) */
+#define EXT4_INODE_FLAG_TOPDIR        0x00020000  /* Top of directory hierarchies */
+#define EXT4_INODE_FLAG_HUGE_FILE     0x00040000  /* Set to each huge file */
+#define EXT4_INODE_FLAG_EXTENTS       0x00080000  /* Inode uses extents */
+#define EXT4_INODE_FLAG_EA_INODE      0x00200000  /* Inode used for large EA */
+#define EXT4_INODE_FLAG_EOFBLOCKS     0x00400000  /* Blocks allocated beyond EOF */
+#define EXT4_INODE_FLAG_RESERVED      0x80000000  /* reserved for ext4 lib */
+
+#define EXT4_INODE_ROOT_INDEX  2
+
+typedef struct ext4_inode_ref {
+	block_t *block;         /* Reference to a block containing this inode */
+	ext4_inode_t *inode;
+	ext4_filesystem_t *fs;
+	uint32_t index;         /* Index number of this inode */
+	bool dirty;
+} ext4_inode_ref_t;
+
+
+#define EXT4_DIRECTORY_FILENAME_LEN  255
+
+#define EXT4_DIRECTORY_FILETYPE_UNKNOWN   0
+#define EXT4_DIRECTORY_FILETYPE_REG_FILE  1
+#define EXT4_DIRECTORY_FILETYPE_DIR       2
+#define EXT4_DIRECTORY_FILETYPE_CHRDEV    3
+#define EXT4_DIRECTORY_FILETYPE_BLKDEV    4
+#define EXT4_DIRECTORY_FILETYPE_FIFO      5
+#define EXT4_DIRECTORY_FILETYPE_SOCK      6
+#define EXT4_DIRECTORY_FILETYPE_SYMLINK   7
+
+/**
+ * Linked list directory entry structure
+ */
+typedef struct ext4_directory_entry_ll {
+	uint32_t inode;         /* I-node for the entry */
+	uint16_t entry_length;  /* Distance to the next directory entry */
+	uint8_t name_length;    /* Lower 8 bits of name length */
+	
+	union {
+		uint8_t name_length_high;  /* Higher 8 bits of name length */
+		uint8_t inode_type;        /* Type of referenced inode (in rev >= 0.5) */
+	} __attribute__ ((packed));
+	
+	uint8_t name[EXT4_DIRECTORY_FILENAME_LEN];  /* Entry name */
+} __attribute__((packed)) ext4_directory_entry_ll_t;
+
+typedef struct ext4_directory_iterator {
+	ext4_inode_ref_t *inode_ref;
+	block_t *current_block;
+	aoff64_t current_offset;
+	ext4_directory_entry_ll_t *current;
+} ext4_directory_iterator_t;
+
+typedef struct ext4_directory_search_result {
+	block_t *block;
+	ext4_directory_entry_ll_t *dentry;
+} ext4_directory_search_result_t;
+
+/* Structures for indexed directory */
+
+typedef struct ext4_directory_dx_countlimit {
+	uint16_t limit;
+	uint16_t count;
+} ext4_directory_dx_countlimit_t;
+
+typedef struct ext4_directory_dx_dot_entry {
+	uint32_t inode;
+	uint16_t entry_length;
+	uint8_t name_length;
+	uint8_t inode_type;
+	uint8_t name[4];
+} ext4_directory_dx_dot_entry_t;
+
+typedef struct ext4_directory_dx_root_info {
+	uint32_t reserved_zero;
+	uint8_t hash_version;
+	uint8_t info_length;
+	uint8_t indirect_levels;
+	uint8_t unused_flags;
+} ext4_directory_dx_root_info_t;
+
+typedef struct ext4_directory_dx_entry {
+	uint32_t hash;
+	uint32_t block;
+} ext4_directory_dx_entry_t;
+
+typedef struct ext4_directory_dx_root {
+	ext4_directory_dx_dot_entry_t dots[2];
+	ext4_directory_dx_root_info_t info;
+	ext4_directory_dx_entry_t entries[0];
+} ext4_directory_dx_root_t;
+
+typedef struct ext4_fake_directory_entry {
+	uint32_t inode;
+	uint16_t entry_length;
+	uint8_t name_length;
+	uint8_t inode_type;
+} ext4_fake_directory_entry_t;
+
+typedef struct ext4_directory_dx_node {
+	ext4_fake_directory_entry_t fake;
+	ext4_directory_dx_entry_t entries[0];
+} ext4_directory_dx_node_t;
+
+typedef struct ext4_directory_dx_block {
+	block_t *block;
+	ext4_directory_dx_entry_t *entries;
+	ext4_directory_dx_entry_t *position;
+} ext4_directory_dx_block_t;
+
+#define EXT4_ERR_BAD_DX_DIR       (-75000)
+#define EXT4_DIRECTORY_HTREE_EOF  UINT32_C(0x7fffffff)
+
+/*
+ * This is the extent on-disk structure.
+ * It's used at the bottom of the tree.
+ */
+typedef struct ext4_extent {
+	uint32_t first_block;  /* First logical block extent covers */
+	uint16_t block_count;  /* Number of blocks covered by extent */
+	uint16_t start_hi;     /* High 16 bits of physical block */
+	uint32_t start_lo;     /* Low 32 bits of physical block */
+} ext4_extent_t;
+
+/*
+ * This is index on-disk structure.
+ * It's used at all the levels except the bottom.
+ */
+typedef struct ext4_extent_index {
+	uint32_t first_block;  /* Index covers logical blocks from 'block' */
+	
+	/**
+	 * Pointer to the physical block of the next
+	 * level. leaf or next index could be there
+	 * high 16 bits of physical block
+	 */
+	uint32_t leaf_lo;
+	uint16_t leaf_hi;
+	uint16_t padding;
+} ext4_extent_index_t;
+
+/*
+ * Each block (leaves and indexes), even inode-stored has header.
+ */
+typedef struct ext4_extent_header {
+	uint16_t magic;
+	uint16_t entries_count;      /* Number of valid entries */
+	uint16_t max_entries_count;  /* Capacity of store in entries */
+	uint16_t depth;              /* Has tree real underlying blocks? */
+	uint32_t generation;         /* generation of the tree */
+} ext4_extent_header_t;
+
+typedef struct ext4_extent_path {
+	block_t *block;
+	uint16_t depth;
+	ext4_extent_header_t *header;
+	ext4_extent_index_t *index;
+	ext4_extent_t *extent;
+} ext4_extent_path_t;
+
+#define EXT4_EXTENT_MAGIC  0xF30A
+
+#define	EXT4_EXTENT_FIRST(header) \
+	((ext4_extent_t *) (((void *) (header)) + sizeof(ext4_extent_header_t)))
+
+#define	EXT4_EXTENT_FIRST_INDEX(header) \
+	((ext4_extent_index_t *) (((void *) (header)) + sizeof(ext4_extent_header_t)))
+
+#define EXT4_HASH_VERSION_LEGACY             0
+#define EXT4_HASH_VERSION_HALF_MD4           1
+#define EXT4_HASH_VERSION_TEA                2
+#define EXT4_HASH_VERSION_LEGACY_UNSIGNED    3
+#define EXT4_HASH_VERSION_HALF_MD4_UNSIGNED  4
+#define EXT4_HASH_VERSION_TEA_UNSIGNED       5
+
+typedef struct ext4_hash_info {
+	uint32_t hash;
+	uint32_t minor_hash;
+	uint32_t hash_version;
+	const uint32_t *seed;
+} ext4_hash_info_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: pace/lib/fb/Makefile
===================================================================
--- uspace/lib/fb/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2011 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.
-#
-
-USPACE_PREFIX = ../..
-LIBRARY = libfb
-
-SOURCES = \
-	fb.c \
-	imgmap.c \
-	screenbuffer.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/lib/fb/fb.c
===================================================================
--- uspace/lib/fb/fb.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,289 +1,0 @@
-/*
- * Copyright (c) 2011 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 libc
- * @{
- */
-/** @file
- */
-
-#include <async.h>
-#include <errno.h>
-#include <as.h>
-#include "fb.h"
-
-static async_exch_t *vp_exchange_begin(async_sess_t *sess, vp_handle_t vp)
-{
-	vp_handle_t cur_vp = (vp_handle_t) async_remote_state_acquire(sess);
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	if (cur_vp != vp) {
-		int ret = async_req_1_0(exch, FB_VP_FOCUS, vp);
-		if (ret != EOK) {
-			async_exchange_end(exch);
-			return NULL;
-		}
-		
-		async_remote_state_update(sess, (void *) vp);
-	}
-	
-	return exch;
-}
-
-static void vp_exchange_end(async_exch_t *exch)
-{
-	async_remote_state_release_exchange(exch);
-}
-
-int fb_get_resolution(async_sess_t *sess, sysarg_t *maxx, sysarg_t *maxy)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int ret = async_req_0_2(exch, FB_GET_RESOLUTION, maxx, maxy);
-	async_exchange_end(exch);
-	
-	return ret;
-}
-
-int fb_yield(async_sess_t *sess)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int ret = async_req_0_0(exch, FB_YIELD);
-	async_exchange_end(exch);
-	
-	return ret;
-}
-
-int fb_claim(async_sess_t *sess)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int ret = async_req_0_0(exch, FB_CLAIM);
-	async_exchange_end(exch);
-	
-	return ret;
-}
-
-int fb_pointer_update(async_sess_t *sess, sysarg_t x, sysarg_t y, bool visible)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int ret = async_req_3_0(exch, FB_POINTER_UPDATE, x, y, visible);
-	async_exchange_end(exch);
-	
-	return ret;
-}
-
-vp_handle_t fb_vp_create(async_sess_t *sess, sysarg_t x, sysarg_t y,
-    sysarg_t width, sysarg_t height)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	vp_handle_t handle;
-	int ret = async_req_4_1(exch, FB_VP_CREATE, x, y, width, height,
-	    &handle);
-	
-	async_exchange_end(exch);
-	
-	if (ret != EOK)
-		return 0;
-	
-	return handle;
-}
-
-frontbuf_handle_t fb_frontbuf_create(async_sess_t *sess,
-    screenbuffer_t *frontbuf)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_0(exch, FB_FRONTBUF_CREATE, &answer);
-	int rc = async_share_out_start(exch, frontbuf, AS_AREA_READ
-	    | AS_AREA_WRITE | AS_AREA_CACHEABLE);
-	
-	async_exchange_end(exch);
-	
-	sysarg_t ret;
-	async_wait_for(req, &ret);
-	
-	if ((rc != EOK) || (ret != EOK))
-		return 0;
-	
-	return (frontbuf_handle_t) IPC_GET_ARG1(answer);
-}
-
-imagemap_handle_t fb_imagemap_create(async_sess_t *sess, imgmap_t *imgmap)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_0(exch, FB_IMAGEMAP_CREATE, &answer);
-	int rc = async_share_out_start(exch, imgmap, AS_AREA_READ
-	    | AS_AREA_WRITE | AS_AREA_CACHEABLE);
-	
-	async_exchange_end(exch);
-	
-	sysarg_t ret;
-	async_wait_for(req, &ret);
-	
-	if ((rc != EOK) || (ret != EOK))
-		return 0;
-	
-	return (imagemap_handle_t) IPC_GET_ARG1(answer);
-}
-
-sequence_handle_t fb_sequence_create(async_sess_t *sess)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	sysarg_t ret;
-	int rc = async_req_0_1(exch, FB_SEQUENCE_CREATE, &ret);
-	
-	async_exchange_end(exch);
-	
-	if (rc != EOK)
-		return 0;
-	
-	return (sequence_handle_t) ret;
-}
-
-int fb_vp_get_dimensions(async_sess_t *sess, vp_handle_t vp, sysarg_t *cols,
-    sysarg_t *rows)
-{
-	async_exch_t *exch = vp_exchange_begin(sess, vp);
-	int ret = async_req_0_2(exch, FB_VP_GET_DIMENSIONS, cols, rows);
-	vp_exchange_end(exch);
-	
-	return ret;
-}
-
-int fb_vp_get_caps(async_sess_t *sess, vp_handle_t vp, console_caps_t *ccaps)
-{
-	async_exch_t *exch = vp_exchange_begin(sess, vp);
-	
-	sysarg_t rv;
-	int ret = async_req_0_1(exch, FB_VP_GET_CAPS, &rv);
-	
-	vp_exchange_end(exch);
-	
-	if (ret == EOK)
-		*ccaps = (console_caps_t) rv;
-	
-	return ret;
-}
-
-int fb_vp_clear(async_sess_t *sess, vp_handle_t vp)
-{
-	async_exch_t *exch = vp_exchange_begin(sess, vp);
-	int ret = async_req_0_0(exch, FB_VP_CLEAR);
-	vp_exchange_end(exch);
-	
-	return ret;
-}
-
-int fb_vp_cursor_update(async_sess_t *sess, vp_handle_t vp,
-    frontbuf_handle_t frontbuf)
-{
-	async_exch_t *exch = vp_exchange_begin(sess, vp);
-	int ret = async_req_1_0(exch, FB_VP_CURSOR_UPDATE, frontbuf);
-	vp_exchange_end(exch);
-	
-	return ret;
-}
-
-int fb_vp_set_style(async_sess_t *sess, vp_handle_t vp, console_style_t style)
-{
-	async_exch_t *exch = vp_exchange_begin(sess, vp);
-	int ret = async_req_1_0(exch, FB_VP_SET_STYLE, style);
-	vp_exchange_end(exch);
-	
-	return ret;
-}
-
-int fb_vp_putchar(async_sess_t *sess, vp_handle_t vp, sysarg_t col,
-    sysarg_t row, wchar_t ch)
-{
-	async_exch_t *exch = vp_exchange_begin(sess, vp);
-	int ret = async_req_3_0(exch, FB_VP_PUTCHAR, col, row, ch);
-	vp_exchange_end(exch);
-	
-	return ret;
-}
-
-int fb_vp_update(async_sess_t *sess, vp_handle_t vp, frontbuf_handle_t frontbuf)
-{
-	async_exch_t *exch = vp_exchange_begin(sess, vp);
-	int ret = async_req_1_0(exch, FB_VP_UPDATE, frontbuf);
-	vp_exchange_end(exch);
-	
-	return ret;
-}
-
-int fb_vp_damage(async_sess_t *sess, vp_handle_t vp, frontbuf_handle_t frontbuf,
-    sysarg_t col, sysarg_t row, sysarg_t cols, sysarg_t rows)
-{
-	async_exch_t *exch = vp_exchange_begin(sess, vp);
-	int ret = async_req_5_0(exch, FB_VP_DAMAGE, frontbuf, col, row,
-	    cols, rows);
-	vp_exchange_end(exch);
-	
-	return ret;
-}
-
-int fb_vp_imagemap_damage(async_sess_t *sess, vp_handle_t vp,
-    imagemap_handle_t imagemap, sysarg_t x, sysarg_t y, sysarg_t width,
-    sysarg_t height)
-{
-	async_exch_t *exch = vp_exchange_begin(sess, vp);
-	int ret = async_req_5_0(exch, FB_VP_IMAGEMAP_DAMAGE, imagemap, x, y,
-	    width, height);
-	vp_exchange_end(exch);
-	
-	return ret;
-}
-
-int fb_sequence_add_imagemap(async_sess_t *sess, sequence_handle_t sequence,
-    imagemap_handle_t imagemap)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	int ret = async_req_2_0(exch, FB_SEQUENCE_ADD_IMAGEMAP, sequence,
-	    imagemap);
-	async_exchange_end(exch);
-	
-	return ret;
-}
-
-int fb_vp_sequence_start(async_sess_t *sess, vp_handle_t vp,
-    sequence_handle_t sequence)
-{
-	async_exch_t *exch = vp_exchange_begin(sess, vp);
-	int ret = async_req_1_0(exch, FB_VP_SEQUENCE_START, sequence);
-	vp_exchange_end(exch);
-	
-	return ret;
-}
-
-/** @}
- */
Index: pace/lib/fb/fb.h
===================================================================
--- uspace/lib/fb/fb.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,136 +1,0 @@
-/*
- * Copyright (c) 2011 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 libc
- * @{
- */
-/** @file
- */
-
-#ifndef IMGMAP_FB_H_
-#define IMGMAP_FB_H_
-
-#include <sys/types.h>
-#include <async.h>
-#include <io/style.h>
-#include <io/console.h>
-#include <ipc/common.h>
-
-typedef enum {
-	/** Screen methods */
-	FB_GET_RESOLUTION = IPC_FIRST_USER_METHOD,
-	FB_YIELD,
-	FB_CLAIM,
-	FB_POINTER_UPDATE,
-	
-	/** Object methods */
-	FB_VP_CREATE,
-	FB_VP_DESTROY,
-	FB_FRONTBUF_CREATE,
-	FB_FRONTBUF_DESTROY,
-	FB_IMAGEMAP_CREATE,
-	FB_IMAGEMAP_DESTROY,
-	FB_SEQUENCE_CREATE,
-	FB_SEQUENCE_DESTROY,
-	FB_SEQUENCE_ADD_IMAGEMAP,
-	
-	/** Viewport stateful methods */
-	FB_VP_FOCUS,
-	FB_VP_CLEAR,
-	FB_VP_GET_DIMENSIONS,
-	FB_VP_GET_CAPS,
-	
-	/** Style methods (viewport specific) */
-	FB_VP_CURSOR_UPDATE,
-	FB_VP_SET_STYLE,
-	FB_VP_SET_COLOR,
-	FB_VP_SET_RGB_COLOR,
-	
-	/** Text methods (viewport specific) */
-	FB_VP_PUTCHAR,
-	FB_VP_UPDATE,
-	FB_VP_DAMAGE,
-	
-	/** Imagemap methods (viewport specific) */
-	FB_VP_IMAGEMAP_DAMAGE,
-	
-	/** Sequence methods (viewport specific) */
-	FB_VP_SEQUENCE_START,
-	FB_VP_SEQUENCE_STOP
-} fb_request_t;
-
-/** Forward declarations */
-struct screenbuffer;
-struct imgmap;
-
-typedef struct screenbuffer screenbuffer_t;
-typedef struct imgmap imgmap_t;
-
-typedef uint32_t pixel_t;
-
-typedef sysarg_t vp_handle_t;
-typedef sysarg_t frontbuf_handle_t;
-typedef sysarg_t imagemap_handle_t;
-typedef sysarg_t sequence_handle_t;
-
-extern int fb_get_resolution(async_sess_t *, sysarg_t *, sysarg_t *);
-extern int fb_yield(async_sess_t *);
-extern int fb_claim(async_sess_t *);
-extern int fb_pointer_update(async_sess_t *, sysarg_t, sysarg_t, bool);
-
-extern vp_handle_t fb_vp_create(async_sess_t *, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t);
-extern frontbuf_handle_t fb_frontbuf_create(async_sess_t *, screenbuffer_t *);
-extern imagemap_handle_t fb_imagemap_create(async_sess_t *, imgmap_t *);
-extern sequence_handle_t fb_sequence_create(async_sess_t *);
-
-extern int fb_vp_get_dimensions(async_sess_t *, vp_handle_t, sysarg_t *,
-    sysarg_t *);
-extern int fb_vp_get_caps(async_sess_t *, vp_handle_t, console_caps_t *);
-extern int fb_vp_clear(async_sess_t *, vp_handle_t);
-
-extern int fb_vp_cursor_update(async_sess_t *, vp_handle_t, frontbuf_handle_t);
-extern int fb_vp_set_style(async_sess_t *, vp_handle_t, console_style_t);
-
-extern int fb_vp_putchar(async_sess_t *, vp_handle_t, sysarg_t, sysarg_t,
-    wchar_t);
-extern int fb_vp_update(async_sess_t *, vp_handle_t, frontbuf_handle_t);
-extern int fb_vp_damage(async_sess_t *, vp_handle_t, frontbuf_handle_t,
-    sysarg_t, sysarg_t, sysarg_t, sysarg_t);
-
-extern int fb_vp_imagemap_damage(async_sess_t *, vp_handle_t, imagemap_handle_t,
-    sysarg_t, sysarg_t, sysarg_t, sysarg_t);
-
-extern int fb_sequence_add_imagemap(async_sess_t *, sequence_handle_t,
-    imagemap_handle_t);
-extern int fb_vp_sequence_start(async_sess_t *, vp_handle_t, sequence_handle_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/fb/imgmap.c
===================================================================
--- uspace/lib/fb/imgmap.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,548 +1,0 @@
-/*
- * Copyright (c) 2011 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 imgmap
- * @{
- */
-/**
- * @file
- */
-
-#include <stdlib.h>
-#include <byteorder.h>
-#include <align.h>
-#include <bool.h>
-#include <mem.h>
-#include <as.h>
-#include "imgmap.h"
-
-struct imgmap {
-	size_t size;
-	imgmap_flags_t flags;
-	sysarg_t width;
-	sysarg_t height;
-	visual_t visual;
-	uint8_t data[];
-};
-
-/** RGB conversion and mask functions.
- *
- * These functions write an RGB pixel value to a memory location
- * in a predefined format. The naming convention corresponds to
- * the names of the visuals and the format created by these functions.
- * The functions use the so called network bit order (i.e. big endian)
- * with respect to their names.
- */
-
-#define RED(pixel, bits)    (((pixel) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
-#define GREEN(pixel, bits)  (((pixel) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1))
-#define BLUE(pixel, bits)   (((pixel) >> (8 - (bits))) & ((1 << (bits)) - 1))
-
-void pixel2rgb_0888(void *dst, pixel_t pixel)
-{
-	*((uint32_t *) dst) = host2uint32_t_be(
-	    (RED(pixel, 8) << 16) | (GREEN(pixel, 8) << 8) | (BLUE(pixel, 8)));
-}
-
-void pixel2bgr_0888(void *dst, pixel_t pixel)
-{
-	*((uint32_t *) dst) = host2uint32_t_be(
-	    (BLUE(pixel, 8) << 16) | (GREEN(pixel, 8) << 8) | (RED(pixel, 8)));
-}
-
-void pixel2rgb_8880(void *dst, pixel_t pixel)
-{
-	*((uint32_t *) dst) = host2uint32_t_be(
-	    (RED(pixel, 8) << 24) | (GREEN(pixel, 8) << 16) | (BLUE(pixel, 8) << 8));
-}
-
-void pixel2bgr_8880(void *dst, pixel_t pixel)
-{
-	*((uint32_t *) dst) = host2uint32_t_be(
-	    (BLUE(pixel, 8) << 24) | (GREEN(pixel, 8) << 16) | (RED(pixel, 8) << 8));
-}
-
-void pixel2rgb_888(void *dst, pixel_t pixel)
-{
-	((uint8_t *) dst)[0] = RED(pixel, 8);
-	((uint8_t *) dst)[1] = GREEN(pixel, 8);
-	((uint8_t *) dst)[2] = BLUE(pixel, 8);
-}
-
-void pixel2bgr_888(void *dst, pixel_t pixel)
-{
-	((uint8_t *) dst)[0] = BLUE(pixel, 8);
-	((uint8_t *) dst)[1] = GREEN(pixel, 8);
-	((uint8_t *) dst)[2] = RED(pixel, 8);
-}
-
-void pixel2rgb_555_be(void *dst, pixel_t pixel)
-{
-	*((uint16_t *) dst) = host2uint16_t_be(
-	    (RED(pixel, 5) << 10) | (GREEN(pixel, 5) << 5) | (BLUE(pixel, 5)));
-}
-
-void pixel2rgb_555_le(void *dst, pixel_t pixel)
-{
-	*((uint16_t *) dst) = host2uint16_t_le(
-	    (RED(pixel, 5) << 10) | (GREEN(pixel, 5) << 5) | (BLUE(pixel, 5)));
-}
-
-void pixel2rgb_565_be(void *dst, pixel_t pixel)
-{
-	*((uint16_t *) dst) = host2uint16_t_be(
-	    (RED(pixel, 5) << 11) | (GREEN(pixel, 6) << 5) | (BLUE(pixel, 5)));
-}
-
-void pixel2rgb_565_le(void *dst, pixel_t pixel)
-{
-	*((uint16_t *) dst) = host2uint16_t_le(
-	    (RED(pixel, 5) << 11) | (GREEN(pixel, 6) << 5) | (BLUE(pixel, 5)));
-}
-
-void pixel2bgr_323(void *dst, pixel_t pixel)
-{
-	*((uint8_t *) dst) =
-	    ~((RED(pixel, 3) << 5) | (GREEN(pixel, 2) << 3) | BLUE(pixel, 3));
-}
-
-void pixel2gray_8(void *dst, pixel_t pixel)
-{
-	uint32_t red = RED(pixel, 8) * 5034375;
-	uint32_t green = GREEN(pixel, 8) * 9886846;
-	uint32_t blue = BLUE(pixel, 8) * 1920103;
-	
-	*((uint8_t *) dst) = (red + green + blue) >> 24;
-}
-
-void visual_mask_0888(void *dst, bool mask)
-{
-	pixel2bgr_0888(dst, mask ? 0xffffff : 0);
-}
-
-void visual_mask_8880(void *dst, bool mask)
-{
-	pixel2bgr_8880(dst, mask ? 0xffffff : 0);
-}
-
-void visual_mask_888(void *dst, bool mask)
-{
-	pixel2bgr_888(dst, mask ? 0xffffff : 0);
-}
-
-void visual_mask_555(void *dst, bool mask)
-{
-	pixel2rgb_555_be(dst, mask ? 0xffffff : 0);
-}
-
-void visual_mask_565(void *dst, bool mask)
-{
-	pixel2rgb_565_be(dst, mask ? 0xffffff : 0);
-}
-
-void visual_mask_323(void *dst, bool mask)
-{
-	pixel2bgr_323(dst, mask ? 0x0 : ~0x0);
-}
-
-void visual_mask_8(void *dst, bool mask)
-{
-	pixel2gray_8(dst, mask ? 0xffffff : 0);
-}
-
-pixel_t rgb_0888_2pixel(void *src)
-{
-	return (uint32_t_be2host(*((uint32_t *) src)) & 0xffffff);
-}
-
-pixel_t bgr_0888_2pixel(void *src)
-{
-	uint32_t val = uint32_t_be2host(*((uint32_t *) src));
-	return (((val & 0xff0000) >> 16) | (val & 0xff00) | ((val & 0xff) << 16));
-}
-
-pixel_t rgb_8880_2pixel(void *src)
-{
-	return (uint32_t_be2host(*((uint32_t *) src)) >> 8);
-}
-
-pixel_t bgr_8880_2pixel(void *src)
-{
-	uint32_t val = uint32_t_be2host(*((uint32_t *) src));
-	return (((val & 0xff000000) >> 24) | ((val & 0xff0000) >> 8) | ((val & 0xff00) << 8));
-}
-
-pixel_t rgb_888_2pixel(void *src)
-{
-	uint8_t red = ((uint8_t *) src)[0];
-	uint8_t green = ((uint8_t *) src)[1];
-	uint8_t blue = ((uint8_t *) src)[2];
-	
-	return ((red << 16) | (green << 8) | (blue));
-}
-
-pixel_t bgr_888_2pixel(void *src)
-{
-	uint8_t blue = ((uint8_t *) src)[0];
-	uint8_t green = ((uint8_t *) src)[1];
-	uint8_t red = ((uint8_t *) src)[2];
-	
-	return ((red << 16) | (green << 8) | (blue));
-}
-
-pixel_t rgb_555_be_2pixel(void *src)
-{
-	uint16_t val = uint16_t_be2host(*((uint16_t *) src));
-	return (((val & 0x7c00) << 9) | ((val & 0x3e0) << 6) | ((val & 0x1f) << 3));
-}
-
-pixel_t rgb_555_le_2pixel(void *src)
-{
-	uint16_t val = uint16_t_le2host(*((uint16_t *) src));
-	return (((val & 0x7c00) << 9) | ((val & 0x3e0) << 6) | ((val & 0x1f) << 3));
-}
-
-pixel_t rgb_565_be_2pixel(void *src)
-{
-	uint16_t val = uint16_t_be2host(*((uint16_t *) src));
-	return (((val & 0xf800) << 8) | ((val & 0x7e0) << 5) | ((val & 0x1f) << 3));
-}
-
-pixel_t rgb_565_le_2pixel(void *src)
-{
-	uint16_t val = uint16_t_le2host(*((uint16_t *) src));
-	return (((val & 0xf800) << 8) | ((val & 0x7e0) << 5) | ((val & 0x1f) << 3));
-}
-
-pixel_t bgr_323_2pixel(void *src)
-{
-	uint8_t val = ~(*((uint8_t *) src));
-	return (((val & 0xe0) << 16) | ((val & 0x18) << 11) | ((val & 0x7) << 5));
-}
-
-pixel_t gray_8_2pixel(void *src)
-{
-	uint8_t val = *((uint8_t *) src);
-	return ((val << 16) | (val << 8) | (val));
-}
-
-typedef struct {
-	uint8_t id_length;
-	uint8_t cmap_type;
-	uint8_t img_type;
-	
-	uint16_t cmap_first_entry;
-	uint16_t cmap_entries;
-	uint8_t cmap_bpp;
-	
-	uint16_t startx;
-	uint16_t starty;
-	uint16_t width;
-	uint16_t height;
-	uint8_t img_bpp;
-	uint8_t img_descr;
-} __attribute__((packed)) tga_header_t;
-
-typedef enum {
-	CMAP_NOT_PRESENT = 0,
-	CMAP_PRESENT = 1,
-	CMAP_RESERVED_START = 2,
-	CMAP_PRIVATE_START = 128
-} cmap_type_t;
-
-typedef enum {
-	IMG_EMTPY = 0,
-	IMG_CMAP = 1,
-	IMG_BGRA = 2,
-	IMG_GRAY = 3,
-	IMG_CMAP_RLE = 9,
-	IMG_BGRA_RLE = 10,
-	IMG_GRAY_RLE = 11
-} img_type_t;
-
-typedef struct {
-	cmap_type_t cmap_type;
-	img_type_t img_type;
-	
-	uint16_t cmap_first_entry;
-	uint16_t cmap_entries;
-	uint8_t cmap_bpp;
-	
-	uint16_t startx;
-	uint16_t starty;
-	uint16_t width;
-	uint16_t height;
-	uint8_t img_bpp;
-	uint8_t img_alpha_bpp;
-	uint8_t img_alpha_dir;
-	
-	void *id_data;
-	size_t id_length;
-	
-	void *cmap_data;
-	size_t cmap_length;
-	
-	void *img_data;
-	size_t img_length;
-} tga_t;
-
-/** Decode Truevision TGA header
- *
- * @param[in]  data Memory representation of TGA.
- * @param[in]  size Size of the representation (in bytes).
- * @param[out] tga  Decoded TGA.
- *
- * @return True on succesful decoding.
- * @return False on failure.
- *
- */
-static bool decode_tga_header(void *data, size_t size, tga_t *tga)
-{
-	/* Header sanity check */
-	if (size < sizeof(tga_header_t))
-		return false;
-	
-	tga_header_t *head = (tga_header_t *) data;
-	
-	/* Image ID field */
-	tga->id_data = data + sizeof(tga_header_t);
-	tga->id_length = head->id_length;
-	
-	if (size < sizeof(tga_header_t) + tga->id_length)
-		return false;
-	
-	/* Color map type */
-	tga->cmap_type = head->cmap_type;
-	
-	/* Image type */
-	tga->img_type = head->img_type;
-	
-	/* Color map specification */
-	tga->cmap_first_entry = uint16_t_le2host(head->cmap_first_entry);
-	tga->cmap_entries = uint16_t_le2host(head->cmap_entries);
-	tga->cmap_bpp = head->cmap_bpp;
-	tga->cmap_data = tga->id_data + tga->id_length;
-	tga->cmap_length = ALIGN_UP(tga->cmap_entries * tga->cmap_bpp, 8) >> 3;
-	
-	if (size < sizeof(tga_header_t) + tga->id_length +
-	    tga->cmap_length)
-		return false;
-	
-	/* Image specification */
-	tga->startx = uint16_t_le2host(head->startx);
-	tga->starty = uint16_t_le2host(head->starty);
-	tga->width = uint16_t_le2host(head->width);
-	tga->height = uint16_t_le2host(head->height);
-	tga->img_bpp = head->img_bpp;
-	tga->img_alpha_bpp = head->img_descr & 0x0f;
-	tga->img_alpha_dir = (head->img_descr & 0xf0) >> 4;
-	tga->img_data = tga->cmap_data + tga->cmap_length;
-	tga->img_length = ALIGN_UP(tga->width * tga->height * tga->img_bpp, 8) >> 3;
-	
-	if (size < sizeof(tga_header_t) + tga->id_length +
-	    tga->cmap_length + tga->img_length)
-		return false;
-	
-	return true;
-}
-
-void imgmap_put_pixel(imgmap_t *imgmap, sysarg_t x, sysarg_t y, pixel_t pixel)
-{
-	if ((x >= imgmap->width) || (y >= imgmap->height))
-		return;
-	
-	size_t offset = y * imgmap->width + x;
-	
-	switch (imgmap->visual) {
-	case VISUAL_RGB_0_8_8_8:
-		pixel2rgb_0888(((uint32_t *) imgmap->data) + offset, pixel);
-		break;
-	default:
-		break;
-	}
-}
-
-pixel_t imgmap_get_pixel(imgmap_t *imgmap, sysarg_t x, sysarg_t y)
-{
-	if ((x >= imgmap->width) || (y >= imgmap->height))
-		return 0;
-	
-	size_t offset = y * imgmap->width + x;
-	
-	switch (imgmap->visual) {
-	case VISUAL_RGB_0_8_8_8:
-		return rgb_0888_2pixel(((uint32_t *) imgmap->data) + offset);
-	default:
-		return 0;
-	}
-}
-
-imgmap_t *imgmap_create(sysarg_t width, sysarg_t height, visual_t visual,
-    imgmap_flags_t flags)
-{
-	size_t bsize;
-	
-	switch (visual) {
-	case VISUAL_RGB_0_8_8_8:
-		bsize = (width * height) << 2;
-		break;
-	default:
-		return NULL;
-	}
-	
-	size_t size = sizeof(imgmap_t) + bsize;
-	imgmap_t *imgmap;
-	
-	if ((flags & IMGMAP_FLAG_SHARED) == IMGMAP_FLAG_SHARED) {
-		imgmap = (imgmap_t *) as_area_create(AS_AREA_ANY, size,
-		    AS_AREA_READ | AS_AREA_WRITE);
-		if (imgmap == AS_MAP_FAILED)
-			return NULL;
-	} else {
-		imgmap = (imgmap_t *) malloc(size);
-		if (imgmap == NULL)
-			return NULL;
-	}
-	
-	imgmap->size = size;
-	imgmap->flags = flags;
-	imgmap->width = width;
-	imgmap->height = height;
-	imgmap->visual = visual;
-	
-	memset(imgmap->data, 0, bsize);
-	
-	return imgmap;
-}
-
-/** Decode Truevision TGA format
- *
- * Decode Truevision TGA format and create an image map
- * from it. The supported variants of TGA are currently
- * limited to uncompressed 24 bit true-color images without
- * alpha channel.
- *
- * @param[in] data  Memory representation of TGA.
- * @param[in] size  Size of the representation (in bytes).
- * @param[in] flags Image map creation flags.
- *
- * @return Newly allocated image map.
- * @return NULL on error or unsupported format.
- *
- */
-imgmap_t *imgmap_decode_tga(void *data, size_t size, imgmap_flags_t flags)
-{
-	tga_t tga;
-	if (!decode_tga_header(data, size, &tga))
-		return NULL;
-	
-	/*
-	 * Check for unsupported features.
-	 */
-	
-	switch (tga.cmap_type) {
-	case CMAP_NOT_PRESENT:
-		break;
-	default:
-		/* Unsupported */
-		return NULL;
-	}
-	
-	switch (tga.img_type) {
-	case IMG_BGRA:
-		if (tga.img_bpp != 24)
-			return NULL;
-		break;
-	case IMG_GRAY:
-		if (tga.img_bpp != 8)
-			return NULL;
-		break;
-	default:
-		/* Unsupported */
-		return NULL;
-	}
-	
-	if (tga.img_alpha_bpp != 0)
-		return NULL;
-	
-	sysarg_t twidth = tga.startx + tga.width;
-	sysarg_t theight = tga.starty + tga.height;
-	
-	imgmap_t *imgmap = imgmap_create(twidth, theight, VISUAL_RGB_0_8_8_8,
-	    flags);
-	if (imgmap == NULL)
-		return NULL;
-	
-	/*
-	 * TGA is encoded in a bottom-up manner, the true-color
-	 * variant is in BGR 8:8:8 encoding.
-	 */
-	
-	switch (tga.img_type) {
-	case IMG_BGRA:
-		for (sysarg_t y = tga.starty; y < theight; y++) {
-			for (sysarg_t x = tga.startx; x < twidth; x++) {
-				size_t offset =
-				    ((y - tga.starty) * tga.width + (x - tga.startx)) * 3;
-				
-				pixel_t pixel =
-				    bgr_888_2pixel(((uint8_t *) tga.img_data) + offset);
-				imgmap_put_pixel(imgmap, x, theight - y - 1, pixel);
-			}
-		}
-		break;
-	case IMG_GRAY:
-		for (sysarg_t y = tga.starty; y < theight; y++) {
-			for (sysarg_t x = tga.startx; x < twidth; x++) {
-				size_t offset =
-				    (y - tga.starty) * tga.width + (x - tga.startx);
-				
-				pixel_t pixel =
-				    gray_8_2pixel(((uint8_t *) tga.img_data) + offset);
-				imgmap_put_pixel(imgmap, x, theight - y - 1, pixel);
-			}
-		}
-		break;
-	default:
-		break;
-	}
-	
-	return imgmap;
-}
-
-void imgmap_get_resolution(imgmap_t *imgmap, sysarg_t *width, sysarg_t *height)
-{
-	assert(width);
-	assert(height);
-	
-	*width = imgmap->width;
-	*height = imgmap->height;
-}
-
-/** @}
- */
Index: pace/lib/fb/imgmap.h
===================================================================
--- uspace/lib/fb/imgmap.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,102 +1,0 @@
-/*
- * Copyright (c) 2011 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 imgmap
- * @{
- */
-/**
- * @file
- */
-
-#ifndef IMGMAP_IMGMAP_H_
-#define IMGMAP_IMGMAP_H_
-
-#include <sys/types.h>
-#include <abi/fb/visuals.h>
-#include <bool.h>
-#include "fb.h"
-
-typedef enum {
-	IMGMAP_FLAG_NONE = 0,
-	IMGMAP_FLAG_SHARED = 1
-} imgmap_flags_t;
-
-/** Function to render a pixel. */
-typedef void (*pixel2visual_t)(void *, pixel_t);
-
-/** Function to render a bit mask. */
-typedef void (*visual_mask_t)(void *, bool);
-
-/** Function to retrieve a pixel. */
-typedef pixel_t (*visual2pixel_t)(void *);
-
-extern void pixel2rgb_0888(void *, pixel_t);
-extern void pixel2bgr_0888(void *, pixel_t);
-extern void pixel2rgb_8880(void *, pixel_t);
-extern void pixel2bgr_8880(void *, pixel_t);
-extern void pixel2rgb_888(void *, pixel_t);
-extern void pixel2bgr_888(void *, pixel_t);
-extern void pixel2rgb_555_be(void *, pixel_t);
-extern void pixel2rgb_555_le(void *, pixel_t);
-extern void pixel2rgb_565_be(void *, pixel_t);
-extern void pixel2rgb_565_le(void *, pixel_t);
-extern void pixel2bgr_323(void *, pixel_t);
-extern void pixel2gray_8(void *, pixel_t);
-
-extern void visual_mask_0888(void *, bool);
-extern void visual_mask_8880(void *, bool);
-extern void visual_mask_888(void *, bool);
-extern void visual_mask_555(void *, bool);
-extern void visual_mask_565(void *, bool);
-extern void visual_mask_323(void *, bool);
-extern void visual_mask_8(void *, bool);
-
-extern pixel_t rgb_0888_2pixel(void *);
-extern pixel_t bgr_0888_2pixel(void *);
-extern pixel_t rgb_8880_2pixel(void *);
-extern pixel_t bgr_8880_2pixel(void *);
-extern pixel_t rgb_888_2pixel(void *);
-extern pixel_t bgr_888_2pixel(void *);
-extern pixel_t rgb_555_be_2pixel(void *);
-extern pixel_t rgb_555_le_2pixel(void *);
-extern pixel_t rgb_565_be_2pixel(void *);
-extern pixel_t rgb_565_le_2pixel(void *);
-extern pixel_t bgr_323_2pixel(void *);
-extern pixel_t gray_8_2pixel(void *);
-
-extern imgmap_t *imgmap_create(sysarg_t, sysarg_t, visual_t, imgmap_flags_t);
-extern void imgmap_put_pixel(imgmap_t *, sysarg_t, sysarg_t, pixel_t);
-extern pixel_t imgmap_get_pixel(imgmap_t *, sysarg_t, sysarg_t);
-
-extern imgmap_t *imgmap_decode_tga(void *, size_t, imgmap_flags_t);
-extern void imgmap_get_resolution(imgmap_t *, sysarg_t *, sysarg_t *);
-
-#endif
-
-/** @}
- */
Index: pace/lib/fb/screenbuffer.c
===================================================================
--- uspace/lib/fb/screenbuffer.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,393 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * 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 console
- * @{
- */
-/** @file
- */
-
-#include <io/style.h>
-#include <malloc.h>
-#include <unistd.h>
-#include <assert.h>
-#include <bool.h>
-#include <as.h>
-#include "screenbuffer.h"
-
-/** Structure for buffering state of one virtual console.
- *
- */
-struct screenbuffer {
-	size_t size;                /**< Structure size */
-	screenbuffer_flag_t flags;  /**< Screenbuffer flags */
-	
-	sysarg_t cols;              /**< Number of columns */
-	sysarg_t rows;              /**< Number of rows */
-	
-	sysarg_t col;               /**< Current column */
-	sysarg_t row;               /**< Current row */
-	bool cursor_visible;        /**< Cursor visibility */
-	
-	char_attrs_t attrs;         /**< Current attributes */
-	
-	sysarg_t top_row;           /**< The first row in the cyclic buffer */
-	charfield_t data[];         /**< Screen contents (cyclic buffer) */
-};
-
-/** Create a screenbuffer.
- *
- * @param[in] cols  Number of columns.
- * @param[in] rows  Number of rows.
- * @param[in] flags Screenbuffer flags.
- *
- * @return New screenbuffer.
- * @return NULL on failure.
- *
- */
-screenbuffer_t *screenbuffer_create(sysarg_t cols, sysarg_t rows,
-    screenbuffer_flag_t flags)
-{
-	size_t size =
-	    sizeof(screenbuffer_t) + cols * rows * sizeof(charfield_t);
-	screenbuffer_t *scrbuf;
-	
-	if ((flags & SCREENBUFFER_FLAG_SHARED) == SCREENBUFFER_FLAG_SHARED) {
-		scrbuf = (screenbuffer_t *) as_area_create(AS_AREA_ANY, size,
-		    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
-		if (scrbuf == AS_MAP_FAILED)
-			return NULL;
-	} else {
-		scrbuf = (screenbuffer_t *) malloc(size);
-		if (scrbuf == NULL)
-			return NULL;
-	}
-	
-	scrbuf->size = size;
-	scrbuf->flags = flags;
-	scrbuf->cols = cols;
-	scrbuf->rows = rows;
-	scrbuf->cursor_visible = false;
-	
-	scrbuf->attrs.type = CHAR_ATTR_STYLE;
-	scrbuf->attrs.val.style = STYLE_NORMAL;
-	
-	scrbuf->top_row = 0;
-	screenbuffer_clear(scrbuf);
-	
-	return scrbuf;
-}
-
-/** Return keyfield by coordinates
- *
- * The back buffer is organized as a cyclic buffer.
- * Therefore we must take into account the topmost column.
- *
- * @param scrbuf Screenbuffer
- * @param col    Column position on screen
- * @param row    Row position on screen
- *
- * @return Keyfield structure on (row, col)
- *
- */
-charfield_t *screenbuffer_field_at(screenbuffer_t *scrbuf, sysarg_t col,
-    sysarg_t row)
-{
-	return scrbuf->data +
-	    ((row + scrbuf->top_row) % scrbuf->rows) * scrbuf->cols +
-	    col;
-}
-
-bool screenbuffer_cursor_at(screenbuffer_t *scrbuf, sysarg_t col, sysarg_t row)
-{
-	return ((scrbuf->cursor_visible) && (scrbuf->col == col) &&
-	    (scrbuf->row == row));
-}
-
-sysarg_t screenbuffer_get_top_row(screenbuffer_t *scrbuf)
-{
-	return scrbuf->top_row;
-}
-
-static sysarg_t screenbuffer_update_rows(screenbuffer_t *scrbuf)
-{
-	if (scrbuf->row == scrbuf->rows) {
-		scrbuf->row = scrbuf->rows - 1;
-		scrbuf->top_row = (scrbuf->top_row + 1) % scrbuf->rows;
-		screenbuffer_clear_row(scrbuf, scrbuf->row);
-		
-		return scrbuf->rows;
-	}
-	
-	return 2;
-}
-
-static sysarg_t screenbuffer_update_cols(screenbuffer_t *scrbuf)
-{
-	/* Column overflow */
-	if (scrbuf->col == scrbuf->cols) {
-		scrbuf->col = 0;
-		scrbuf->row++;
-		return screenbuffer_update_rows(scrbuf);
-	}
-	
-	return 1;
-}
-
-/** Store one character to screenbuffer.
- *
- * Its position is determined by scrbuf->col
- * and scrbuf->row.
- *
- * @param scrbuf Screenbuffer.
- * @param ch     Character to store.
- * @param update Update coordinates.
- *
- * @return Number of rows which have been affected. In usual
- *         situations this is 1. If the current position was
- *         updated to a new row, this value is 2.
- *
- */
-sysarg_t screenbuffer_putchar(screenbuffer_t *scrbuf, wchar_t ch, bool update)
-{
-	assert(scrbuf->col < scrbuf->cols);
-	assert(scrbuf->row < scrbuf->rows);
-	
-	charfield_t *field =
-	    screenbuffer_field_at(scrbuf, scrbuf->col, scrbuf->row);
-	
-	field->ch = ch;
-	field->attrs = scrbuf->attrs;
-	field->flags |= CHAR_FLAG_DIRTY;
-	
-	if (update) {
-		scrbuf->col++;
-		return screenbuffer_update_cols(scrbuf);
-	}
-	
-	return 1;
-}
-
-/** Jump to a new row in screenbuffer.
- *
- * @param scrbuf Screenbuffer.
- *
- * @return Number of rows which have been affected. In usual
- *         situations this is 2 (the original row and the new
- *         row).
- *
- */
-sysarg_t screenbuffer_newline(screenbuffer_t *scrbuf)
-{
-	assert(scrbuf->col < scrbuf->cols);
-	assert(scrbuf->row < scrbuf->rows);
-	
-	scrbuf->col = 0;
-	scrbuf->row++;
-	
-	return screenbuffer_update_rows(scrbuf);
-}
-
-/** Jump to a new row in screenbuffer.
- *
- * @param scrbuf   Screenbuffer.
- * @param tab_size Tab size.
- *
- * @return Number of rows which have been affected. In usual
- *         situations this is 1. If the current position was
- *         updated to a new row, this value is 2.
- *
- */
-sysarg_t screenbuffer_tabstop(screenbuffer_t *scrbuf, sysarg_t tab_size)
-{
-	assert(scrbuf->col < scrbuf->cols);
-	assert(scrbuf->row < scrbuf->rows);
-	
-	sysarg_t spaces = tab_size - scrbuf->cols % tab_size;
-	sysarg_t flush = 1;
-	
-	for (sysarg_t i = 0; i < spaces; i++)
-		flush += screenbuffer_putchar(scrbuf, ' ', true) - 1;
-	
-	return flush;
-}
-
-/** Jump to the previous character in screenbuffer.
- *
- * Currently no scrollback is supported.
- *
- * @param scrbuf Screenbuffer.
- *
- * @return Number of rows which have been affected. In usual
- *         situations this is 1. If the current position was
- *         updated to the previous row, this value is 2.
- * @return 0 if no backspace is possible.
- *
- */
-sysarg_t screenbuffer_backspace(screenbuffer_t *scrbuf)
-{
-	assert(scrbuf->col < scrbuf->cols);
-	assert(scrbuf->row < scrbuf->rows);
-	
-	if ((scrbuf->col == 0) && (scrbuf->row == 0))
-		return 0;
-	
-	if (scrbuf->col == 0) {
-		scrbuf->col = scrbuf->cols - 1;
-		scrbuf->row--;
-		
-		screenbuffer_putchar(scrbuf, ' ', false);
-		return 2;
-	}
-	
-	scrbuf->col--;
-	screenbuffer_putchar(scrbuf, ' ', false);
-	return 1;
-}
-
-/** Clear the screenbuffer.
- *
- * @param scrbuf Screenbuffer.
- *
- */
-void screenbuffer_clear(screenbuffer_t *scrbuf)
-{
-	for (size_t pos = 0; pos < (scrbuf->cols * scrbuf->rows); pos++) {
-		scrbuf->data[pos].ch = 0;
-		scrbuf->data[pos].attrs = scrbuf->attrs;
-		scrbuf->data[pos].flags = CHAR_FLAG_DIRTY;
-	}
-	
-	scrbuf->col = 0;
-	scrbuf->row = 0;
-}
-
-/** Update current screenbuffer coordinates
- *
- * @param scrbuf Screenbuffer.
- * @param col    New column.
- * @param row    New row.
- *
- */
-void screenbuffer_set_cursor(screenbuffer_t *scrbuf, sysarg_t col, sysarg_t row)
-{
-	scrbuf->col = col;
-	scrbuf->row = row;
-}
-
-void screenbuffer_set_cursor_visibility(screenbuffer_t *scrbuf, bool visible)
-{
-	scrbuf->cursor_visible = visible;
-}
-
-/** Get current screenbuffer coordinates
- *
- * @param scrbuf Screenbuffer.
- * @param col    Column.
- * @param row    Row.
- *
- */
-void screenbuffer_get_cursor(screenbuffer_t *scrbuf, sysarg_t *col,
-    sysarg_t *row)
-{
-	assert(col);
-	assert(row);
-	
-	*col = scrbuf->col;
-	*row = scrbuf->row;
-}
-
-bool screenbuffer_get_cursor_visibility(screenbuffer_t *scrbuf)
-{
-	return scrbuf->cursor_visible;
-}
-
-/** Clear one buffer row.
- *
- * @param scrbuf Screenbuffer.
- * @param row    Row to clear.
- *
- */
-void screenbuffer_clear_row(screenbuffer_t *scrbuf, sysarg_t row)
-{
-	for (sysarg_t col = 0; col < scrbuf->cols; col++) {
-		charfield_t *field =
-		    screenbuffer_field_at(scrbuf, col, row);
-		
-		field->ch = 0;
-		field->attrs = scrbuf->attrs;
-		field->flags |= CHAR_FLAG_DIRTY;
-	}
-}
-
-/** Set screenbuffer style.
- *
- * @param scrbuf Screenbuffer.
- * @param style  Style.
- *
- */
-void screenbuffer_set_style(screenbuffer_t *scrbuf, console_style_t style)
-{
-	scrbuf->attrs.type = CHAR_ATTR_STYLE;
-	scrbuf->attrs.val.style = style;
-}
-
-/** Set screenbuffer color.
- *
- * @param scrbuf  Screenbuffer.
- * @param bgcolor Background color.
- * @param fgcolor Foreground color.
- * @param attr    Color attribute.
- *
- */
-void screenbuffer_set_color(screenbuffer_t *scrbuf, console_color_t bgcolor,
-    console_color_t fgcolor, console_color_attr_t attr)
-{
-	scrbuf->attrs.type = CHAR_ATTR_INDEX;
-	scrbuf->attrs.val.index.bgcolor = bgcolor;
-	scrbuf->attrs.val.index.fgcolor = fgcolor;
-	scrbuf->attrs.val.index.attr = attr;
-}
-
-/** Set screenbuffer RGB color.
- *
- * @param scrbuf  Screenbuffer.
- * @param bgcolor Background color.
- * @param fgcolor Foreground color.
- *
- */
-void screenbuffer_set_rgb_color(screenbuffer_t *scrbuf, pixel_t bgcolor,
-    pixel_t fgcolor)
-{
-	scrbuf->attrs.type = CHAR_ATTR_RGB;
-	scrbuf->attrs.val.rgb.bgcolor = bgcolor;
-	scrbuf->attrs.val.rgb.fgcolor = fgcolor;
-}
-
-/** @}
- */
Index: pace/lib/fb/screenbuffer.h
===================================================================
--- uspace/lib/fb/screenbuffer.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,147 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * 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 IMGMAP_SCREENBUFFER_H__
-#define IMGMAP_SCREENBUFFER_H__
-
-#include <sys/types.h>
-#include <bool.h>
-#include <io/color.h>
-#include <io/style.h>
-#include "fb.h"
-
-typedef enum {
-	SCREENBUFFER_FLAG_NONE = 0,
-	SCREENBUFFER_FLAG_SHARED = 1
-} screenbuffer_flag_t;
-
-typedef enum {
-	CHAR_ATTR_STYLE,
-	CHAR_ATTR_INDEX,
-	CHAR_ATTR_RGB
-} char_attr_type_t;
-
-typedef enum {
-	CHAR_FLAG_NONE = 0,
-	CHAR_FLAG_DIRTY = 1
-} char_flags_t;
-
-typedef struct {
-	console_color_t bgcolor;
-	console_color_t fgcolor;
-	console_color_attr_t attr;
-} char_attr_index_t;
-
-typedef struct {
-	pixel_t bgcolor;  /**< Background color */
-	pixel_t fgcolor;  /**< Foreground color */
-} char_attr_rgb_t;
-
-typedef union {
-	console_style_t style;
-	char_attr_index_t index;
-	char_attr_rgb_t rgb;
-} char_attr_val_t;
-
-typedef struct {
-	char_attr_type_t type;
-	char_attr_val_t val;
-} char_attrs_t;
-
-/** One field on screen. It contain one character and its attributes. */
-typedef struct {
-	wchar_t ch;          /**< Character itself */
-	char_attrs_t attrs;  /**< Character attributes */
-	char_flags_t flags;  /**< Character flags */
-} charfield_t;
-
-/** Compare two sets of attributes.
- *
- * @param a1 First attribute.
- * @param a2 Second attribute.
- *
- * @return True on equality
- *
- */
-static inline bool attrs_same(char_attrs_t a1, char_attrs_t a2)
-{
-	if (a1.type != a2.type)
-		return false;
-	
-	switch (a1.type) {
-	case CHAR_ATTR_STYLE:
-		return (a1.val.style == a2.val.style);
-	case CHAR_ATTR_INDEX:
-		return (a1.val.index.bgcolor == a2.val.index.bgcolor)
-		    && (a1.val.index.fgcolor == a2.val.index.fgcolor)
-		    && (a1.val.index.attr == a2.val.index.attr);
-	case CHAR_ATTR_RGB:
-		return (a1.val.rgb.bgcolor == a2.val.rgb.bgcolor)
-		    && (a1.val.rgb.fgcolor == a2.val.rgb.fgcolor);
-	}
-	
-	return false;
-}
-
-extern screenbuffer_t *screenbuffer_create(sysarg_t, sysarg_t,
-    screenbuffer_flag_t);
-
-extern charfield_t *screenbuffer_field_at(screenbuffer_t *, sysarg_t, sysarg_t);
-extern bool screenbuffer_cursor_at(screenbuffer_t *, sysarg_t, sysarg_t);
-
-extern sysarg_t screenbuffer_get_top_row(screenbuffer_t *);
-
-extern sysarg_t screenbuffer_putchar(screenbuffer_t *, wchar_t, bool);
-extern sysarg_t screenbuffer_newline(screenbuffer_t *);
-extern sysarg_t screenbuffer_tabstop(screenbuffer_t *, sysarg_t);
-extern sysarg_t screenbuffer_backspace(screenbuffer_t *);
-
-extern void screenbuffer_clear(screenbuffer_t *);
-extern void screenbuffer_clear_row(screenbuffer_t *, sysarg_t);
-
-extern void screenbuffer_set_cursor(screenbuffer_t *, sysarg_t, sysarg_t);
-extern void screenbuffer_set_cursor_visibility(screenbuffer_t *, bool);
-extern bool screenbuffer_get_cursor_visibility(screenbuffer_t *);
-
-extern void screenbuffer_get_cursor(screenbuffer_t *, sysarg_t *, sysarg_t *);
-
-extern void screenbuffer_set_style(screenbuffer_t *, console_style_t);
-extern void screenbuffer_set_color(screenbuffer_t *, console_color_t,
-    console_color_t, console_color_attr_t);
-extern void screenbuffer_set_rgb_color(screenbuffer_t *, pixel_t, pixel_t);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/fs/libfs.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -631,12 +631,7 @@
 						async_answer_0(rid, rc);
 					} else {
-						aoff64_t size = ops->size_get(fn);
-						async_answer_5(rid, fs_handle,
-						    service_id,
-						    ops->index_get(fn),
-						    LOWER32(size),
-						    UPPER32(size),
-						    ops->lnkcnt_get(fn));
-						(void) ops->node_put(fn);
+						(void) ops->node_put(cur);
+						cur = fn;
+						goto out_with_answer;
 					}
 				} else
@@ -715,12 +710,7 @@
 					async_answer_0(rid, rc);
 				} else {
-					aoff64_t size = ops->size_get(fn);
-					async_answer_5(rid, fs_handle,
-					    service_id,
-					    ops->index_get(fn),
-					    LOWER32(size),
-					    UPPER32(size),
-					    ops->lnkcnt_get(fn));
-					(void) ops->node_put(fn);
+					(void) ops->node_put(cur);
+					cur = fn;
+					goto out_with_answer;
 				}
 			} else
Index: uspace/lib/graph/Makefile
===================================================================
--- uspace/lib/graph/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/graph/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2011 Petr Koupy
+# 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 = ../..
+LIBRARY = libgraph
+SLIBRARY = libgraph.so.0.0
+LSONAME = libgraph.so0
+
+SOURCES = \
+	graph.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/graph/graph.c
===================================================================
--- uspace/lib/graph/graph.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/graph/graph.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,650 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 graph
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <as.h>
+#include "graph.h"
+
+#define NAMESPACE         "graphemu"
+#define VISUALIZER_NAME   "vsl"
+#define RENDERER_NAME     "rnd"
+
+static sysarg_t namespace_idx = 0;
+static sysarg_t visualizer_idx = 0;
+static sysarg_t renderer_idx = 0;
+
+static LIST_INITIALIZE(visualizer_list);
+static LIST_INITIALIZE(renderer_list);
+
+static FIBRIL_MUTEX_INITIALIZE(visualizer_list_mtx);
+static FIBRIL_MUTEX_INITIALIZE(renderer_list_mtx);
+
+visualizer_t *graph_alloc_visualizer(void)
+{
+	visualizer_t *vs = (visualizer_t *) malloc(sizeof(visualizer_t));
+	if (vs == NULL) {
+		return NULL;
+	}
+	
+	return vs;
+}
+
+renderer_t *graph_alloc_renderer(void)
+{
+	// TODO
+	renderer_t *rnd = (renderer_t *) malloc(sizeof(renderer_t));
+	if (rnd == NULL) {
+		return NULL;
+	}
+
+	return rnd;
+}
+
+void graph_init_visualizer(visualizer_t *vs)
+{
+	link_initialize(&vs->link);
+	atomic_set(&vs->ref_cnt, 0);
+	vs->notif_sess = NULL;
+	fibril_mutex_initialize(&vs->mode_mtx);
+	list_initialize(&vs->modes);
+	vs->mode_set = false;
+	vs->cells.data = NULL;
+	vs->dev_ctx = NULL;
+}
+
+void graph_init_renderer(renderer_t *rnd)
+{
+	// TODO
+	link_initialize(&rnd->link);
+	atomic_set(&rnd->ref_cnt, 0);
+}
+
+int graph_register_visualizer(visualizer_t *vs)
+{
+	int rc = EOK;
+	
+	char node[LOC_NAME_MAXLEN + 1];
+	snprintf(node, LOC_NAME_MAXLEN, "%s%zu/%s%zu", NAMESPACE,
+	    namespace_idx, VISUALIZER_NAME, visualizer_idx++);
+
+	category_id_t cat;
+	rc = loc_category_get_id("visualizer", &cat, 0);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = loc_service_register(node, &vs->reg_svc_handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = loc_service_add_to_cat(vs->reg_svc_handle, cat);
+	if (rc != EOK) {
+		loc_service_unregister(vs->reg_svc_handle);
+		return rc;
+	}
+
+	fibril_mutex_lock(&visualizer_list_mtx);
+	list_append(&vs->link, &visualizer_list);
+	fibril_mutex_unlock(&visualizer_list_mtx);
+
+	return rc;
+}
+
+int graph_register_renderer(renderer_t *rnd)
+{
+	int rc = EOK;
+
+	char node[LOC_NAME_MAXLEN + 1];
+	snprintf(node, LOC_NAME_MAXLEN, "%s%zu/%s%zu", NAMESPACE,
+	    namespace_idx, RENDERER_NAME, renderer_idx++);
+
+	category_id_t cat;
+	rc = loc_category_get_id("renderer", &cat, 0);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = loc_service_register(node, &rnd->reg_svc_handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = loc_service_add_to_cat(rnd->reg_svc_handle, cat);
+	if (rc != EOK) {
+		loc_service_unregister(rnd->reg_svc_handle);
+		return rc;
+	}
+
+	fibril_mutex_lock(&renderer_list_mtx);
+	list_append(&rnd->link, &renderer_list);
+	fibril_mutex_unlock(&renderer_list_mtx);
+
+	return rc;
+}
+
+visualizer_t *graph_get_visualizer(sysarg_t handle)
+{
+	visualizer_t *vs = NULL;
+
+	fibril_mutex_lock(&visualizer_list_mtx);
+	list_foreach(visualizer_list, link) {
+		visualizer_t *cur = list_get_instance(link, visualizer_t, link);
+		if (cur->reg_svc_handle == handle) {
+			vs = cur;
+			break;
+		}
+	}
+	fibril_mutex_unlock(&visualizer_list_mtx);
+
+	return vs;
+}
+
+renderer_t *graph_get_renderer(sysarg_t handle)
+{
+	renderer_t *rnd = NULL;
+
+	fibril_mutex_lock(&renderer_list_mtx);
+	list_foreach(renderer_list, link) {
+		renderer_t *cur = list_get_instance(link, renderer_t, link);
+		if (cur->reg_svc_handle == handle) {
+			rnd = cur;
+			break;
+		}
+	}
+	fibril_mutex_unlock(&renderer_list_mtx);
+
+	return rnd;
+}
+
+int graph_unregister_visualizer(visualizer_t *vs)
+{
+	int rc = EOK;
+
+	fibril_mutex_lock(&visualizer_list_mtx);
+	rc = loc_service_unregister(vs->reg_svc_handle);
+	list_remove(&vs->link);
+	fibril_mutex_unlock(&visualizer_list_mtx);
+
+	return rc;
+}
+
+int graph_unregister_renderer(renderer_t *rnd)
+{
+	int rc = EOK;
+
+	fibril_mutex_lock(&renderer_list_mtx);
+	rc = loc_service_unregister(rnd->reg_svc_handle);
+	list_remove(&rnd->link);
+	fibril_mutex_unlock(&renderer_list_mtx);
+
+	return rc;
+}
+
+void graph_destroy_visualizer(visualizer_t *vs)
+{
+	assert(atomic_get(&vs->ref_cnt) == 0);
+	assert(vs->notif_sess == NULL);
+	assert(!fibril_mutex_is_locked(&vs->mode_mtx));
+	assert(list_empty(&vs->modes));
+	assert(vs->mode_set == false);
+	assert(vs->cells.data == NULL);
+	assert(vs->dev_ctx == NULL);
+
+	free(vs);
+}
+
+void graph_destroy_renderer(renderer_t *rnd)
+{
+	// TODO
+	assert(atomic_get(&rnd->ref_cnt) == 0);
+
+	free(rnd);
+}
+
+int graph_notify_mode_change(async_sess_t *sess, sysarg_t handle, sysarg_t mode_idx)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_2_0(exch, VISUALIZER_MODE_CHANGE, handle, mode_idx);
+	async_exchange_end(exch);
+
+	return ret;
+}
+
+int graph_notify_disconnect(async_sess_t *sess, sysarg_t handle)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int ret = async_req_1_0(exch, VISUALIZER_DISCONNECT, handle);
+	async_exchange_end(exch);
+
+	async_hangup(sess);
+
+	return ret;
+}
+
+static void vs_claim(visualizer_t *vs, ipc_callid_t iid, ipc_call_t *icall)
+{
+	vs->client_side_handle = IPC_GET_ARG1(*icall);
+	int rc = vs->ops.claim(vs);
+	async_answer_0(iid, rc);
+}
+
+static void vs_yield(visualizer_t *vs, ipc_callid_t iid, ipc_call_t *icall)
+{
+	/* Deallocate resources for the current mode. */
+	if (vs->mode_set) {
+		if (vs->cells.data != NULL) {
+			as_area_destroy((void *) vs->cells.data);
+			vs->cells.data = NULL;
+		}
+	}
+
+	/* Driver might also deallocate resources for the current mode. */
+	int rc = vs->ops.yield(vs);
+
+	/* Now that the driver was given a chance to deallocate resources,
+	 * current mode can be unset. */
+	if (vs->mode_set) {
+		vs->mode_set = false;
+	}
+
+	async_answer_0(iid, rc);
+}
+
+static void vs_enumerate_modes(visualizer_t *vs, ipc_callid_t iid, ipc_call_t *icall)
+{
+	fibril_mutex_lock(&vs->mode_mtx);
+	link_t *link = list_nth(&vs->modes, IPC_GET_ARG1(*icall));
+
+	if (link != NULL) {
+		vslmode_list_element_t *mode_elem =
+		    list_get_instance(link, vslmode_list_element_t, link);
+		vslmode_t mode = mode_elem->mode;
+		fibril_mutex_unlock(&vs->mode_mtx);
+
+		ipc_callid_t callid;
+		size_t len;
+
+        if (!async_data_read_receive(&callid, &len)) {
+			async_answer_0(iid, EINVAL);
+			return;
+        }
+        int rc = async_data_read_finalize(callid, &mode, len);
+		if (rc != EOK) {
+			async_answer_0(iid, ENOMEM);
+			return;
+		}
+
+		async_answer_0(iid, EOK);
+	} else {
+		async_answer_0(iid, ENOENT);
+	}
+}
+
+static void vs_get_default_mode(visualizer_t *vs, ipc_callid_t iid, ipc_call_t *icall)
+{
+	fibril_mutex_lock(&vs->mode_mtx);
+	vslmode_list_element_t *mode_elem = NULL;
+	list_foreach(vs->modes, link) {
+		vslmode_list_element_t *cur = list_get_instance(link, vslmode_list_element_t, link);
+		if (cur->mode.index == vs->def_mode_idx) {
+			mode_elem = cur;
+			break;
+		}
+	}
+
+	vslmode_t mode;
+	if (mode_elem != NULL) {
+		mode = mode_elem->mode;
+		fibril_mutex_unlock(&vs->mode_mtx);
+
+		ipc_callid_t callid;
+		size_t len;
+
+		if (!async_data_read_receive(&callid, &len)) {
+			async_answer_0(iid, EINVAL);
+			return;
+		}
+		int rc = async_data_read_finalize(callid, &mode, len);
+		if (rc != EOK) {
+			async_answer_0(iid, ENOMEM);
+			return;
+		}
+		async_answer_0(iid, EOK);
+	} else {
+		fibril_mutex_unlock(&vs->mode_mtx);
+		async_answer_0(iid, ENOENT);
+	}
+}
+
+static void vs_get_current_mode(visualizer_t *vs, ipc_callid_t iid, ipc_call_t *icall)
+{
+	if (vs->mode_set) {
+		ipc_callid_t callid;
+		size_t len;
+
+		if (!async_data_read_receive(&callid, &len)) {
+			async_answer_0(iid, EINVAL);
+			return;
+		}
+		int rc = async_data_read_finalize(callid, &vs->cur_mode, len);
+		if (rc != EOK) {
+			async_answer_0(iid, ENOMEM);
+			return;
+		}
+
+		async_answer_0(iid, EOK);
+	} else {
+		async_answer_0(iid, ENOENT);
+	}
+}
+
+static void vs_get_mode(visualizer_t *vs, ipc_callid_t iid, ipc_call_t *icall)
+{
+	sysarg_t mode_idx = IPC_GET_ARG1(*icall);
+
+	fibril_mutex_lock(&vs->mode_mtx);
+	vslmode_list_element_t *mode_elem = NULL;
+	list_foreach(vs->modes, link) {
+		vslmode_list_element_t *cur = list_get_instance(link, vslmode_list_element_t, link);
+		if (cur->mode.index == mode_idx) {
+			mode_elem = cur;
+			break;
+		}
+	}
+
+	vslmode_t mode;
+	if (mode_elem != NULL) {
+		mode = mode_elem->mode;
+		fibril_mutex_unlock(&vs->mode_mtx);
+
+		ipc_callid_t callid;
+		size_t len;
+
+		if (!async_data_read_receive(&callid, &len)) {
+			async_answer_0(iid, EINVAL);
+			return;
+		}
+		int rc = async_data_read_finalize(callid, &mode, len);
+		if (rc != EOK) {
+			async_answer_0(iid, ENOMEM);
+			return;
+		}
+		async_answer_0(iid, EOK);
+	} else {
+		fibril_mutex_unlock(&vs->mode_mtx);
+		async_answer_0(iid, ENOENT);
+	}
+}
+
+static void vs_set_mode(visualizer_t *vs, ipc_callid_t iid, ipc_call_t *icall)
+{
+	int rc = EOK;
+
+	/* Retrieve mode index and version. */
+	sysarg_t mode_idx = IPC_GET_ARG1(*icall);
+	sysarg_t mode_version = IPC_GET_ARG2(*icall);
+
+	/* Find mode in the list. */
+	fibril_mutex_lock(&vs->mode_mtx);
+	vslmode_list_element_t *mode_elem = NULL;
+	list_foreach(vs->modes, link) {
+		vslmode_list_element_t *cur = list_get_instance(link, vslmode_list_element_t, link);
+		if (cur->mode.index == mode_idx) {
+			mode_elem = cur;
+			break;
+		}
+	}
+
+	/* Extract mode description from the list node. */
+	vslmode_t new_mode;
+	if (mode_elem != NULL) {
+		new_mode = mode_elem->mode;
+		fibril_mutex_unlock(&vs->mode_mtx);
+	} else {
+		fibril_mutex_unlock(&vs->mode_mtx);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	/* Check whether the mode is still up-to-date. */
+	if (new_mode.version != mode_version) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	ipc_callid_t callid;
+	size_t size;
+	unsigned int flags;
+
+	/* Retrieve the shared cell storage for the new mode. */
+	if (!async_share_out_receive(&callid, &size, &flags)) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	void *new_cell_storage;
+	rc = async_share_out_finalize(callid, &new_cell_storage);
+	if ((rc != EOK) || (new_cell_storage == AS_MAP_FAILED)) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	/* Change device internal state. */
+	rc = vs->ops.change_mode(vs, new_mode);
+
+	/* Device driver could not establish new mode. Rollback. */
+	if (rc != EOK) {
+		as_area_destroy(new_cell_storage);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	/* Because resources for the new mode were successfully claimed,
+	 * it is finally possible to free resources allocated for the old mode. */
+	if (vs->mode_set) {
+		if (vs->cells.data != NULL) {
+			as_area_destroy((void *) vs->cells.data);
+			vs->cells.data = NULL;
+		}
+	}
+
+	/* Insert new mode into the visualizer. */
+	vs->cells.width = new_mode.screen_width;
+	vs->cells.height = new_mode.screen_height;
+	vs->cells.data = (pixel_t *) new_cell_storage;
+	vs->cur_mode = new_mode;
+	vs->mode_set = true;
+
+	async_answer_0(iid, EOK);
+}
+
+static void vs_update_damaged_region(visualizer_t *vs, ipc_callid_t iid, ipc_call_t *icall)
+{
+#ifdef __32_BITS__
+	sysarg_t x_offset = (IPC_GET_ARG5(*icall) >> 16);
+	sysarg_t y_offset = (IPC_GET_ARG5(*icall) & 0x0000ffff);
+#else
+	sysarg_t x_offset = (IPC_GET_ARG5(*icall) >> 32);
+	sysarg_t y_offset = (IPC_GET_ARG5(*icall) & 0xffffffff);
+#endif
+
+	int rc = vs->ops.handle_damage(vs,
+	    IPC_GET_ARG1(*icall), IPC_GET_ARG2(*icall),
+	    IPC_GET_ARG3(*icall), IPC_GET_ARG4(*icall),
+		x_offset, y_offset);
+	async_answer_0(iid, rc);
+}
+
+static void vs_suspend(visualizer_t *vs, ipc_callid_t iid, ipc_call_t *icall)
+{
+	int rc = vs->ops.suspend(vs);
+	async_answer_0(iid, rc);
+}
+
+static void vs_wakeup(visualizer_t *vs, ipc_callid_t iid, ipc_call_t *icall)
+{
+	int rc = vs->ops.wakeup(vs);
+	async_answer_0(iid, rc);
+}
+
+void graph_visualizer_connection(visualizer_t *vs,
+    ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ipc_call_t call;
+	ipc_callid_t callid;
+
+	/* Claim the visualizer. */
+	if (!cas(&vs->ref_cnt, 0, 1)) {
+		async_answer_0(iid, ELIMIT);
+		return;
+	}
+
+	/* Accept the connection. */
+	async_answer_0(iid, EOK);
+
+	/* Establish callback session. */
+	callid = async_get_call(&call);
+	vs->notif_sess = async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
+	if (vs->notif_sess != NULL) {
+		async_answer_0(callid, EOK);
+	} else {
+		async_answer_0(callid, ELIMIT);
+	}
+
+	/* Enter command loop. */
+	while (true) {
+		callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			async_answer_0(callid, EINVAL);
+			break;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case VISUALIZER_CLAIM:
+			vs_claim(vs, callid, &call);
+			break;
+		case VISUALIZER_YIELD:
+			vs_yield(vs, callid, &call);
+			goto terminate;
+		case VISUALIZER_ENUMERATE_MODES:
+			vs_enumerate_modes(vs, callid, &call);
+			break;
+		case VISUALIZER_GET_DEFAULT_MODE:
+			vs_get_default_mode(vs, callid, &call);
+			break;
+		case VISUALIZER_GET_CURRENT_MODE:
+			vs_get_current_mode(vs, callid, &call);
+			break;
+		case VISUALIZER_GET_MODE:
+			vs_get_mode(vs, callid, &call);
+			break;
+		case VISUALIZER_SET_MODE:
+			vs_set_mode(vs, callid, &call);
+			break;
+		case VISUALIZER_UPDATE_DAMAGED_REGION:
+			vs_update_damaged_region(vs, callid, &call);
+			break;
+		case VISUALIZER_SUSPEND:
+			vs_suspend(vs, callid, &call);
+			break;
+		case VISUALIZER_WAKE_UP:
+			vs_wakeup(vs, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+			goto terminate;
+		}
+	}
+
+terminate:
+	async_hangup(vs->notif_sess);
+	vs->notif_sess = NULL;
+	atomic_set(&vs->ref_cnt, 0);
+}
+
+void graph_renderer_connection(renderer_t *rnd,
+    ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	// TODO
+
+	ipc_call_t call;
+	ipc_callid_t callid;
+
+	/* Accept the connection. */
+	atomic_inc(&rnd->ref_cnt);
+	async_answer_0(iid, EOK);
+
+	/* Enter command loop. */
+	while (true) {
+		callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			async_answer_0(callid, EINVAL);
+			break;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		default:
+			async_answer_0(callid, EINVAL);
+			goto terminate;
+		}
+	}
+
+terminate:
+	atomic_dec(&rnd->ref_cnt);
+}
+
+void graph_client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Find the visualizer or renderer with the given service ID. */
+	visualizer_t *vs = graph_get_visualizer(IPC_GET_ARG1(*icall));
+	renderer_t *rnd = graph_get_renderer(IPC_GET_ARG1(*icall));
+
+	if (vs != NULL) {
+		graph_visualizer_connection(vs, iid, icall, arg);
+	} else if (rnd != NULL) {
+		graph_renderer_connection(rnd, iid, icall, arg);
+	} else {
+		async_answer_0(iid, ENOENT);
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/graph/graph.h
===================================================================
--- uspace/lib/graph/graph.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/graph/graph.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 graph
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef GRAPH_GRAPH_H_
+#define GRAPH_GRAPH_H_
+
+#include <sys/types.h>
+#include <bool.h>
+#include <loc.h>
+#include <async.h>
+#include <atomic.h>
+#include <fibril_synch.h>
+#include <adt/list.h>
+#include <io/mode.h>
+#include <io/pixelmap.h>
+#include <ipc/graph.h>
+
+struct visualizer;
+struct renderer;
+
+typedef struct {
+	/**
+	 * Device driver shall allocate any necessary internal structures
+	 * specific for a claimed visualizer. */
+	int (* claim)(struct visualizer *vs);
+	
+	/**
+	 * Device driver shall deallocate any necessary internal structures
+	 * specific for a claimed visualizer. Driver shall also check whether
+	 * the mode is set and if so it shall change its internal state
+	 * accordingly (e.g. deallocate frame buffers). */
+	int (* yield)(struct visualizer *vs);
+	
+	/**
+	 * Device driver shall first try to claim all resources required for
+	 * a new mode (e.g. allocate new framebuffers) and only if successful
+	 * it shall free resources for the old mode. Although such behaviour
+	 * might not be always possible, it is preferable since libgraph tries to
+	 * keep current mode functional if the new mode cannot be set (for any
+	 * reason). If it is convenient for the device driver (e.g. for better
+	 * optimization), the pointer to the handle_damage operation can be
+	 * changed at this point. */
+	int (* change_mode)(struct visualizer *vs, vslmode_t new_mode);
+	
+	/**
+	 * Device driver shall render the cells from damaged region into its
+	 * internal framebuffer. In case the driver use multi-buffering, it
+	 * shall also switch internal buffers (e.g. by pageflip). Offsets
+	 * are intended to support basic vertical and horizontal scrolling on
+	 * the shared backbuffer (i.e. when reading from backbuffer, the offsets
+	 * shall be added to the coordinates and if necessary the result shall be
+	 * wrapped around the edge of the backbuffer). */
+	int (* handle_damage)(struct visualizer *vs,
+	    sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height,
+		sysarg_t x_offset, sysarg_t y_offset);
+	
+	/**
+	 * Upper layers of the graphic stack might report inactivity. In such
+	 * case, device driver might enable power saving mode on the device
+	 * corresponding to the visualizer. */
+	int (* suspend)(struct visualizer *vs);
+	
+	/**
+	 * When upper layers detect activity on suspended visualizer, device
+	 * driver shall disable power saving mode on the corresponding device. */
+	int (* wakeup)(struct visualizer *vs);
+} visualizer_ops_t;
+
+/**
+ * Represents final output device (e.g. monitor connected to the port
+ * on the graphic adapter, serial console, local/remote virtual monitor).
+ */
+typedef struct visualizer {
+	/**
+	 * Link to the list of all visualizers belonging to the graphic device.
+	 * Field is fully managed by libgraph. */
+	link_t link;
+	
+	/**
+	 * When reference count equals 1, visualizer is claimed by a client,
+	 * when equals 0, visualizer is not claimed. At the time, visualizer
+	 * can be claimed only by a single client.
+	 * Field is fully managed by libgraph. */
+	atomic_t ref_cnt;
+	
+	/**
+	 * Visualizer ID assigned by some particular registration service
+	 * in the system (either location service or device manager). Intended
+	 * for cleanup duties (e.g. unregistering visualizer).
+	 * If the visualizer is registered through libgraph functions, then the
+	 * field is fully managed by libgraph. Otherwise, it is a driver
+	 * responsibility to set and update this field. */
+	sysarg_t reg_svc_handle;
+	
+	/**
+	 * Visualizer ID in the client context. When client gets notified by
+	 * libgraph about some event, it can use this identification to lookup
+	 * data structures corresponding to a particular visualizer (e.g. viewports
+	 * in the compositor).
+	 * Field is fully managed by libgraph. It is assigned when the visualizer
+	 * gets claimed and is valid until it is yielded. */
+	sysarg_t client_side_handle;
+	
+	/**
+	 * Callback session to the client. Established by libgraph during initial
+	 * phase of client connection. Can be used to notify client about
+	 * external asynchronous changes to the output device state
+	 * (e.g. monitor gets disconnected from the graphic adapter, virtual
+	 * monitor is terminated by the user, pivot monitor is rotated by 90
+	 * degrees, virtual monitor is resized by the user).
+	 * Field is fully managed by libgraph. Device driver can use it indirectly
+	 * through notification functions. */
+	async_sess_t *notif_sess;
+	
+	/**
+	 * Mutex protecting the mode list and default mode index. This is required
+	 * for the case when device driver might asynchronously update these
+	 * upon the request from the final output device (e.g. to change mode
+	 * dimensions when virtual monitor is resized).
+	 * Both device driver and libgraph must lock on this mutex when accessing
+	 * modes list or default mode index. */
+	fibril_mutex_t mode_mtx;
+	
+	/**
+	 * List of all modes that can be set by this visualizer. List is populated
+	 * by device driver when creating a new visualizer or when handling the
+	 * request from the final output device to change the available modes.
+	 * When this happens, the device driver is expected to increment version
+	 * numbers in the modified modes. Modes in the list typically represent
+	 * the intersection of modes supported by device driver (graphic adapter)
+	 * and final output device (e.g. monitor).
+	 * Field is fully managed by device driver, libgraph reads it with locked
+	 * mutex. */
+	list_t modes;
+	
+	/**
+	 * Index of the default mode. Might come in handy to the clients that are
+	 * not able to enumerate modes and present the choice to the user
+	 * (either the client does not have such functionality or the client is
+	 * bootstraping without any preliminary knowledge). Device driver shall
+	 * maintain this field at the same time when it is doing any changes to the
+	 * mode list.
+	 * Field is fully managed by device driver, libgraph reads it with locked
+	 * mutex. */
+	sysarg_t def_mode_idx;
+	
+	/**
+	 * Copy of the currently established mode. It is read by both libgraph and
+	 * device driver when deallocating resources for the current mode. Device
+	 * driver can also read it to properly interpret the cell type and its
+	 * internal structures when handling the damage.
+	 * Field is fully managed by libgraph, can be read by device driver. */
+	vslmode_t cur_mode;
+	
+	/**
+	 * Determines whether the visualizer is currently set to some mode or not,
+	 * that is whether cur_mode field contains up-to-date data.
+	 * Field is fully managed by libgraph, can be read by device driver. */
+	bool mode_set;
+	
+	/**
+	 * Device driver function pointers.
+	 * Field is fully managed by device driver, libgraph invokes driver's
+	 * functions through it. */
+	visualizer_ops_t ops;
+	
+	/**
+	 * Backbuffer shared with the client. Sharing is established by libgraph.
+	 * Device driver reads the cells when handling damage. Cells shall be
+	 * interpreted according to the currently set mode.
+	 * Field is fully managed by libgraph, can be read by device driver. */
+	pixelmap_t cells;
+	
+	/**
+	 * Device driver context, completely opaque to the libgraph. Intended to
+	 * contain pointers to frontbuffers or information representing the
+	 * final output device (e.g. hardware port for physical monitor).
+	 * Field is fully managed by device driver. */
+	void *dev_ctx;
+} visualizer_t;
+
+typedef struct {
+	// TODO
+	int dummy;
+} renderer_ops_t;
+
+/**
+ * NOTE: Following description is just a result of brainstorming on how the
+ *       driver of real physical graphic accelerator could be supported by
+ *       libgraph.
+ *
+ * Renderer represents the hardware graphic accelerator. If the device driver
+ * handles more than one physical accelerator (e.g. graphic cards connected in
+ * SLI mode or single graphic card with two GPUs), it is up to the driver
+ * whether the load balancing will be exposed to the clients (that is the
+ * driver will provide multiple renderers) or not (just a single renderer
+ * handling the load balancing internally).
+ *
+ * At runtime, renderer is represented by scheduling thread and multiple
+ * connection fibrils handling client requests. For each client, there is
+ * command queue, condition variable and device context. Connection fibril puts
+ * the command into the command queue and blocks on the condition variable.
+ * Scheduling thread decides what client to serve, switches corresponding device
+ * context into the accelerator, consumes the command from the command queue and
+ * executes it on the accelerator. When the command execution is finished, the
+ * condition variable si signalled and the connection fibril answers the client.
+ *
+ * Operations that are not implemented in the hardware of the accelerator might
+ * be carried out by worker threads managed by scheduling thread. If the
+ * accelerator physical memory is mapped to the address space of the driver, it
+ * could be extended by allowing scheduling thread to page out the memory and
+ * to handle the page faults.
+ *
+ * NOTE: It is not entirely clear which parts should be implemented in libgraph
+ *       and which in the device driver. As a rough sketch, the connection
+ *       fibril routine, command queue and memory paging should be handled
+ *       by libgraph. The scheduling thread and device context should be
+ *       provided by device driver.
+ */
+typedef struct renderer {
+	// TODO
+	link_t link;
+	
+	atomic_t ref_cnt;
+	
+	sysarg_t reg_svc_handle;
+	
+	renderer_ops_t ops;
+} renderer_t;
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Fill in the basic visualizer structure. The device driver shall take the
+ * created torso and to complete it by adding its specific structures
+ * (device context, modes). */
+extern void graph_init_visualizer(visualizer_t *);
+
+extern void graph_init_renderer(renderer_t *);
+
+/*----------------------------------------------------------------------------*/
+
+/*
+ * NOTE: All functions in this section are intended to be used only by various
+ *       driver emulators (e.g. compositor client containing emulated driver
+ *       to render the framebuffer of other compositor or console server).
+ *       Driver of the physical hardware shall instead use similar functions
+ *       from libdrv.
+ */
+
+/**
+ * Allocate the visualizer so it can be initialized. */
+extern visualizer_t *graph_alloc_visualizer(void);
+
+/**
+ * Register the completely prepared visualizer to the location service and
+ * add it to the driver visualizer list. After the registration, the visualizer
+ * is considered ready to handle client connection. Since visualizer
+ * list is guarded by the mutex, visualizers might be added even after the
+ * initialialization of the device driver. */
+extern int graph_register_visualizer(visualizer_t *);
+
+/** 
+ * Retrieve the visualizer from the visualizer list according to its
+ * service ID. */
+extern visualizer_t *graph_get_visualizer(sysarg_t);
+
+/**
+ * Unregister the visualizer from the location service and remove it 
+ * from the driver visualizer list. Function shall be called by device driver
+ * before deallocating the resources for the visualizer. */
+extern int graph_unregister_visualizer(visualizer_t *);
+
+/** 
+ * Destroy the rest of the visualizer. Device driver shall call this function
+ * only after it has unregistered the visualizer and deallocated all the
+ * resources for which the driver is responsible. */
+extern void graph_destroy_visualizer(visualizer_t *);
+
+extern renderer_t *graph_alloc_renderer(void);
+extern int graph_register_renderer(renderer_t *);
+extern renderer_t *graph_get_renderer(sysarg_t);
+extern int graph_unregister_renderer(renderer_t *);
+extern void graph_destroy_renderer(renderer_t *);
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Device driver can call this function to notify the client through the
+ * callback connection that the visualizer with a specified service ID should
+ * be switched to the mode with the given index. */
+extern int graph_notify_mode_change(async_sess_t *, sysarg_t, sysarg_t);
+
+/**
+ * Device driver can call this function to notify the client through the
+ * callback connection that the visualizer with a specified service ID has
+ * lost its output device (e.g. virtual monitor was closed by a user). */
+extern int graph_notify_disconnect(async_sess_t *, sysarg_t);
+
+/*----------------------------------------------------------------------------*/
+
+/** Shall be registered to libdrv by physical device driver. */
+extern void graph_visualizer_connection(visualizer_t *, ipc_callid_t, ipc_call_t *, void *);
+
+/** Shall be registered to libdrv by physical device driver. */
+extern void graph_renderer_connection(renderer_t *, ipc_callid_t, ipc_call_t *, void *);
+
+/** Shall be registered to location service by emulated device driver. */
+extern void graph_client_connection(ipc_callid_t, ipc_call_t *, void *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/gui/Makefile
===================================================================
--- uspace/lib/gui/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2012 Petr Koupy
+# 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 = ../..
+LIBRARY = libgui
+SLIBRARY = libgui.so.0.0
+LSONAME = libgui.so0
+EXTRA_CFLAGS += -I$(LIBDRAW_PREFIX) -I$(LIBSOFTREND_PREFIX) -I$(LIBGRAPH_PREFIX)
+
+SOURCES = \
+	button.c \
+	connection.c \
+	grid.c \
+	label.c \
+	minimal.c \
+	terminal.c \
+	widget.c \
+	window.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/gui/button.c
===================================================================
--- uspace/lib/gui/button.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/button.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 <str.h>
+#include <malloc.h>
+
+#include <drawctx.h>
+#include <surface.h>
+
+#include "window.h"
+#include "button.h"
+
+static void paint_internal(widget_t *w)
+{
+	button_t *btn = (button_t *) w;
+
+	surface_t *surface = window_claim(btn->widget.window);
+	if (!surface) {
+		window_yield(btn->widget.window);
+	}
+
+	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);
+		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) {
+			drawctx_print(&drawctx, btn->caption, x, y);
+		}
+	}
+
+	window_yield(btn->widget.window);
+}
+
+void deinit_button(button_t *btn)
+{
+	widget_deinit(&btn->widget);
+	free(btn->caption);
+	font_release(&btn->font);
+}
+
+static void button_destroy(widget_t *widget)
+{
+	button_t *btn = (button_t *) widget;
+
+	deinit_button(btn);
+	
+	free(btn);
+}
+
+static void button_reconfigure(widget_t *widget)
+{
+	/* no-op */
+}
+
+static void button_rearrange(widget_t *widget, sysarg_t hpos, sysarg_t vpos,
+    sysarg_t width, sysarg_t height)
+{
+	widget_modify(widget, hpos, vpos, width, height);
+	paint_internal(widget);
+}
+
+static void button_repaint(widget_t *widget)
+{
+	paint_internal(widget);
+	window_damage(widget->window);
+}
+
+static void button_handle_keyboard_event(widget_t *widget, kbd_event_t event)
+{
+	button_t *btn = (button_t *) widget;
+	if (event.key == KC_ENTER && event.type == KEY_PRESS) {
+		sig_send(&btn->clicked, NULL);
+	}
+}
+
+static void button_handle_position_event(widget_t *widget, pos_event_t event)
+{
+	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) {
+			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)
+{
+	widget_init(&btn->widget, parent);
+
+	btn->widget.destroy = button_destroy;
+	btn->widget.reconfigure = button_reconfigure;
+	btn->widget.rearrange = button_rearrange;
+	btn->widget.repaint = button_repaint;
+	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) {
+		btn->caption = NULL;
+	} 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;
+
+	return true;
+}
+
+button_t *create_button(widget_t *parent,
+    const char *caption, uint16_t points, pixel_t background, pixel_t foreground)
+{
+	button_t *btn = (button_t *) malloc(sizeof(button_t));
+	if (!btn) {
+		return NULL;
+	}
+
+	if (init_button(btn, parent, caption, points, background, foreground)) {
+		return btn;
+	} else {
+		free(btn);
+		return NULL;
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/gui/button.h
===================================================================
--- uspace/lib/gui/button.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/button.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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_BUTTON_H_
+#define GUI_BUTTON_H_
+
+#include <sys/types.h>
+#include <io/pixel.h>
+
+#include <source.h>
+#include <font.h>
+
+#include "connection.h"
+#include "widget.h"
+
+typedef struct button {
+	widget_t widget;
+	source_t background;
+	source_t foreground;
+	char *caption;
+	font_t font;
+	signal_t clicked;
+} 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 void deinit_button(button_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/gui/connection.c
===================================================================
--- uspace/lib/gui/connection.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/connection.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 <mem.h>
+#include <malloc.h>
+#include <adt/list.h>
+#include <adt/prodcons.h>
+#include <fibril_synch.h>
+#include <io/window.h>
+
+#include "window.h"
+#include "widget.h"
+#include "connection.h"
+
+typedef struct {
+	link_t link;
+	widget_t *widget;
+	slot_t slot;
+} slot_node_t;
+
+typedef struct {
+	link_t link;
+	signal_t *signal;
+	list_t slots;
+} signal_node_t;
+
+static FIBRIL_RWLOCK_INITIALIZE(connection_guard);
+static LIST_INITIALIZE(connection_list);
+
+void sig_connect(signal_t *signal, widget_t *widget, slot_t slot)
+{
+	fibril_rwlock_write_lock(&connection_guard);
+
+	signal_node_t *sig_node = NULL;
+	list_foreach(connection_list, link) {
+		signal_node_t *cur = list_get_instance(link, signal_node_t, link);
+		if (cur->signal == signal) {
+			sig_node = cur;
+			break;
+		}
+	}
+
+	if (!sig_node) {
+		sig_node = (signal_node_t *) malloc(sizeof(signal_node_t));
+		if (!sig_node) {
+			fibril_rwlock_write_unlock(&connection_guard);
+			return;
+		}
+
+		sig_node->signal = signal;
+		link_initialize(&sig_node->link);
+		list_initialize(&sig_node->slots);
+
+		list_append(&sig_node->link, &connection_list);
+	}
+
+	slot_node_t *slt_node = NULL;
+	list_foreach(sig_node->slots, link) {
+		slot_node_t *cur = list_get_instance(link, slot_node_t, link);
+		if (cur->widget == widget && cur->slot == slot) {
+			slt_node = cur;
+			fibril_rwlock_write_unlock(&connection_guard);
+			break;
+		}
+	}
+
+	if (!slt_node) {
+		slt_node = (slot_node_t *) malloc(sizeof(slot_node_t));
+		if (!slt_node) {
+			fibril_rwlock_write_unlock(&connection_guard);
+			return;
+		}
+
+		slt_node->widget = widget;
+		slt_node->slot = slot;
+		link_initialize(&slt_node->link);
+
+		list_append(&slt_node->link, &sig_node->slots);
+	} else {
+		/* Already connected. */
+	}
+
+	fibril_rwlock_write_unlock(&connection_guard);
+}
+
+void sig_disconnect(signal_t *signal, widget_t *widget, slot_t slot)
+{
+	fibril_rwlock_write_lock(&connection_guard);
+
+	signal_node_t *sig_node = NULL;
+	list_foreach(connection_list, link) {
+		signal_node_t *cur = list_get_instance(link, signal_node_t, link);
+		if (cur->signal == signal) {
+			sig_node = cur;
+			break;
+		}
+	}
+
+	if (!sig_node) {
+		fibril_rwlock_write_unlock(&connection_guard);
+		return;
+	}
+
+	slot_node_t *slt_node = NULL;
+	list_foreach(sig_node->slots, link) {
+		slot_node_t *cur = list_get_instance(link, slot_node_t, link);
+		if (cur->widget == widget && cur->slot == slot) {
+			slt_node = cur;
+			break;
+		}
+	}
+
+	if (!slt_node) {
+		fibril_rwlock_write_unlock(&connection_guard);
+		return;
+	}
+
+	list_remove(&slt_node->link);
+	free(slt_node);
+
+	if (list_empty(&sig_node->slots)) {
+		list_remove(&sig_node->link);
+		free(sig_node);
+	}
+
+	fibril_rwlock_write_unlock(&connection_guard);
+}
+
+void sig_send(signal_t *signal, void *data)
+{
+	fibril_rwlock_read_lock(&connection_guard);
+
+	signal_node_t *sig_node = NULL;
+	list_foreach(connection_list, link) {
+		signal_node_t *cur = list_get_instance(link, signal_node_t, link);
+		if (cur->signal == signal) {
+			sig_node = cur;
+			break;
+		}
+	}
+
+	if (!sig_node) {
+		fibril_rwlock_read_unlock(&connection_guard);
+		return;
+	}
+
+	list_foreach(sig_node->slots, link) {
+		slot_node_t *cur = list_get_instance(link, slot_node_t, link);
+		cur->slot(cur->widget, data);
+	}
+
+	fibril_rwlock_read_unlock(&connection_guard);
+}
+
+void sig_post(signal_t *signal, void *data, size_t data_size)
+{
+	fibril_rwlock_read_lock(&connection_guard);
+
+	signal_node_t *sig_node = NULL;
+	list_foreach(connection_list, link) {
+		signal_node_t *cur = list_get_instance(link, signal_node_t, link);
+		if (cur->signal == signal) {
+			sig_node = cur;
+			break;
+		}
+	}
+
+	if (!sig_node) {
+		fibril_rwlock_read_unlock(&connection_guard);
+		return;
+	}
+
+	list_foreach(sig_node->slots, link) {
+		slot_node_t *cur = list_get_instance(link, slot_node_t, link);
+
+		void *data_copy = NULL;
+		if (data != NULL) {
+			data_copy = malloc(data_size);
+		}
+		if (data_copy != NULL) {
+			memcpy(data_copy, data, data_size);
+		}
+		window_event_t *event =
+			(window_event_t *) malloc(sizeof(window_event_t));
+
+		if (event) {
+			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;
+			prodcons_produce(&cur->widget->window->events, &event->link);
+		} else {
+			if (data_copy != NULL) {
+				free(data_copy);
+			}
+		}
+	}
+
+	fibril_rwlock_read_unlock(&connection_guard);
+}
+
+/** @}
+ */
Index: uspace/lib/gui/connection.h
===================================================================
--- uspace/lib/gui/connection.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/connection.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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_CONNECTION_H_
+#define GUI_CONNECTION_H_
+
+#include <sys/types.h>
+
+struct widget;
+typedef struct widget widget_t;
+
+typedef sysarg_t signal_t;
+typedef void (*slot_t)(widget_t *, void *);
+
+extern void sig_connect(signal_t *, widget_t *, slot_t);
+extern void sig_disconnect(signal_t *, widget_t *, slot_t);
+
+extern void sig_send(signal_t *, void *);
+extern void sig_post(signal_t *, void *, size_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/gui/grid.c
===================================================================
--- uspace/lib/gui/grid.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/grid.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 <assert.h>
+#include <mem.h>
+#include <malloc.h>
+#include <surface.h>
+
+#include "window.h"
+#include "grid.h"
+
+static void paint_internal(widget_t *w)
+{
+	grid_t *grid = (grid_t *) w;
+
+	surface_t *surface = window_claim(grid->widget.window);
+	if (!surface) {
+		window_yield(grid->widget.window);
+	}
+
+	for (sysarg_t y = w->vpos; y <  w->vpos + w->height; ++y) {
+		for (sysarg_t x = w->hpos; x < w->hpos + w->width; ++x) {
+			surface_put_pixel(surface, x, y, grid->background);
+		}
+	}
+
+	window_yield(grid->widget.window);
+}
+
+static widget_t **widget_at(grid_t *grid, size_t row, size_t col)
+{
+	if (row < grid->rows && col < grid->cols) {
+		return grid->layout + (row * grid->cols + col);
+	} else {
+		return NULL;
+	}
+}
+
+void deinit_grid(grid_t *grid)
+{
+	widget_deinit(&grid->widget);
+	free(grid->layout);
+}
+
+static void grid_destroy(widget_t *widget)
+{
+	grid_t *grid = (grid_t *) widget;
+
+	deinit_grid(grid);
+
+	free(grid);
+}
+
+static void grid_reconfigure(widget_t *widget)
+{
+	/* no-op */
+}
+
+static void grid_rearrange(widget_t *widget, sysarg_t hpos, sysarg_t vpos,
+    sysarg_t width, sysarg_t height)
+{
+	grid_t *grid = (grid_t *) widget;
+
+	widget_modify(widget, hpos, vpos, width, height);
+	paint_internal(widget);
+
+	sysarg_t cell_width = width / grid->cols;
+	sysarg_t cell_height = height / grid->rows;
+
+	list_foreach(widget->children, link) {
+		widget_t *child = list_get_instance(link, widget_t, link);
+
+		sysarg_t widget_hpos = 0;
+		sysarg_t widget_vpos = 0;
+		sysarg_t widget_width = 0;
+		sysarg_t widget_height = 0;
+
+		size_t r = 0;
+		size_t c = 0;
+		for (r = 0; r < grid->rows; ++r) {
+			bool found = false;
+			for (c = 0; c < grid->cols; ++c) {
+				widget_t **cell = widget_at(grid, r, c);
+				if (cell && *cell == child) {
+					found = true;
+					break;
+				}
+			}
+			if (found) {
+				break;
+			}
+		}
+
+		widget_hpos = cell_width * c + hpos;
+		widget_vpos = cell_height * r + vpos;
+
+		for (size_t _c = c; _c < grid->cols; ++_c) {
+			widget_t **cell = widget_at(grid, r, _c);
+			if (cell && *cell == child) {
+				widget_width += cell_width;
+			} else {
+				break;
+			}
+		}
+
+		for (size_t _r = r; _r < grid->rows; ++_r) {
+			widget_t **cell = widget_at(grid, _r, c);
+			if (cell && *cell == child) {
+				widget_height += cell_height;
+			} else {
+				break;
+			}
+		}
+
+		if (widget_width > 0 && widget_height > 0) {
+			child->rearrange(child,
+			    widget_hpos, widget_vpos, widget_width, widget_height);
+		}
+	}
+}
+
+static void grid_repaint(widget_t *widget)
+{
+	paint_internal(widget);
+	list_foreach(widget->children, link) {
+		widget_t *child = list_get_instance(link, widget_t, link);
+		child->repaint(child);
+	}
+	window_damage(widget->window);
+}
+
+static void grid_handle_keyboard_event(widget_t *widget, kbd_event_t event)
+{
+	/* no-op */
+}
+
+static void grid_handle_position_event(widget_t *widget, pos_event_t event)
+{
+	grid_t *grid = (grid_t *) widget;
+
+	if ((widget->height / grid->rows) == 0) {
+		return;
+	}
+	if ((widget->width / grid->cols) == 0) {
+		return;
+	}
+
+	sysarg_t row = (event.vpos - widget->vpos) / (widget->height / grid->rows);
+	sysarg_t col = (event.hpos - widget->hpos) / (widget->width / grid->cols);
+
+	widget_t **cell = widget_at(grid, row, col);
+	if (cell && *cell) {
+		(*cell)->handle_position_event(*cell, event);
+	}
+}
+
+static void grid_add(grid_t *grid, widget_t *widget,
+    size_t row, size_t col, size_t rows, size_t cols)
+{
+	assert(row + rows <= grid->rows);
+	assert(col + cols <= grid->cols);
+
+	widget->parent = (widget_t *) grid;
+	list_append(&widget->link, &grid->widget.children);
+	widget->window = grid->widget.window;
+
+	for (size_t r = row; r < row + rows; ++r) {
+		for (size_t c = col; c < col + cols; ++c) {
+			widget_t **cell = widget_at(grid, r, c);
+			if (cell) {
+				*cell = widget;
+			}
+		}
+	}
+}
+
+bool init_grid(grid_t *grid,
+    widget_t *parent, size_t rows, size_t cols, pixel_t background)
+{
+	assert(rows > 0);
+	assert(cols > 0);
+
+	widget_t **layout = (widget_t **) malloc(rows * cols * sizeof(widget_t *));
+	if (!layout) {
+		return false;
+	}
+	memset(layout, 0, rows * cols * sizeof(widget_t *));
+
+	widget_init(&grid->widget, parent);
+
+	grid->widget.destroy = grid_destroy;
+	grid->widget.reconfigure = grid_reconfigure;
+	grid->widget.rearrange = grid_rearrange;
+	grid->widget.repaint = grid_repaint;
+	grid->widget.handle_keyboard_event = grid_handle_keyboard_event;
+	grid->widget.handle_position_event = grid_handle_position_event;
+
+	grid->add = grid_add;
+	grid->background = background;
+	grid->rows = rows;
+	grid->cols = cols;
+	grid->layout = layout;
+
+	return true;
+}
+
+grid_t *create_grid(widget_t *parent, size_t rows, size_t cols, pixel_t background)
+{
+	grid_t *grid = (grid_t *) malloc(sizeof(grid_t));
+	if (!grid) {
+		return NULL;
+	}
+
+	if (init_grid(grid, parent, rows, cols, background)) {
+		return grid;
+	} else {
+		free(grid);
+		return NULL;
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/gui/grid.h
===================================================================
--- uspace/lib/gui/grid.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/grid.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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_GRID_H_
+#define GUI_GRID_H_
+
+#include <sys/types.h>
+#include <io/pixel.h>
+
+#include "widget.h"
+
+struct grid;
+typedef struct grid grid_t;
+
+typedef struct grid {
+	widget_t widget;
+	pixel_t background;
+	size_t rows;
+	size_t cols;
+	widget_t **layout;
+	void (*add)(grid_t *, widget_t *, size_t, size_t, size_t, size_t);
+} grid_t;
+
+extern bool init_grid(grid_t *, widget_t *, size_t, size_t, pixel_t);
+extern grid_t *create_grid(widget_t *, size_t, size_t, pixel_t);
+extern void deinit_grid(grid_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/gui/label.c
===================================================================
--- uspace/lib/gui/label.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/label.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 <str.h>
+#include <malloc.h>
+
+#include <drawctx.h>
+#include <surface.h>
+
+#include "window.h"
+#include "label.h"
+
+static void paint_internal(widget_t *w)
+{
+	label_t *lbl = (label_t *) w;
+
+	surface_t *surface = window_claim(lbl->widget.window);
+	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);
+
+	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);
+		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) {
+			drawctx_print(&drawctx, lbl->caption, x, y);
+		}
+	}
+
+	window_yield(lbl->widget.window);
+}
+
+static void on_rewrite(widget_t *widget, void *data)
+{
+	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);
+	}
+}
+
+void deinit_label(label_t *lbl)
+{
+	widget_deinit(&lbl->widget);
+	free(lbl->caption);
+	font_release(&lbl->font);
+}
+
+static void label_destroy(widget_t *widget)
+{
+	label_t *lbl = (label_t *) widget;
+
+	deinit_label(lbl);
+	
+	free(lbl);
+}
+
+static void label_reconfigure(widget_t *widget)
+{
+	/* no-op */
+}
+
+static void label_rearrange(widget_t *widget, sysarg_t hpos, sysarg_t vpos,
+    sysarg_t width, sysarg_t height)
+{
+	widget_modify(widget, hpos, vpos, width, height);
+	paint_internal(widget);
+}
+
+static void label_repaint(widget_t *widget)
+{
+	paint_internal(widget);
+	window_damage(widget->window);
+}
+
+static void label_handle_keyboard_event(widget_t *widget, kbd_event_t event)
+{
+	/* no-op */
+}
+
+static void label_handle_position_event(widget_t *widget, pos_event_t event)
+{
+	/* no-op */
+}
+
+bool init_label(label_t *lbl, widget_t *parent,
+    const char *caption, uint16_t points, pixel_t background, pixel_t foreground)
+{
+	widget_init(&lbl->widget, parent);
+
+	lbl->widget.destroy = label_destroy;
+	lbl->widget.reconfigure = label_reconfigure;
+	lbl->widget.rearrange = label_rearrange;
+	lbl->widget.repaint = label_repaint;
+	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) {
+		lbl->caption = NULL;
+	} 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 *lbl = (label_t *) malloc(sizeof(label_t));
+	if (!lbl) {
+		return NULL;
+	}
+
+	if (init_label(lbl, parent, caption, points, background, foreground)) {
+		return lbl;
+	} else {
+		free(lbl);
+		return NULL;
+	}
+}
+
+/** @}
+ */
+
Index: uspace/lib/gui/label.h
===================================================================
--- uspace/lib/gui/label.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/label.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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_LABEL_H_
+#define GUI_LABEL_H_
+
+#include <sys/types.h>
+#include <io/pixel.h>
+
+#include <source.h>
+#include <font.h>
+
+#include "connection.h"
+#include "widget.h"
+
+typedef struct label {
+	widget_t widget;
+	source_t background;
+	source_t foreground;
+	char *caption;
+	font_t font;
+	slot_t rewrite;
+} 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 void deinit_label(label_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/gui/minimal.c
===================================================================
--- uspace/lib/gui/minimal.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/minimal.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 <malloc.h>
+#include <surface.h>
+
+#include "window.h"
+#include "minimal.h"
+
+static void paint_internal(widget_t *w)
+{
+	minimal_t *min = (minimal_t *) w;
+
+	surface_t *surface = window_claim(min->widget.window);
+	if (!surface) {
+		window_yield(min->widget.window);
+	}
+
+	for (sysarg_t y = w->vpos; y <  w->vpos + w->height; ++y) {
+		for (sysarg_t x = w->hpos; x < w->hpos + w->width; ++x) {
+			if (y % 2) {
+				if (x % 2) {
+					surface_put_pixel(surface, x, y, min->pix_a);
+				} else {
+					surface_put_pixel(surface, x, y, min->pix_b);
+				}
+			} else {
+				if (x % 2) {
+					surface_put_pixel(surface, x, y, min->pix_b);
+				} else {
+					surface_put_pixel(surface, x, y, min->pix_a);
+				}
+			}
+		}
+	}
+	
+	window_yield(min->widget.window);
+}
+
+void deinit_minimal(minimal_t *min)
+{
+	widget_deinit(&min->widget);
+}
+
+static void minimal_destroy(widget_t *widget)
+{
+	minimal_t *min = (minimal_t *) widget;
+
+	deinit_minimal(min);
+
+	free(min);
+}
+
+static void minimal_reconfigure(widget_t *widget)
+{
+	/* no-op */
+}
+
+static void minimal_rearrange(widget_t *widget, sysarg_t hpos, sysarg_t vpos,
+    sysarg_t width, sysarg_t height)
+{
+	widget_modify(widget, hpos, vpos, width, height);
+	paint_internal(widget);
+}
+
+static void minimal_repaint(widget_t *widget)
+{
+	paint_internal(widget);
+	window_damage(widget->window);
+}
+
+static void minimal_handle_keyboard_event(widget_t *widget, kbd_event_t event)
+{
+	/* no-op */
+}
+
+static void minimal_handle_position_event(widget_t *widget, pos_event_t event)
+{
+	/* no-op */
+}
+
+bool init_minimal(minimal_t *min, widget_t *parent, pixel_t a, pixel_t b)
+{
+	widget_init(&min->widget, parent);
+
+	min->widget.destroy = minimal_destroy;
+	min->widget.reconfigure = minimal_reconfigure;
+	min->widget.rearrange = minimal_rearrange;
+	min->widget.repaint = minimal_repaint;
+	min->widget.handle_keyboard_event = minimal_handle_keyboard_event;
+	min->widget.handle_position_event = minimal_handle_position_event;
+
+	min->pix_a = a;
+	min->pix_b = b;
+
+	return true;
+}
+
+minimal_t *create_minimal(widget_t *parent, pixel_t a, pixel_t b)
+{
+	minimal_t *min = (minimal_t *) malloc(sizeof(minimal_t));
+	if (!min) {
+		return NULL;
+	}
+
+	if (init_minimal(min, parent, a, b)) {
+		return min;
+	} else {
+		free(min);
+		return NULL;
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/gui/minimal.h
===================================================================
--- uspace/lib/gui/minimal.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/minimal.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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_MINIMAL_H_
+#define GUI_MINIMAL_H_
+
+#include <bool.h>
+#include <sys/types.h>
+#include <io/pixel.h>
+
+#include "widget.h"
+
+typedef struct minimal {
+	widget_t widget;
+	pixel_t pix_a;
+	pixel_t pix_b;
+} minimal_t;
+
+extern bool init_minimal(minimal_t *, widget_t *, pixel_t, pixel_t);
+extern minimal_t *create_minimal(widget_t *, pixel_t, pixel_t);
+extern void deinit_minimal(minimal_t *);
+
+#endif
+
+/** @}
+ */
+
Index: uspace/lib/gui/terminal.c
===================================================================
--- uspace/lib/gui/terminal.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/terminal.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,778 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 <errno.h>
+#include <malloc.h>
+#include <io/chargrid.h>
+#include <surface.h>
+#include <gfx/font-8x16.h>
+#include <io/con_srv.h>
+#include <io/concaps.h>
+#include <io/console.h>
+#include <task.h>
+#include <adt/list.h>
+#include <adt/prodcons.h>
+#include <atomic.h>
+#include <stdarg.h>
+#include "window.h"
+#include "terminal.h"
+
+#define NAME       "vterm"
+#define NAMESPACE  "vterm"
+
+#define LOCFS_MOUNT_POINT  "/loc"
+
+#define APP_GETTERM  "/app/getterm"
+
+#define TERM_CAPS \
+	(CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB)
+
+static LIST_INITIALIZE(terms);
+
+static int term_open(con_srvs_t *, con_srv_t *);
+static int term_close(con_srv_t *);
+static int term_read(con_srv_t *, void *, size_t);
+static int term_write(con_srv_t *, void *, size_t);
+static void term_sync(con_srv_t *);
+static void term_clear(con_srv_t *);
+static void term_set_pos(con_srv_t *, sysarg_t col, sysarg_t row);
+static int term_get_pos(con_srv_t *, sysarg_t *, sysarg_t *);
+static int term_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
+static int term_get_color_cap(con_srv_t *, console_caps_t *);
+static void term_set_style(con_srv_t *, console_style_t);
+static void term_set_color(con_srv_t *, console_color_t, console_color_t,
+    console_color_attr_t);
+static void term_set_rgb_color(con_srv_t *, pixel_t, pixel_t);
+static void term_set_cursor_visibility(con_srv_t *, bool);
+static int term_get_event(con_srv_t *, kbd_event_t *);
+
+static con_ops_t con_ops = {
+	.open = term_open,
+	.close = term_close,
+	.read = term_read,
+	.write = term_write,
+	.sync = term_sync,
+	.clear = term_clear,
+	.set_pos = term_set_pos,
+	.get_pos = term_get_pos,
+	.get_size = term_get_size,
+	.get_color_cap = term_get_color_cap,
+	.set_style = term_set_style,
+	.set_color = term_set_color,
+	.set_rgb_color = term_set_rgb_color,
+	.set_cursor_visibility = term_set_cursor_visibility,
+	.get_event = term_get_event
+};
+
+static terminal_t *srv_to_terminal(con_srv_t *srv)
+{
+	return srv->srvs->sarg;
+}
+
+static void getterm(const char *svc, const char *app)
+{
+	char term[LOC_NAME_MAXLEN];
+	snprintf(term, LOC_NAME_MAXLEN, "%s/%s", LOCFS_MOUNT_POINT, svc);
+	
+	/* Wait for the terminal service to be ready */
+	service_id_t service_id;
+	int rc = loc_service_get_id(svc, &service_id, IPC_FLAG_BLOCKING);
+	if (rc != EOK)
+		return;
+	
+	task_spawnl(NULL, APP_GETTERM, APP_GETTERM, "-w", term, app, NULL);
+}
+
+static pixel_t color_table[16] = {
+	[COLOR_BLACK]       = PIXEL(255, 0, 0, 0),
+	[COLOR_BLUE]        = PIXEL(255, 0, 0, 240),
+	[COLOR_GREEN]       = PIXEL(255, 0, 240, 0),
+	[COLOR_CYAN]        = PIXEL(255, 0, 240, 240),
+	[COLOR_RED]         = PIXEL(255, 240, 0, 0),
+	[COLOR_MAGENTA]     = PIXEL(255, 240, 0, 240),
+	[COLOR_YELLOW]      = PIXEL(255, 240, 240, 0),
+	[COLOR_WHITE]       = PIXEL(255, 240, 240, 240),
+	
+	[COLOR_BLACK + 8]   = PIXEL(255, 0, 0, 0),
+	[COLOR_BLUE + 8]    = PIXEL(255, 0, 0, 255),
+	[COLOR_GREEN + 8]   = PIXEL(255, 0, 255, 0),
+	[COLOR_CYAN + 8]    = PIXEL(255, 0, 255, 255),
+	[COLOR_RED + 8]     = PIXEL(255, 255, 0, 0),
+	[COLOR_MAGENTA + 8] = PIXEL(255, 255, 0, 255),
+	[COLOR_YELLOW + 8]  = PIXEL(255, 255, 255, 0),
+	[COLOR_WHITE + 8]   = PIXEL(255, 255, 255, 255),
+};
+
+static inline void attrs_rgb(char_attrs_t attrs, pixel_t *bgcolor, pixel_t *fgcolor)
+{
+	switch (attrs.type) {
+	case CHAR_ATTR_STYLE:
+		switch (attrs.val.style) {
+		case STYLE_NORMAL:
+			*bgcolor = color_table[COLOR_WHITE];
+			*fgcolor = color_table[COLOR_BLACK];
+			break;
+		case STYLE_EMPHASIS:
+			*bgcolor = color_table[COLOR_WHITE];
+			*fgcolor = color_table[COLOR_RED];
+			break;
+		case STYLE_INVERTED:
+			*bgcolor = color_table[COLOR_BLACK];
+			*fgcolor = color_table[COLOR_WHITE];
+			break;
+		case STYLE_SELECTED:
+			*bgcolor = color_table[COLOR_RED];
+			*fgcolor = color_table[COLOR_WHITE];
+			break;
+		}
+		break;
+	case CHAR_ATTR_INDEX:
+		*bgcolor = color_table[(attrs.val.index.bgcolor & 7) |
+		    ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
+		*fgcolor = color_table[(attrs.val.index.fgcolor & 7) |
+		    ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
+		break;
+	case CHAR_ATTR_RGB:
+		*bgcolor = 0xff000000 | attrs.val.rgb.bgcolor;
+		*fgcolor = 0xff000000 | attrs.val.rgb.fgcolor;
+		break;
+	}
+}
+
+static void term_update_char(terminal_t *term, surface_t *surface,
+    sysarg_t sx, sysarg_t sy, sysarg_t col, sysarg_t row)
+{
+	charfield_t *field =
+	    chargrid_charfield_at(term->backbuf, col, row);
+	
+	bool inverted = chargrid_cursor_at(term->backbuf, col, row);
+	
+	sysarg_t bx = sx + (col * FONT_WIDTH);
+	sysarg_t by = sy + (row * FONT_SCANLINES);
+	
+	pixel_t bgcolor = 0;
+	pixel_t fgcolor = 0;
+	
+	if (inverted)
+		attrs_rgb(field->attrs, &fgcolor, &bgcolor);
+	else
+		attrs_rgb(field->attrs, &bgcolor, &fgcolor);
+	
+	// FIXME: Glyph type should be actually uint32_t
+	//        for full UTF-32 coverage.
+	
+	uint16_t glyph = fb_font_glyph(field->ch);
+	
+	// FIXME: This font drawing routine is shamelessly
+	//        suboptimal. It should be optimized for
+	//        aligned memory transfers, etc.
+	
+	for (unsigned int y = 0; y < FONT_SCANLINES; y++) {
+		for (unsigned int x = 0; x < FONT_WIDTH; x++) {
+			pixel_t pixel =
+			    (fb_font[glyph][y] & (1 << (7 - x))) ? fgcolor : bgcolor;
+			surface_put_pixel(surface, bx + x, by + y, pixel);
+		}
+	}
+}
+
+static bool term_update_scroll(terminal_t *term, surface_t *surface,
+    sysarg_t sx, sysarg_t sy)
+{
+	sysarg_t top_row = chargrid_get_top_row(term->frontbuf);
+	
+	if (term->top_row == top_row)
+		return false;
+	
+	term->top_row = top_row;
+	
+	for (sysarg_t row = 0; row < term->rows; row++) {
+		for (sysarg_t col = 0; col < term->cols; col++) {
+			charfield_t *front_field =
+			    chargrid_charfield_at(term->frontbuf, col, row);
+			charfield_t *back_field =
+			    chargrid_charfield_at(term->backbuf, col, row);
+			bool update = false;
+			
+			if (front_field->ch != back_field->ch) {
+				back_field->ch = front_field->ch;
+				update = true;
+			}
+			
+			if (!attrs_same(front_field->attrs, back_field->attrs)) {
+				back_field->attrs = front_field->attrs;
+				update = true;
+			}
+			
+			front_field->flags &= ~CHAR_FLAG_DIRTY;
+			
+			if (update)
+				term_update_char(term, surface, sx, sy, col, row);
+		}
+	}
+	
+	return true;
+}
+
+static bool term_update_cursor(terminal_t *term, surface_t *surface,
+    sysarg_t sx, sysarg_t sy)
+{
+	bool damage = false;
+	
+	sysarg_t front_col;
+	sysarg_t front_row;
+	chargrid_get_cursor(term->frontbuf, &front_col, &front_row);
+	
+	sysarg_t back_col;
+	sysarg_t back_row;
+	chargrid_get_cursor(term->backbuf, &back_col, &back_row);
+	
+	bool front_visibility =
+	    chargrid_get_cursor_visibility(term->frontbuf);
+	bool back_visibility =
+	    chargrid_get_cursor_visibility(term->backbuf);
+	
+	if (front_visibility != back_visibility) {
+		chargrid_set_cursor_visibility(term->backbuf,
+		    front_visibility);
+		term_update_char(term, surface, sx, sy, back_col, back_row);
+		damage = true;
+	}
+	
+	if ((front_col != back_col) || (front_row != back_row)) {
+		chargrid_set_cursor(term->backbuf, front_col, front_row);
+		term_update_char(term, surface, sx, sy, back_col, back_row);
+		term_update_char(term, surface, sx, sy, front_col, front_row);
+		damage = true;
+	}
+	
+	return damage;
+}
+
+static void term_update(terminal_t *term)
+{
+	fibril_mutex_lock(&term->mtx);
+	
+	surface_t *surface = window_claim(term->widget.window);
+	if (!surface) {
+		window_yield(term->widget.window);
+		fibril_mutex_unlock(&term->mtx);
+		return;
+	}
+	
+	bool damage = false;
+	sysarg_t sx = term->widget.hpos;
+	sysarg_t sy = term->widget.vpos;
+	
+	if (term_update_scroll(term, surface, sx, sy)) {
+		damage = true;
+	} else {
+		for (sysarg_t y = 0; y < term->rows; y++) {
+			for (sysarg_t x = 0; x < term->cols; x++) {
+				charfield_t *front_field =
+				    chargrid_charfield_at(term->frontbuf, x, y);
+				charfield_t *back_field =
+				    chargrid_charfield_at(term->backbuf, x, y);
+				bool update = false;
+				
+				if ((front_field->flags & CHAR_FLAG_DIRTY) ==
+				    CHAR_FLAG_DIRTY) {
+					if (front_field->ch != back_field->ch) {
+						back_field->ch = front_field->ch;
+						update = true;
+					}
+					
+					if (!attrs_same(front_field->attrs,
+					    back_field->attrs)) {
+						back_field->attrs = front_field->attrs;
+						update = true;
+					}
+					
+					front_field->flags &= ~CHAR_FLAG_DIRTY;
+				}
+				
+				if (update) {
+					term_update_char(term, surface, sx, sy, x, y);
+					damage = true;
+				}
+			}
+		}
+	}
+	
+	if (term_update_cursor(term, surface, sx, sy))
+		damage = true;
+	
+	window_yield(term->widget.window);
+	
+	if (damage)
+		window_damage(term->widget.window);
+	
+	fibril_mutex_unlock(&term->mtx);
+}
+
+static void term_damage(terminal_t *term)
+{
+	fibril_mutex_lock(&term->mtx);
+	
+	surface_t *surface = window_claim(term->widget.window);
+	if (!surface) {
+		window_yield(term->widget.window);
+		fibril_mutex_unlock(&term->mtx);
+		return;
+	}
+	
+	sysarg_t sx = term->widget.hpos;
+	sysarg_t sy = term->widget.vpos;
+	
+	if (!term_update_scroll(term, surface, sx, sy)) {
+		for (sysarg_t y = 0; y < term->rows; y++) {
+			for (sysarg_t x = 0; x < term->cols; x++) {
+				charfield_t *front_field =
+				    chargrid_charfield_at(term->frontbuf, x, y);
+				charfield_t *back_field =
+				    chargrid_charfield_at(term->backbuf, x, y);
+				
+				back_field->ch = front_field->ch;
+				back_field->attrs = front_field->attrs;
+				front_field->flags &= ~CHAR_FLAG_DIRTY;
+				
+				term_update_char(term, surface, sx, sy, x, y);
+			}
+		}
+	}
+	
+	term_update_cursor(term, surface, sx, sy);
+	
+	window_yield(term->widget.window);
+	window_damage(term->widget.window);
+	
+	fibril_mutex_unlock(&term->mtx);
+}
+
+static int term_open(con_srvs_t *srvs, con_srv_t *srv)
+{
+	return EOK;
+}
+
+static int term_close(con_srv_t *srv)
+{
+	return EOK;
+}
+
+static int term_read(con_srv_t *srv, void *buf, size_t size)
+{
+	terminal_t *term = srv_to_terminal(srv);
+	uint8_t *bbuf = buf;
+	size_t pos = 0;
+	
+	/*
+	 * Read input from keyboard and copy it to the buffer.
+	 * We need to handle situation when wchar is split by 2 following
+	 * reads.
+	 */
+	while (pos < size) {
+		/* Copy to the buffer remaining characters. */
+		while ((pos < size) && (term->char_remains_len > 0)) {
+			bbuf[pos] = term->char_remains[0];
+			pos++;
+			
+			/* Unshift the array. */
+			for (size_t i = 1; i < term->char_remains_len; i++)
+				term->char_remains[i - 1] = term->char_remains[i];
+			
+			term->char_remains_len--;
+		}
+		
+		/* Still not enough? Then get another key from the queue. */
+		if (pos < size) {
+			link_t *link = prodcons_consume(&term->input_pc);
+			kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
+			
+			/* Accept key presses of printable chars only. */
+			if ((event->type == KEY_PRESS) && (event->c != 0)) {
+				wchar_t tmp[2] = {
+					event->c,
+					0
+				};
+				
+				wstr_to_str(term->char_remains, UTF8_CHAR_BUFFER_SIZE, tmp);
+				term->char_remains_len = str_size(term->char_remains);
+			}
+			
+			free(event);
+		}
+	}
+	
+	return size;
+}
+
+static void term_write_char(terminal_t *term, wchar_t ch)
+{
+	sysarg_t updated = 0;
+	
+	fibril_mutex_lock(&term->mtx);
+	
+	switch (ch) {
+	case '\n':
+		updated = chargrid_newline(term->frontbuf);
+		break;
+	case '\r':
+		break;
+	case '\t':
+		updated = chargrid_tabstop(term->frontbuf, 8);
+		break;
+	case '\b':
+		updated = chargrid_backspace(term->frontbuf);
+		break;
+	default:
+		updated = chargrid_putchar(term->frontbuf, ch, true);
+	}
+	
+	fibril_mutex_unlock(&term->mtx);
+	
+	if (updated > 1)
+		term_update(term);
+}
+
+static int term_write(con_srv_t *srv, void *data, size_t size)
+{
+	terminal_t *term = srv_to_terminal(srv);
+	
+	size_t off = 0;
+	while (off < size)
+		term_write_char(term, str_decode(data, &off, size));
+	
+	return size;
+}
+
+static void term_sync(con_srv_t *srv)
+{
+	terminal_t *term = srv_to_terminal(srv);
+	
+	term_update(term);
+}
+
+static void term_clear(con_srv_t *srv)
+{
+	terminal_t *term = srv_to_terminal(srv);
+	
+	fibril_mutex_lock(&term->mtx);
+	chargrid_clear(term->frontbuf);
+	fibril_mutex_unlock(&term->mtx);
+	
+	term_update(term);
+}
+
+static void term_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
+{
+	terminal_t *term = srv_to_terminal(srv);
+	
+	fibril_mutex_lock(&term->mtx);
+	chargrid_set_cursor(term->frontbuf, col, row);
+	fibril_mutex_unlock(&term->mtx);
+	
+	term_update(term);
+}
+
+static int term_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
+{
+	terminal_t *term = srv_to_terminal(srv);
+	
+	fibril_mutex_lock(&term->mtx);
+	chargrid_get_cursor(term->frontbuf, col, row);
+	fibril_mutex_unlock(&term->mtx);
+	
+	return EOK;
+}
+
+static int term_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
+{
+	terminal_t *term = srv_to_terminal(srv);
+	
+	fibril_mutex_lock(&term->mtx);
+	*cols = term->cols;
+	*rows = term->rows;
+	fibril_mutex_unlock(&term->mtx);
+	
+	return EOK;
+}
+
+static int term_get_color_cap(con_srv_t *srv, console_caps_t *caps)
+{
+	(void) srv;
+	*caps = TERM_CAPS;
+	
+	return EOK;
+}
+
+static void term_set_style(con_srv_t *srv, console_style_t style)
+{
+	terminal_t *term = srv_to_terminal(srv);
+	
+	fibril_mutex_lock(&term->mtx);
+	chargrid_set_style(term->frontbuf, style);
+	fibril_mutex_unlock(&term->mtx);
+}
+
+static void term_set_color(con_srv_t *srv, console_color_t bgcolor,
+    console_color_t fgcolor, console_color_attr_t attr)
+{
+	terminal_t *term = srv_to_terminal(srv);
+	
+	fibril_mutex_lock(&term->mtx);
+	chargrid_set_color(term->frontbuf, bgcolor, fgcolor, attr);
+	fibril_mutex_unlock(&term->mtx);
+}
+
+static void term_set_rgb_color(con_srv_t *srv, pixel_t bgcolor,
+    pixel_t fgcolor)
+{
+	terminal_t *term = srv_to_terminal(srv);
+	
+	fibril_mutex_lock(&term->mtx);
+	chargrid_set_rgb_color(term->frontbuf, bgcolor, fgcolor);
+	fibril_mutex_unlock(&term->mtx);
+}
+
+static void term_set_cursor_visibility(con_srv_t *srv, bool visible)
+{
+	terminal_t *term = srv_to_terminal(srv);
+	
+	fibril_mutex_lock(&term->mtx);
+	chargrid_set_cursor_visibility(term->frontbuf, visible);
+	fibril_mutex_unlock(&term->mtx);
+	
+	term_update(term);
+}
+
+static int term_get_event(con_srv_t *srv, kbd_event_t *event)
+{
+	terminal_t *term = srv_to_terminal(srv);
+	link_t *link = prodcons_consume(&term->input_pc);
+	kbd_event_t *kevent = list_get_instance(link, kbd_event_t, link);
+	
+	*event = *kevent;
+	free(kevent);
+	return EOK;
+}
+
+void deinit_terminal(terminal_t *term)
+{
+	list_remove(&term->link);
+	widget_deinit(&term->widget);
+	
+	if (term->frontbuf)
+		chargrid_destroy(term->frontbuf);
+	
+	if (term->backbuf)
+		chargrid_destroy(term->backbuf);
+}
+
+static void terminal_destroy(widget_t *widget)
+{
+	terminal_t *term = (terminal_t *) widget;
+	
+	deinit_terminal(term);
+	free(term);
+}
+
+static void terminal_reconfigure(widget_t *widget)
+{
+	/* No-op */
+}
+
+static void terminal_rearrange(widget_t *widget, sysarg_t hpos, sysarg_t vpos,
+    sysarg_t width, sysarg_t height)
+{
+	terminal_t *term = (terminal_t *) widget;
+	
+	widget_modify(widget, hpos, vpos, width, height);
+	widget->width_ideal = width;
+	widget->height_ideal = height;
+	
+	term_damage(term);
+}
+
+static void terminal_repaint(widget_t *widget)
+{
+	terminal_t *term = (terminal_t *) widget;
+	
+	term_damage(term);
+}
+
+static void terminal_handle_keyboard_event(widget_t *widget,
+    kbd_event_t kbd_event)
+{
+	terminal_t *term = (terminal_t *) widget;
+	
+	/* Got key press/release event */
+	kbd_event_t *event =
+	    (kbd_event_t *) malloc(sizeof(kbd_event_t));
+	if (event == NULL)
+		return;
+	
+	link_initialize(&event->link);
+	event->type = kbd_event.type;
+	event->key = kbd_event.key;
+	event->mods = kbd_event.mods;
+	event->c = kbd_event.c;
+	
+	prodcons_produce(&term->input_pc, &event->link);
+}
+
+static void terminal_handle_position_event(widget_t *widget, pos_event_t event)
+{
+	/*
+	 * Mouse events are ignored so far.
+	 * There is no consumer for it.
+	 */
+}
+
+static void term_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	terminal_t *term = NULL;
+	
+	list_foreach(terms, link) {
+		terminal_t *cur = list_get_instance(link, terminal_t, link);
+		
+		if (cur->dsid == (service_id_t) IPC_GET_ARG1(*icall)) {
+			term = cur;
+			break;
+		}
+	}
+	
+	if (term == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	if (atomic_postinc(&term->refcnt) == 0)
+		chargrid_set_cursor_visibility(term->frontbuf, true);
+	
+	con_conn(iid, icall, &term->srvs);
+}
+
+bool init_terminal(terminal_t *term, widget_t *parent, sysarg_t width,
+    sysarg_t height)
+{
+	widget_init(&term->widget, parent);
+	
+	link_initialize(&term->link);
+	fibril_mutex_initialize(&term->mtx);
+	atomic_set(&term->refcnt, 0);
+	
+	prodcons_initialize(&term->input_pc);
+	term->char_remains_len = 0;
+	
+	term->widget.width = width;
+	term->widget.height = height;
+	term->widget.width_ideal = width;
+	term->widget.height_ideal = height;
+	
+	term->widget.destroy = terminal_destroy;
+	term->widget.reconfigure = terminal_reconfigure;
+	term->widget.rearrange = terminal_rearrange;
+	term->widget.repaint = terminal_repaint;
+	term->widget.handle_keyboard_event = terminal_handle_keyboard_event;
+	term->widget.handle_position_event = terminal_handle_position_event;
+	
+	term->cols = width / FONT_WIDTH;
+	term->rows = height / FONT_SCANLINES;
+	
+	term->frontbuf = NULL;
+	term->backbuf = NULL;
+	
+	term->frontbuf = chargrid_create(term->cols, term->rows,
+	    CHARGRID_FLAG_NONE);
+	if (!term->frontbuf) {
+		widget_deinit(&term->widget);
+		return false;
+	}
+	
+	term->backbuf = chargrid_create(term->cols, term->rows,
+	    CHARGRID_FLAG_NONE);
+	if (!term->backbuf) {
+		widget_deinit(&term->widget);
+		return false;
+	}
+	
+	chargrid_clear(term->frontbuf);
+	chargrid_clear(term->backbuf);
+	term->top_row = 0;
+	
+	async_set_client_connection(term_connection);
+	con_srvs_init(&term->srvs);
+	term->srvs.ops = &con_ops;
+	term->srvs.sarg = term;
+	
+	int rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		widget_deinit(&term->widget);
+		return false;
+	}
+	
+	char vc[LOC_NAME_MAXLEN + 1];
+	snprintf(vc, LOC_NAME_MAXLEN, "%s/%" PRIu64, NAMESPACE,
+	    task_get_id());
+	
+	rc = loc_service_register(vc, &term->dsid);
+	if (rc != EOK) {
+		widget_deinit(&term->widget);
+		return false;
+	}
+	
+	list_append(&term->link, &terms);
+	getterm(vc, "/app/bdsh");
+	
+	return true;
+}
+
+terminal_t *create_terminal(widget_t *parent, sysarg_t width, sysarg_t height)
+{
+	terminal_t *term = (terminal_t *) malloc(sizeof(terminal_t));
+	if (!term)
+		return NULL;
+	
+	bool ret = init_terminal(term, parent, width, height);
+	if (!ret) {
+		free(term);
+		return NULL;
+	}
+	
+	return term;
+}
+
+/** @}
+ */
Index: uspace/lib/gui/terminal.h
===================================================================
--- uspace/lib/gui/terminal.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/terminal.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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_TERMINAL_H_
+#define GUI_TERMINAL_H_
+
+#include <sys/types.h>
+#include <fibril_synch.h>
+#include <font.h>
+#include <io/chargrid.h>
+#include <io/con_srv.h>
+#include <adt/list.h>
+#include <adt/prodcons.h>
+#include <atomic.h>
+#include "widget.h"
+
+#define UTF8_CHAR_BUFFER_SIZE  (STR_BOUNDS(1) + 1)
+
+typedef struct terminal {
+	widget_t widget;
+	
+	fibril_mutex_t mtx;
+	link_t link;
+	atomic_t refcnt;
+	
+	prodcons_t input_pc;
+	char char_remains[UTF8_CHAR_BUFFER_SIZE];
+	size_t char_remains_len;
+	
+	sysarg_t cols;
+	sysarg_t rows;
+	chargrid_t *frontbuf;
+	chargrid_t *backbuf;
+	sysarg_t top_row;
+	
+	service_id_t dsid;
+	con_srvs_t srvs;
+} terminal_t;
+
+extern bool init_terminal(terminal_t *, widget_t *, sysarg_t, sysarg_t);
+extern terminal_t *create_terminal(widget_t *, sysarg_t, sysarg_t);
+extern void deinit_terminal(terminal_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/gui/widget.c
===================================================================
--- uspace/lib/gui/widget.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/widget.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 "widget.h"
+
+void widget_init(widget_t *widget, widget_t *parent)
+{
+	link_initialize(&widget->link);
+	list_initialize(&widget->children);
+	if (parent) {
+		widget->parent = parent;
+		list_append(&widget->link, &parent->children);
+		widget->window = parent->window;
+	} else {
+		widget->parent = NULL;
+		widget->window = NULL;
+	}
+
+	widget->hpos = 0;
+	widget->vpos = 0;
+	widget->width = 0;
+	widget->height = 0;
+
+	widget->width_min = 0;
+	widget->height_min = 0;
+	widget->width_ideal = 0;
+	widget->height_ideal = 0;
+	widget->width_max = SIZE_MAX;
+	widget->height_max = SIZE_MAX;
+}
+
+void widget_modify(widget_t *widget, sysarg_t hpos, sysarg_t vpos,
+    sysarg_t width, sysarg_t height)
+{
+	widget->hpos = hpos;
+	widget->vpos = vpos;
+	widget->width = width;
+	widget->height = height;
+}
+
+void widget_deinit(widget_t *widget)
+{
+	if (widget->parent) {
+		list_remove(&widget->link);
+	}
+}
+
+/** @}
+ */
+
Index: uspace/lib/gui/widget.h
===================================================================
--- uspace/lib/gui/widget.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/widget.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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_WIDGET_H_
+#define GUI_WIDGET_H_
+
+#include <sys/types.h>
+#include <adt/list.h>
+#include <io/window.h>
+
+struct window;
+typedef struct window window_t;
+
+struct widget;
+typedef struct widget widget_t;
+
+/**
+ * Base class for all widgets. This structure should be first data member of
+ * any derived widget structure.
+ */
+typedef struct widget {
+	link_t link;
+	widget_t *parent; /**< Parent widget of this widget. NULL for root widget. */
+	list_t children; /**< Children widgets of this widget. */
+	window_t *window; /**< Window into which this widget belongs. */
+
+	sysarg_t hpos; /**< Horizontal position in window coordinates. */
+	sysarg_t vpos; /**< Vertical position in window coordinates. */
+	sysarg_t width;
+	sysarg_t height;
+	
+	sysarg_t width_min;
+	sysarg_t height_min;
+	sysarg_t width_ideal; /**< Width size hint for initialization. */
+	sysarg_t height_ideal; /**< Height size hint for initialization, */
+	sysarg_t width_max;
+	sysarg_t height_max;
+
+	/**
+	 * Virtual destructor. Apart from deallocating the resources specific for
+	 * the particular widget, each widget shall remove itself from parents
+	 * children and deallocate itself. */
+	void (*destroy)(widget_t *);
+
+	/**
+	 * Reserved for bottom-top traversal when widget changes its properties and
+	 * want to inform its ancestors in widget hierarchy to consider rearranging
+	 * their children. As a reaction to this call, each widget shall fetch
+	 * information from its children and decide whether its own properties have
+	 * to be changed. If not, widget shall calculate new layout for its children
+	 * and call rearrange() on each of them. Otherwise, widget shall change its
+	 * own properties and call reconfigure() on its parent. */
+	void (*reconfigure)(widget_t *);
+
+	/**
+	 * Reserved for top-bottom traversal when widget decides to change layout
+	 * of its childer. As a reaction to this call, widget shall change its
+	 * position and size according to provided arguments, paint itself,
+	 * calculate new layout for its children and call rearrange() on each
+	 * of them. */
+	void (*rearrange)(widget_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+
+	/**
+	 * As a reaction to window refresh event, widget hierarchy is traversed
+	 * in top-bottom order and repaint() is called on each widget. Widget shall
+	 * either paint itself or copy its private buffer onto window surface.
+	 * Widget shall also post damage event into window event loop. */
+	void (*repaint)(widget_t *);
+
+	/**
+	 * Keyboard events are delivered to widgets that have keyboard focus. As a
+	 * reaction to the event, widget might call reconfigure() on its parent or
+	 * rearrange() on its children. If the widget wants to change its visual
+	 * information, refresh event should be posted to the window event loop. */
+	void (*handle_keyboard_event)(widget_t *, kbd_event_t);
+
+	/**
+	 * Position events are delivered to those widgets that have mouse grab or
+	 * those that intersects with cursor. As a reaction to the event, widget
+	 * might call reconfigure() on its parent or rearrange() on its children.
+	 * If the widget wants to change its visual information, refresh event
+	 * should be posted to the window event loop. If the widget accepts
+	 * keyboard events, it should take ownership of keyboard focus. Widget can
+	 * also acquire or release mouse grab. */
+	void (*handle_position_event)(widget_t *, pos_event_t);
+} widget_t;
+
+/*
+ * Note on derived widget constructor/destructor:
+ * In order to support inheritance, wach widget shall provide init and deinit
+ * function. These functions take already allocated widget and are responsible
+ * for (de)initializing all widget-specific resources, inserting/removing the
+ * widget into/from widget hierarchy and (de)initializing all data and functions
+ * from the top-level base class defined above. For convenience, each widget
+ * should also provide constructor to allocate and init the widget in one step.
+ */
+
+/** Link widget with parent and initialize default position and size. */
+extern void widget_init(widget_t *, widget_t *);
+/** Just convenience function to change position and size of the widget. */
+extern void widget_modify(widget_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+/** Unlink widget from its parent. */
+extern void widget_deinit(widget_t *);
+
+#endif
+
+/** @}
+ */
+
Index: uspace/lib/gui/window.c
===================================================================
--- uspace/lib/gui/window.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/window.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,654 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 <bool.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <as.h>
+#include <malloc.h>
+#include <str.h>
+
+#include <fibril.h>
+#include <task.h>
+#include <adt/prodcons.h>
+#include <adt/list.h>
+
+#include <async.h>
+#include <loc.h>
+
+#include <io/pixel.h>
+#include <source.h>
+#include <font.h>
+#include <drawctx.h>
+#include <surface.h>
+
+#include "connection.h"
+#include "widget.h"
+#include "window.h"
+
+static sysarg_t border_thickness = 5;
+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_bgcolor = PIXEL(255, 25, 25, 112);
+static pixel_t header_fgcolor = 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);
+	}
+
+	source_t source;
+	font_t font;
+	drawctx_t drawctx;
+
+	source_init(&source);
+	font_init(&font, FONT_DECODER_EMBEDDED, NULL, 16);
+	drawctx_init(&drawctx, surface);
+	drawctx_set_source(&drawctx, &source);
+	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, header_bgcolor);
+	drawctx_transfer(&drawctx,
+	    w->hpos + border_thickness, w->vpos + border_thickness,
+		w->width - 2 * border_thickness, header_height);
+
+	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, header_fgcolor);
+	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);
+	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);
+		}
+	}
+
+	font_release(&font);
+	window_yield(w->window);
+}
+
+static void root_destroy(widget_t *widget)
+{
+	widget_deinit(widget);
+}
+
+static void root_reconfigure(widget_t *widget)
+{
+	if (widget->window->is_decorated) {
+		list_foreach(widget->children, link) {
+			widget_t *child = list_get_instance(link, widget_t, link);
+			child->rearrange(child, 
+			    widget->hpos + border_thickness,
+			    widget->vpos + border_thickness + header_height,
+			    widget->width - 2 * border_thickness,
+			    widget->height - 2 * border_thickness - header_height);
+		}
+	} else {
+		list_foreach(widget->children, link) {
+			widget_t *child = list_get_instance(link, widget_t, link);
+			child->rearrange(child, widget->hpos, widget->vpos,
+			    widget->width, widget->height);
+		}
+	}
+}
+
+static void root_rearrange(widget_t *widget, sysarg_t hpos, sysarg_t vpos,
+    sysarg_t width, sysarg_t height)
+{
+	widget_modify(widget, hpos, vpos, width, height);
+	if (widget->window->is_decorated) {
+		paint_internal(widget);
+		list_foreach(widget->children, link) {
+			widget_t *child = list_get_instance(link, widget_t, link);
+			child->rearrange(child, 
+			    hpos + border_thickness,
+			    vpos + border_thickness + header_height,
+			    width - 2 * border_thickness,
+			    height - 2 * border_thickness - header_height);
+		}
+	} else {
+		list_foreach(widget->children, link) {
+			widget_t *child = list_get_instance(link, widget_t, link);
+			child->rearrange(child, hpos, vpos, width, height);
+		}
+	}
+}
+
+static void root_repaint(widget_t *widget)
+{
+	if (widget->window->is_decorated) {
+		paint_internal(widget);
+	}
+	list_foreach(widget->children, link) {
+		widget_t *child = list_get_instance(link, widget_t, link);
+		child->repaint(child);
+	}
+	if (widget->window->is_decorated) {
+		window_damage(widget->window);
+	}
+}
+
+static void root_handle_keyboard_event(widget_t *widget, kbd_event_t event)
+{
+	if (!list_empty(&widget->children)) {
+		widget_t *child = (widget_t *) list_first(&widget->children);
+		child->handle_keyboard_event(child, event);
+	}
+}
+
+static void root_handle_position_event(widget_t *widget, pos_event_t event)
+{
+	if (widget->window->is_decorated) {
+		sysarg_t width = widget->width;
+		sysarg_t height = widget->height;
+
+		bool btn_left = (event.btn_num == 1) && (event.type == POS_PRESS);
+		bool btn_right = (event.btn_num == 2) && (event.type == POS_PRESS);
+		bool allowed_button = btn_left || btn_right;
+
+		bool left = (event.hpos < border_thickness);
+		bool right = (event.hpos >= width - border_thickness);
+		bool top = (event.vpos < border_thickness);
+		bool bottom = (event.vpos >= height - border_thickness);
+		bool header = (event.hpos >= border_thickness) &&
+		    (event.hpos < width - border_thickness) &&
+		    (event.vpos >= border_thickness) &&
+		    (event.vpos < border_thickness + header_height);
+		bool close = header && (event.hpos >= width - border_thickness - close_width);
+
+		if (top && left && allowed_button) {
+			window_grab_flags_t flags = GF_EMPTY;
+			flags |= GF_MOVE_X;
+			flags |= GF_MOVE_Y;
+			flags |= btn_left ? GF_RESIZE_X : GF_SCALE_X;
+			flags |= btn_left ? GF_RESIZE_Y : GF_SCALE_Y;
+			win_grab(widget->window->osess, event.pos_id, flags);
+		} else if (bottom && left && allowed_button) {
+			window_grab_flags_t flags = GF_EMPTY;
+			flags |= GF_MOVE_X;
+			flags |= btn_left ? GF_RESIZE_X : GF_SCALE_X;
+			flags |= btn_left ? GF_RESIZE_Y : GF_SCALE_Y;
+			win_grab(widget->window->osess, event.pos_id, flags);
+		} else if (bottom && right && allowed_button) {
+			window_grab_flags_t flags = GF_EMPTY;
+			flags |= btn_left ? GF_RESIZE_X : GF_SCALE_X;
+			flags |= btn_left ? GF_RESIZE_Y : GF_SCALE_Y;
+			win_grab(widget->window->osess, event.pos_id, flags);
+		} else if (top && right && allowed_button) {
+			window_grab_flags_t flags = GF_EMPTY;
+			flags |= GF_MOVE_Y;
+			flags |= btn_left ? GF_RESIZE_X : GF_SCALE_X;
+			flags |= btn_left ? GF_RESIZE_Y : GF_SCALE_Y;
+			win_grab(widget->window->osess, event.pos_id, flags);
+		} else if (top && allowed_button) {
+			window_grab_flags_t flags = GF_EMPTY;
+			flags |= GF_MOVE_Y;
+			flags |= btn_left ? GF_RESIZE_Y : GF_SCALE_Y;
+			win_grab(widget->window->osess, event.pos_id, flags);
+		} else if (left && allowed_button) {
+			window_grab_flags_t flags = GF_EMPTY;
+			flags |= GF_MOVE_X;
+			flags |= btn_left ? GF_RESIZE_X : GF_SCALE_X;
+			win_grab(widget->window->osess, event.pos_id, flags);
+		} else if (bottom && allowed_button) {
+			window_grab_flags_t flags = GF_EMPTY;
+			flags |= btn_left ? GF_RESIZE_Y : GF_SCALE_Y;
+			win_grab(widget->window->osess, event.pos_id, flags);
+		} else if (right && allowed_button) {
+			window_grab_flags_t flags = GF_EMPTY;
+			flags |= btn_left ? GF_RESIZE_X : GF_SCALE_X;
+			win_grab(widget->window->osess, event.pos_id, flags);
+		} else if (close && btn_left) {
+			win_close_request(widget->window->osess);
+		} else if (header && btn_left) {
+			window_grab_flags_t flags = GF_EMPTY;
+			flags |= GF_MOVE_X;
+			flags |= GF_MOVE_Y;
+			win_grab(widget->window->osess, event.pos_id, flags);
+		} else {
+			list_foreach(widget->children, link) {
+				widget_t *child = list_get_instance(link, widget_t, link);
+				child->handle_position_event(child, event);
+			}
+		}
+	} else {
+		list_foreach(widget->children, link) {
+			widget_t *child = list_get_instance(link, widget_t, link);
+			child->handle_position_event(child, event);
+		}
+	}
+}
+
+static void deliver_keyboard_event(window_t *win, kbd_event_t event)
+{
+	if (win->focus) {
+		win->focus->handle_keyboard_event(win->focus, event);
+	} else {
+		win->root.handle_keyboard_event(&win->root, event);
+	}
+}
+
+static void deliver_position_event(window_t *win, pos_event_t event)
+{
+	if (win->grab) {
+		win->grab->handle_position_event(win->grab, event);
+	} else {
+		win->root.handle_position_event(&win->root, event);
+	}
+}
+
+static void handle_signal_event(window_t *win, sig_event_t event)
+{
+	widget_t *widget = (widget_t *) event.object;
+	slot_t slot = (slot_t) event.slot;
+	void *data = (void *) event.argument;
+
+	slot(widget, data);
+
+	free(data);
+}
+
+static void handle_resize(window_t *win, sysarg_t width, sysarg_t height)
+{
+	int rc;
+	surface_t *old_surface;
+	surface_t *new_surface;
+
+	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) {
+		return;
+	}
+
+	/* Switch new and old surface. */
+	fibril_mutex_lock(&win->guard);
+	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. */
+	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));
+
+	if (rc != EOK) {
+		/* Rollback to old surface. Reverse all changes. */
+
+		sysarg_t old_width = 0;
+		sysarg_t old_height = 0;
+		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);
+		
+		if (win->surface) {
+			fibril_mutex_lock(&win->guard);
+			surface_reset_damaged_region(win->surface);
+			fibril_mutex_unlock(&win->guard);
+		}
+
+		surface_destroy(new_surface);
+		return;
+	}
+
+	/* Finally deallocate old surface. */
+	if (old_surface) {
+		surface_destroy(old_surface);
+	}
+}
+
+static void handle_refresh(window_t *win)
+{
+	win->root.repaint(&win->root);
+}
+
+static void handle_damage(window_t *win)
+{
+	sysarg_t x, y, width, height;
+	fibril_mutex_lock(&win->guard);
+	surface_get_damaged_region(win->surface, &x, &y, &width, &height);
+	surface_reset_damaged_region(win->surface);
+	fibril_mutex_unlock(&win->guard);
+
+	if (width > 0 && height > 0) {
+		/* Notify compositor. */
+		win_damage(win->osess, x, y, width, height);
+	}
+}
+
+static void destroy_children(widget_t *widget)
+{
+	/* Recursively destroy widget tree in bottom-top order. */
+	while (!list_empty(&widget->children)) {
+		widget_t *child =
+		    list_get_instance(list_first(&widget->children), widget_t, link);
+		destroy_children(child);
+		child->destroy(child);
+	}
+}
+
+static void handle_close(window_t *win)
+{
+	destroy_children(&win->root);
+	win->root.destroy(&win->root);
+	win->grab = NULL;
+	win->focus = NULL;
+
+	win_close(win->osess);
+	async_hangup(win->isess);
+	async_hangup(win->osess);
+
+	while (!list_empty(&win->events.list)) {
+		list_remove(list_first(&win->events.list));
+	}
+
+	if (win->surface) {
+		surface_destroy(win->surface);
+	}
+
+	free(win->caption);
+
+	free(win);
+}
+
+/* Window event loop. Runs in own dedicated fibril. */
+static int event_loop(void *arg)
+{
+	bool is_main = false;
+	bool terminate = false;
+	window_t *win = (window_t *) arg;
+
+	while (true) {
+		window_event_t *event = (window_event_t *) prodcons_consume(&win->events);
+
+		switch (event->type) {
+		case ET_KEYBOARD_EVENT:
+			deliver_keyboard_event(win, event->data.kbd);
+			break;
+		case ET_POSITION_EVENT:
+			deliver_position_event(win, event->data.pos);
+			break;
+		case ET_SIGNAL_EVENT:
+			handle_signal_event(win, event->data.sig);
+			break;
+		case ET_WINDOW_RESIZE:
+			handle_resize(win, event->data.rsz.width, event->data.rsz.height);
+			break;
+		case ET_WINDOW_REFRESH:
+			handle_refresh(win);
+			break;
+		case ET_WINDOW_DAMAGE:
+			handle_damage(win);
+			break;
+		case ET_WINDOW_CLOSE:
+			is_main = win->is_main;
+			handle_close(win);
+			terminate = true;
+			break;
+		default:
+			break;
+		}
+
+		free(event);
+		if (terminate) {
+			break;
+		}
+	}
+
+	if (is_main) {
+		exit(0); /* Terminate whole task. */
+	}
+	return 0;
+}
+
+/* Input fetcher from compositor. Runs in own dedicated fibril. */
+static int fetch_input(void *arg)
+{
+	int rc;
+	bool terminate = false;
+	window_t *win = (window_t *) arg;
+
+	while (true) {
+		window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
+		
+		if (event) {
+			rc = win_get_event(win->isess, event);
+			if (rc == EOK) {
+				terminate = (event->type == ET_WINDOW_CLOSE);
+				link_initialize(&event->link);
+				prodcons_produce(&win->events, &event->link);
+			} else {
+				free(event);
+				terminate = true;
+			}
+		} else {
+			terminate = true;
+		}
+
+		if (terminate) {
+			break;
+		}
+	}
+
+	return 0;
+}
+
+window_t *window_open(char *winreg, bool is_main, bool is_decorated, const char *caption)
+{
+	int rc;
+
+	window_t *win = (window_t *) malloc(sizeof(window_t));
+	if (!win) {
+		return NULL;
+	}
+
+	win->is_main = is_main;
+	win->is_decorated = is_decorated;
+	prodcons_initialize(&win->events);
+	fibril_mutex_initialize(&win->guard);
+	widget_init(&win->root, NULL);
+	win->root.window = win;
+	win->root.destroy = root_destroy;
+	win->root.reconfigure = root_reconfigure;
+	win->root.rearrange = root_rearrange;
+	win->root.repaint = root_repaint;
+	win->root.handle_keyboard_event = root_handle_keyboard_event;
+	win->root.handle_position_event = root_handle_position_event;
+	win->grab = NULL;
+	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);
+	if (rc != EOK) {
+		free(win);
+		return NULL;
+	}
+
+	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);
+	async_hangup(reg_sess);
+	if (rc != EOK) {
+		free(win);
+		return NULL;
+	}
+
+	win->osess = loc_service_connect(EXCHANGE_SERIALIZE, out_dsid, 0);
+	if (win->osess == NULL) {
+		free(win);
+		return NULL;
+	}
+
+	win->isess = loc_service_connect(EXCHANGE_SERIALIZE, in_dsid, 0);
+	if (win->isess == NULL) {
+		async_hangup(win->osess);
+		free(win);
+		return NULL;
+	}
+
+	if (caption == NULL) {
+		win->caption = NULL;
+	} else {
+		win->caption = str_dup(caption);
+	}
+
+	return win;
+}
+
+void window_resize(window_t *win, sysarg_t width, sysarg_t height)
+{
+	window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
+	if (event) {
+		link_initialize(&event->link);
+		event->type = ET_WINDOW_RESIZE;
+		event->data.rsz.width = width;
+		event->data.rsz.height = height;
+		prodcons_produce(&win->events, &event->link);
+	}
+}
+
+void window_refresh(window_t *win)
+{
+	window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
+	if (event) {
+		link_initialize(&event->link);
+		event->type = ET_WINDOW_REFRESH;
+		prodcons_produce(&win->events, &event->link);
+	}
+}
+
+void window_damage(window_t *win)
+{
+	window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
+	if (event) {
+		link_initialize(&event->link);
+		event->type = ET_WINDOW_DAMAGE;
+		prodcons_produce(&win->events, &event->link);
+	}
+}
+
+widget_t *window_root(window_t *win)
+{
+	return &win->root;
+}
+
+void window_exec(window_t *win)
+{
+	fid_t ev_fid = fibril_create(event_loop, win);
+	fid_t fi_fid = fibril_create(fetch_input, win);
+	if (!ev_fid || !fi_fid) {
+		return;
+	}
+	fibril_add_ready(ev_fid);
+	fibril_add_ready(fi_fid);
+}
+
+surface_t *window_claim(window_t *win)
+{
+	fibril_mutex_lock(&win->guard);
+	return win->surface;
+}
+
+void window_yield(window_t *win)
+{
+	fibril_mutex_unlock(&win->guard);
+}
+
+void window_close(window_t *win)
+{
+	/* Request compositor to init closing cascade. */
+	win_close_request(win->osess);
+}
+
+/** @}
+ */
Index: uspace/lib/gui/window.h
===================================================================
--- uspace/lib/gui/window.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/gui/window.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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_WINDOW_H_
+#define GUI_WINDOW_H_
+
+#include <sys/types.h>
+#include <async.h>
+#include <adt/prodcons.h>
+#include <fibril_synch.h>
+#include <ipc/window.h>
+#include <io/window.h>
+#include <surface.h>
+
+#include "widget.h"
+
+typedef struct window {
+	bool is_main; /**< True for the main window of the application. */
+	bool is_decorated; /**< True if the window decorations should be rendered. */
+	char *caption; /**< Text title of the window header. */
+	async_sess_t *isess; /**< Input events from compositor. */
+	async_sess_t *osess; /**< Mainly for damage reporting to compositor. */
+	prodcons_t events; /**< Queue for window event loop. */
+	widget_t root; /**< Decoration widget serving as a root of widget hiearchy. */
+	widget_t *grab; /**< Widget owning the mouse or NULL. */
+	widget_t *focus; /**< Widget owning the keyboard or NULL. */
+	fibril_mutex_t guard; /**< Mutex guarding window surface. */
+	surface_t *surface; /**< Window surface shared with compositor. */
+} window_t;
+
+/**
+ * Allocate all resources for new window and register it in the compositor.
+ * 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(char *, bool, bool, const char *);
+
+/**
+ * Post resize event into event loop. Window negotiates new surface with
+ * compositor and asks all widgets in the tree to calculate their new properties
+ * 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);
+
+/**
+ * Post refresh event into event loop. Widget tree is traversed and all widgets
+ * are asked to repaint themselves in top-bottom order. Should be called by
+ * widget after such change of its internal state that does not need resizing
+ * of neither parent nor children (). */
+extern void window_refresh(window_t *);
+
+/**
+ * Post damage event into event loop. Handler informs compositor to update the
+ * window surface on the screen. Should be called by widget after painting
+ * itself or copying its buffer onto window surface. */
+extern void window_damage(window_t *);
+
+/**
+ * Retrieve dummy root widget of the window widget tree. Intended to be called
+ * by proper top-level widget to set his parent. */
+extern widget_t *window_root(window_t *);
+
+/**
+ * Prepare and enqueue window fibrils for event loop and input fetching. When
+ * async_manager() function is called, event loop is executed. */
+extern void window_exec(window_t *);
+
+/**
+ * Claim protected window surface. Intended for widgets painting from their
+ * internal fibrils (e.g. terminal, animation, video). */
+extern surface_t *window_claim(window_t *);
+
+/**
+ * Yield protected window surface after painting. */
+extern void window_yield(window_t *);
+
+/**
+ * Initiate the closing cascade for the window. First, compositor deallocates
+ * output resources, prepares special closing input event for the window and
+ * deallocates input resources after the event is dispatched. When window
+ * fetches closing event, it is posted into event loop and input fibril
+ * terminates. When event loop fibril handles closing event, all window
+ * resources are deallocated and fibril also terminates. Moreover, if the
+ * window is main window of the application, whole task terminates. */
+extern void window_close(window_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/nic/include/nic.h
===================================================================
--- uspace/lib/nic/include/nic.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/nic/include/nic.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,4 +40,5 @@
 
 #include <adt/list.h>
+#include <adt/hash_table.h>
 #include <ddf/driver.h>
 #include <device/hw_res_parsed.h>
@@ -53,5 +54,5 @@
  */
 typedef struct nic_wol_virtue {
-	link_t item;
+	ht_link_t item;
 	nic_wv_id_t id;
 	nic_wv_type_t type;
Index: uspace/lib/nic/include/nic_addr_db.h
===================================================================
--- uspace/lib/nic/include/nic_addr_db.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/nic/include/nic_addr_db.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -43,14 +43,5 @@
 #endif
 
-#include <adt/hash_set.h>
-
-/**
- * Initial size of DB's hash set
- */
-#define NIC_ADDR_DB_INIT_SIZE 	8
-/**
- * Maximal length of addresses in the DB (in bytes).
- */
-#define NIC_ADDR_MAX_LENGTH		16
+#include <adt/hash_table.h>
 
 /**
@@ -58,25 +49,14 @@
  */
 typedef struct nic_addr_db {
-	hash_set_t set;
+	hash_table_t set;
 	size_t addr_len;
 } nic_addr_db_t;
 
-/**
- * Helper structure for keeping the address in the hash set.
- */
-typedef struct nic_addr_entry {
-	link_t item;
-	size_t addr_len;
-	uint8_t addr[NIC_ADDR_MAX_LENGTH];
-} nic_addr_entry_t;
 
 extern int nic_addr_db_init(nic_addr_db_t *db, size_t addr_len);
 extern void nic_addr_db_clear(nic_addr_db_t *db);
 extern void nic_addr_db_destroy(nic_addr_db_t *db);
-extern size_t nic_addr_db_count(const nic_addr_db_t *db);
 extern int nic_addr_db_insert(nic_addr_db_t *db, const uint8_t *addr);
 extern int nic_addr_db_remove(nic_addr_db_t *db, const uint8_t *addr);
-extern void nic_addr_db_remove_selected(nic_addr_db_t *db,
-	int (*func)(const uint8_t *, void *), void *arg);
 extern int nic_addr_db_contains(const nic_addr_db_t *db, const uint8_t *addr);
 extern void nic_addr_db_foreach(const nic_addr_db_t *db,
Index: uspace/lib/nic/include/nic_wol_virtues.h
===================================================================
--- uspace/lib/nic/include/nic_wol_virtues.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/nic/include/nic_wol_virtues.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -51,5 +51,5 @@
 	 * Operations for table
 	 */
-	hash_table_operations_t table_operations;
+	hash_table_ops_t table_operations;
 	/**
 	 * WOL virtues hashed by their ID's.
Index: uspace/lib/nic/src/nic_addr_db.c
===================================================================
--- uspace/lib/nic/src/nic_addr_db.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/nic/src/nic_addr_db.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,4 +35,6 @@
  * @brief Generic hash-set based database of addresses
  */
+#include "nic_addr_db.h"
+#include "libarch/common.h"
 #include <assert.h>
 #include <stdlib.h>
@@ -40,49 +42,72 @@
 #include <errno.h>
 #include <mem.h>
-
-#include "nic_addr_db.h"
-
-/**
- * Hash set helper function
- */
-static int nic_addr_equals(const link_t *item1, const link_t *item2)
-{
-	assert(item1 && item2);
-	size_t addr_len = ((const nic_addr_entry_t *) item1)->addr_len;
-
-	assert(addr_len	== ((const nic_addr_entry_t *) item2)->addr_len);
-
-	size_t i;
-	for (i = 0; i < addr_len; ++i) {
-		if (((nic_addr_entry_t *) item1)->addr[i] !=
-			((nic_addr_entry_t *) item2)->addr[i])
-			return false;
+#include <adt/hash_table.h>
+#include <macros.h>
+#include <stdint.h>
+
+
+/**
+ * Helper structure for keeping the address in the hash set.
+ */
+typedef struct nic_addr_entry {
+	ht_link_t link;
+	uint8_t len;
+	uint8_t addr[1];
+} nic_addr_entry_t;
+
+
+/* 
+ * Hash table helper functions 
+ */
+typedef struct {
+	size_t len;
+	const uint8_t *addr;
+} addr_key_t;
+
+static bool nic_addr_key_equal(void *key_arg, const ht_link_t *item)
+{
+	addr_key_t *key = (addr_key_t*)key_arg;
+	nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
+	
+	return 0 == bcmp(entry->addr, key->addr, entry->len);
+}
+
+static size_t addr_hash(size_t len, const uint8_t *addr)
+{
+	size_t hash = 0;
+	
+	for (size_t i = 0; i < len; ++i) {
+		hash = (hash << 5) ^ addr[i];
 	}
-	return true;
-}
-
-/**
- * Hash set helper function
- */
-static unsigned long nic_addr_hash(const link_t *item)
-{
-	assert(item);
-	const nic_addr_entry_t *entry = (const nic_addr_entry_t *) item;
-	unsigned long hash = 0;
-
-	size_t i;
-	for (i = 0; i < entry->addr_len; ++i) {
-		hash = (hash << 8) ^ (hash >> 24) ^ entry->addr[i];
-	}
+	
 	return hash;
 }
 
-/**
- * Helper wrapper
- */
-static void nic_addr_destroy(link_t *item, void *unused)
-{
-	free(item);
-}
+static size_t nic_addr_key_hash(void *k)
+{
+	addr_key_t *key = (addr_key_t*)k;
+	return addr_hash(key->len, key->addr);
+}
+
+static size_t nic_addr_hash(const ht_link_t *item)
+{
+	nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
+	return addr_hash(entry->len, entry->addr);
+}
+
+static void nic_addr_removed(ht_link_t *item)
+{
+	nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
+	
+	free(entry);
+}
+
+static hash_table_ops_t set_ops = {
+	.hash = nic_addr_hash,
+	.key_hash = nic_addr_key_hash,
+	.key_equal = nic_addr_key_equal,
+	.equal = NULL,
+	.remove_callback = nic_addr_removed
+};
 
 /**
@@ -99,11 +124,11 @@
 {
 	assert(db);
-	if (addr_len > NIC_ADDR_MAX_LENGTH) {
+	
+	if (addr_len > UCHAR_MAX)
 		return EINVAL;
-	}
-	if (!hash_set_init(&db->set, nic_addr_hash, nic_addr_equals,
-		NIC_ADDR_DB_INIT_SIZE)) {
+	
+	if (!hash_table_create(&db->set, 0, 0, &set_ops))
 		return ENOMEM;
-	}
+	
 	db->addr_len = addr_len;
 	return EOK;
@@ -118,5 +143,5 @@
 {
 	assert(db);
-	hash_set_clear(&db->set, nic_addr_destroy, NULL);
+	hash_table_clear(&db->set);
 }
 
@@ -129,20 +154,7 @@
 {
 	assert(db);
-	hash_set_apply(&db->set, nic_addr_destroy, NULL);
-	hash_set_destroy(&db->set);
-}
-
-/**
- * Get number of addresses in the db
- *
- * @param	db
- *
- * @return Number of adresses
- */
-size_t nic_addr_db_count(const nic_addr_db_t *db)
-{
-	assert(db);
-	return hash_set_count(&db->set);
-}
+	hash_table_destroy(&db->set);
+}
+
 
 /**
@@ -160,12 +172,22 @@
 {
 	assert(db && addr);
-	nic_addr_entry_t *entry = malloc(sizeof (nic_addr_entry_t));
-	if (entry == NULL) {
+
+	addr_key_t key = {
+		.len = db->addr_len,
+		.addr = addr
+	};
+	
+	if (hash_table_find(&db->set, &key))
+		return EEXIST;
+	
+	nic_addr_entry_t *entry = malloc(sizeof(nic_addr_entry_t) + db->addr_len - 1);
+	if (entry == NULL) 
 		return ENOMEM;
-	}
-	entry->addr_len = db->addr_len;
+
+	entry->len = (uint8_t) db->addr_len;
 	memcpy(entry->addr, addr, db->addr_len);
-
-	return hash_set_insert(&db->set, &entry->item) ? EOK : EEXIST;
+	
+	hash_table_insert(&db->set, &entry->link);
+	return EOK;
 }
 
@@ -182,11 +204,14 @@
 {
 	assert(db && addr);
-	nic_addr_entry_t entry;
-	entry.addr_len = db->addr_len;
-	memcpy(entry.addr, addr, db->addr_len);
-
-	link_t *removed = hash_set_remove(&db->set, &entry.item);
-	free(removed);
-	return removed != NULL ? EOK : ENOENT;
+	
+	addr_key_t key = {
+		.len = db->addr_len,
+		.addr = addr
+	};
+	
+	if (hash_table_remove(&db->set, &key))
+		return EOK;
+	else
+		return ENOENT;
 }
 
@@ -202,9 +227,11 @@
 {
 	assert(db && addr);
-	nic_addr_entry_t entry;
-	entry.addr_len = db->addr_len;
-	memcpy(entry.addr, addr, db->addr_len);
-
-	return hash_set_contains(&db->set, &entry.item);
+	
+	addr_key_t key = {
+		.len = db->addr_len,
+		.addr = addr
+	};
+	
+	return 0 != hash_table_find(&db->set, &key);
 }
 
@@ -220,7 +247,10 @@
  * Helper function for nic_addr_db_foreach
  */
-static void nic_addr_db_fe_helper(link_t *item, void *arg) {
+static bool nic_addr_db_fe_helper(ht_link_t *item, void *arg) 
+{
 	nic_addr_db_fe_arg_t *hs = (nic_addr_db_fe_arg_t *) arg;
-	hs->func(((nic_addr_entry_t *) item)->addr, hs->arg);
+	nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
+	hs->func(entry->addr, hs->arg);
+	return true;
 }
 
@@ -237,39 +267,5 @@
 {
 	nic_addr_db_fe_arg_t hs = { .func = func, .arg = arg };
-	hash_set_apply((hash_set_t *) &db->set, nic_addr_db_fe_helper, &hs);
-}
-
-/**
- * Helper structure for nic_addr_db_remove_selected
- */
-typedef struct {
-	int (*func)(const uint8_t *, void *);
-	void *arg;
-} nic_addr_db_rs_arg_t;
-
-/**
- * Helper function for nic_addr_db_foreach
- */
-static int nic_addr_db_rs_helper(link_t *item, void *arg) {
-	nic_addr_db_rs_arg_t *hs = (nic_addr_db_rs_arg_t *) arg;
-	int retval = hs->func(((nic_addr_entry_t *) item)->addr, hs->arg);
-	if (retval) {
-		free(item);
-	}
-	return retval;
-}
-
-/**
- * Removes all addresses for which the function returns non-zero.
- *
- * @param	db
- * @param	func	User-defined function
- * @param	arg		Custom argument passed to the function
- */
-void nic_addr_db_remove_selected(nic_addr_db_t *db,
-	int (*func)(const uint8_t *, void *), void *arg)
-{
-	nic_addr_db_rs_arg_t hs = { .func = func, .arg = arg };
-	hash_set_remove_selected(&db->set, nic_addr_db_rs_helper, &hs);
+	hash_table_apply((hash_table_t*)&db->set, nic_addr_db_fe_helper, &hs);
 }
 
Index: uspace/lib/nic/src/nic_driver.c
===================================================================
--- uspace/lib/nic/src/nic_driver.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/nic/src/nic_driver.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,5 +47,4 @@
 #include <sysinfo.h>
 #include <as.h>
-#include <devman.h>
 #include <ddf/interrupt.h>
 #include <ops/nic.h>
@@ -250,12 +249,12 @@
 {
 	ddf_dev_t *dev = nic_data->dev;
+	async_sess_t *parent_sess;
 	
 	/* Connect to the parent's driver. */
-	dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-		dev->handle, IPC_FLAG_BLOCKING);
-	if (dev->parent_sess == NULL)
+	parent_sess = ddf_dev_parent_sess_create(dev, EXCHANGE_SERIALIZE);
+	if (parent_sess == NULL)
 		return EPARTY;
 	
-	return hw_res_get_list_parsed(nic_data->dev->parent_sess, resources, 0);
+	return hw_res_get_list_parsed(parent_sess, resources, 0);
 }
 
@@ -650,19 +649,16 @@
  *
  */
-static nic_t *nic_create(void)
-{
-	nic_t *nic_data = malloc(sizeof(nic_t));
+static nic_t *nic_create(ddf_dev_t *dev)
+{
+	nic_t *nic_data = ddf_dev_data_alloc(dev, sizeof(nic_t));
 	if (nic_data == NULL)
 		return NULL;
 	
 	/* Force zero to all uninitialized fields (e.g. added in future) */
-	bzero(nic_data, sizeof(nic_t));
 	if (nic_rxc_init(&nic_data->rx_control) != EOK) {
-		free(nic_data);
 		return NULL;
 	}
 	
 	if (nic_wol_virtues_init(&nic_data->wol_virtues) != EOK) {
-		free(nic_data);
 		return NULL;
 	}
@@ -705,13 +701,9 @@
 nic_t *nic_create_and_bind(ddf_dev_t *device)
 {
-	assert(device);
-	assert(!device->driver_data);
-	
-	nic_t *nic_data = nic_create();
+	nic_t *nic_data = nic_create(device);
 	if (!nic_data)
 		return NULL;
 	
 	nic_data->dev = device;
-	device->driver_data = nic_data;
 	
 	return nic_data;
@@ -724,11 +716,7 @@
  * @param data
  */
-static void nic_destroy(nic_t *nic_data) {
-	if (nic_data->client_session != NULL) {
-		async_hangup(nic_data->client_session);
-	}
-
+static void nic_destroy(nic_t *nic_data)
+{
 	free(nic_data->specific);
-	free(nic_data);
 }
 
@@ -740,12 +728,7 @@
  * @param device The NIC device structure
  */
-void nic_unbind_and_destroy(ddf_dev_t *device){
-	if (!device)
-		return;
-	if (!device->driver_data)
-		return;
-
-	nic_destroy((nic_t *) device->driver_data);
-	device->driver_data = NULL;
+void nic_unbind_and_destroy(ddf_dev_t *device)
+{
+	nic_destroy(nic_get_from_ddf_dev(device));
 	return;
 }
@@ -983,6 +966,6 @@
 nic_t *nic_get_from_ddf_dev(ddf_dev_t *dev)
 {
-	return (nic_t *) dev->driver_data;
-};
+	return (nic_t *) ddf_dev_data_get(dev);
+}
 
 /** 
@@ -992,6 +975,6 @@
 nic_t *nic_get_from_ddf_fun(ddf_fun_t *fun)
 {
-	return (nic_t *) fun->driver_data;
-};
+	return (nic_t *) ddf_fun_data_get(fun);
+}
 
 /**
Index: uspace/lib/nic/src/nic_impl.c
===================================================================
--- uspace/lib/nic/src/nic_impl.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/nic/src/nic_impl.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -54,5 +54,5 @@
 int nic_get_state_impl(ddf_fun_t *fun, nic_device_state_t *state)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->main_lock);
 	*state = nic_data->state;
@@ -78,5 +78,5 @@
 	}
 
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 
 	fibril_rwlock_write_lock(&nic_data->main_lock);
@@ -170,5 +170,5 @@
 int nic_send_frame_impl(ddf_fun_t *fun, void *data, size_t size)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 
 	fibril_rwlock_read_lock(&nic_data->main_lock);
@@ -192,5 +192,5 @@
 int nic_callback_create_impl(ddf_fun_t *fun)
 {
-	nic_t *nic = (nic_t *) fun->driver_data;
+	nic_t *nic = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_write_lock(&nic->main_lock);
 	
@@ -218,5 +218,5 @@
 {
 	assert(address);
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->main_lock);
 	memcpy(address, &nic_data->mac, sizeof (nic_address_t));
@@ -236,5 +236,5 @@
 int nic_get_stats_impl(ddf_fun_t *fun, nic_device_stats_t *stats)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	assert (stats != NULL);
 	fibril_rwlock_read_lock(&nic_data->stats_lock);
@@ -259,5 +259,5 @@
 	size_t max_count, nic_address_t *addr_list, size_t *addr_count)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->rxc_lock);
 	nic_rxc_unicast_get_mode(&nic_data->rx_control, mode, max_count,
@@ -291,5 +291,5 @@
 	}
 
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_write_lock(&nic_data->rxc_lock);
 	int rc = ENOTSUP;
@@ -326,5 +326,5 @@
 	size_t max_count, nic_address_t *addr_list, size_t *addr_count)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->rxc_lock);
 	nic_rxc_multicast_get_mode(&nic_data->rx_control, mode, max_count,
@@ -358,5 +358,5 @@
 	}
 
-	nic_t *nic_data = (nic_t *) fun->dev->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_write_lock(&nic_data->rxc_lock);
 	int rc = ENOTSUP;
@@ -382,5 +382,5 @@
 int nic_broadcast_get_mode_impl(ddf_fun_t *fun, nic_broadcast_mode_t *mode)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->rxc_lock);
 	nic_rxc_broadcast_get_mode(&nic_data->rx_control, mode);
@@ -402,5 +402,5 @@
 int nic_broadcast_set_mode_impl(ddf_fun_t *fun, nic_broadcast_mode_t mode)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_write_lock(&nic_data->rxc_lock);
 	int rc = ENOTSUP;
@@ -429,5 +429,5 @@
 	size_t max_count, nic_address_t *addr_list, size_t *addr_count)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->rxc_lock);
 	nic_rxc_blocked_sources_get(&nic_data->rx_control,
@@ -452,5 +452,5 @@
 	const nic_address_t *addr_list, size_t addr_count)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_write_lock(&nic_data->rxc_lock);
 	if (nic_data->on_blocked_sources_change) {
@@ -474,5 +474,5 @@
 int nic_vlan_get_mask_impl(ddf_fun_t *fun, nic_vlan_mask_t *mask)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->rxc_lock);
 	int rc = nic_rxc_vlan_get_mask(&nic_data->rx_control, mask);
@@ -492,5 +492,5 @@
 int nic_vlan_set_mask_impl(ddf_fun_t *fun, const nic_vlan_mask_t *mask)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_write_lock(&nic_data->rxc_lock);
 	int rc = nic_rxc_vlan_set_mask(&nic_data->rx_control, mask);
@@ -520,5 +520,5 @@
 	const void *data, size_t length, nic_wv_id_t *new_id)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	if (nic_data->on_wol_virtue_add == NULL
 		|| nic_data->on_wol_virtue_remove == NULL) {
@@ -594,5 +594,5 @@
 int nic_wol_virtue_remove_impl(ddf_fun_t *fun, nic_wv_id_t id)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	if (nic_data->on_wol_virtue_add == NULL
 		|| nic_data->on_wol_virtue_remove == NULL) {
@@ -631,5 +631,5 @@
 	nic_wv_type_t *type, size_t max_length, void *data, size_t *length)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->wv_lock);
 	const nic_wol_virtue_t *virtue =
@@ -669,5 +669,5 @@
 	size_t max_count, nic_wv_id_t *id_list, size_t *id_count)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->wv_lock);
 	int rc = nic_wol_virtues_list(&nic_data->wol_virtues, type,
@@ -689,5 +689,5 @@
 int nic_wol_virtue_get_caps_impl(ddf_fun_t *fun, nic_wv_type_t type, int *count)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->wv_lock);
 	*count = nic_data->wol_virtues.caps_max[type]
@@ -712,5 +712,5 @@
 	nic_poll_mode_t *mode, struct timeval *period)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->main_lock);
 	*mode = nic_data->poll_mode;
@@ -735,5 +735,5 @@
 	nic_poll_mode_t mode, const struct timeval *period)
 {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	/* If the driver does not implement the poll mode change handler it cannot
 	 * switch off interrupts and this is not supported. */
@@ -783,5 +783,5 @@
  */
 int nic_poll_now_impl(ddf_fun_t *fun) {
-	nic_t *nic_data = (nic_t *) fun->driver_data;
+	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	fibril_rwlock_read_lock(&nic_data->main_lock);
 	if (nic_data->poll_mode != NIC_POLL_ON_DEMAND) {
Index: uspace/lib/nic/src/nic_wol_virtues.c
===================================================================
--- uspace/lib/nic/src/nic_wol_virtues.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/nic/src/nic_wol_virtues.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,32 +37,28 @@
 
 #include "nic_wol_virtues.h"
+#include "nic.h"
 #include <assert.h>
 #include <errno.h>
 
-#define NIC_WV_HASH_COUNT 32
-
-/**
- * Hash table helper function
- */
-static int nic_wv_compare(unsigned long key[], hash_count_t keys,
-	link_t *item)
+
+/*
+ * Hash table helper functions
+ */
+
+static size_t nic_wv_key_hash(void *key)
+{
+	return *(nic_wv_id_t*) key;
+}
+
+static size_t nic_wv_hash(const ht_link_t *item)
 {
 	nic_wol_virtue_t *virtue = (nic_wol_virtue_t *) item;
-	return (virtue->id == (nic_wv_id_t) key[0]);
-}
-
-/**
- * Hash table helper function
- */
-static void nic_wv_rc(link_t *item)
-{
-}
-
-/**
- * Hash table helper function
- */
-static hash_index_t nic_wv_hash(unsigned long keys[])
-{
-	return keys[0] % NIC_WV_HASH_COUNT;
+	return virtue->id;
+}
+
+static bool nic_wv_key_equal(void *key, const ht_link_t *item)
+{
+	nic_wol_virtue_t *virtue = (nic_wol_virtue_t *) item;
+	return (virtue->id == *(nic_wv_id_t*) key);
 }
 
@@ -77,10 +73,12 @@
 int nic_wol_virtues_init(nic_wol_virtues_t *wvs)
 {
-	bzero(wvs, sizeof (nic_wol_virtues_t));
-	wvs->table_operations.compare = nic_wv_compare;
+	bzero(wvs, sizeof(nic_wol_virtues_t));
 	wvs->table_operations.hash = nic_wv_hash;
-	wvs->table_operations.remove_callback = nic_wv_rc;
-	if (!hash_table_create(&wvs->table, NIC_WV_HASH_COUNT, 1,
-		&wvs->table_operations)) {
+	wvs->table_operations.key_hash = nic_wv_key_hash;
+	wvs->table_operations.key_equal = nic_wv_key_equal;
+	wvs->table_operations.equal = 0;
+	wvs->table_operations.remove_callback = 0;
+	
+	if (!hash_table_create(&wvs->table, 0, 0, &wvs->table_operations)) {
 		return ENOMEM;
 	}
@@ -170,8 +168,6 @@
 	do {
 		virtue->id = wvs->next_id++;
-	} while (NULL !=
-		hash_table_find(&wvs->table, (unsigned long *) &virtue->id));
-	hash_table_insert(&wvs->table,
-		(unsigned long *) &virtue->id, &virtue->item);
+	} while (NULL != hash_table_find(&wvs->table, &virtue->id));
+	hash_table_insert(&wvs->table, &virtue->item);
 	virtue->next = wvs->lists[virtue->type];
 	wvs->lists[virtue->type] = virtue;
@@ -191,6 +187,6 @@
 nic_wol_virtue_t *nic_wol_virtues_remove(nic_wol_virtues_t *wvs, nic_wv_id_t id)
 {
-	nic_wol_virtue_t *virtue = (nic_wol_virtue_t *)
-		hash_table_find(&wvs->table, (unsigned long *) &id);
+	nic_wol_virtue_t *virtue = 
+		(nic_wol_virtue_t *) hash_table_find(&wvs->table, &id);
 	if (virtue == NULL) {
 		return NULL;
@@ -198,5 +194,5 @@
 
 	/* Remove from filter_table */
-	hash_table_remove(&wvs->table, (unsigned long *) &id, 1);
+	hash_table_remove_item(&wvs->table, &virtue->item);
 
 	/* Remove from filter_types */
@@ -235,6 +231,5 @@
 	 * constant virtue the retyping is correct.
 	 */
-	link_t *virtue = hash_table_find(
-		&((nic_wol_virtues_t *) wvs)->table, (unsigned long *) &id);
+	ht_link_t *virtue = hash_table_find(&((nic_wol_virtues_t *) wvs)->table, &id);
 	return (const nic_wol_virtue_t *) virtue;
 }
Index: uspace/lib/posix/Makefile
===================================================================
--- uspace/lib/posix/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/posix/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,5 +33,7 @@
 LSONAME = libposix.so0
 
-INCLUDE_LIBC = ./libc
+EXTRA_CFLAGS = -Iinclude/
+
+INCLUDE_LIBC = ./include/libc
 
 PRE_DEPEND = $(INCLUDE_LIBC)
@@ -39,27 +41,27 @@
 
 SOURCES = \
-	ctype.c \
-	errno.c \
-	fcntl.c \
-	fnmatch.c \
-	getopt.c \
-	locale.c \
-	math.c \
-	pwd.c \
-	signal.c \
-	stdio.c \
-	stdio/scanf.c \
-	stdlib.c \
-	stdlib/strtol.c \
-	stdlib/strtold.c \
-	string.c \
-	strings.c \
-	sys/stat.c \
-	sys/wait.c \
-	time.c \
-	unistd.c
+	source/ctype.c \
+	source/errno.c \
+	source/fcntl.c \
+	source/fnmatch.c \
+	source/getopt.c \
+	source/locale.c \
+	source/math.c \
+	source/pwd.c \
+	source/signal.c \
+	source/stdio.c \
+	source/stdio/scanf.c \
+	source/stdlib.c \
+	source/stdlib/strtol.c \
+	source/stdlib/strtold.c \
+	source/string.c \
+	source/strings.c \
+	source/sys/stat.c \
+	source/sys/wait.c \
+	source/time.c \
+	source/unistd.c
 
 include $(USPACE_PREFIX)/Makefile.common
 
 $(INCLUDE_LIBC): ../c/include
-	ln -s -f -n $^ $@
+	ln -s -f -n ../$^ $@
Index: pace/lib/posix/assert.h
===================================================================
--- uspace/lib/posix/assert.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Program assertion.
- */
-
-/* NO include guard on purpose. */
-
-#include "libc/assert.h"
-
-#undef assert
-
-#ifndef NDEBUG
-	#define assert(expr) ((expr) ? (void) 0 : assert_abort(#expr, __FILE__, __LINE__))
-#else
-	#define assert(expr) ((void) 0)
-#endif
-
-/** @}
- */
Index: pace/lib/posix/ctype.c
===================================================================
--- uspace/lib/posix/ctype.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,131 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Character classification.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "ctype.h"
-
-/**
- * Checks whether character is a hexadecimal digit.
- *
- * @param c Character to inspect.
- * @return Non-zero if character match the definition, zero otherwise.
- */
-int posix_isxdigit(int c)
-{
-	return isdigit(c) ||
-	    (c >= 'a' && c <= 'f') ||
-	    (c >= 'A' && c <= 'F');
-}
-
-/**
- * Checks whether character is a word separator.
- *
- * @param c Character to inspect.
- * @return Non-zero if character match the definition, zero otherwise.
- */
-int posix_isblank(int c)
-{
-	return c == ' ' || c == '\t';
-}
-
-/**
- * Checks whether character is a control character.
- *
- * @param c Character to inspect.
- * @return Non-zero if character match the definition, zero otherwise.
- */
-int posix_iscntrl(int c)
-{
-	return c < 0x20 || c == 0x7E;
-}
-
-/**
- * Checks whether character is any printing character except space.
- *
- * @param c Character to inspect.
- * @return Non-zero if character match the definition, zero otherwise.
- */
-int posix_isgraph(int c)
-{
-	return posix_isprint(c) && c != ' ';
-}
-
-/**
- * Checks whether character is a printing character.
- *
- * @param c Character to inspect.
- * @return Non-zero if character match the definition, zero otherwise.
- */
-int posix_isprint(int c)
-{
-	return posix_isascii(c) && !posix_iscntrl(c);
-}
-
-/**
- * Checks whether character is a punctuation.
- *
- * @param c Character to inspect.
- * @return Non-zero if character match the definition, zero otherwise.
- */
-int posix_ispunct(int c)
-{
-	return !isspace(c) && !isalnum(c) && posix_isprint(c);
-}
-
-/**
- * Checks whether character is ASCII. (obsolete)
- *
- * @param c Character to inspect.
- * @return Non-zero if character match the definition, zero otherwise.
- */
-int posix_isascii(int c)
-{
-	return c >= 0 && c < 128;
-}
-
-/**
- * Converts argument to a 7-bit ASCII character. (obsolete)
- *
- * @param c Character to convert.
- * @return Coverted character.
- */
-int posix_toascii(int c)
-{
-	return c & 0x7F;
-}
-
-/** @}
- */
Index: pace/lib/posix/ctype.h
===================================================================
--- uspace/lib/posix/ctype.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,73 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Character classification.
- */
-
-#ifndef POSIX_CTYPE_H_
-#define POSIX_CTYPE_H_
-
-#include "libc/ctype.h"
-
-/* Classification of Characters */
-extern int posix_isxdigit(int c);
-extern int posix_isblank(int c);
-extern int posix_iscntrl(int c);
-extern int posix_isgraph(int c);
-extern int posix_isprint(int c);
-extern int posix_ispunct(int c);
-
-/* Obsolete Functions and Macros */
-extern int posix_isascii(int c);
-extern int posix_toascii(int c);
-#undef _tolower
-#define _tolower(c) ((c) - 'A' + 'a')
-#undef _toupper
-#define _toupper(c) ((c) - 'a' + 'A')
-
-
-#ifndef LIBPOSIX_INTERNAL
-	#define isxdigit posix_isxdigit
-	#define isblank posix_isblank
-	#define iscntrl posix_iscntrl
-	#define isgraph posix_isgraph
-	#define isprint posix_isprint
-	#define ispunct posix_ispunct
-	
-	#define isascii posix_isascii
-	#define toascii posix_toascii
-#endif
-
-#endif /* POSIX_CTYPE_H_ */
-
-/** @}
- */
Index: pace/lib/posix/errno.c
===================================================================
--- uspace/lib/posix/errno.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,52 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file System error numbers.
- */
-
-#include "errno.h"
-
-#include "stdlib.h"
-#include "libc/fibril.h"
-
-static fibril_local int _posix_errno;
-
-int *__posix_errno(void)
-{
-	if (*__errno() != 0) {
-		_posix_errno = abs(*__errno());
-		*__errno() = 0;
-	}
-	return &_posix_errno;
-}
-
-/** @}
- */
Index: pace/lib/posix/errno.h
===================================================================
--- uspace/lib/posix/errno.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,328 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file System error numbers.
- */
-
-#ifndef POSIX_ERRNO_H_
-#define POSIX_ERRNO_H_
-
-#include "libc/errno.h"
-
-/* IMPORTANT:
- * Since libc uses negative errorcodes, some sort of conversion is necessary to
- * keep POSIX programs and libraries from breaking. This file maps POSIX error
- * codes to absolute values of corresponding libc codes where available, and
- * assigns new code where there is no prior definition in libc.
- *
- * A new errno variable is defined. When accessed, the function first looks at
- * libc errno and iff it is != 0, sets the POSIX errno to absolute value of
- * libc errno. Given that no library function sets errno to 0 and that all
- * POSIX libraries will be used solely by POSIX programs (thus, there only needs
- * to be one way correspondence between errno and posix_errno), this approach
- * should work as expected in most cases and does not require any wrappers for
- * libc routines that would just change errno values.
- *
- * There is no conditioning by LIBPOSIX_INTERNAL for redefinitions of macros.
- * If there is a need to check errno for a value not defined by POSIX, it's
- * necessary to compare errno against abs(ECODE), because there is no
- * redefinition for such error codes.
- *
- * XXX: maybe all HOS error codes should be redefined
- *
- * NOTE: This redefinition is slightly POSIX incompatible, since the
- *  specification requires the macro values to be usable in preprocessing
- *  directives. I don't think that's very important, though.
- */
-
-#undef errno
-#define errno (*__posix_errno())
-
-#include "unistd.h"
-
-extern int *__posix_errno(void);
-
-#define __TOP_ERRNO (-NO_DATA)
-
-enum {
-	POSIX_E2BIG = __TOP_ERRNO + 1,
-	POSIX_EACCES = __TOP_ERRNO + 2,
-	POSIX_EADDRINUSE = -EADDRINUSE,
-	POSIX_EADDRNOTAVAIL = -EADDRNOTAVAIL,
-	POSIX_EAFNOSUPPORT = -EAFNOSUPPORT,
-	POSIX_EAGAIN = -EAGAIN,
-	POSIX_EALREADY = __TOP_ERRNO + 3,
-	POSIX_EBADF = -EBADF,
-	POSIX_EBADMSG = __TOP_ERRNO + 4,
-	POSIX_EBUSY = -EBUSY,
-	POSIX_ECANCELED = __TOP_ERRNO + 5,
-	POSIX_ECHILD = __TOP_ERRNO + 6,
-	POSIX_ECONNABORTED = __TOP_ERRNO + 7,
-	POSIX_ECONNREFUSED = __TOP_ERRNO + 8,
-	POSIX_ECONNRESET = __TOP_ERRNO + 9,
-	POSIX_EDEADLK = __TOP_ERRNO + 10,
-	POSIX_EDESTADDRREQ = -EDESTADDRREQ,
-	POSIX_EDOM = __TOP_ERRNO + 11,
-	POSIX_EDQUOT = __TOP_ERRNO + 12,
-	POSIX_EEXIST = -EEXIST,
-	POSIX_EFAULT = __TOP_ERRNO + 13,
-	POSIX_EFBIG = __TOP_ERRNO + 14,
-	POSIX_EHOSTUNREACH = __TOP_ERRNO + 15,
-	POSIX_EIDRM = __TOP_ERRNO + 16,
-	POSIX_EILSEQ = __TOP_ERRNO + 17,
-	POSIX_EINPROGRESS = -EINPROGRESS,
-	POSIX_EINTR = -EINTR,
-	POSIX_EINVAL = -EINVAL,
-	POSIX_EIO = -EIO,
-	POSIX_EISCONN = __TOP_ERRNO + 18,
-	POSIX_EISDIR = -EISDIR,
-	POSIX_ELOOP = __TOP_ERRNO + 19,
-	POSIX_EMFILE = -EMFILE,
-	POSIX_EMLINK = -EMLINK,
-	POSIX_EMSGSIZE = __TOP_ERRNO + 20,
-	POSIX_EMULTIHOP = __TOP_ERRNO + 21,
-	POSIX_ENAMETOOLONG = -ENAMETOOLONG,
-	POSIX_ENETDOWN = __TOP_ERRNO + 22,
-	POSIX_ENETRESET = __TOP_ERRNO + 23,
-	POSIX_ENETUNREACH = __TOP_ERRNO + 24,
-	POSIX_ENFILE = __TOP_ERRNO + 25,
-	POSIX_ENOBUFS = __TOP_ERRNO + 26,
-	POSIX_ENODATA = -NO_DATA,
-	POSIX_ENODEV = __TOP_ERRNO + 27,
-	POSIX_ENOENT = -ENOENT,
-	POSIX_ENOEXEC = __TOP_ERRNO + 28,
-	POSIX_ENOLCK = __TOP_ERRNO + 29,
-	POSIX_ENOLINK = __TOP_ERRNO + 30,
-	POSIX_ENOMEM = -ENOMEM,
-	POSIX_ENOMSG = __TOP_ERRNO + 31,
-	POSIX_ENOPROTOOPT = __TOP_ERRNO + 32,
-	POSIX_ENOSPC = -ENOSPC,
-	POSIX_ENOSR = __TOP_ERRNO + 33,
-	POSIX_ENOSTR = __TOP_ERRNO + 34,
-	POSIX_ENOSYS = __TOP_ERRNO + 35,
-	POSIX_ENOTCONN = -ENOTCONN,
-	POSIX_ENOTDIR = -ENOTDIR,
-	POSIX_ENOTEMPTY = -ENOTEMPTY,
-	POSIX_ENOTRECOVERABLE = __TOP_ERRNO + 36,
-	POSIX_ENOTSOCK = -ENOTSOCK,
-	POSIX_ENOTSUP = -ENOTSUP,
-	POSIX_ENOTTY = __TOP_ERRNO + 37,
-	POSIX_ENXIO = __TOP_ERRNO + 38,
-	POSIX_EOPNOTSUPP = __TOP_ERRNO + 39,
-	POSIX_EOVERFLOW = -EOVERFLOW,
-	POSIX_EOWNERDEAD = __TOP_ERRNO + 40,
-	POSIX_EPERM = -EPERM,
-	POSIX_EPIPE = __TOP_ERRNO + 41,
-	POSIX_EPROTO = __TOP_ERRNO + 42,
-	POSIX_EPROTONOSUPPORT = -EPROTONOSUPPORT,
-	POSIX_EPROTOTYPE = __TOP_ERRNO + 43,
-	POSIX_ERANGE = -ERANGE,
-	POSIX_EROFS = __TOP_ERRNO + 44,
-	POSIX_ESPIPE = __TOP_ERRNO + 45,
-	POSIX_ESRCH = __TOP_ERRNO + 46,
-	POSIX_ESTALE = __TOP_ERRNO + 47,
-	POSIX_ETIME = __TOP_ERRNO + 48,
-	POSIX_ETIMEDOUT = __TOP_ERRNO + 49,
-	POSIX_ETXTBSY = __TOP_ERRNO + 50,
-	POSIX_EWOULDBLOCK = __TOP_ERRNO + 51,
-	POSIX_EXDEV = -EXDEV,
-};
-
-#undef __TOP_ERRNO
-
-#undef E2BIG
-#undef EACCES
-#undef EADDRINUSE
-#undef EADDRNOTAVAIL
-#undef EAFNOSUPPORT
-#undef EAGAIN
-#undef EALREADY
-#undef EBADF
-#undef EBADMSG
-#undef EBUSY
-#undef ECANCELED
-#undef ECHILD
-#undef ECONNABORTED
-#undef ECONNREFUSED
-#undef ECONNRESET
-#undef EDEADLK
-#undef EDESTADDRREQ
-#undef EDOM
-#undef EDQUOT
-#undef EEXIST
-#undef EFAULT
-#undef EFBIG
-#undef EHOSTUNREACH
-#undef EIDRM
-#undef EILSEQ
-#undef EINPROGRESS
-#undef EINTR
-#undef EINVAL
-#undef EIO
-#undef EISCONN
-#undef EISDIR
-#undef ELOOP
-#undef EMFILE
-#undef EMLINK
-#undef EMSGSIZE
-#undef EMULTIHOP
-#undef ENAMETOOLONG
-#undef ENETDOWN
-#undef ENETRESET
-#undef ENETUNREACH
-#undef ENFILE
-#undef ENOBUFS
-#undef ENODATA
-#undef ENODEV
-#undef ENOENT
-#undef ENOEXEC
-#undef ENOLCK
-#undef ENOLINK
-#undef ENOMEM
-#undef ENOMSG
-#undef ENOPROTOOPT
-#undef ENOSPC
-#undef ENOSR
-#undef ENOSTR
-#undef ENOSYS
-#undef ENOTCONN
-#undef ENOTDIR
-#undef ENOTEMPTY
-#undef ENOTRECOVERABLE
-#undef ENOTSOCK
-#undef ENOTSUP
-#undef ENOTTY
-#undef ENXIO
-#undef EOPNOTSUPP
-#undef EOVERFLOW
-#undef EOWNERDEAD
-#undef EPERM
-#undef EPIPE
-#undef EPROTO
-#undef EPROTONOSUPPORT
-#undef EPROTOTYPE
-#undef ERANGE
-#undef EROFS
-#undef ESPIPE
-#undef ESRCH
-#undef ESTALE
-#undef ETIME
-#undef ETIMEDOUT
-#undef ETXTBSY
-#undef EWOULDBLOCK
-#undef EXDEV
-
-#define E2BIG POSIX_E2BIG
-#define EACCES POSIX_EACCES
-#define EADDRINUSE POSIX_EADDRINUSE
-#define EADDRNOTAVAIL POSIX_EADDRNOTAVAIL
-#define EAFNOSUPPORT POSIX_EAFNOSUPPORT
-#define EAGAIN POSIX_EAGAIN
-#define EALREADY POSIX_EALREADY
-#define EBADF POSIX_EBADF
-#define EBADMSG POSIX_EBADMSG
-#define EBUSY POSIX_EBUSY
-#define ECANCELED POSIX_ECANCELED
-#define ECHILD POSIX_ECHILD
-#define ECONNABORTED POSIX_ECONNABORTED
-#define ECONNREFUSED POSIX_ECONNREFUSED
-#define ECONNRESET POSIX_ECONNRESET
-#define EDEADLK POSIX_EDEADLK
-#define EDESTADDRREQ POSIX_EDESTADDRREQ
-#define EDOM POSIX_EDOM
-#define EDQUOT POSIX_EDQUOT
-#define EEXIST POSIX_EEXIST
-#define EFAULT POSIX_EFAULT
-#define EFBIG POSIX_EFBIG
-#define EHOSTUNREACH POSIX_EHOSTUNREACH
-#define EIDRM POSIX_EIDRM
-#define EILSEQ POSIX_EILSEQ
-#define EINPROGRESS POSIX_EINPROGRESS
-#define EINTR POSIX_EINTR
-#define EINVAL POSIX_EINVAL
-#define EIO POSIX_EIO
-#define EISCONN POSIX_EISCONN
-#define EISDIR POSIX_EISDIR
-#define ELOOP POSIX_ELOOP
-#define EMFILE POSIX_EMFILE
-#define EMLINK POSIX_EMLINK
-#define EMSGSIZE POSIX_EMSGSIZE
-#define EMULTIHOP POSIX_EMULTIHOP
-#define ENAMETOOLONG POSIX_ENAMETOOLONG
-#define ENETDOWN POSIX_ENETDOWN
-#define ENETRESET POSIX_ENETRESET
-#define ENETUNREACH POSIX_ENETUNREACH
-#define ENFILE POSIX_ENFILE
-#define ENOBUFS POSIX_ENOBUFS
-#define ENODATA POSIX_ENODATA
-#define ENODEV POSIX_ENODEV
-#define ENOENT POSIX_ENOENT
-#define ENOEXEC POSIX_ENOEXEC
-#define ENOLCK POSIX_ENOLCK
-#define ENOLINK POSIX_ENOLINK
-#define ENOMEM POSIX_ENOMEM
-#define ENOMSG POSIX_ENOMSG
-#define ENOPROTOOPT POSIX_ENOPROTOOPT
-#define ENOSPC POSIX_ENOSPC
-#define ENOSR POSIX_ENOSR
-#define ENOSTR POSIX_ENOSTR
-#define ENOSYS POSIX_ENOSYS
-#define ENOTCONN POSIX_ENOTCONN
-#define ENOTDIR POSIX_ENOTDIR
-#define ENOTEMPTY POSIX_ENOTEMPTY
-#define ENOTRECOVERABLE POSIX_ENOTRECOVERABLE
-#define ENOTSOCK POSIX_ENOTSOCK
-#define ENOTSUP POSIX_ENOTSUP
-#define ENOTTY POSIX_ENOTTY
-#define ENXIO POSIX_ENXIO
-#define EOPNOTSUPP POSIX_EOPNOTSUPP
-#define EOVERFLOW POSIX_EOVERFLOW
-#define EOWNERDEAD POSIX_EOWNERDEAD
-#define EPERM POSIX_EPERM
-#define EPIPE POSIX_EPIPE
-#define EPROTO POSIX_EPROTO
-#define EPROTONOSUPPORT POSIX_EPROTONOSUPPORT
-#define EPROTOTYPE POSIX_EPROTOTYPE
-#define ERANGE POSIX_ERANGE
-#define EROFS POSIX_EROFS
-#define ESPIPE POSIX_ESPIPE
-#define ESRCH POSIX_ESRCH
-#define ESTALE POSIX_ESTALE
-#define ETIME POSIX_ETIME
-#define ETIMEDOUT POSIX_ETIMEDOUT
-#define ETXTBSY POSIX_ETXTBSY
-#define EWOULDBLOCK POSIX_EWOULDBLOCK
-#define EXDEV POSIX_EXDEV
-
-#endif /* POSIX_ERRNO_H_ */
-
-/** @}
- */
Index: pace/lib/posix/fcntl.c
===================================================================
--- uspace/lib/posix/fcntl.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,98 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file File control.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "internal/common.h"
-#include "fcntl.h"
-
-#include "libc/unistd.h"
-#include "libc/vfs/vfs.h"
-#include "errno.h"
-
-/**
- * Performs set of operations on the opened files.
- *
- * @param fd File descriptor of the opened file.
- * @param cmd Operation to carry out.
- * @return Non-negative on success. Might have special meaning corresponding
- *     to the requested operation.
- */
-int posix_fcntl(int fd, int cmd, ...)
-{
-	int flags;
-
-	switch (cmd) {
-	case F_DUPFD:
-	case F_DUPFD_CLOEXEC:
-		/* VFS currently does not provide the functionality to duplicate
-		 * opened file descriptor. */
-		// FIXME: implement this once dup() is available
-		errno = ENOTSUP;
-		return -1;
-	case F_GETFD:
-		/* FD_CLOEXEC is not supported. There are no other flags. */
-		return 0;
-	case F_SETFD:
-		/* FD_CLOEXEC is not supported. Ignore arguments and report success. */
-		return 0;
-	case F_GETFL:
-		/* File status flags (i.e. O_APPEND) are currently private to the
-		 * VFS server so it cannot be easily retrieved. */
-		flags = 0;
-		/* File access flags are currently not supported for file descriptors.
-		 * Provide full access. */
-		flags |= O_RDWR;
-		return flags;
-	case F_SETFL:
-		/* File access flags are currently not supported for file descriptors.
-		 * Ignore arguments and report success. */
-		return 0;
-	case F_GETOWN:
-	case F_SETOWN:
-	case F_GETLK:
-	case F_SETLK:
-	case F_SETLKW:
-		/* Signals (SIGURG) and file locks are not supported. */
-		errno = ENOTSUP;
-		return -1;
-	default:
-		/* Unknown command */
-		errno = EINVAL;
-		return -1;
-	}
-}
-
-/** @}
- */
Index: pace/lib/posix/fcntl.h
===================================================================
--- uspace/lib/posix/fcntl.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,94 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file File control.
- */
-
-#ifndef POSIX_FCNTL_H_
-#define POSIX_FCNTL_H_
-
-#include "sys/types.h"
-#include "libc/fcntl.h"
-#include "errno.h"
-
-/* Mask for file access modes. */
-#undef O_ACCMODE
-#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
-
-/* fcntl commands */
-#undef F_DUPFD
-#undef F_DUPFD_CLOEXEC
-#undef F_GETFD
-#undef F_SETFD
-#undef F_GETFL
-#undef F_SETFL
-#undef F_GETOWN
-#undef F_SETOWN
-#undef F_GETLK
-#undef F_SETLK
-#undef F_SETLKW
-#define F_DUPFD            0 /* Duplicate file descriptor. */
-#define F_DUPFD_CLOEXEC    1 /* Same as F_DUPFD but with FD_CLOEXEC flag set. */
-#define F_GETFD            2 /* Get file descriptor flags. */
-#define F_SETFD            3 /* Set file descriptor flags. */
-#define F_GETFL            4 /* Get file status and access flags. */
-#define F_SETFL            5 /* Set file status flags. */
-#define F_GETOWN           6 /* Get socket owner. */
-#define F_SETOWN           7 /* Set socket owner. */
-#define F_GETLK            8 /* Get locking information. */
-#define F_SETLK            9 /* Set locking information. */
-#define F_SETLKW          10 /* Set locking information; wait if blocked. */
-
-/* File descriptor flags used with F_GETFD and F_SETFD. */
-#undef FD_CLOEXEC
-#define FD_CLOEXEC         1 /* Close on exec. */
-
-#undef open
-#define open(path, ...) \
-	({ \
-		int rc = open(path, ##__VA_ARGS__); \
-		if (rc < 0) { \
-			errno = -rc; \
-			rc = -1; \
-		} \
-		rc; \
-	})
-
-extern int posix_fcntl(int fd, int cmd, ...);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define fcntl posix_fcntl
-#endif
-
-#endif /* POSIX_FCNTL_H_ */
-
-/** @}
- */
Index: pace/lib/posix/float.h
===================================================================
--- uspace/lib/posix/float.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,43 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Floating type support.
- */
-
-#ifndef POSIX_FLOAT_H_
-#define POSIX_FLOAT_H_
-
-/* Empty. Just to satisfy preprocessor. */
-
-#endif /* POSIX_FLOAT_H_ */
-
-/** @}
- */
Index: pace/lib/posix/fnmatch.c
===================================================================
--- uspace/lib/posix/fnmatch.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,716 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Filename-matching.
- */
-
-/* This file contains an implementation of the fnmatch() pattern matching
- * function. There is more code than necessary to account for the possibility
- * of adding POSIX-like locale support to the system in the future. Functions
- * that are only necessary for locale support currently simply use single
- * characters for "collation elements". 
- * When (or if) locales are properly implemented, extending this implementation
- * will be fairly straightforward.
- */
-
-#include "stdbool.h"
-#include "ctype.h"
-#include "string.h"
-#include "stdlib.h"
-#include "assert.h"
-
-#define LIBPOSIX_INTERNAL
-
-#include "internal/common.h"
-#include "fnmatch.h"
-
-/* Returned by _match... functions. */
-#define INVALID_PATTERN -1
-
-/* Type for collating element, simple identity with characters now,
- * but may be extended for better locale support.
- */
-typedef int coll_elm_t;
-
-/** Return value indicating that the element in question
- * is not valid in the current locale. (That is, if locales are supported.)
- */
-#define COLL_ELM_INVALID -1
-
-/**
- * Get collating element matching a string.
- *
- * @param str String representation of the element.
- * @return Matching collating element or COLL_ELM_INVALID.
- */
-static coll_elm_t _coll_elm_get(const char* str)
-{
-	if (str[0] == '\0' || str[1] != '\0') {
-		return COLL_ELM_INVALID;
-	}
-	return str[0];
-}
-
-/**
- * Get collating element matching a single character.
- *
- * @param c Character representation of the element.
- * @return Matching collating element.
- */
-static coll_elm_t _coll_elm_char(int c)
-{
-	return c;
-}
-
-/**
- * Match collating element with a beginning of a string.
- *
- * @param elm Collating element to match.
- * @param str String which beginning should match the element.
- * @return 0 if the element doesn't match, or the number of characters matched.
- */
-static int _coll_elm_match(coll_elm_t elm, const char *str)
-{
-	return elm == *str;
-}
-
-/**
- * Checks whether a string begins with a collating element in the given range.
- * Ordering depends on the locale (if locales are supported).
- *
- * @param first First element of the range.
- * @param second Last element of the range.
- * @param str String to match.
- * @return 0 if there is no match, or the number of characters matched.
- */
-static int _coll_elm_between(coll_elm_t first, coll_elm_t second,
-    const char *str)
-{
-	return *str >= first && *str <= second;
-}
-
-/**
- * Read a string delimited by [? and ?].
- *
- * @param pattern Pointer to the string to read from. Its position is moved
- *    to the first character after the closing ].
- * @param seq The character on the inside of brackets.
- * @param buf Read buffer.
- * @param buf_sz Read buffer's size. If the buffer is not large enough for
- *    the entire string, the string is cut with no error indication.
- * @param flags Flags modifying the behavior.
- * @return True on success, false if the pattern is invalid.
- */
-static bool _get_delimited(
-    const char **pattern, int seq,
-    char *buf, size_t buf_sz, int flags)
-{
-	const bool noescape = (flags & FNM_NOESCAPE) != 0;
-	const bool pathname = (flags & FNM_PATHNAME) != 0;
-
-	const char *p = *pattern;
-	assert(p[0] == '[' && p[1] == seq /* Caller should ensure this. */);
-	p += 2;
-
-	while (true) {
-		if (*p == seq && *(p + 1) == ']') {
-			/* String properly ended, return. */
-			*pattern = p + 2;
-			*buf = '\0';
-			return true;
-		}
-		if (!noescape && *p == '\\') {
-			p++;
-		}
-		if (*p == '\0') {
-			/* String not ended properly, invalid pattern. */
-			return false;
-		}
-		if (pathname && *p == '/') {
-			/* Slash in a pathname pattern is invalid. */
-			return false;
-		}
-		if (buf_sz > 1) {
-			/* Only add to the buffer if there is space. */
-			*buf = *p;
-			buf++;
-			buf_sz--;
-		}
-		p++;
-	}
-}
-
-/************** CHARACTER CLASSES ****************/
-
-#define MAX_CLASS_OR_COLL_LEN 6
-
-struct _char_class {
-	const char *name;
-	int (*func) (int);
-};
-
-/* List of supported character classes. */
-static const struct _char_class _char_classes[] = {
-	{ "alnum", isalnum },
-	{ "alpha", isalpha },
-	{ "blank", isblank },
-	{ "cntrl", iscntrl },
-	{ "digit", isdigit },
-	{ "graph", isgraph },
-	{ "lower", islower },
-	{ "print", isprint },
-	{ "punct", ispunct },
-	{ "space", isspace },
-	{ "upper", isupper },
-	{ "xdigit", isxdigit }
-};
-
-/**
- * Compare function for binary search in the _char_classes array.
- * 
- * @param key Key of the searched element.
- * @param elem Element of _char_classes array.
- * @return Ordering indicator (-1 less than, 0 equal, 1 greater than).
- */
-static int _class_compare(const void *key, const void *elem)
-{
-	const struct _char_class *class = elem;
-	return strcmp((const char *) key, class->name);
-}
-
-/**
- * Returns whether the given character belongs to the specified character class.
- * 
- * @param cname Name of the character class.
- * @param c Character.
- * @return True if the character belongs to the class, false otherwise.
- */
-static bool _is_in_class (const char *cname, int c)
-{
-	/* Search for class in the array of supported character classes. */
-	const struct _char_class *class = bsearch(cname, _char_classes,
-	    sizeof(_char_classes) / sizeof(struct _char_class),
-	    sizeof(struct _char_class), _class_compare);
-
-	if (class == NULL) {
-		/* No such class supported - treat as an empty class. */
-		return false;
-	} else {
-		/* Class matched. */
-		return class->func(c);
-	}
-}
-
-/**
- * Tries to parse an initial part of the pattern as a character class pattern,
- * and if successful, matches the beginning of the given string against the class.
- * 
- * @param pattern Pointer to the pattern to match. Must begin with a class
- *    specifier and is repositioned to the first character after the specifier
- *    if successful.
- * @param str String to match.
- * @param flags Flags modifying the behavior (see fnmatch()).
- * @return INVALID_PATTERN if the pattern doesn't start with a valid class
- *    specifier, 0 if the beginning of the matched string doesn't belong
- *    to the class, or positive number of characters matched.
- */
-static int _match_char_class(const char **pattern, const char *str, int flags)
-{
-	char class[MAX_CLASS_OR_COLL_LEN + 1];
-
-	if (!_get_delimited(pattern, ':', class, sizeof(class), flags)) {
-		return INVALID_PATTERN;
-	}
-
-	return _is_in_class(class, *str);
-}
-
-/************** END CHARACTER CLASSES ****************/
-
-/**
- * Reads the next collating element in the pattern, taking into account
- * locale (if supported) and flags (see fnmatch()).
- * 
- * @param pattern Pattern.
- * @param flags Flags given to fnmatch().
- * @return Collating element on success,
- *     or COLL_ELM_INVALID if the pattern is invalid.
- */
-static coll_elm_t _next_coll_elm(const char **pattern, int flags)
-{
-	assert(pattern != NULL);
-	assert(*pattern != NULL);
-	assert(**pattern != '\0');
-
-	const char *p = *pattern;
-	const bool noescape = (flags & FNM_NOESCAPE) != 0;
-	const bool pathname = (flags & FNM_PATHNAME) != 0;
-
-	if (*p == '[') {
-		if (*(p + 1) == '.') {
-			char buf[MAX_CLASS_OR_COLL_LEN + 1];
-			if (!_get_delimited(pattern, '.', buf, sizeof(buf), flags)) {
-				return COLL_ELM_INVALID;
-			}
-			return _coll_elm_get(buf);
-		}
-
-		if (*(p + 1) == '=') {
-			char buf[MAX_CLASS_OR_COLL_LEN + 1];
-			if (!_get_delimited(pattern, '=', buf, sizeof(buf), flags)) {
-				return COLL_ELM_INVALID;
-			}
-			return _coll_elm_get(buf);
-		}
-	}
-
-	if (!noescape && *p == '\\') {
-		p++;
-		if (*p == '\0') {
-			*pattern = p;
-			return COLL_ELM_INVALID;
-		}
-	}
-	if (pathname && *p == '/') {
-		return COLL_ELM_INVALID;
-	}
-	
-	*pattern = p + 1;
-	return _coll_elm_char(*p);
-}
-
-/**
- * Matches the beginning of the given string against a bracket expression
- * the pattern begins with.
- * 
- * @param pattern Pointer to the beginning of a bracket expression in a pattern.
- *     On success, the pointer is moved to the first character after the
- *     bracket expression.
- * @param str Unmatched part of the string.
- * @param flags Flags given to fnmatch().
- * @return INVALID_PATTERN if the pattern is invalid, 0 if there is no match
- *     or the number of matched characters on success.
- */
-static int _match_bracket_expr(const char **pattern, const char *str, int flags)
-{
-	const bool pathname = (flags & FNM_PATHNAME) != 0;
-	const bool special_period = (flags & FNM_PERIOD) != 0;
-	const char *p = *pattern;
-	bool negative = false;
-	int matched = 0;
-
-	#define _matched(match) { \
-		int _match = match; \
-		if (_match < 0) { \
-			/* Invalid pattern */ \
-			return _match; \
-		} else if (matched == 0 && _match > 0) { \
-			/* First match */ \
-			matched = _match; \
-		} \
-	}
-
-	assert(*p == '[');  /* calling code should ensure this */
-	p++;
-
-	if (*str == '\0' || (pathname && *str == '/') ||
-	    (pathname && special_period && *str == '.' && *(str - 1) == '/')) {
-		/* No bracket expression matches end of string,
-		 * slash in pathname match or initial period with FNM_PERIOD
-		 * option.
-		 */
-		return 0;
-	}
-
-	if (*p == '^' || *p == '!') {
-		negative = true;
-		p++;
-	}
-
-	if (*p == ']') {
-		/* When ']' is first, treat it as a normal character. */
-		_matched(*str == ']');
-		p++;
-	}
-	
-	coll_elm_t current_elm = COLL_ELM_INVALID;
-	
-	while (*p != ']') {
-		if (*p == '-' && *(p + 1) != ']' &&
-		    current_elm != COLL_ELM_INVALID) {
-			/* Range expression. */
-			p++;
-			coll_elm_t end_elm = _next_coll_elm(&p, flags);
-			if (end_elm == COLL_ELM_INVALID) {
-				return INVALID_PATTERN;
-			}
-			_matched(_coll_elm_between(current_elm, end_elm, str));
-			continue;
-		}
-	
-		if (*p == '[' && *(p + 1) == ':') {
-			current_elm = COLL_ELM_INVALID;
-			_matched(_match_char_class(&p, str, flags));
-			continue;
-		}
-		
-		current_elm = _next_coll_elm(&p, flags);
-		if (current_elm == COLL_ELM_INVALID) {
-			return INVALID_PATTERN;
-		}
-		_matched(_coll_elm_match(current_elm, str));
-	}
-
-	/* No error occured - update pattern pointer. */
-	*pattern = p + 1;
-
-	if (matched == 0) {
-		/* No match found */
-		return negative;
-	} else {
-		/* Matched 'match' characters. */
-		return negative ? 0 : matched;
-	}
-
-	#undef _matched
-}
-
-/**
- * Matches a portion of the pattern containing no asterisks (*) against
- * the given string.
- * 
- * @param pattern Pointer to the unmatched portion of the pattern.
- *     On success, the pointer is moved to the first asterisk, or to the
- *     terminating nul character, whichever occurs first.
- * @param string Pointer to the input string. On success, the pointer is moved
- *     to the first character that wasn't explicitly matched.
- * @param flags Flags given to fnmatch().
- * @return True if the entire subpattern matched. False otherwise.
- */
-static bool _partial_match(const char **pattern, const char **string, int flags)
-{
-	/* Only a single *-delimited subpattern is matched here.
-	 * So in this function, '*' is understood as the end of pattern.
-	 */
-
-	const bool pathname = (flags & FNM_PATHNAME) != 0;
-	const bool special_period = (flags & FNM_PERIOD) != 0;
-	const bool noescape = (flags & FNM_NOESCAPE) != 0;
-	const bool leading_dir = (flags & FNM_LEADING_DIR) != 0;
-
-	const char *s = *string;
-	const char *p = *pattern;
-
-	while (*p != '*') {
-		/* Bracket expression. */
-		if (*p == '[') {
-			int matched = _match_bracket_expr(&p, s, flags);
-			if (matched == 0) {
-				/* Doesn't match. */
-				return false;
-			}
-			if (matched != INVALID_PATTERN) {
-				s += matched;
-				continue;
-			}
-
-			assert(matched == INVALID_PATTERN);
-			/* Fall through to match [ as an ordinary character. */
-		}
-
-		/* Wildcard match. */
-		if (*p == '?') {
-			if (*s == '\0') {
-				/* No character to match. */
-				return false;
-			}
-			if (pathname && *s == '/') {
-				/* Slash must be matched explicitly. */
-				return false;
-			}
-			if (special_period && pathname &&
-			    *s == '.' && *(s - 1) == '/') {
-				/* Initial period must be matched explicitly. */
-				return false;
-			}
-			
-			/* None of the above, match anything else. */
-			p++;
-			s++;
-			continue;
-		}
-
-		if (!noescape && *p == '\\') {
-			/* Escaped character. */
-			p++;
-		}
-
-		if (*p == '\0') {
-			/* End of pattern, must match end of string or
-			 * an end of subdirectory name (optional).
-			 */
-
-			if (*s == '\0' || (leading_dir && *s == '/')) {
-				break;
-			}
-
-			return false;
-		}
-
-		if (*p == *s) {
-			/* Exact match. */
-			p++;
-			s++;
-			continue;
-		}
-
-		/* Nothing matched. */
-		return false;
-	}
-
-	/* Entire sub-pattern matched. */
-	
-	/* postconditions */
-	assert(*p == '\0' || *p == '*');
-	assert(*p != '\0' || *s == '\0' || (leading_dir && *s == '/'));
-	
-	*pattern = p;
-	*string = s;
-	return true;
-}
-
-/**
- * Match string against a pattern.
- * 
- * @param pattern Pattern.
- * @param string String to match.
- * @param flags Flags given to fnmatch().
- * @return True if the string matched the pattern, false otherwise.
- */
-static bool _full_match(const char *pattern, const char *string, int flags)
-{
-	const bool pathname = (flags & FNM_PATHNAME) != 0;
-	const bool special_period = (flags & FNM_PERIOD) != 0;
-	const bool leading_dir = (flags & FNM_LEADING_DIR) != 0;
-
-	if (special_period && *string == '.') {
-		/* Initial dot must be matched by an explicit dot in pattern. */
-		if (*pattern != '.') {
-			return false;
-		}
-		pattern++;
-		string++;
-	}
-
-	if (*pattern != '*') {
-		if (!_partial_match(&pattern, &string, flags)) {
-			/* The initial match must succeed. */
-			return false;
-		}
-	}
-
-	while (*pattern != '\0') {
-		assert(*pattern == '*');
-		pattern++;
-
-		bool matched = false;
-
-		const char *end;
-		if (pathname && special_period &&
-		    *string == '.' && *(string - 1) == '/') {
-			end = string;
-		} else {
-			end = strchrnul(string, pathname ? '/' : '\0');
-		}
-
-		/* Try to match every possible offset. */
-		while (string <= end) {
-			if (_partial_match(&pattern, &string, flags)) {
-				matched = true;
-				break;
-			}
-			string++;
-		}
-
-		if (matched) {
-			continue;
-		}
-
-		return false;
-	}
-
-	return *string == '\0' || (leading_dir && *string == '/');
-}
-
-/**
- * Transform the entire string to lowercase.
- * 
- * @param s Input string.
- * @return Newly allocated copy of the input string with all uppercase
- *     characters folded to their lowercase variants.
- */
-static char *_casefold(const char *s)
-{
-	assert(s != NULL);
-	char *result = strdup(s);
-	for (char *i = result; *i != '\0'; ++i) {
-		*i = tolower(*i);
-	}
-	return result;
-}
-
-/**
- * Filename pattern matching.
- *
- * @param pattern Pattern to match the string against.
- * @param string Matched string.
- * @param flags Flags altering the matching of special characters
- *     (mainly for dot and slash).
- * @return Zero if the string matches the pattern, FNM_NOMATCH otherwise.
- */
-int posix_fnmatch(const char *pattern, const char *string, int flags)
-{
-	assert(pattern != NULL);
-	assert(string != NULL);
-
-	// TODO: don't fold everything in advance, but only when needed
-
-	if ((flags & FNM_CASEFOLD) != 0) {
-		/* Just fold the entire pattern and string. */
-		pattern = _casefold(pattern);
-		string = _casefold(string);
-	}
-
-	bool result = _full_match(pattern, string, flags);
-
-	if ((flags & FNM_CASEFOLD) != 0) {
-		if (pattern) {
-			free((char *) pattern);
-		}
-		if (string) {
-			free((char *) string);
-		}
-	}
-
-	return result ? 0 : FNM_NOMATCH;
-}
-
-// FIXME: put the testcases to the app/tester after fnmatch is included into libc
-
-#if 0
-
-#include <stdio.h>
-
-void __posix_fnmatch_test()
-{
-	int fail = 0;
-
-	#undef assert
-	#define assert(x) { if (x) printf("SUCCESS: "#x"\n"); else { printf("FAILED: "#x"\n"); fail++; } }
-	#define match(s1, s2, flags) assert(posix_fnmatch(s1, s2, flags) == 0)
-	#define nomatch(s1, s2, flags) assert(posix_fnmatch(s1, s2, flags) == FNM_NOMATCH)
-
-	assert(FNM_PATHNAME == FNM_FILE_NAME);
-	match("", "", 0);
-	match("*", "hello", 0);
-	match("hello", "hello", 0);
-	match("hello*", "hello", 0);
-	nomatch("hello?", "hello", 0);
-	match("*hello", "prdel hello", 0);
-	match("he[sl]lo", "hello", 0);
-	match("he[sl]lo", "heslo", 0);
-	nomatch("he[sl]lo", "heblo", 0);
-	nomatch("he[^sl]lo", "hello", 0);
-	nomatch("he[^sl]lo", "heslo", 0);
-	match("he[^sl]lo", "heblo", 0);
-	nomatch("he[!sl]lo", "hello", 0);
-	nomatch("he[!sl]lo", "heslo", 0);
-	match("he[!sl]lo", "heblo", 0);
-	match("al*[c-t]a*vis*ta", "alheimer talir jehovista", 0);
-	match("al*[c-t]a*vis*ta", "alfons had jehovista", 0);
-	match("[a-ce-z]", "a", 0);
-	match("[a-ce-z]", "c", 0);
-	nomatch("[a-ce-z]", "d", 0);
-	match("[a-ce-z]", "e", 0);
-	match("[a-ce-z]", "z", 0);
-	nomatch("[^a-ce-z]", "a", 0);
-	nomatch("[^a-ce-z]", "c", 0);
-	match("[^a-ce-z]", "d", 0);
-	nomatch("[^a-ce-z]", "e", 0);
-	nomatch("[^a-ce-z]", "z", 0);
-	match("helen??", "helenos", 0);
-	match("****booo****", "booo", 0);
-	
-	match("hello[[:space:]]world", "hello world", 0);
-	nomatch("hello[[:alpha:]]world", "hello world", 0);
-	
-	match("/hoooo*", "/hooooooo/hooo", 0);
-	nomatch("/hoooo*", "/hooooooo/hooo", FNM_PATHNAME);
-	nomatch("/hoooo*/", "/hooooooo/hooo", FNM_PATHNAME);
-	match("/hoooo*/*", "/hooooooo/hooo", FNM_PATHNAME);
-	match("/hoooo*/hooo", "/hooooooo/hooo", FNM_PATHNAME);
-	match("/hoooo*", "/hooooooo/hooo", FNM_PATHNAME | FNM_LEADING_DIR);
-	nomatch("/hoooo*/", "/hooooooo/hooo", FNM_PATHNAME | FNM_LEADING_DIR);
-	nomatch("/hoooo", "/hooooooo/hooo", FNM_LEADING_DIR);
-	match("/hooooooo", "/hooooooo/hooo", FNM_LEADING_DIR);
-	
-	match("*", "hell", 0);
-	match("*?", "hell", 0);
-	match("?*?", "hell", 0);
-	match("?*??", "hell", 0);
-	match("??*??", "hell", 0);
-	nomatch("???*??", "hell", 0);
-	
-	nomatch("", "hell", 0);
-	nomatch("?", "hell", 0);
-	nomatch("??", "hell", 0);
-	nomatch("???", "hell", 0);
-	match("????", "hell", 0);
-	
-	match("*", "h.ello", FNM_PERIOD);
-	match("*", "h.ello", FNM_PATHNAME | FNM_PERIOD);
-	nomatch("*", ".hello", FNM_PERIOD);
-	match("h?ello", "h.ello", FNM_PERIOD);
-	nomatch("?hello", ".hello", FNM_PERIOD);
-	match("/home/user/.*", "/home/user/.hello", FNM_PATHNAME | FNM_PERIOD);
-	match("/home/user/*", "/home/user/.hello", FNM_PERIOD);
-	nomatch("/home/user/*", "/home/user/.hello", FNM_PATHNAME | FNM_PERIOD);
-
-	nomatch("HeLlO", "hello", 0);
-	match("HeLlO", "hello", FNM_CASEFOLD);
-
-	printf("Failed: %d\n", fail);
-}
-
-#endif
-
-/** @}
- */
Index: pace/lib/posix/fnmatch.h
===================================================================
--- uspace/lib/posix/fnmatch.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,67 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Filename-matching.
- */
-
-#ifndef POSIX_FNMATCH_H_
-#define POSIX_FNMATCH_H_
-
-/* Error Values */
-#undef FNM_NOMATCH
-#define FNM_NOMATCH 1
-
-/* Flags */
-#undef FNM_PATHNAME
-#undef FNM_PERIOD
-#undef FNM_NOESCAPE
-#define FNM_PATHNAME 1
-#define FNM_PERIOD 2
-#define FNM_NOESCAPE 4
-
-/* GNU Extensions */
-#undef FNM_FILE_NAME
-#undef FNM_LEADING_DIR
-#undef FNM_CASEFOLD
-#define FNM_FILE_NAME FNM_PATHNAME
-#define FNM_LEADING_DIR 8
-#define FNM_CASEFOLD 16
-
-extern int posix_fnmatch(const char *pattern, const char *string, int flags);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define fnmatch posix_fnmatch
-#endif
-
-#endif /* POSIX_FNMATCH_H_ */
-
-/** @}
- */
Index: pace/lib/posix/getopt.c
===================================================================
--- uspace/lib/posix/getopt.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2012 Vojtech Horky
- * 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 libposix
- * @{
- */
-/** @file Command line argument parsing.
- */
-#define LIBPOSIX_INTERNAL
-
-#include "internal/common.h"
-#include "libc/getopt.h"
-#include "getopt.h"
-
-
-int posix_getopt_long(int argc, char * const argv[],
-    const char *opt_string, const struct option *long_opts, int *long_index)
-{
-	int rc = getopt_long(argc, argv, opt_string, long_opts, long_index);
-	posix_optarg = (char *) optarg;
-	return rc;
-}
-
-int posix_getopt(int argc, char * const argv[], const char *opt_string)
-{
-	int rc = getopt(argc, argv, opt_string);
-	posix_optarg = (char *) optarg;
-	return rc;
-}
Index: pace/lib/posix/getopt.h
===================================================================
--- uspace/lib/posix/getopt.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,64 +1,0 @@
-/*
- * Copyright (c) 2012 Vojtech Horky
- * 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 libposix
- * @{
- */
-/** @file Command line argument parsing.
- */
-#ifndef POSIX_GETOPT_H
-#define POSIX_GETOPT_H
-
-#include "unistd.h"
-
-/* Option Arguments */
-#define no_argument        0
-#define required_argument  1
-#define optional_argument  2
-
-#ifndef LIBPOSIX_INTERNAL
-struct option {
-	const char *name;
-	int has_arg;
-	int *flag;
-	int val;
-};
-#endif
-
-extern int posix_getopt_long(int, char * const [], const char *, const struct option *, int *);
-
-
-#ifndef LIBPOSIX_INTERNAL
-	#define getopt_long posix_getopt_long
-#endif
-
-
-#endif
-/**
- * @}
- */
Index: uspace/lib/posix/include/posix/assert.h
===================================================================
--- uspace/lib/posix/include/posix/assert.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/assert.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Program assertion.
+ */
+
+/* NO include guard on purpose. */
+
+#include "libc/assert.h"
+
+#undef assert
+
+#ifndef NDEBUG
+	#define assert(expr) ((expr) ? (void) 0 : assert_abort(#expr, __FILE__, __LINE__))
+#else
+	#define assert(expr) ((void) 0)
+#endif
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/ctype.h
===================================================================
--- uspace/lib/posix/include/posix/ctype.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/ctype.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Character classification.
+ */
+
+#ifndef POSIX_CTYPE_H_
+#define POSIX_CTYPE_H_
+
+#include "libc/ctype.h"
+
+/* Classification of Characters */
+extern int posix_isxdigit(int c);
+extern int posix_isblank(int c);
+extern int posix_iscntrl(int c);
+extern int posix_isgraph(int c);
+extern int posix_isprint(int c);
+extern int posix_ispunct(int c);
+
+/* Obsolete Functions and Macros */
+extern int posix_isascii(int c);
+extern int posix_toascii(int c);
+#undef _tolower
+#define _tolower(c) ((c) - 'A' + 'a')
+#undef _toupper
+#define _toupper(c) ((c) - 'a' + 'A')
+
+
+#ifndef LIBPOSIX_INTERNAL
+	#define isxdigit posix_isxdigit
+	#define isblank posix_isblank
+	#define iscntrl posix_iscntrl
+	#define isgraph posix_isgraph
+	#define isprint posix_isprint
+	#define ispunct posix_ispunct
+	
+	#define isascii posix_isascii
+	#define toascii posix_toascii
+#endif
+
+#endif /* POSIX_CTYPE_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/errno.h
===================================================================
--- uspace/lib/posix/include/posix/errno.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/errno.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file System error numbers.
+ */
+
+#ifndef POSIX_ERRNO_H_
+#define POSIX_ERRNO_H_
+
+#include "libc/errno.h"
+
+/* IMPORTANT:
+ * Since libc uses negative errorcodes, some sort of conversion is necessary to
+ * keep POSIX programs and libraries from breaking. This file maps POSIX error
+ * codes to absolute values of corresponding libc codes where available, and
+ * assigns new code where there is no prior definition in libc.
+ *
+ * A new errno variable is defined. When accessed, the function first looks at
+ * libc errno and iff it is != 0, sets the POSIX errno to absolute value of
+ * libc errno. Given that no library function sets errno to 0 and that all
+ * POSIX libraries will be used solely by POSIX programs (thus, there only needs
+ * to be one way correspondence between errno and posix_errno), this approach
+ * should work as expected in most cases and does not require any wrappers for
+ * libc routines that would just change errno values.
+ *
+ * There is no conditioning by LIBPOSIX_INTERNAL for redefinitions of macros.
+ * If there is a need to check errno for a value not defined by POSIX, it's
+ * necessary to compare errno against abs(ECODE), because there is no
+ * redefinition for such error codes.
+ *
+ * XXX: maybe all HOS error codes should be redefined
+ *
+ * NOTE: This redefinition is slightly POSIX incompatible, since the
+ *  specification requires the macro values to be usable in preprocessing
+ *  directives. I don't think that's very important, though.
+ */
+
+#undef errno
+#define errno (*__posix_errno())
+
+extern int *__posix_errno(void);
+
+#define __TOP_ERRNO (-NO_DATA)
+
+enum {
+	POSIX_E2BIG = __TOP_ERRNO + 1,
+	POSIX_EACCES = __TOP_ERRNO + 2,
+	POSIX_EADDRINUSE = -EADDRINUSE,
+	POSIX_EADDRNOTAVAIL = -EADDRNOTAVAIL,
+	POSIX_EAFNOSUPPORT = -EAFNOSUPPORT,
+	POSIX_EAGAIN = -EAGAIN,
+	POSIX_EALREADY = __TOP_ERRNO + 3,
+	POSIX_EBADF = -EBADF,
+	POSIX_EBADMSG = __TOP_ERRNO + 4,
+	POSIX_EBUSY = -EBUSY,
+	POSIX_ECANCELED = __TOP_ERRNO + 5,
+	POSIX_ECHILD = __TOP_ERRNO + 6,
+	POSIX_ECONNABORTED = __TOP_ERRNO + 7,
+	POSIX_ECONNREFUSED = __TOP_ERRNO + 8,
+	POSIX_ECONNRESET = __TOP_ERRNO + 9,
+	POSIX_EDEADLK = __TOP_ERRNO + 10,
+	POSIX_EDESTADDRREQ = -EDESTADDRREQ,
+	POSIX_EDOM = __TOP_ERRNO + 11,
+	POSIX_EDQUOT = __TOP_ERRNO + 12,
+	POSIX_EEXIST = -EEXIST,
+	POSIX_EFAULT = __TOP_ERRNO + 13,
+	POSIX_EFBIG = __TOP_ERRNO + 14,
+	POSIX_EHOSTUNREACH = __TOP_ERRNO + 15,
+	POSIX_EIDRM = __TOP_ERRNO + 16,
+	POSIX_EILSEQ = __TOP_ERRNO + 17,
+	POSIX_EINPROGRESS = -EINPROGRESS,
+	POSIX_EINTR = -EINTR,
+	POSIX_EINVAL = -EINVAL,
+	POSIX_EIO = -EIO,
+	POSIX_EISCONN = __TOP_ERRNO + 18,
+	POSIX_EISDIR = -EISDIR,
+	POSIX_ELOOP = __TOP_ERRNO + 19,
+	POSIX_EMFILE = -EMFILE,
+	POSIX_EMLINK = -EMLINK,
+	POSIX_EMSGSIZE = __TOP_ERRNO + 20,
+	POSIX_EMULTIHOP = __TOP_ERRNO + 21,
+	POSIX_ENAMETOOLONG = -ENAMETOOLONG,
+	POSIX_ENETDOWN = __TOP_ERRNO + 22,
+	POSIX_ENETRESET = __TOP_ERRNO + 23,
+	POSIX_ENETUNREACH = __TOP_ERRNO + 24,
+	POSIX_ENFILE = __TOP_ERRNO + 25,
+	POSIX_ENOBUFS = __TOP_ERRNO + 26,
+	POSIX_ENODATA = -NO_DATA,
+	POSIX_ENODEV = __TOP_ERRNO + 27,
+	POSIX_ENOENT = -ENOENT,
+	POSIX_ENOEXEC = __TOP_ERRNO + 28,
+	POSIX_ENOLCK = __TOP_ERRNO + 29,
+	POSIX_ENOLINK = __TOP_ERRNO + 30,
+	POSIX_ENOMEM = -ENOMEM,
+	POSIX_ENOMSG = __TOP_ERRNO + 31,
+	POSIX_ENOPROTOOPT = __TOP_ERRNO + 32,
+	POSIX_ENOSPC = -ENOSPC,
+	POSIX_ENOSR = __TOP_ERRNO + 33,
+	POSIX_ENOSTR = __TOP_ERRNO + 34,
+	POSIX_ENOSYS = __TOP_ERRNO + 35,
+	POSIX_ENOTCONN = -ENOTCONN,
+	POSIX_ENOTDIR = -ENOTDIR,
+	POSIX_ENOTEMPTY = -ENOTEMPTY,
+	POSIX_ENOTRECOVERABLE = __TOP_ERRNO + 36,
+	POSIX_ENOTSOCK = -ENOTSOCK,
+	POSIX_ENOTSUP = -ENOTSUP,
+	POSIX_ENOTTY = __TOP_ERRNO + 37,
+	POSIX_ENXIO = __TOP_ERRNO + 38,
+	POSIX_EOPNOTSUPP = __TOP_ERRNO + 39,
+	POSIX_EOVERFLOW = -EOVERFLOW,
+	POSIX_EOWNERDEAD = __TOP_ERRNO + 40,
+	POSIX_EPERM = -EPERM,
+	POSIX_EPIPE = __TOP_ERRNO + 41,
+	POSIX_EPROTO = __TOP_ERRNO + 42,
+	POSIX_EPROTONOSUPPORT = -EPROTONOSUPPORT,
+	POSIX_EPROTOTYPE = __TOP_ERRNO + 43,
+	POSIX_ERANGE = -ERANGE,
+	POSIX_EROFS = __TOP_ERRNO + 44,
+	POSIX_ESPIPE = __TOP_ERRNO + 45,
+	POSIX_ESRCH = __TOP_ERRNO + 46,
+	POSIX_ESTALE = __TOP_ERRNO + 47,
+	POSIX_ETIME = __TOP_ERRNO + 48,
+	POSIX_ETIMEDOUT = __TOP_ERRNO + 49,
+	POSIX_ETXTBSY = __TOP_ERRNO + 50,
+	POSIX_EWOULDBLOCK = __TOP_ERRNO + 51,
+	POSIX_EXDEV = -EXDEV,
+};
+
+#undef __TOP_ERRNO
+
+#undef E2BIG
+#undef EACCES
+#undef EADDRINUSE
+#undef EADDRNOTAVAIL
+#undef EAFNOSUPPORT
+#undef EAGAIN
+#undef EALREADY
+#undef EBADF
+#undef EBADMSG
+#undef EBUSY
+#undef ECANCELED
+#undef ECHILD
+#undef ECONNABORTED
+#undef ECONNREFUSED
+#undef ECONNRESET
+#undef EDEADLK
+#undef EDESTADDRREQ
+#undef EDOM
+#undef EDQUOT
+#undef EEXIST
+#undef EFAULT
+#undef EFBIG
+#undef EHOSTUNREACH
+#undef EIDRM
+#undef EILSEQ
+#undef EINPROGRESS
+#undef EINTR
+#undef EINVAL
+#undef EIO
+#undef EISCONN
+#undef EISDIR
+#undef ELOOP
+#undef EMFILE
+#undef EMLINK
+#undef EMSGSIZE
+#undef EMULTIHOP
+#undef ENAMETOOLONG
+#undef ENETDOWN
+#undef ENETRESET
+#undef ENETUNREACH
+#undef ENFILE
+#undef ENOBUFS
+#undef ENODATA
+#undef ENODEV
+#undef ENOENT
+#undef ENOEXEC
+#undef ENOLCK
+#undef ENOLINK
+#undef ENOMEM
+#undef ENOMSG
+#undef ENOPROTOOPT
+#undef ENOSPC
+#undef ENOSR
+#undef ENOSTR
+#undef ENOSYS
+#undef ENOTCONN
+#undef ENOTDIR
+#undef ENOTEMPTY
+#undef ENOTRECOVERABLE
+#undef ENOTSOCK
+#undef ENOTSUP
+#undef ENOTTY
+#undef ENXIO
+#undef EOPNOTSUPP
+#undef EOVERFLOW
+#undef EOWNERDEAD
+#undef EPERM
+#undef EPIPE
+#undef EPROTO
+#undef EPROTONOSUPPORT
+#undef EPROTOTYPE
+#undef ERANGE
+#undef EROFS
+#undef ESPIPE
+#undef ESRCH
+#undef ESTALE
+#undef ETIME
+#undef ETIMEDOUT
+#undef ETXTBSY
+#undef EWOULDBLOCK
+#undef EXDEV
+
+#define E2BIG POSIX_E2BIG
+#define EACCES POSIX_EACCES
+#define EADDRINUSE POSIX_EADDRINUSE
+#define EADDRNOTAVAIL POSIX_EADDRNOTAVAIL
+#define EAFNOSUPPORT POSIX_EAFNOSUPPORT
+#define EAGAIN POSIX_EAGAIN
+#define EALREADY POSIX_EALREADY
+#define EBADF POSIX_EBADF
+#define EBADMSG POSIX_EBADMSG
+#define EBUSY POSIX_EBUSY
+#define ECANCELED POSIX_ECANCELED
+#define ECHILD POSIX_ECHILD
+#define ECONNABORTED POSIX_ECONNABORTED
+#define ECONNREFUSED POSIX_ECONNREFUSED
+#define ECONNRESET POSIX_ECONNRESET
+#define EDEADLK POSIX_EDEADLK
+#define EDESTADDRREQ POSIX_EDESTADDRREQ
+#define EDOM POSIX_EDOM
+#define EDQUOT POSIX_EDQUOT
+#define EEXIST POSIX_EEXIST
+#define EFAULT POSIX_EFAULT
+#define EFBIG POSIX_EFBIG
+#define EHOSTUNREACH POSIX_EHOSTUNREACH
+#define EIDRM POSIX_EIDRM
+#define EILSEQ POSIX_EILSEQ
+#define EINPROGRESS POSIX_EINPROGRESS
+#define EINTR POSIX_EINTR
+#define EINVAL POSIX_EINVAL
+#define EIO POSIX_EIO
+#define EISCONN POSIX_EISCONN
+#define EISDIR POSIX_EISDIR
+#define ELOOP POSIX_ELOOP
+#define EMFILE POSIX_EMFILE
+#define EMLINK POSIX_EMLINK
+#define EMSGSIZE POSIX_EMSGSIZE
+#define EMULTIHOP POSIX_EMULTIHOP
+#define ENAMETOOLONG POSIX_ENAMETOOLONG
+#define ENETDOWN POSIX_ENETDOWN
+#define ENETRESET POSIX_ENETRESET
+#define ENETUNREACH POSIX_ENETUNREACH
+#define ENFILE POSIX_ENFILE
+#define ENOBUFS POSIX_ENOBUFS
+#define ENODATA POSIX_ENODATA
+#define ENODEV POSIX_ENODEV
+#define ENOENT POSIX_ENOENT
+#define ENOEXEC POSIX_ENOEXEC
+#define ENOLCK POSIX_ENOLCK
+#define ENOLINK POSIX_ENOLINK
+#define ENOMEM POSIX_ENOMEM
+#define ENOMSG POSIX_ENOMSG
+#define ENOPROTOOPT POSIX_ENOPROTOOPT
+#define ENOSPC POSIX_ENOSPC
+#define ENOSR POSIX_ENOSR
+#define ENOSTR POSIX_ENOSTR
+#define ENOSYS POSIX_ENOSYS
+#define ENOTCONN POSIX_ENOTCONN
+#define ENOTDIR POSIX_ENOTDIR
+#define ENOTEMPTY POSIX_ENOTEMPTY
+#define ENOTRECOVERABLE POSIX_ENOTRECOVERABLE
+#define ENOTSOCK POSIX_ENOTSOCK
+#define ENOTSUP POSIX_ENOTSUP
+#define ENOTTY POSIX_ENOTTY
+#define ENXIO POSIX_ENXIO
+#define EOPNOTSUPP POSIX_EOPNOTSUPP
+#define EOVERFLOW POSIX_EOVERFLOW
+#define EOWNERDEAD POSIX_EOWNERDEAD
+#define EPERM POSIX_EPERM
+#define EPIPE POSIX_EPIPE
+#define EPROTO POSIX_EPROTO
+#define EPROTONOSUPPORT POSIX_EPROTONOSUPPORT
+#define EPROTOTYPE POSIX_EPROTOTYPE
+#define ERANGE POSIX_ERANGE
+#define EROFS POSIX_EROFS
+#define ESPIPE POSIX_ESPIPE
+#define ESRCH POSIX_ESRCH
+#define ESTALE POSIX_ESTALE
+#define ETIME POSIX_ETIME
+#define ETIMEDOUT POSIX_ETIMEDOUT
+#define ETXTBSY POSIX_ETXTBSY
+#define EWOULDBLOCK POSIX_EWOULDBLOCK
+#define EXDEV POSIX_EXDEV
+
+#endif /* POSIX_ERRNO_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/fcntl.h
===================================================================
--- uspace/lib/posix/include/posix/fcntl.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/fcntl.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file File control.
+ */
+
+#ifndef POSIX_FCNTL_H_
+#define POSIX_FCNTL_H_
+
+#include "sys/types.h"
+#include "libc/fcntl.h"
+#include "errno.h"
+
+/* Mask for file access modes. */
+#undef O_ACCMODE
+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+
+/* fcntl commands */
+#undef F_DUPFD
+#undef F_DUPFD_CLOEXEC
+#undef F_GETFD
+#undef F_SETFD
+#undef F_GETFL
+#undef F_SETFL
+#undef F_GETOWN
+#undef F_SETOWN
+#undef F_GETLK
+#undef F_SETLK
+#undef F_SETLKW
+#define F_DUPFD            0 /* Duplicate file descriptor. */
+#define F_DUPFD_CLOEXEC    1 /* Same as F_DUPFD but with FD_CLOEXEC flag set. */
+#define F_GETFD            2 /* Get file descriptor flags. */
+#define F_SETFD            3 /* Set file descriptor flags. */
+#define F_GETFL            4 /* Get file status and access flags. */
+#define F_SETFL            5 /* Set file status flags. */
+#define F_GETOWN           6 /* Get socket owner. */
+#define F_SETOWN           7 /* Set socket owner. */
+#define F_GETLK            8 /* Get locking information. */
+#define F_SETLK            9 /* Set locking information. */
+#define F_SETLKW          10 /* Set locking information; wait if blocked. */
+
+/* File descriptor flags used with F_GETFD and F_SETFD. */
+#undef FD_CLOEXEC
+#define FD_CLOEXEC         1 /* Close on exec. */
+
+extern int posix_open(const char *pathname, int flags, ...);
+extern int posix_fcntl(int fd, int cmd, ...);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define fcntl posix_fcntl
+	#define open posix_open
+#endif
+
+#endif /* POSIX_FCNTL_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/float.h
===================================================================
--- uspace/lib/posix/include/posix/float.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/float.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Floating type support.
+ */
+
+#ifndef POSIX_FLOAT_H_
+#define POSIX_FLOAT_H_
+
+/* Empty. Just to satisfy preprocessor. */
+
+#endif /* POSIX_FLOAT_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/fnmatch.h
===================================================================
--- uspace/lib/posix/include/posix/fnmatch.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/fnmatch.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Filename-matching.
+ */
+
+#ifndef POSIX_FNMATCH_H_
+#define POSIX_FNMATCH_H_
+
+/* Error Values */
+#undef FNM_NOMATCH
+#define FNM_NOMATCH 1
+
+/* Flags */
+#undef FNM_PATHNAME
+#undef FNM_PERIOD
+#undef FNM_NOESCAPE
+#define FNM_PATHNAME 1
+#define FNM_PERIOD 2
+#define FNM_NOESCAPE 4
+
+/* GNU Extensions */
+#undef FNM_FILE_NAME
+#undef FNM_LEADING_DIR
+#undef FNM_CASEFOLD
+#define FNM_FILE_NAME FNM_PATHNAME
+#define FNM_LEADING_DIR 8
+#define FNM_CASEFOLD 16
+
+extern int posix_fnmatch(const char *pattern, const char *string, int flags);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define fnmatch posix_fnmatch
+#endif
+
+#endif /* POSIX_FNMATCH_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/getopt.h
===================================================================
--- uspace/lib/posix/include/posix/getopt.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/getopt.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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 libposix
+ * @{
+ */
+/** @file Command line argument parsing.
+ */
+#ifndef POSIX_GETOPT_H
+#define POSIX_GETOPT_H
+
+#include "unistd.h"
+
+/* Option Arguments */
+#define no_argument        0
+#define required_argument  1
+#define optional_argument  2
+
+#ifndef LIBPOSIX_INTERNAL
+struct option {
+	const char *name;
+	int has_arg;
+	int *flag;
+	int val;
+};
+#endif
+
+extern int posix_getopt_long(int, char * const [], const char *, const struct option *, int *);
+
+
+#ifndef LIBPOSIX_INTERNAL
+	#define getopt_long posix_getopt_long
+#endif
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/posix/include/posix/inttypes.h
===================================================================
--- uspace/lib/posix/include/posix/inttypes.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/inttypes.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Fixed size integer types.
+ */
+
+#ifndef POSIX_INTTYPES_H_
+#define POSIX_INTTYPES_H_
+
+#include "stdint.h"
+#include "libc/inttypes.h"
+
+extern posix_intmax_t posix_strtoimax(const char *restrict nptr,
+    char **restrict endptr, int base);
+extern posix_uintmax_t posix_strtoumax(const char *restrict nptr,
+    char **restrict endptr, int base);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define strtoimax posix_strtoimax
+	#define strtoumax posix_strtoumax
+#endif
+
+#endif /* POSIX_INTTYPES_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/iso646.h
===================================================================
--- uspace/lib/posix/include/posix/iso646.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/iso646.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Alternative spellings.
+ */
+
+#ifndef POSIX_ISO646_H_
+#define POSIX_ISO646_H_
+
+#define and &&
+#define and_eq &=
+#define bitand &
+#define bitor |
+#define compl ˜
+#define not !
+#define not_eq !=
+#define or ||
+#define or_eq |=
+#define xor ^
+#define xor_eq ^=
+
+#endif /* POSIX_ISO646_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/limits.h
===================================================================
--- uspace/lib/posix/include/posix/limits.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/limits.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Implementation-defined limit constants.
+ */
+
+#ifndef POSIX_LIMITS_H_
+#define POSIX_LIMITS_H_
+
+#include "stdint.h"
+#include "libc/sys/types.h"
+
+#undef SHRT_MIN
+#undef SHRT_MAX
+#undef USHRT_MAX
+#define SHRT_MIN SHORT_MIN
+#define SHRT_MAX SHORT_MAX
+#define USHRT_MAX USHORT_MAX
+
+#undef PATH_MAX
+#define PATH_MAX 256
+
+#endif /* POSIX_LIMITS_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/locale.h
===================================================================
--- uspace/lib/posix/include/posix/locale.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/locale.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Locale-specific definitions.
+ */
+
+#ifndef POSIX_LOCALE_H_
+#define POSIX_LOCALE_H_
+
+#ifndef NULL
+	#define NULL ((void *) 0)
+#endif
+
+#ifndef __locale_t_defined
+	#define __locale_t_defined
+	typedef struct __posix_locale *posix_locale_t;
+	#ifndef LIBPOSIX_INTERNAL
+		#define locale_t posix_locale_t
+	#endif
+#endif
+
+#undef LC_ALL
+#undef LC_COLLATE
+#undef LC_CTYPE
+#undef LC_MESSAGES
+#undef LC_MONETARY
+#undef LC_NUMERIC
+#undef LC_TIME
+#define LC_ALL 0
+#define LC_COLLATE 1
+#define LC_CTYPE 2
+#define LC_MESSAGES 3
+#define LC_MONETARY 4
+#define LC_NUMERIC 5
+#define LC_TIME 6
+
+#undef LC_COLLATE_MASK
+#undef LC_CTYPE_MASK
+#undef LC_MESSAGES_MASK
+#undef LC_MONETARY_MASK
+#undef LC_NUMERIC_MASK
+#undef LC_TIME_MASK
+#undef LC_ALL_MASK
+#define LC_COLLATE_MASK (1 << 0)
+#define LC_CTYPE_MASK (1 << 1)
+#define LC_MESSAGES_MASK (1 << 2)
+#define LC_MONETARY_MASK (1 << 3)
+#define LC_NUMERIC_MASK (1 << 4)
+#define LC_TIME_MASK (1 << 5)
+#define LC_ALL_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | \
+    LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK)
+
+#undef LC_GLOBAL_LOCALE
+#define LC_GLOBAL_LOCALE NULL
+
+struct posix_lconv {
+	char *currency_symbol;
+	char *decimal_point;
+	char  frac_digits;
+	char *grouping;
+	char *int_curr_symbol;
+	char  int_frac_digits;
+	char  int_n_cs_precedes;
+	char  int_n_sep_by_space;
+	char  int_n_sign_posn;
+	char  int_p_cs_precedes;
+	char  int_p_sep_by_space;
+	char  int_p_sign_posn;
+	char *mon_decimal_point;
+	char *mon_grouping;
+	char *mon_thousands_sep;
+	char *negative_sign;
+	char  n_cs_precedes;
+	char  n_sep_by_space;
+	char  n_sign_posn;
+	char *positive_sign;
+	char  p_cs_precedes;
+	char  p_sep_by_space;
+	char  p_sign_posn;
+	char *thousands_sep;
+};
+
+extern char *posix_setlocale(int category, const char *locale);
+extern struct posix_lconv *posix_localeconv(void);
+
+/* POSIX Extensions */
+extern posix_locale_t posix_duplocale(posix_locale_t locobj);
+extern void posix_freelocale(posix_locale_t locobj);
+extern posix_locale_t posix_newlocale(int category_mask, const char *locale,
+    posix_locale_t base);
+extern posix_locale_t posix_uselocale(posix_locale_t newloc);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define lconv posix_lconv
+
+	#define setlocale posix_setlocale
+	#define localeconv posix_localeconv
+
+	#define newlocale posix_newlocale
+	#define uselocale posix_uselocale
+	#define duplocale posix_duplocale
+	#define freelocale posix_freelocale
+#endif
+
+#endif /* POSIX_LOCALE_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/malloc.h
===================================================================
--- uspace/lib/posix/include/posix/malloc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/malloc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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 libposix
+ * @{
+ */
+#ifndef POSIX_MALLOC_H_
+#define POSIX_MALLOC_H_
+
+/* Empty. Just to satisfy preprocessor. */
+
+#endif /* POSIX_MALLOC_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/math.h
===================================================================
--- uspace/lib/posix/include/posix/math.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/math.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Mathematical operations.
+ */
+
+#ifndef POSIX_MATH_H_
+#define POSIX_MATH_H_
+
+/* Normalization Functions */
+extern double posix_ldexp(double x, int exp);
+extern double posix_frexp(double num, int *exp);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define ldexp posix_ldexp
+	#define frexp posix_frexp
+#endif
+
+#endif /* POSIX_MATH_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/pwd.h
===================================================================
--- uspace/lib/posix/include/posix/pwd.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/pwd.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Password handling.
+ */
+
+#ifndef POSIX_PWD_H_
+#define POSIX_PWD_H_
+
+#include "sys/types.h"
+
+struct posix_passwd {
+	char *pw_name;
+	posix_uid_t pw_uid;
+	posix_gid_t pw_gid;
+	char *pw_dir;
+	char *pw_shell;
+};
+
+extern struct posix_passwd *posix_getpwent(void);
+extern void posix_setpwent(void);
+extern void posix_endpwent(void);
+
+extern struct posix_passwd *posix_getpwnam(const char *name);
+extern int posix_getpwnam_r(const char *name, struct posix_passwd *pwd,
+    char *buffer, size_t bufsize, struct posix_passwd **result);
+
+extern struct posix_passwd *posix_getpwuid(posix_uid_t uid);
+extern int posix_getpwuid_r(posix_uid_t uid, struct posix_passwd *pwd,
+    char *buffer, size_t bufsize, struct posix_passwd **result);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define passwd posix_passwd
+	
+	#define getpwent posix_getpwent
+	#define setpwent posix_setpwent
+	#define endpwent posix_endpwent
+
+	#define getpwnam posix_getpwnam
+	#define getpwnam_r posix_getpwnam_r
+
+	#define getpwuid posix_getpwuid
+	#define getpwuid_r posix_getpwuid_r
+#endif
+
+#endif /* POSIX_PWD_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/signal.h
===================================================================
--- uspace/lib/posix/include/posix/signal.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/signal.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Signal handling.
+ */
+
+#ifndef POSIX_SIGNAL_H_
+#define POSIX_SIGNAL_H_
+
+#include "sys/types.h"
+
+extern void __posix_default_signal_handler(int signo);
+extern void __posix_hold_signal_handler(int signo);
+extern void __posix_ignore_signal_handler(int signo);
+
+#undef SIG_DFL
+#define SIG_DFL ((void (*)(int)) __posix_default_signal_handler)
+#undef SIG_ERR
+#define SIG_ERR ((void (*)(int)) NULL)
+#undef SIG_HOLD
+#define SIG_HOLD ((void (*)(int)) __posix_hold_signal_handler)
+#undef SIG_IGN
+#define SIG_IGN ((void (*)(int)) __posix_ignore_signal_handler)
+
+typedef int posix_sig_atomic_t;
+typedef uint32_t posix_sigset_t;
+typedef struct posix_mcontext {
+	/* must not be empty to avoid compiler warnings (-pedantic) */
+	int dummy;
+} posix_mcontext_t;
+
+union posix_sigval {
+	int sival_int;
+	void *sival_ptr;
+};
+
+struct posix_sigevent {
+	int sigev_notify; /* Notification type. */
+	int sigev_signo; /* Signal number. */
+	union posix_sigval sigev_value; /* Signal value. */
+	void (*sigev_notify_function)(union posix_sigval); /* Notification function. */
+	posix_thread_attr_t *sigev_notify_attributes; /* Notification attributes. */
+};
+
+typedef struct {
+	int si_signo;
+	int si_code;
+
+	int si_errno;
+
+	posix_pid_t si_pid;
+	posix_uid_t si_uid;
+	void *si_addr;
+	int si_status;
+
+	long si_band;
+
+	union posix_sigval si_value;
+} posix_siginfo_t;
+
+struct posix_sigaction {
+	void (*sa_handler)(int);
+	posix_sigset_t sa_mask;
+	int sa_flags;
+	void (*sa_sigaction)(int, posix_siginfo_t *, void *);
+};
+
+typedef struct {
+	void *ss_sp;
+	size_t ss_size;
+	int ss_flags;
+} posix_stack_t;
+
+typedef struct posix_ucontext {
+	struct posix_ucontext *uc_link;
+	posix_sigset_t uc_sigmask;
+	posix_stack_t uc_stack;
+	posix_mcontext_t uc_mcontext;
+} posix_ucontext_t;
+
+/* Values of posix_sigevent::sigev_notify */
+#undef SIGEV_NONE
+#undef SIGEV_SIGNAL
+#undef SIGEV_THREAD
+#define SIGEV_NONE 0
+#define SIGEV_SIGNAL 0
+#define SIGEV_THREAD 0
+
+#undef SIGRT_MIN
+#undef SIGRT_MAX
+#define SIGRT_MIN 0
+#define SIGRT_MAX 0
+
+#undef SIG_BLOCK
+#undef SIG_UNBLOCK
+#undef SIG_SETMASK
+#define SIG_BLOCK 0
+#define SIG_UNBLOCK 1
+#define SIG_SETMASK 2
+
+#undef SA_NOCLDSTOP
+#undef SA_ONSTACK
+#undef SA_RESETHAND
+#undef SA_RESTART
+#undef SA_SIGINFO
+#undef SA_NOCLDWAIT
+#undef SA_NODEFER
+#define SA_NOCLDSTOP (1 << 0)
+#define SA_ONSTACK (1 << 1)
+#define SA_RESETHAND (1 << 2)
+#define SA_RESTART (1 << 3)
+#define SA_SIGINFO (1 << 4)
+#define SA_NOCLDWAIT (1 << 5)
+#define SA_NODEFER (1 << 6)
+
+#undef SS_ONSTACK
+#undef SS_DISABLE
+#define SS_ONSTACK 0
+#define SS_DISABLE 0
+
+#undef MINSIGSTKSZ
+#undef SIGSTKSZ
+#define MINSIGSTKSZ 0
+#define SIGSTKSZ 0
+
+/* Full POSIX set */
+enum {
+	/* Termination Signals */
+	SIGABRT,
+	SIGQUIT,
+	SIGINT,
+	SIGTERM,
+	
+	/* Child Signal */
+	SIGCHLD,
+	
+	/* User signals */
+	SIGUSR1,
+	SIGUSR2,
+
+	/* Timer */
+	SIGALRM,
+	SIGVTALRM,
+	SIGPROF, /* obsolete */
+
+	_TOP_CATCHABLE_SIGNAL = SIGPROF,
+
+	/* Process Scheduler Interaction - not supported */
+	SIGSTOP,
+	SIGCONT,
+
+	/* Process Termination - can't be caught */
+	SIGKILL,
+
+	_TOP_SENDABLE_SIGNAL = SIGKILL,
+
+	/* Hardware Exceptions - can't be caught or sent */
+	SIGFPE,
+	SIGBUS,
+	SIGILL,
+	SIGSEGV,
+
+	/* Other Exceptions - not supported */
+	SIGSYS,
+	SIGXCPU,
+	SIGXFSZ,
+
+	/* Debugging - not supported */
+	SIGTRAP,
+
+	/* Communication Signals - not supported */
+	SIGHUP,
+	SIGPIPE,
+	SIGPOLL, /* obsolete */
+	SIGURG,
+
+	/* Terminal Signals - not supported */
+	SIGTSTP,
+	SIGTTIN,
+	SIGTTOU,
+	
+	_TOP_SIGNAL = SIGTTOU
+};
+
+/* Values for sigaction field si_code. */
+enum {
+	SI_USER,
+	SI_QUEUE,
+	SI_TIMER,
+	SI_ASYNCIO,
+	SI_MESGQ,
+	ILL_ILLOPC,
+	ILL_ILLOPN,
+	ILL_ILLADR,
+	ILL_ILLTRP,
+	ILL_PRVOPC,
+	ILL_PRVREG,
+	ILL_COPROC,
+	ILL_BADSTK,
+	FPE_INTDIV,
+	FPE_INTOVF,
+	FPE_FLTDIV,
+	FPE_FLTOVF,
+	FPE_FLTUND,
+	FPE_FLTRES,
+	FPE_FLTINV,
+	FPE_FLTSUB,
+	SEGV_MAPERR,
+	SEGV_ACCERR,
+	BUS_ADRALN,
+	BUS_ADRERR,
+	BUS_OBJERR,
+	TRAP_BRKPT,
+	TRAP_TRACE,
+	CLD_EXITED,
+	CLD_KILLED,
+	CLD_DUMPED,
+	CLD_TRAPPED,
+	CLD_STOPPED,
+	CLD_CONTINUED,
+	POLL_IN,
+	POLL_OUT,
+	POLL_MSG,
+	POLL_ERR,
+	POLL_PRI,
+	POLL_HUP
+};
+
+extern int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
+    struct posix_sigaction *restrict oact);
+
+extern void (*posix_signal(int sig, void (*func)(int)))(int);
+extern int posix_raise(int sig);
+extern int posix_kill(posix_pid_t pid, int sig);
+extern int posix_killpg(posix_pid_t pid, int sig);
+
+extern void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message);
+extern void posix_psignal(int signum, const char *message);
+
+extern int posix_sigemptyset(posix_sigset_t *set);
+extern int posix_sigfillset(posix_sigset_t *set);
+extern int posix_sigaddset(posix_sigset_t *set, int signo);
+extern int posix_sigdelset(posix_sigset_t *set, int signo);
+extern int posix_sigismember(const posix_sigset_t *set, int signo);
+
+extern int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
+    posix_sigset_t *restrict oset);
+extern int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
+    posix_sigset_t *restrict oset);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define sig_atomic_t posix_sig_atomic_t
+	#define sigset_t posix_sigset_t
+	#define sigval posix_sigval
+	#ifndef sigevent
+		#define sigevent posix_sigevent
+	#endif
+	#define mcontext_t posix_mcontext_t
+	#define ucontext_t posix_ucontext_t
+	#define stack_t posix_stack_t
+	#define siginfo_t posix_siginfo_t
+
+	#define sigaction posix_sigaction
+
+	#define signal posix_signal
+	#define raise posix_raise
+	#define kill posix_kill
+	#define killpg posix_killpg
+
+	#define psiginfo posix_psiginfo
+	#define psignal posix_psignal
+
+	#define sigemptyset posix_sigemptyset
+	#define sigfillset posix_sigfillset
+	#define sigaddset posix_sigaddset
+	#define sigdelset posix_sigdelset
+	#define sigismember posix_sigismember
+
+	#define pthread_sigmask posix_thread_sigmask
+	#define sigprocmask posix_sigprocmask
+#endif
+
+#endif /* POSIX_SIGNAL_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/stdarg.h
===================================================================
--- uspace/lib/posix/include/posix/stdarg.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/stdarg.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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 libposix
+ * @{
+ */
+
+#ifndef POSIX_STDARG_H_
+#define POSIX_STDARG_H_
+
+typedef __builtin_va_list va_list;
+
+#define va_start(ap, last)  __builtin_va_start(ap, last)
+#define va_arg(ap, type)    __builtin_va_arg(ap, type)
+#define va_end(ap)          __builtin_va_end(ap)
+#define va_copy(dst, src)   __builtin_va_copy(dst, src)
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/stdbool.h
===================================================================
--- uspace/lib/posix/include/posix/stdbool.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/stdbool.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Boolean type and values.
+ */
+
+#ifndef POSIX_STDBOOL_H_
+#define POSIX_STDBOOL_H_
+
+#ifdef LIBC_BOOL_H_
+
+#if (!defined(POSIX_STDIO_H_)) && \
+    (!defined(POSIX_STDLIB_H_)) && \
+    (!defined(POSIX_STRING_H_))
+	#error "You can't include bool.h and stdbool.h at the same time."
+#endif
+
+#endif /* LIBC_BOOL_H */
+
+#define LIBC_BOOL_H_
+
+#define bool _Bool
+#define true 1
+#define false 0
+#define __bool_true_false_are_defined 1
+
+#endif /* POSIX_STDBOOL_H_ */
Index: uspace/lib/posix/include/posix/stddef.h
===================================================================
--- uspace/lib/posix/include/posix/stddef.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/stddef.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Standard type definitions.
+ */
+
+#ifndef POSIX_STDDEF_H_
+#define POSIX_STDDEF_H_
+
+#include "sys/types.h"
+
+#ifndef NULL
+	#define NULL  ((void *) 0)
+#endif
+
+#define offsetof(type,member) ((size_t) &(((type *) 0)->member))
+
+typedef ssize_t posix_ptrdiff_t;
+
+#ifndef LIBPOSIX_INTERNAL
+	#define ptrdiff_t posix_ptrdiff_t
+#endif
+
+#endif /* POSIX_STDDEF_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/stdint.h
===================================================================
--- uspace/lib/posix/include/posix/stdint.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/stdint.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Integer types.
+ */
+
+#ifndef POSIX_STDINT_H_
+#define POSIX_STDINT_H_
+
+#include "libc/stdint.h"
+
+#undef INT8_MAX
+#undef INT8_MIN
+#define INT8_MAX  127
+#define INT8_MIN  (-128)
+
+#undef UINT8_MAX
+#undef UINT8_MIN
+#define UINT8_MAX  255
+#define UINT8_MIN  0
+
+#undef INT16_MAX
+#undef INT16_MIN
+#define INT16_MAX  32767
+#define INT16_MIN  (-32768)
+
+#undef UINT16_MAX
+#undef UINT16_MIN
+#define UINT16_MAX  65535
+#define UINT16_MIN  0
+
+#undef INT32_MAX
+#undef INT32_MIN
+#define INT32_MAX  2147483647
+#define INT32_MIN  (-INT32_MAX - 1)
+
+#undef UINT32_MAX
+#undef UINT32_MIN
+#define UINT32_MAX  4294967295U
+#define UINT32_MIN  0U
+
+#undef INT64_MAX
+#undef INT64_MIN
+#define INT64_MAX  9223372036854775807LL
+#define INT64_MIN  (-INT64_MAX - 1LL)
+
+#undef UINT64_MAX
+#undef  UINT64_MIN
+#define UINT64_MAX  18446744073709551615ULL
+#define UINT64_MIN  0ULL
+
+#undef OFF64_MAX
+#undef OFF64_MIN
+#define OFF64_MAX  INT64_MAX
+#define OFF64_MIN  INT64_MIN
+
+#undef AOFF64_MAX
+#undef AOFF64_MIN
+#define AOFF64_MAX  UINT64_MAX
+#define AOFF64_MIN  UINT64_MIN
+
+#undef INTMAX_MIN
+#undef INTMAX_MAX
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+
+#undef UINTMAX_MIN
+#undef UINTMAX_MAX
+#define UINTMAX_MIN UINT64_MIN
+#define UINTMAX_MAX UINT64_MAX
+
+#include "libc/sys/types.h"
+
+typedef int64_t posix_intmax_t;
+typedef uint64_t posix_uintmax_t;
+
+#ifndef LIBPOSIX_INTERNAL
+	#define intmax_t posix_intmax_t
+	#define uintmax_t posix_uintmax_t
+#endif
+
+#endif /* POSIX_STDINT_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/stdio.h
===================================================================
--- uspace/lib/posix/include/posix/stdio.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/stdio.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Standard buffered input/output.
+ */
+
+#ifndef POSIX_STDIO_H_
+#define POSIX_STDIO_H_
+
+#include "stddef.h"
+#include "unistd.h"
+#include "libc/io/verify.h"
+#include "sys/types.h"
+#include "stdarg.h"
+#include "limits.h"
+
+/*
+ * These are the same as in HelenOS libc.
+ * It would be possible to directly include <stdio.h> but
+ * it is better not to pollute POSIX namespace with other functions
+ * defined in that header.
+ *
+ * Because libposix is always linked with libc, providing only these
+ * forward declarations ought to be enough.
+ */
+#define EOF (-1)
+
+#define BUFSIZ  4096
+#define SEEK_SET  0
+#define SEEK_CUR  1
+#define SEEK_END  2
+
+typedef struct _IO_FILE FILE;
+
+extern FILE *stdin;
+extern FILE *stdout;
+extern FILE *stderr;
+
+extern int fgetc(FILE *);
+extern char *fgets(char *, int, FILE *);
+
+extern int getchar(void);
+extern char *gets(char *, size_t);
+
+extern int fputc(wchar_t, FILE *);
+extern int fputs(const char *, FILE *);
+
+extern int putchar(wchar_t);
+extern int puts(const char *);
+
+extern int fprintf(FILE *, const char*, ...) PRINTF_ATTRIBUTE(2, 3);
+extern int vfprintf(FILE *, const char *, va_list);
+
+extern int printf(const char *, ...) PRINTF_ATTRIBUTE(1, 2);
+extern int vprintf(const char *, va_list);
+
+extern int snprintf(char *, size_t , const char *, ...) PRINTF_ATTRIBUTE(3, 4);
+#ifdef _GNU_SOURCE
+extern int asprintf(char **, const char *, ...) PRINTF_ATTRIBUTE(2, 3);
+#endif
+extern int vsnprintf(char *, size_t, const char *, va_list);
+
+extern FILE *fopen(const char *, const char *);
+extern FILE *fdopen(int, const char *);
+extern int fclose(FILE *);
+
+extern size_t fread(void *, size_t, size_t, FILE *);
+extern size_t fwrite(const void *, size_t, size_t, FILE *);
+
+extern int fseek(FILE *, off64_t, int);
+extern void rewind(FILE *);
+extern off64_t ftell(FILE *);
+extern int feof(FILE *);
+extern int fileno(FILE *);
+
+extern int fflush(FILE *);
+extern int ferror(FILE *);
+extern void clearerr(FILE *);
+
+extern void setvbuf(FILE *, void *, int, size_t);
+
+
+/* POSIX specific stuff. */
+
+/* Identifying the Terminal */
+#undef L_ctermid
+#define L_ctermid PATH_MAX
+extern char *posix_ctermid(char *s);
+
+/* Error Recovery */
+extern void posix_clearerr(FILE *stream);
+
+/* Input/Output */
+#undef putc
+#define putc fputc
+extern int posix_fputs(const char *restrict s, FILE *restrict stream);
+#undef getc
+#define getc fgetc
+extern int posix_ungetc(int c, FILE *stream);
+extern ssize_t posix_getdelim(char **restrict lineptr, size_t *restrict n,
+    int delimiter, FILE *restrict stream);
+extern ssize_t posix_getline(char **restrict lineptr, size_t *restrict n,
+    FILE *restrict stream);
+
+/* Opening Streams */
+extern FILE *posix_freopen(const char *restrict filename,
+    const char *restrict mode, FILE *restrict stream);
+
+/* Error Messages */
+extern void posix_perror(const char *s);
+
+/* File Positioning */
+typedef struct _posix_fpos posix_fpos_t;
+extern int posix_fsetpos(FILE *stream, const posix_fpos_t *pos);
+extern int posix_fgetpos(FILE *restrict stream, posix_fpos_t *restrict pos);
+extern int posix_fseek(FILE *stream, long offset, int whence);
+extern int posix_fseeko(FILE *stream, posix_off_t offset, int whence);
+extern long posix_ftell(FILE *stream);
+extern posix_off_t posix_ftello(FILE *stream);
+
+/* Flushing Buffers */
+extern int posix_fflush(FILE *stream);
+
+/* Formatted Output */
+extern int posix_dprintf(int fildes, const char *restrict format, ...)
+    PRINTF_ATTRIBUTE(2, 3);
+extern int posix_vdprintf(int fildes, const char *restrict format, va_list ap);
+extern int posix_sprintf(char *restrict s, const char *restrict format, ...)
+    PRINTF_ATTRIBUTE(2, 3);
+extern int posix_vsprintf(char *restrict s, const char *restrict format, va_list ap);
+
+/* Formatted Input */
+extern int posix_fscanf(
+    FILE *restrict stream, const char *restrict format, ...);
+extern int posix_vfscanf(
+    FILE *restrict stream, const char *restrict format, va_list arg);
+extern int posix_scanf(const char *restrict format, ...);
+extern int posix_vscanf(const char *restrict format, va_list arg);
+extern int posix_sscanf(
+    const char *restrict s, const char *restrict format, ...);
+extern int posix_vsscanf(
+    const char *restrict s, const char *restrict format, va_list arg);
+
+/* File Locking */
+extern void posix_flockfile(FILE *file);
+extern int posix_ftrylockfile(FILE *file);
+extern void posix_funlockfile(FILE *file);
+extern int posix_getc_unlocked(FILE *stream);
+extern int posix_getchar_unlocked(void);
+extern int posix_putc_unlocked(int c, FILE *stream);
+extern int posix_putchar_unlocked(int c);
+
+/* Deleting Files */
+extern int posix_remove(const char *path);
+
+/* Renaming Files */
+extern int posix_rename(const char *old, const char *new);
+
+/* Temporary Files */
+#undef L_tmpnam
+#define L_tmpnam PATH_MAX
+extern char *posix_tmpnam(char *s);
+extern char *posix_tempnam(const char *dir, const char *pfx);
+extern FILE *posix_tmpfile(void);
+
+#ifndef LIBPOSIX_INTERNAL
+	/* DEBUG macro does not belong to POSIX stdio.h. Its unconditional
+	 * definition in the native stdio.h causes unexpected behaviour of
+	 * applications which uses their own DEBUG macro (e.g. debugging
+	 * output is printed even if not desirable). */
+	#undef DEBUG
+
+	#define ctermid posix_ctermid
+
+	#define clearerr posix_clearerr
+
+	#define fputs posix_fputs
+	#define ungetc posix_ungetc
+	#define getdelim posix_getdelim
+	#define getline posix_getline
+
+	#define freopen posix_freopen
+
+	#define perror posix_perror
+
+	#define fpos_t posix_fpos_t
+	#define fsetpos posix_fsetpos
+	#define fgetpos posix_fgetpos
+	#define fseek posix_fseek
+	#define fseeko posix_fseeko
+	#define ftell posix_ftell
+	#define ftello posix_ftello
+
+	#define fflush posix_fflush
+
+	#define dprintf posix_dprintf
+	#define vdprintf posix_vdprintf
+	#define sprintf posix_sprintf
+	#define vsprintf posix_vsprintf
+
+	#define fscanf posix_fscanf
+	#define vfscanf posix_vfscanf
+	#define vscanf posix_vscanf
+	#define scanf posix_scanf
+	#define sscanf posix_sscanf
+	#define vsscanf posix_vsscanf
+
+	#define flockfile posix_flockfile
+	#define ftrylockfile posix_ftrylockfile
+	#define funlockfile posix_funlockfile
+
+	#define getc_unlocked posix_getc_unlocked
+	#define getchar_unlocked posix_getchar_unlocked
+	#define putc_unlocked posix_putc_unlocked
+	#define putchar_unlocked posix_putchar_unlocked
+
+	#define remove posix_remove
+
+	#define rename posix_rename
+
+	#define tmpnam posix_tmpnam
+	#define tempnam posix_tempnam
+	#define tmpfile posix_tmpfile
+#endif
+
+#endif /* POSIX_STDIO_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/stdlib.h
===================================================================
--- uspace/lib/posix/include/posix/stdlib.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/stdlib.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Standard library definitions.
+ */
+
+#ifndef POSIX_STDLIB_H_
+#define POSIX_STDLIB_H_
+
+#include "sys/types.h"
+
+#ifndef NULL
+	#define NULL  ((void *) 0)
+#endif
+
+/* Process Termination */
+#undef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#undef EXIT_SUCCESS
+#define EXIT_SUCCESS 0
+#define _Exit exit
+extern int posix_atexit(void (*func)(void));
+extern void exit(int status);
+extern void abort(void) __attribute__((noreturn));
+
+/* Absolute Value */
+extern int posix_abs(int i);
+extern long posix_labs(long i);
+extern long long posix_llabs(long long i);
+
+/* Integer Division */
+
+typedef struct {
+	int quot, rem;
+} posix_div_t;
+
+typedef struct {
+	long quot, rem;
+} posix_ldiv_t;
+
+typedef struct {
+	long long quot, rem;
+} posix_lldiv_t;
+
+extern posix_div_t posix_div(int numer, int denom);
+extern posix_ldiv_t posix_ldiv(long numer, long denom);
+extern posix_lldiv_t posix_lldiv(long long numer, long long denom);
+
+/* Array Functions */
+extern void posix_qsort(void *array, size_t count, size_t size,
+    int (*compare)(const void *, const void *));
+extern void *posix_bsearch(const void *key, const void *base,
+    size_t nmemb, size_t size, int (*compar)(const void *, const void *));
+
+/* Environment Access */
+extern char *posix_getenv(const char *name);
+extern int posix_putenv(char *string);
+extern int posix_system(const char *string);
+
+/* Symbolic Links */
+extern char *posix_realpath(const char *restrict name, char *restrict resolved);
+
+/* Floating Point Conversion */
+extern double posix_atof(const char *nptr);
+extern float posix_strtof(const char *restrict nptr, char **restrict endptr);
+extern double posix_strtod(const char *restrict nptr, char **restrict endptr);
+extern long double posix_strtold(const char *restrict nptr, char **restrict endptr);
+
+/* Integer Conversion */
+extern int posix_atoi(const char *nptr);
+extern long int posix_atol(const char *nptr);
+extern long long int posix_atoll(const char *nptr);
+extern long int posix_strtol(const char *restrict nptr,
+    char **restrict endptr, int base);
+extern long long int posix_strtoll(const char *restrict nptr,
+    char **restrict endptr, int base);
+extern unsigned long int posix_strtoul(const char *restrict nptr,
+    char **restrict endptr, int base);
+extern unsigned long long int posix_strtoull(
+    const char *restrict nptr, char **restrict endptr, int base);
+
+/* Memory Allocation */
+extern void *posix_malloc(size_t size);
+extern void *posix_calloc(size_t nelem, size_t elsize);
+extern void *posix_realloc(void *ptr, size_t size);
+extern void posix_free(void *ptr);
+
+/* Temporary Files */
+extern int posix_mkstemp(char *tmpl);
+
+/* Legacy Declarations */
+extern char *posix_mktemp(char *tmpl);
+extern int bsd_getloadavg(double loadavg[], int nelem);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define atexit posix_atexit
+
+	#define abs posix_abs
+	#define labs posix_labs
+	#define llabs posix_llabs
+
+	#define div_t posix_div_t
+	#define ldiv_t posix_ldiv_t
+	#define lldiv_t posix_lldiv_t
+	#define div posix_div
+	#define ldiv posix_ldiv
+	#define lldiv posix_lldiv
+
+	#define qsort posix_qsort
+	#define bsearch posix_bsearch
+
+	#define getenv posix_getenv
+	#define putenv posix_putenv
+	#define system posix_system
+
+	#define realpath posix_realpath
+	
+	#define atof posix_atof
+	#define strtof posix_strtof
+	#define strtod posix_strtod
+	#define strtold posix_strtold
+	
+	#define atoi posix_atoi
+	#define atol posix_atol
+	#define atoll posix_atoll
+	#define strtol posix_strtol
+	#define strtoll posix_strtoll
+	#define strtoul posix_strtoul
+	#define strtoull posix_strtoull
+
+	#define malloc posix_malloc
+	#define calloc posix_calloc
+	#define realloc posix_realloc
+	#define free posix_free
+
+	#define mkstemp posix_mkstemp
+
+	#define mktemp posix_mktemp
+	#define getloadavg bsd_getloadavg
+#endif
+
+#endif  // POSIX_STDLIB_H_
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/string.h
===================================================================
--- uspace/lib/posix/include/posix/string.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/string.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file String manipulation.
+ */
+
+#ifndef POSIX_STRING_H_
+#define POSIX_STRING_H_
+
+#include "sys/types.h"
+
+/*
+ * TODO: not implemented due to missing locale support
+ *
+ * int      strcoll_l(const char *, const char *, locale_t);
+ * char    *strerror_l(int, locale_t);
+ * size_t   strxfrm_l(char *restrict, const char *restrict, size_t, locale_t);
+ */
+
+#ifndef NULL
+	#define NULL  ((void *) 0)
+#endif
+
+/*
+ * These are the same as in HelenOS libc.
+ * It would be possible to directly include <str.h> and <mem.h> but
+ * it is better not to pollute POSIX namespace with other functions
+ * defined in that header.
+ *
+ * Because libposix is always linked with libc, providing only these
+ * forward declarations ought to be enough.
+ */
+/* From str.h. */
+extern char * strtok_r(char *, const char *, char **);
+extern char * strtok(char *, const char *);
+
+/* From mem.h */
+#define bzero(ptr, len)  memset((ptr), 0, (len))
+extern void *memset(void *, int, size_t);
+extern void *memcpy(void *, const void *, size_t);
+extern void *memmove(void *, const void *, size_t);
+
+
+/* Copying and Concatenation */
+extern char *posix_strcpy(char *restrict dest, const char *restrict src);
+extern char *posix_strncpy(char *restrict dest, const char *restrict src, size_t n);
+extern char *posix_stpcpy(char *restrict dest, const char *restrict src);
+extern char *posix_stpncpy(char *restrict dest, const char *restrict src, size_t n);
+extern char *posix_strcat(char *restrict dest, const char *restrict src);
+extern char *posix_strncat(char *restrict dest, const char *restrict src, size_t n);
+extern void *posix_memccpy(void *restrict dest, const void *restrict src, int c, size_t n);
+extern char *posix_strdup(const char *s);
+extern char *posix_strndup(const char *s, size_t n);
+
+/* String/Array Comparison */
+extern int posix_memcmp(const void *mem1, const void *mem2, size_t n);
+extern int posix_strcmp(const char *s1, const char *s2);
+extern int posix_strncmp(const char *s1, const char *s2, size_t n);
+
+/* Search Functions */
+extern void *posix_memchr(const void *mem, int c, size_t n);
+extern char *posix_strchr(const char *s, int c);
+extern char *posix_strrchr(const char *s, int c);
+extern char *gnu_strchrnul(const char *s, int c);
+extern char *posix_strpbrk(const char *s1, const char *s2);
+extern size_t posix_strcspn(const char *s1, const char *s2);
+extern size_t posix_strspn(const char *s1, const char *s2);
+extern char *posix_strstr(const char *haystack, const char *needle);
+
+/* Collation Functions */
+extern int posix_strcoll(const char *s1, const char *s2);
+extern size_t posix_strxfrm(char *restrict s1, const char *restrict s2, size_t n);
+
+/* Error Messages */
+extern char *posix_strerror(int errnum);
+extern int posix_strerror_r(int errnum, char *buf, size_t bufsz);
+
+/* String Length */
+extern size_t posix_strlen(const char *s);
+extern size_t posix_strnlen(const char *s, size_t n);
+
+/* Signal Messages */
+extern char *posix_strsignal(int signum);
+
+/* Legacy Declarations */
+#ifndef POSIX_STRINGS_H_
+extern int posix_ffs(int i);
+extern int posix_strcasecmp(const char *s1, const char *s2);
+extern int posix_strncasecmp(const char *s1, const char *s2, size_t n);
+#endif
+
+#ifndef LIBPOSIX_INTERNAL
+	#define strcpy posix_strcpy
+	#define strncpy posix_strncpy
+	#define stpcpy posix_stpcpy
+	#define stpncpy posix_stpncpy
+	#define strcat posix_strcat
+	#define strncat posix_strncat
+	#define memccpy posix_memccpy
+	#define strdup posix_strdup
+	#define strndup posix_strndup
+
+	#define memcmp posix_memcmp
+	#define strcmp posix_strcmp
+	#define strncmp posix_strncmp
+
+	#define memchr posix_memchr
+	#define strchr posix_strchr
+	#define strrchr posix_strrchr
+	#define strchrnul gnu_strchrnul
+	#define strpbrk posix_strpbrk
+	#define strcspn posix_strcspn
+	#define strspn posix_strspn
+	#define strstr posix_strstr
+
+	#define strcoll posix_strcoll
+	#define strxfrm posix_strxfrm
+
+	#define strerror posix_strerror
+	#define strerror_r posix_strerror_r
+
+	#define strlen posix_strlen
+	#define strnlen posix_strnlen
+
+	#define strsignal posix_strsignal
+
+	#define ffs posix_ffs
+	#define strcasecmp posix_strcasecmp
+	#define strncasecmp posix_strncasecmp
+#endif
+
+#endif  // POSIX_STRING_H_
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/strings.h
===================================================================
--- uspace/lib/posix/include/posix/strings.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/strings.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Additional string manipulation.
+ */
+
+#ifndef POSIX_STRINGS_H_
+#define POSIX_STRINGS_H_
+
+/* Search Functions */
+#ifndef POSIX_STRING_H_
+extern int posix_ffs(int i);
+#endif
+
+/* String/Array Comparison */
+#ifndef POSIX_STRING_H_
+extern int posix_strcasecmp(const char *s1, const char *s2);
+extern int posix_strncasecmp(const char *s1, const char *s2, size_t n);
+#endif
+
+/* TODO: not implemented due to missing locale support
+ *
+ * int strcasecmp_l(const char *, const char *, locale_t);
+ * int strncasecmp_l(const char *, const char *, size_t, locale_t);
+ */
+
+/* Legacy Functions */
+extern int posix_bcmp(const void *mem1, const void *mem2, size_t n);
+extern void posix_bcopy(const void *src, void *dest, size_t n);
+extern void posix_bzero(void *mem, size_t n);
+extern char *posix_index(const char *s, int c);
+extern char *posix_rindex(const char *s, int c);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define ffs posix_ffs
+
+	#define strcasecmp posix_strcasecmp
+	#define strncasecmp posix_strncasecmp
+
+	#define bcmp posix_bcmp
+	#define bcopy posix_bcopy
+	#undef bzero
+	#define bzero posix_bzero
+	#define index posix_index
+	#define rindex posix_rindex
+#endif
+
+#endif  // POSIX_STRINGS_H_
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/sys/mman.h
===================================================================
--- uspace/lib/posix/include/posix/sys/mman.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/sys/mman.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Memory management declarations.
+ */
+
+#ifndef POSIX_SYS_MMAN_H_
+#define POSIX_SYS_MMAN_H_
+
+#include "sys/types.h"
+#include <abi/mm/as.h>
+
+#define MAP_FAILED ((void *) -1)
+
+#define MAP_SHARED     (1 << 0)
+#define MAP_PRIVATE    (1 << 1)
+#define MAP_FIXED      (1 << 2)
+#define MAP_ANONYMOUS  (1 << 3)
+
+#undef PROT_NONE
+#undef PROT_READ
+#undef PROT_WRITE
+#undef PROT_EXEC
+#define PROT_NONE  0
+#define PROT_READ  AS_AREA_READ
+#define PROT_WRITE AS_AREA_WRITE
+#define PROT_EXEC  AS_AREA_EXEC
+
+extern void *mmap(void *start, size_t length, int prot, int flags, int fd,
+    posix_off_t offset);
+extern int munmap(void *start, size_t length);
+
+#endif /* POSIX_SYS_MMAN_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/sys/stat.h
===================================================================
--- uspace/lib/posix/include/posix/sys/stat.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/sys/stat.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file File status handling.
+ */
+
+#ifndef POSIX_SYS_STAT_H_
+#define POSIX_SYS_STAT_H_
+
+#include "types.h"
+#include "../time.h"
+
+/* values are the same as on Linux */
+
+#undef S_IFMT
+#undef S_IFSOCK
+#undef S_IFLNK
+#undef S_IFREG
+#undef S_IFBLK
+#undef S_IFDIR
+#undef S_IFCHR
+#undef S_IFIFO
+#define S_IFMT     0170000   /* all file types */
+#define S_IFSOCK   0140000   /* socket */
+#define S_IFLNK    0120000   /* symbolic link */
+#define S_IFREG    0100000   /* regular file */
+#define S_IFBLK    0060000   /* block device */
+#define S_IFDIR    0040000   /* directory */
+#define S_IFCHR    0020000   /* character device */
+#define S_IFIFO    0010000   /* FIFO */
+
+#undef S_ISUID
+#undef S_ISGID
+#undef S_ISVTX
+#define S_ISUID    0004000   /* SUID */
+#define S_ISGID    0002000   /* SGID */
+#define S_ISVTX    0001000   /* sticky */
+
+#undef S_IRWXU
+#undef S_IRUSR
+#undef S_IWUSR
+#undef S_IXUSR
+#define S_IRWXU    00700     /* owner permissions */
+#define S_IRUSR    00400
+#define S_IWUSR    00200
+#define S_IXUSR    00100
+
+#undef S_IRWXG
+#undef S_IRGRP
+#undef S_IWGRP
+#undef S_IXGRP
+#define S_IRWXG    00070     /* group permissions */
+#define S_IRGRP    00040
+#define S_IWGRP    00020
+#define S_IXGRP    00010
+
+#undef S_IRWXO
+#undef S_IROTH
+#undef S_IWOTH
+#undef S_IXOTH
+#define S_IRWXO    00007     /* other permissions */
+#define S_IROTH    00004
+#define S_IWOTH    00002
+#define S_IXOTH    00001
+
+#undef S_ISREG
+#undef S_ISDIR
+#undef S_ISCHR
+#undef S_ISBLK
+#undef S_ISFIFO
+#undef S_ISLNK
+#undef S_ISSOCK
+#define S_ISREG(m) ((m & S_IFREG) != 0)
+#define S_ISDIR(m) ((m & S_IFDIR) != 0)
+#define S_ISCHR(m) ((m & S_IFCHR) != 0)
+#define S_ISBLK(m) ((m & S_IFBLK) != 0)
+#define S_ISFIFO(m) ((m & S_IFIFO) != 0)
+#define S_ISLNK(m) ((m & S_IFLNK) != 0) /* symbolic link? (Not in POSIX.1-1996.) */
+#define S_ISSOCK(m) ((m & S_IFSOCK) != 0) /* socket? (Not in POSIX.1-1996.) */
+
+struct posix_stat {
+	posix_dev_t     st_dev;     /* ID of device containing file */
+	posix_ino_t     st_ino;     /* inode number */
+	mode_t          st_mode;    /* protection */
+	posix_nlink_t   st_nlink;   /* number of hard links */
+	posix_uid_t     st_uid;     /* user ID of owner */
+	posix_gid_t     st_gid;     /* group ID of owner */
+	posix_dev_t     st_rdev;    /* device ID (if special file) */
+	posix_off_t     st_size;    /* total size, in bytes */
+	posix_blksize_t st_blksize; /* blocksize for file system I/O */
+	posix_blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
+	time_t          st_atime;   /* time of last access */
+	time_t          st_mtime;   /* time of last modification */
+	time_t          st_ctime;   /* time of last status change */
+};
+
+extern int posix_fstat(int fd, struct posix_stat *st);
+extern int posix_lstat(const char *restrict path, struct posix_stat *restrict st);
+extern int posix_stat(const char *restrict path, struct posix_stat *restrict st);
+extern int posix_chmod(const char *path, mode_t mode);
+extern mode_t posix_umask(mode_t mask);
+extern int mkdir(const char *, mode_t);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define fstat posix_fstat
+	#define lstat posix_lstat
+	#define stat posix_stat
+	#define chmod posix_chmod
+	#define umask posix_umask
+#endif
+
+#endif /* POSIX_SYS_STAT_H */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/sys/types.h
===================================================================
--- uspace/lib/posix/include/posix/sys/types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/sys/types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Data types definitions.
+ */
+
+#ifndef POSIX_SYS_TYPES_H_
+#define POSIX_SYS_TYPES_H_
+
+#include "libc/sys/types.h"
+#include "libc/sys/time.h"
+
+typedef unsigned int posix_ino_t;
+typedef unsigned int posix_nlink_t;
+typedef unsigned int posix_uid_t;
+typedef unsigned int posix_gid_t;
+typedef off64_t posix_off_t;
+typedef long posix_blksize_t;
+typedef long posix_blkcnt_t;
+typedef int64_t posix_pid_t;
+typedef sysarg_t posix_dev_t;
+
+/* PThread Types */
+typedef struct posix_thread_attr posix_thread_attr_t;
+
+/* Clock Types */
+typedef long posix_clock_t;
+typedef int posix_clockid_t;
+
+#ifndef LIBPOSIX_INTERNAL
+	#define ino_t posix_ino_t
+	#define nlink_t posix_nlink_t
+	#define uid_t posix_uid_t
+	#define gid_t posix_gid_t
+	#define off_t posix_off_t
+	#define blksize_t posix_blksize_t
+	#define blkcnt_t posix_blkcnt_t
+	#define pid_t posix_pid_t
+	#define dev_t posix_dev_t
+	
+	#define pthread_attr_t posix_thread_attr_t
+	
+	#define clock_t posix_clock_t
+	#define clockid_t posix_clockid_t
+#endif
+
+#endif /* POSIX_SYS_TYPES_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/sys/wait.h
===================================================================
--- uspace/lib/posix/include/posix/sys/wait.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/sys/wait.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Support for waiting.
+ */
+
+#ifndef POSIX_SYS_WAIT_H_
+#define POSIX_SYS_WAIT_H_
+
+#include "types.h"
+
+#undef WIFEXITED
+#undef WEXITSTATUS
+#undef WIFSIGNALED
+#undef WTERMSIG
+#define WIFEXITED(status) __posix_wifexited(status)
+#define WEXITSTATUS(status) __posix_wexitstatus(status)
+#define WIFSIGNALED(status) __posix_wifsignaled(status)
+#define WTERMSIG(status) __posix_wtermsig(status)
+
+extern int __posix_wifexited(int status);
+extern int __posix_wexitstatus(int status);
+extern int __posix_wifsignaled(int status);
+extern int __posix_wtermsig(int status);
+
+extern posix_pid_t posix_wait(int *stat_ptr);
+extern posix_pid_t posix_waitpid(posix_pid_t pid, int *stat_ptr, int options);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define wait posix_wait
+	#define waitpid posix_waitpid
+#endif
+
+#endif /* POSIX_SYS_WAIT_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/time.h
===================================================================
--- uspace/lib/posix/include/posix/time.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/time.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Time measurement support.
+ */
+
+#ifndef POSIX_TIME_H_
+#define POSIX_TIME_H_
+
+#include "sys/types.h"
+
+#ifndef NULL
+	#define NULL  ((void *) 0)
+#endif
+
+#ifndef CLOCKS_PER_SEC
+	#define CLOCKS_PER_SEC (1000000L)
+#endif
+
+#ifndef __locale_t_defined
+	#define __locale_t_defined
+	typedef struct __posix_locale *posix_locale_t;
+	#ifndef LIBPOSIX_INTERNAL
+		#define locale_t posix_locale_t
+	#endif
+#endif
+
+#ifndef POSIX_SIGNAL_H_
+	struct posix_sigevent;
+	#ifndef LIBPOSIX_INTERNAL
+		#define sigevent posix_sigevent
+	#endif
+#endif
+
+#undef CLOCK_REALTIME
+#define CLOCK_REALTIME ((posix_clockid_t) 0)
+
+struct posix_timespec {
+	time_t tv_sec; /* Seconds. */
+	long tv_nsec; /* Nanoseconds. */
+};
+
+struct posix_itimerspec {
+	struct posix_timespec it_interval; /* Timer period. */
+	struct posix_timespec it_value; /* Timer expiration. */
+};
+
+typedef struct __posix_timer *posix_timer_t;
+
+/* Timezones */
+extern int posix_daylight;
+extern long posix_timezone;
+extern char *posix_tzname[2];
+extern void posix_tzset(void);
+
+/* Broken-down Time */
+extern struct tm *posix_gmtime_r(const time_t *restrict timer,
+    struct tm *restrict result);
+extern struct tm *posix_gmtime(const time_t *restrict timep);
+extern struct tm *posix_localtime_r(const time_t *restrict timer,
+    struct tm *restrict result);
+extern struct tm *posix_localtime(const time_t *restrict timep);
+
+/* Formatting Calendar Time */
+extern char *posix_asctime_r(const struct tm *restrict timeptr,
+    char *restrict buf);
+extern char *posix_asctime(const struct tm *restrict timeptr);
+extern char *posix_ctime_r(const time_t *timer, char *buf);
+extern char *posix_ctime(const time_t *timer);
+
+/* Clocks */
+extern int posix_clock_getres(posix_clockid_t clock_id,
+    struct posix_timespec *res);
+extern int posix_clock_gettime(posix_clockid_t clock_id,
+    struct posix_timespec *tp);
+extern int posix_clock_settime(posix_clockid_t clock_id,
+    const struct posix_timespec *tp); 
+extern int posix_clock_nanosleep(posix_clockid_t clock_id, int flags,
+    const struct posix_timespec *rqtp, struct posix_timespec *rmtp);
+
+/* CPU Time */
+extern posix_clock_t posix_clock(void);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define timespec    posix_timespec
+	#define itimerspec  posix_itimerspec
+	#define timer_t     posix_timer_t
+
+	#define daylight    posix_daylight
+	#define timezone    posix_timezone
+	#define tzname      posix_tzname
+	#define tzset       posix_tzset
+
+	#define gmtime_r    posix_gmtime_r
+	#define gmtime      posix_gmtime
+	#define localtime_r posix_localtime_r
+	#define localtime   posix_localtime
+
+	#define asctime_r   posix_asctime_r
+	#define asctime     posix_asctime
+	#define ctime_r     posix_ctime_r
+	#define ctime       posix_ctime
+
+	#define clock_getres posix_clock_getres
+	#define clock_gettime posix_clock_gettime
+	#define clock_settime posix_clock_settime
+	#define clock_nanosleep posix_clock_nanosleep
+
+	#define clock posix_clock
+#endif
+
+#endif  // POSIX_TIME_H_
+
+/** @}
+ */
Index: uspace/lib/posix/include/posix/unistd.h
===================================================================
--- uspace/lib/posix/include/posix/unistd.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/include/posix/unistd.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Miscellaneous standard definitions.
+ */
+
+#ifndef POSIX_UNISTD_H_
+#define POSIX_UNISTD_H_
+
+#include "sys/types.h"
+#include "stddef.h"
+
+/* Process Termination */
+#define _exit exit
+
+extern char *posix_optarg;
+extern int optind, opterr, optopt;
+extern int posix_getopt(int, char * const [], const char *);
+
+/* Environment */
+extern char **posix_environ;
+
+/* Login Information */
+extern char *posix_getlogin(void);
+extern int posix_getlogin_r(char *name, size_t namesize);
+
+/* Identifying Terminals */
+extern int posix_isatty(int fd);
+
+/* Working Directory */
+extern char *posix_getcwd(char *buf, size_t size);
+extern int posix_chdir(const char *path);
+
+/* Query Memory Parameters */
+extern int posix_getpagesize(void);
+
+/* Process Identification */
+extern posix_pid_t posix_getpid(void);
+extern posix_uid_t posix_getuid(void);
+extern posix_gid_t posix_getgid(void);
+
+/* File Manipulation */
+extern int posix_close(int fildes);
+extern ssize_t posix_read(int fildes, void *buf, size_t nbyte);
+extern ssize_t posix_write(int fildes, const void *buf, size_t nbyte);
+extern int posix_fsync(int fildes);
+extern int posix_ftruncate(int fildes, posix_off_t length);
+extern int posix_rmdir(const char *path);
+extern int posix_unlink(const char *path);
+extern int posix_dup(int fildes);
+extern int posix_dup2(int fildes, int fildes2);
+
+/* Standard Streams */
+#undef STDIN_FILENO
+#define STDIN_FILENO (fileno(stdin))
+#undef STDOUT_FILENO
+#define STDOUT_FILENO (fileno(stdout))
+#undef STDERR_FILENO
+#define STDERR_FILENO (fileno(stderr))
+
+/* File Accessibility */
+#undef F_OK
+#undef X_OK
+#undef W_OK
+#undef R_OK
+#define	F_OK 0 /* Test for existence. */
+#define	X_OK 1 /* Test for execute permission. */
+#define	W_OK 2 /* Test for write permission. */
+#define	R_OK 4 /* Test for read permission. */
+extern int posix_access(const char *path, int amode);
+
+/* System Parameters */
+enum {
+	_SC_PHYS_PAGES,
+	_SC_AVPHYS_PAGES,
+	_SC_PAGESIZE,
+	_SC_CLK_TCK
+};
+extern long posix_sysconf(int name);
+
+/* Path Configuration Parameters */
+enum {
+	_PC_2_SYMLINKS,
+	_PC_ALLOC_SIZE_MIN,
+	_PC_ASYNC_IO,
+	_PC_CHOWN_RESTRICTED,
+	_PC_FILESIZEBITS,
+	_PC_LINK_MAX,
+	_PC_MAX_CANON,
+	_PC_MAX_INPUT,
+	_PC_NAME_MAX,
+	_PC_NO_TRUNC,
+	_PC_PATH_MAX,
+	_PC_PIPE_BUF,
+	_PC_PRIO_IO,
+	_PC_REC_INCR_XFER_SIZE,
+	_PC_REC_MIN_XFER_SIZE,
+	_PC_REC_XFER_ALIGN,
+	_PC_SYMLINK_MAX,
+	_PC_SYNC_IO,
+	_PC_VDISABLE
+};
+extern long posix_pathconf(const char *path, int name);
+
+/* Creating a Process */
+extern posix_pid_t posix_fork(void);
+
+/* Executing a File */
+extern int posix_execv(const char *path, char *const argv[]);
+extern int posix_execvp(const char *file, char *const argv[]);
+
+/* Creating a Pipe */
+extern int posix_pipe(int fildes[2]);
+
+#ifndef LIBPOSIX_INTERNAL
+	#define getopt posix_getopt
+	#define optarg posix_optarg
+
+	#define environ posix_environ
+
+	#define getlogin posix_getlogin
+	#define getlogin_r posix_getlogin_r
+
+	#define getcwd posix_getcwd
+	#define chdir posix_chdir
+
+	#define isatty posix_isatty
+
+	#undef getpagesize
+	#define getpagesize posix_getpagesize
+
+	#define getpid posix_getpid
+	#define getuid posix_getuid
+	#define getgid posix_getgid
+
+	#define close posix_close
+	#define read posix_read
+	#define write posix_write
+	#define fsync posix_fsync
+	#define ftruncate posix_ftruncate
+	#define rmdir posix_rmdir
+	#define unlink posix_unlink
+	#define dup posix_dup
+	#define dup2 posix_dup2
+
+	#define access posix_access
+
+	#define sysconf posix_sysconf
+
+	#define pathconf posix_pathconf
+
+	#define fork posix_fork
+
+	#define execv posix_execv
+	#define execvp posix_execvp
+
+	#define pipe posix_pipe
+#endif
+
+#endif /* POSIX_UNISTD_H_ */
+
+/** @}
+ */
Index: pace/lib/posix/internal/common.h
===================================================================
--- uspace/lib/posix/internal/common.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Helper definitions common for all libposix files.
- */
-
-#ifndef LIBPOSIX_COMMON_H_
-#define LIBPOSIX_COMMON_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#define not_implemented() (fprintf(stderr, \
-    "Function %s() in file %s at line %d is not implemented\n", \
-    __func__, __FILE__, __LINE__), abort())
-
-/* A little helper macro to avoid typing this over and over. */
-#define errnify(func, ...) ({ \
-	int rc = func(__VA_ARGS__); \
-	if (rc < 0) { \
-		errno = -rc; \
-		rc = -1; \
-	} \
-	rc; \
-})
-
-#endif /* LIBPOSIX_COMMON_H_ */
-
-/** @}
- */
Index: pace/lib/posix/inttypes.h
===================================================================
--- uspace/lib/posix/inttypes.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Fixed size integer types.
- */
-
-#ifndef POSIX_INTTYPES_H_
-#define POSIX_INTTYPES_H_
-
-#include "stdint.h"
-#include "libc/inttypes.h"
-
-extern posix_intmax_t posix_strtoimax(const char *restrict nptr,
-    char **restrict endptr, int base);
-extern posix_uintmax_t posix_strtoumax(const char *restrict nptr,
-    char **restrict endptr, int base);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define strtoimax posix_strtoimax
-	#define strtoumax posix_strtoumax
-#endif
-
-#endif /* POSIX_INTTYPES_H_ */
-
-/** @}
- */
Index: pace/lib/posix/iso646.h
===================================================================
--- uspace/lib/posix/iso646.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,53 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Alternative spellings.
- */
-
-#ifndef POSIX_ISO646_H_
-#define POSIX_ISO646_H_
-
-#define and &&
-#define and_eq &=
-#define bitand &
-#define bitor |
-#define compl ˜
-#define not !
-#define not_eq !=
-#define or ||
-#define or_eq |=
-#define xor ^
-#define xor_eq ^=
-
-#endif /* POSIX_ISO646_H_ */
-
-/** @}
- */
Index: pace/lib/posix/limits.h
===================================================================
--- uspace/lib/posix/limits.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Implementation-defined limit constants.
- */
-
-#ifndef POSIX_LIMITS_H_
-#define POSIX_LIMITS_H_
-
-#include "stdint.h"
-#include "libc/sys/types.h"
-
-#undef SHRT_MIN
-#undef SHRT_MAX
-#undef USHRT_MAX
-#define SHRT_MIN SHORT_MIN
-#define SHRT_MAX SHORT_MAX
-#define USHRT_MAX USHORT_MAX
-
-#undef PATH_MAX
-#define PATH_MAX 256
-
-#endif /* POSIX_LIMITS_H_ */
-
-/** @}
- */
Index: pace/lib/posix/locale.c
===================================================================
--- uspace/lib/posix/locale.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,183 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Locale-specific definitions.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "internal/common.h"
-#include "locale.h"
-
-#include "errno.h"
-#include "limits.h"
-#include "string.h"
-
-/* Just a very basic dummy implementation.
- * This should allow code using locales to work properly, but doesn't provide
- * any localization functionality.
- * Should be extended/rewritten when or if HelenOS supports locales natively.
- */
-
-struct __posix_locale {
-	int _dummy;
-};
-
-const struct posix_lconv C_LOCALE = {
-	.currency_symbol = (char *) "",
-	.decimal_point = (char *) ".",
-	.frac_digits = CHAR_MAX,
-	.grouping = (char *) "",
-	.int_curr_symbol = (char *) "",
-	.int_frac_digits = CHAR_MAX,
-	.int_n_cs_precedes = CHAR_MAX,
-	.int_n_sep_by_space = CHAR_MAX,
-	.int_n_sign_posn = CHAR_MAX,
-	.int_p_cs_precedes = CHAR_MAX,
-	.int_p_sep_by_space = CHAR_MAX,
-	.int_p_sign_posn = CHAR_MAX,
-	.mon_decimal_point = (char *) "",
-	.mon_grouping = (char *) "",
-	.mon_thousands_sep = (char *) "",
-	.negative_sign = (char *) "",
-	.n_cs_precedes = CHAR_MAX,
-	.n_sep_by_space = CHAR_MAX,
-	.n_sign_posn = CHAR_MAX,
-	.positive_sign = (char *) "",
-	.p_cs_precedes = CHAR_MAX,
-	.p_sep_by_space = CHAR_MAX,
-	.p_sign_posn = CHAR_MAX,
-	.thousands_sep = (char *) ""
-};
-
-/**
- * Set program locale.
- * 
- * @param category What category to set.
- * @param locale Locale name.
- * @return Original locale name on success, NULL on failure.
- */
-char *posix_setlocale(int category, const char *locale)
-{
-	// TODO
-	if (locale == NULL || *locale == '\0' ||
-	    posix_strcmp(locale, "C") == 0) {
-		return (char *) "C";
-	}
-	return NULL;
-}
-
-/**
- * Return locale-specific information.
- * 
- * @return Information about the current locale.
- */
-struct posix_lconv *posix_localeconv(void)
-{
-	// TODO
-	return (struct posix_lconv *) &C_LOCALE;
-}
-
-/**
- * Duplicate locale object.
- * 
- * @param locobj Object to duplicate.
- * @return Duplicated object.
- */
-posix_locale_t posix_duplocale(posix_locale_t locobj)
-{
-	if (locobj == NULL) {
-		errno = EINVAL;
-		return NULL;
-	}
-	posix_locale_t copy = malloc(sizeof(struct __posix_locale));
-	if (copy == NULL) {
-		errno = ENOMEM;
-		return NULL;
-	}
-	memcpy(copy, locobj, sizeof(struct __posix_locale));
-	return copy;
-}
-
-/**
- * Free locale object.
- * 
- * @param locobj Object to free.
- */
-void posix_freelocale(posix_locale_t locobj)
-{
-	if (locobj) {
-		free(locobj);
-	}
-}
-
-/**
- * Create or modify a locale object.
- * 
- * @param category_mask Mask of categories to be set or modified.
- * @param locale Locale to be used.
- * @param base Object to modify. 0 if new object is to be created.
- * @return The new/modified locale object.
- */
-posix_locale_t posix_newlocale(int category_mask, const char *locale,
-    posix_locale_t base)
-{
-	if (locale == NULL ||
-	    (category_mask & LC_ALL_MASK) != category_mask) {
-		errno = EINVAL;
-		return NULL;
-	}
-	// TODO
-	posix_locale_t new = malloc(sizeof(struct __posix_locale));
-	if (new == NULL) {
-		errno = ENOMEM;
-		return NULL;
-	}
-	if (base != NULL) {
-		posix_freelocale(base);
-	}
-	return new;
-}
-
-/**
- * Set locale for the current thread.
- * 
- * @param newloc Locale to use.
- * @return The previously set locale or LC_GLOBAL_LOCALE
- */
-posix_locale_t posix_uselocale(posix_locale_t newloc)
-{
-	// TODO
-	return LC_GLOBAL_LOCALE;
-}
-
-/** @}
- */
Index: pace/lib/posix/locale.h
===================================================================
--- uspace/lib/posix/locale.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,136 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Locale-specific definitions.
- */
-
-#ifndef POSIX_LOCALE_H_
-#define POSIX_LOCALE_H_
-
-#ifndef NULL
-	#define NULL ((void *) 0)
-#endif
-
-#ifndef __locale_t_defined
-	#define __locale_t_defined
-	typedef struct __posix_locale *posix_locale_t;
-	#ifndef LIBPOSIX_INTERNAL
-		#define locale_t posix_locale_t
-	#endif
-#endif
-
-#undef LC_ALL
-#undef LC_COLLATE
-#undef LC_CTYPE
-#undef LC_MESSAGES
-#undef LC_MONETARY
-#undef LC_NUMERIC
-#undef LC_TIME
-#define LC_ALL 0
-#define LC_COLLATE 1
-#define LC_CTYPE 2
-#define LC_MESSAGES 3
-#define LC_MONETARY 4
-#define LC_NUMERIC 5
-#define LC_TIME 6
-
-#undef LC_COLLATE_MASK
-#undef LC_CTYPE_MASK
-#undef LC_MESSAGES_MASK
-#undef LC_MONETARY_MASK
-#undef LC_NUMERIC_MASK
-#undef LC_TIME_MASK
-#undef LC_ALL_MASK
-#define LC_COLLATE_MASK (1 << 0)
-#define LC_CTYPE_MASK (1 << 1)
-#define LC_MESSAGES_MASK (1 << 2)
-#define LC_MONETARY_MASK (1 << 3)
-#define LC_NUMERIC_MASK (1 << 4)
-#define LC_TIME_MASK (1 << 5)
-#define LC_ALL_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | \
-    LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK)
-
-#undef LC_GLOBAL_LOCALE
-#define LC_GLOBAL_LOCALE NULL
-
-struct posix_lconv {
-	char *currency_symbol;
-	char *decimal_point;
-	char  frac_digits;
-	char *grouping;
-	char *int_curr_symbol;
-	char  int_frac_digits;
-	char  int_n_cs_precedes;
-	char  int_n_sep_by_space;
-	char  int_n_sign_posn;
-	char  int_p_cs_precedes;
-	char  int_p_sep_by_space;
-	char  int_p_sign_posn;
-	char *mon_decimal_point;
-	char *mon_grouping;
-	char *mon_thousands_sep;
-	char *negative_sign;
-	char  n_cs_precedes;
-	char  n_sep_by_space;
-	char  n_sign_posn;
-	char *positive_sign;
-	char  p_cs_precedes;
-	char  p_sep_by_space;
-	char  p_sign_posn;
-	char *thousands_sep;
-};
-
-extern char *posix_setlocale(int category, const char *locale);
-extern struct posix_lconv *posix_localeconv(void);
-
-/* POSIX Extensions */
-extern posix_locale_t posix_duplocale(posix_locale_t locobj);
-extern void posix_freelocale(posix_locale_t locobj);
-extern posix_locale_t posix_newlocale(int category_mask, const char *locale,
-    posix_locale_t base);
-extern posix_locale_t posix_uselocale(posix_locale_t newloc);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define lconv posix_lconv
-
-	#define setlocale posix_setlocale
-	#define localeconv posix_localeconv
-
-	#define newlocale posix_newlocale
-	#define uselocale posix_uselocale
-	#define duplocale posix_duplocale
-	#define freelocale posix_freelocale
-#endif
-
-#endif /* POSIX_LOCALE_H_ */
-
-/** @}
- */
Index: pace/lib/posix/math.c
===================================================================
--- uspace/lib/posix/math.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,65 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Mathematical operations.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "internal/common.h"
-#include "math.h"
-
-/**
- * 
- * @param x
- * @param exp
- * @return
- */
-double posix_ldexp(double x, int exp)
-{
-	// TODO: low priority, just a compile-time dependency of binutils
-	not_implemented();
-}
-
-/**
- * 
- * @param num
- * @param exp
- * @return
- */
-double posix_frexp(double num, int *exp)
-{
-	// TODO: low priority, just a compile-time dependency of binutils
-	not_implemented();
-}
-
-/** @}
- */
Index: pace/lib/posix/math.h
===================================================================
--- uspace/lib/posix/math.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Mathematical operations.
- */
-
-#ifndef POSIX_MATH_H_
-#define POSIX_MATH_H_
-
-/* Normalization Functions */
-extern double posix_ldexp(double x, int exp);
-extern double posix_frexp(double num, int *exp);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define ldexp posix_ldexp
-	#define frexp posix_frexp
-#endif
-
-#endif /* POSIX_MATH_H_ */
-
-/** @}
- */
Index: pace/lib/posix/pwd.c
===================================================================
--- uspace/lib/posix/pwd.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,190 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Password handling.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "pwd.h"
-#include "string.h"
-#include "errno.h"
-#include "assert.h"
-
-static bool entry_read = false;
-
-/* dummy user account */
-static const struct posix_passwd dummy_pwd = {
-	.pw_name = (char *) "user",
-	.pw_uid = 0,
-	.pw_gid = 0,
-	.pw_dir = (char *) "/",
-	.pw_shell = (char *) "/app/bdsh"
-};
-
-/**
- * Retrieve next broken-down entry from the user database.
- *
- * Since HelenOS doesn't have user accounts, this always returns
- * the same made-up entry.
- *
- * @return Next user database entry or NULL if not possible. Since HelenOS
- *     doesn't have user accounts, this always returns the same made-up entry.
- */
-struct posix_passwd *posix_getpwent(void)
-{
-	if (entry_read) {
-		return NULL;
-	}
-
-	entry_read = true;
-	return (struct posix_passwd *) &dummy_pwd;
-}
-
-/**
- * Rewind the user list.
- */
-void posix_setpwent(void)
-{
-	entry_read = false;
-}
-
-/**
- * Ends enumerating and releases all resources. (Noop)
- */
-void posix_endpwent(void)
-{
-	/* noop */
-}
-
-/**
- * Find an entry by name.
- *
- * @param name Name of the entry.
- * @return Either found entry or NULL if no such entry exists.
- */
-struct posix_passwd *posix_getpwnam(const char *name)
-{
-	assert(name != NULL);
-
-	if (posix_strcmp(name, "user") != 0) {
-		return NULL;
-	}
-
-	return (struct posix_passwd *) &dummy_pwd;
-}
-
-/**
- * Find an entry by name, thread safely.
- *
- * @param name Name of the entry.
- * @param pwd Original structure.
- * @param buffer Buffer for the strings referenced from the result structure.
- * @param bufsize Length of the buffer.
- * @param result Where to store updated structure.
- * @return Zero on success (either found or not found, but without an error),
- *     non-zero error number if error occured.
- */
-int posix_getpwnam_r(const char *name, struct posix_passwd *pwd,
-    char *buffer, size_t bufsize, struct posix_passwd **result)
-{
-	assert(name != NULL);
-	assert(pwd != NULL);
-	assert(buffer != NULL);
-	assert(result != NULL);
-	
-	if (posix_strcmp(name, "user") != 0) {
-		*result = NULL;
-		return 0;
-	}
-	
-	return posix_getpwuid_r(0, pwd, buffer, bufsize, result);
-}
-
-/**
- * Find an entry by UID.
- *
- * @param uid UID of the entry.
- * @return Either found entry or NULL if no such entry exists.
- */
-struct posix_passwd *posix_getpwuid(posix_uid_t uid)
-{
-	if (uid != 0) {
-		return NULL;
-	}
-
-	return (struct posix_passwd *) &dummy_pwd;
-}
-
-/**
- * Find an entry by UID, thread safely.
- *
- * @param uid UID of the entry.
- * @param pwd Original structure.
- * @param buffer Buffer for the strings referenced from the result structure.
- * @param bufsize Length of the buffer.
- * @param result Where to store updated structure.
- * @return Zero on success (either found or not found, but without an error),
- *     non-zero error number if error occured.
- */
-int posix_getpwuid_r(posix_uid_t uid, struct posix_passwd *pwd,
-    char *buffer, size_t bufsize, struct posix_passwd **result)
-{
-	assert(pwd != NULL);
-	assert(buffer != NULL);
-	assert(result != NULL);
-	
-	static const char bf[] = { 'u', 's', 'e', 'r', '\0',
-	    '/', '\0', 'b', 'd', 's', 'h', '\0' };
-	
-	if (uid != 0) {
-		*result = NULL;
-		return 0;
-	}
-	if (bufsize < sizeof(bf)) {
-		*result = NULL;
-		return ERANGE;
-	}
-
-	memcpy(buffer, bf, sizeof(bf));
-
-	pwd->pw_name = (char *) bf;
-	pwd->pw_uid = 0;
-	pwd->pw_gid = 0;
-	pwd->pw_dir = (char *) bf + 5;
-	pwd->pw_shell = (char *) bf + 7;
-	*result = (struct posix_passwd *) pwd;
-
-	return 0;
-}
-
-/** @}
- */
Index: pace/lib/posix/pwd.h
===================================================================
--- uspace/lib/posix/pwd.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,77 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Password handling.
- */
-
-#ifndef POSIX_PWD_H_
-#define POSIX_PWD_H_
-
-#include "sys/types.h"
-
-struct posix_passwd {
-	char *pw_name;
-	posix_uid_t pw_uid;
-	posix_gid_t pw_gid;
-	char *pw_dir;
-	char *pw_shell;
-};
-
-extern struct posix_passwd *posix_getpwent(void);
-extern void posix_setpwent(void);
-extern void posix_endpwent(void);
-
-extern struct posix_passwd *posix_getpwnam(const char *name);
-extern int posix_getpwnam_r(const char *name, struct posix_passwd *pwd,
-    char *buffer, size_t bufsize, struct posix_passwd **result);
-
-extern struct posix_passwd *posix_getpwuid(posix_uid_t uid);
-extern int posix_getpwuid_r(posix_uid_t uid, struct posix_passwd *pwd,
-    char *buffer, size_t bufsize, struct posix_passwd **result);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define passwd posix_passwd
-	
-	#define getpwent posix_getpwent
-	#define setpwent posix_setpwent
-	#define endpwent posix_endpwent
-
-	#define getpwnam posix_getpwnam
-	#define getpwnam_r posix_getpwnam_r
-
-	#define getpwuid posix_getpwuid
-	#define getpwuid_r posix_getpwuid_r
-#endif
-
-#endif /* POSIX_PWD_H_ */
-
-/** @}
- */
Index: pace/lib/posix/signal.c
===================================================================
--- uspace/lib/posix/signal.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,566 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Signal handling.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "signal.h"
-#include "internal/common.h"
-#include "limits.h"
-#include "stdlib.h"
-#include "string.h"
-#include "errno.h"
-
-#include "libc/fibril_synch.h"
-#include "libc/task.h"
-
-/* This file implements a fairly dumb and incomplete "simulation" of
- * POSIX signals. Since HelenOS doesn't support signals and mostly doesn't
- * have any equivalent functionality, most of the signals are useless. The
- * main purpose of this implementation is thus to help port applications using
- * signals with minimal modification, but if the application uses signals for
- * anything non-trivial, it's quite probable it won't work properly even if
- * it builds without problems.
- */
-
-/* Used to serialize signal handling. */
-static FIBRIL_MUTEX_INITIALIZE(_signal_mutex);
-
-static LIST_INITIALIZE(_signal_queue);
-
-static posix_sigset_t _signal_mask = 0;
-
-#define DEFAULT_HANDLER { .sa_handler = SIG_DFL, \
-    .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL }
-
-/* Actions associated with each signal number. */
-static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = {
-	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
-	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
-	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
-	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
-	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
-	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
-	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER
-};
-
-/**
- * Default signal handler. Executes the default action for each signal,
- * as reasonable within HelenOS.
- *
- * @param signo Signal number.
- */
-void __posix_default_signal_handler(int signo)
-{
-	switch (signo) {
-	case SIGABRT:
-		abort();
-	case SIGQUIT:
-		fprintf(stderr, "Quit signal raised. Exiting.\n");
-		exit(EXIT_FAILURE);
-	case SIGINT:
-		fprintf(stderr, "Interrupt signal caught. Exiting.\n");
-		exit(EXIT_FAILURE);
-	case SIGTERM:
-		fprintf(stderr, "Termination signal caught. Exiting.\n");
-		exit(EXIT_FAILURE);
-	case SIGSTOP:
-		fprintf(stderr, "Stop signal caught, but unsupported. Ignoring.\n");
-		break;
-	case SIGKILL:
-		/* This will only occur when raise or similar is called. */
-		/* Commit suicide. */
-		task_kill(task_get_id());
-		
-		/* Should not be reached. */
-		abort();
-	case SIGFPE:
-	case SIGBUS:
-	case SIGILL:
-	case SIGSEGV:
-		posix_psignal(signo, "Hardware exception raised by user code");
-		abort();
-	case SIGSYS:
-	case SIGXCPU:
-	case SIGXFSZ:
-	case SIGTRAP:
-	case SIGHUP:
-	case SIGPIPE:
-	case SIGPOLL:
-	case SIGURG:
-	case SIGTSTP:
-	case SIGTTIN:
-	case SIGTTOU:
-		posix_psignal(signo, "Unsupported signal caught");
-		abort();
-	case SIGCHLD:
-	case SIGUSR1:
-	case SIGUSR2:
-	case SIGALRM:
-	case SIGVTALRM:
-	case SIGPROF:
-	case SIGCONT:
-		/* ignored */
-		break;
-	}
-}
-
-/**
- * Just an empty function to get an unique pointer value for comparison.
- *
- * @param signo Signal number.
- */
-void __posix_hold_signal_handler(int signo)
-{
-	/* Nothing */
-}
-
-/**
- * Empty function to be used as ignoring handler.
- * 
- * @param signo Signal number.
- */
-void __posix_ignore_signal_handler(int signo)
-{
-	/* Nothing */
-}
-
-/**
- * Clear the signal set.
- * 
- * @param set Pointer to the signal set.
- * @return Always returns zero.
- */
-int posix_sigemptyset(posix_sigset_t *set)
-{
-	assert(set != NULL);
-
-	*set = 0;
-	return 0;
-}
-
-/**
- * Fill the signal set (i.e. add all signals).
- * 
- * @param set Pointer to the signal set.
- * @return Always returns zero.
- */
-int posix_sigfillset(posix_sigset_t *set)
-{
-	assert(set != NULL);
-
-	*set = UINT32_MAX;
-	return 0;
-}
-
-/**
- * Add a signal to the set.
- * 
- * @param set Pointer to the signal set.
- * @param signo Signal number to add.
- * @return Always returns zero.
- */
-int posix_sigaddset(posix_sigset_t *set, int signo)
-{
-	assert(set != NULL);
-
-	*set |= (1 << signo);
-	return 0;
-}
-
-/**
- * Delete a signal from the set.
- * 
- * @param set Pointer to the signal set.
- * @param signo Signal number to remove.
- * @return Always returns zero.
- */
-int posix_sigdelset(posix_sigset_t *set, int signo)
-{
-	assert(set != NULL);
-
-	*set &= ~(1 << signo);
-	return 0;
-}
-
-/**
- * Inclusion test for a signal set.
- * 
- * @param set Pointer to the signal set.
- * @param signo Signal number to query.
- * @return 1 if the signal is in the set, 0 otherwise.
- */
-int posix_sigismember(const posix_sigset_t *set, int signo)
-{
-	assert(set != NULL);
-	
-	return (*set & (1 << signo)) != 0;
-}
-
-/**
- * Unsafe variant of the sigaction() function.
- * Doesn't do any checking of its arguments and
- * does not deal with thread-safety.
- * 
- * @param sig
- * @param act
- * @param oact
- */
-static void _sigaction_unsafe(int sig, const struct posix_sigaction *restrict act,
-    struct posix_sigaction *restrict oact)
-{
-	if (oact != NULL) {
-		memcpy(oact, &_signal_actions[sig],
-		    sizeof(struct posix_sigaction));
-	}
-
-	if (act != NULL) {
-		memcpy(&_signal_actions[sig], act,
-		    sizeof(struct posix_sigaction));
-	}
-}
-
-/**
- * Sets a new action for the given signal number.
- * 
- * @param sig Signal number to set action for.
- * @param act If not NULL, contents of this structure are
- *     used as the new action for the signal.
- * @param oact If not NULL, the original action associated with the signal
- *     is stored in the structure pointer to. 
- * @return -1 with errno set on failure, 0 on success.
- */
-int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
-    struct posix_sigaction *restrict oact)
-{
-	if (sig > _TOP_SIGNAL || (act != NULL &&
-	    (sig == SIGKILL || sig == SIGSTOP))) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	if (sig > _TOP_CATCHABLE_SIGNAL) {
-		posix_psignal(sig,
-		    "WARNING: registering handler for a partially"
-		    " or fully unsupported signal. This handler may only be"
-		    " invoked by the raise() function, which may not be what"
-		    " the application developer intended");
-	}
-
-	fibril_mutex_lock(&_signal_mutex);
-	_sigaction_unsafe(sig, act, oact);
-	fibril_mutex_unlock(&_signal_mutex);
-
-	return 0;
-}
-
-/**
- * Sets a new handler for the given signal number.
- * 
- * @param sig Signal number to set handler for.
- * @param func Handler function.
- * @return SIG_ERR on failure, original handler on success.
- */
-void (*posix_signal(int sig, void (*func)(int)))(int)
-{
-	struct posix_sigaction new = {
-		.sa_handler = func,
-		.sa_mask = 0,
-		.sa_flags = 0,
-		.sa_sigaction = NULL
-	};
-	struct posix_sigaction old;
-	if (posix_sigaction(sig, func == NULL ? NULL : &new, &old) == 0) {
-		return old.sa_handler;
-	} else {
-		return SIG_ERR;
-	}
-}
-
-typedef struct {
-	link_t link;
-	int signo;
-	posix_siginfo_t siginfo;
-} signal_queue_item;
-
-/**
- * Queue blocked signal.
- *
- * @param signo Signal number.
- * @param siginfo Additional information about the signal.
- */
-static void _queue_signal(int signo, posix_siginfo_t *siginfo)
-{
-	assert(signo >= 0 && signo <= _TOP_SIGNAL);
-	assert(siginfo != NULL);
-	
-	signal_queue_item *item = malloc(sizeof(signal_queue_item));
-	link_initialize(&(item->link));
-	item->signo = signo;
-	memcpy(&item->siginfo, siginfo, sizeof(posix_siginfo_t));
-	list_append(&(item->link), &_signal_queue);
-}
-
-
-/**
- * Executes an action associated with the given signal.
- *
- * @param signo Signal number.
- * @param siginfo Additional information about the circumstances of this raise.
- * @return 0 if the action has been successfully executed. -1 if the signal is
- *     blocked.
- */
-static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
-{
-	assert(signo >= 0 && signo <= _TOP_SIGNAL);
-	assert(siginfo != NULL);
-
-	fibril_mutex_lock(&_signal_mutex);
-
-	struct posix_sigaction action = _signal_actions[signo];
-
-	if (posix_sigismember(&_signal_mask, signo) ||
-	    action.sa_handler == SIG_HOLD) {
-		_queue_signal(signo, siginfo);
-		fibril_mutex_unlock(&_signal_mutex);
-		return -1;
-	}
-
-	/* Modifying signal mask is unnecessary,
-	 * signal handling is serialized.
-	 */
-
-	if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) {
-		_signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER;
-	}
-
-	if (action.sa_flags & SA_SIGINFO) {
-		assert(action.sa_sigaction != NULL);
-		action.sa_sigaction(signo, siginfo, NULL);
-	} else {
-		assert(action.sa_handler != NULL);
-		action.sa_handler(signo);
-	}
-
-	fibril_mutex_unlock(&_signal_mutex);
-
-	return 0;
-}
-
-/**
- * Raise all unblocked previously queued signals.
- */
-static void _dequeue_unblocked_signals()
-{
-	link_t *iterator = _signal_queue.head.next;
-	link_t *next;
-	
-	while (iterator != &(_signal_queue).head) {
-		next = iterator->next;
-		
-		signal_queue_item *item =
-		    list_get_instance(iterator, signal_queue_item, link);
-		
-		if (!posix_sigismember(&_signal_mask, item->signo) &&
-		    _signal_actions[item->signo].sa_handler != SIG_HOLD) {
-			list_remove(&(item->link));
-			_raise_sigaction(item->signo, &(item->siginfo));
-			free(item);
-		}
-		
-		iterator = next;
-	}
-}
-
-/**
- * Raise a signal for the calling process.
- * 
- * @param sig Signal number.
- * @return -1 with errno set on failure, 0 on success.
- */
-int posix_raise(int sig)
-{
-	if (sig >= 0 && sig <= _TOP_SIGNAL) {
-		posix_siginfo_t siginfo = {
-			.si_signo = sig,
-			.si_code = SI_USER
-		};
-		return _raise_sigaction(sig, &siginfo);
-	} else {
-		errno = EINVAL;
-		return -1;
-	}
-}
-
-/**
- * Raises a signal for a selected process.
- * 
- * @param pid PID of the process for which the signal shall be raised.
- * @param signo Signal to raise.
- * @return -1 with errno set on failure (possible errors include unsupported
- *     action, invalid signal number, lack of permissions, etc.), 0 on success.
- */
-int posix_kill(posix_pid_t pid, int signo)
-{
-	if (pid < 1) {
-		// TODO
-		errno = ENOTSUP;
-		return -1;
-	}
-
-	if (signo > _TOP_SIGNAL) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	if (pid == (posix_pid_t) task_get_id()) {
-		return posix_raise(signo);
-	}
-
-	switch (signo) {
-	case SIGKILL:
-		task_kill(pid);
-		break;
-	default:
-		/* Nothing else supported yet. */
-		errno = ENOTSUP;
-		return -1;
-	}
-
-	return 0;
-}
-
-/**
- * Send a signal to a process group. Always fails at the moment because of
- * lack of this functionality in HelenOS.
- * 
- * @param pid PID of the process group.
- * @param sig Signal number.
- * @return -1 on failure, 0 on success (see kill()).
- */
-int posix_killpg(posix_pid_t pid, int sig)
-{
-	assert(pid > 1);
-	return posix_kill(-pid, sig);
-}
-
-/**
- * Outputs information about the signal to the standard error stream.
- * 
- * @param pinfo SigInfo struct to write.
- * @param message String to output alongside human-readable signal description.
- */
-void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message)
-{
-	assert(pinfo != NULL);
-	posix_psignal(pinfo->si_signo, message);
-	// TODO: print si_code
-}
-
-/**
- * Outputs information about the signal to the standard error stream.
- * 
- * @param signum Signal number.
- * @param message String to output alongside human-readable signal description.
- */
-void posix_psignal(int signum, const char *message)
-{
-	char *sigmsg = posix_strsignal(signum);
-	if (message == NULL || *message == '\0') {
-		fprintf(stderr, "%s\n", sigmsg);
-	} else {
-		fprintf(stderr, "%s: %s\n", message, sigmsg);
-	}
-}
-
-/**
- * Manipulate the signal mask of the calling thread.
- * 
- * @param how What to do with the mask.
- * @param set Signal set to work with.
- * @param oset If not NULL, the original signal mask is coppied here.
- * @return 0 success, errorcode on failure.
- */
-int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
-    posix_sigset_t *restrict oset)
-{
-	fibril_mutex_lock(&_signal_mutex);
-
-	if (oset != NULL) {
-		*oset = _signal_mask;
-	}
-	if (set != NULL) {
-		switch (how) {
-		case SIG_BLOCK:
-			_signal_mask |= *set;
-			break;
-		case SIG_UNBLOCK:
-			_signal_mask &= ~*set;
-			break;
-		case SIG_SETMASK:
-			_signal_mask = *set;
-			break;
-		default:
-			fibril_mutex_unlock(&_signal_mutex);
-			return EINVAL;
-		}
-	}
-	
-	_dequeue_unblocked_signals();
-
-	fibril_mutex_unlock(&_signal_mutex);
-
-	return 0;
-}
-
-/**
- * Manipulate the signal mask of the process.
- * 
- * @param how What to do with the mask.
- * @param set Signal set to work with.
- * @param oset If not NULL, the original signal mask is coppied here.
- * @return 0 on success, -1 with errno set on failure.
- */
-int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
-    posix_sigset_t *restrict oset)
-{
-	int result = posix_thread_sigmask(how, set, oset);
-	if (result != 0) {
-		errno = result;
-		return -1;
-	}
-	return 0;
-}
-
-/** @}
- */
Index: pace/lib/posix/signal.h
===================================================================
--- uspace/lib/posix/signal.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,315 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Signal handling.
- */
-
-#ifndef POSIX_SIGNAL_H_
-#define POSIX_SIGNAL_H_
-
-#include "libc/errno.h"
-#include "sys/types.h"
-
-extern void __posix_default_signal_handler(int signo);
-extern void __posix_hold_signal_handler(int signo);
-extern void __posix_ignore_signal_handler(int signo);
-
-#undef SIG_DFL
-#define SIG_DFL ((void (*)(int)) __posix_default_signal_handler)
-#undef SIG_ERR
-#define SIG_ERR ((void (*)(int)) NULL)
-#undef SIG_HOLD
-#define SIG_HOLD ((void (*)(int)) __posix_hold_signal_handler)
-#undef SIG_IGN
-#define SIG_IGN ((void (*)(int)) __posix_ignore_signal_handler)
-
-typedef int posix_sig_atomic_t;
-typedef uint32_t posix_sigset_t;
-typedef struct posix_mcontext {
-	/* must not be empty to avoid compiler warnings (-pedantic) */
-	int dummy;
-} posix_mcontext_t;
-
-union posix_sigval {
-	int sival_int;
-	void *sival_ptr;
-};
-
-struct posix_sigevent {
-	int sigev_notify; /* Notification type. */
-	int sigev_signo; /* Signal number. */
-	union posix_sigval sigev_value; /* Signal value. */
-	void (*sigev_notify_function)(union posix_sigval); /* Notification function. */
-	posix_thread_attr_t *sigev_notify_attributes; /* Notification attributes. */
-};
-
-typedef struct {
-	int si_signo;
-	int si_code;
-
-	int si_errno;
-
-	posix_pid_t si_pid;
-	posix_uid_t si_uid;
-	void *si_addr;
-	int si_status;
-
-	long si_band;
-
-	union posix_sigval si_value;
-} posix_siginfo_t;
-
-struct posix_sigaction {
-	void (*sa_handler)(int);
-	posix_sigset_t sa_mask;
-	int sa_flags;
-	void (*sa_sigaction)(int, posix_siginfo_t *, void *);
-};
-
-typedef struct {
-	void *ss_sp;
-	size_t ss_size;
-	int ss_flags;
-} posix_stack_t;
-
-typedef struct posix_ucontext {
-	struct posix_ucontext *uc_link;
-	posix_sigset_t uc_sigmask;
-	posix_stack_t uc_stack;
-	posix_mcontext_t uc_mcontext;
-} posix_ucontext_t;
-
-/* Values of posix_sigevent::sigev_notify */
-#undef SIGEV_NONE
-#undef SIGEV_SIGNAL
-#undef SIGEV_THREAD
-#define SIGEV_NONE 0
-#define SIGEV_SIGNAL 0
-#define SIGEV_THREAD 0
-
-#undef SIGRT_MIN
-#undef SIGRT_MAX
-#define SIGRT_MIN 0
-#define SIGRT_MAX 0
-
-#undef SIG_BLOCK
-#undef SIG_UNBLOCK
-#undef SIG_SETMASK
-#define SIG_BLOCK 0
-#define SIG_UNBLOCK 1
-#define SIG_SETMASK 2
-
-#undef SA_NOCLDSTOP
-#undef SA_ONSTACK
-#undef SA_RESETHAND
-#undef SA_RESTART
-#undef SA_SIGINFO
-#undef SA_NOCLDWAIT
-#undef SA_NODEFER
-#define SA_NOCLDSTOP (1 << 0)
-#define SA_ONSTACK (1 << 1)
-#define SA_RESETHAND (1 << 2)
-#define SA_RESTART (1 << 3)
-#define SA_SIGINFO (1 << 4)
-#define SA_NOCLDWAIT (1 << 5)
-#define SA_NODEFER (1 << 6)
-
-#undef SS_ONSTACK
-#undef SS_DISABLE
-#define SS_ONSTACK 0
-#define SS_DISABLE 0
-
-#undef MINSIGSTKSZ
-#undef SIGSTKSZ
-#define MINSIGSTKSZ 0
-#define SIGSTKSZ 0
-
-/* Full POSIX set */
-enum {
-	/* Termination Signals */
-	SIGABRT,
-	SIGQUIT,
-	SIGINT,
-	SIGTERM,
-	
-	/* Child Signal */
-	SIGCHLD,
-	
-	/* User signals */
-	SIGUSR1,
-	SIGUSR2,
-
-	/* Timer */
-	SIGALRM,
-	SIGVTALRM,
-	SIGPROF, /* obsolete */
-
-	_TOP_CATCHABLE_SIGNAL = SIGPROF,
-
-	/* Process Scheduler Interaction - not supported */
-	SIGSTOP,
-	SIGCONT,
-
-	/* Process Termination - can't be caught */
-	SIGKILL,
-
-	_TOP_SENDABLE_SIGNAL = SIGKILL,
-
-	/* Hardware Exceptions - can't be caught or sent */
-	SIGFPE,
-	SIGBUS,
-	SIGILL,
-	SIGSEGV,
-
-	/* Other Exceptions - not supported */
-	SIGSYS,
-	SIGXCPU,
-	SIGXFSZ,
-
-	/* Debugging - not supported */
-	SIGTRAP,
-
-	/* Communication Signals - not supported */
-	SIGHUP,
-	SIGPIPE,
-	SIGPOLL, /* obsolete */
-	SIGURG,
-
-	/* Terminal Signals - not supported */
-	SIGTSTP,
-	SIGTTIN,
-	SIGTTOU,
-	
-	_TOP_SIGNAL = SIGTTOU
-};
-
-/* Values for sigaction field si_code. */
-enum {
-	SI_USER,
-	SI_QUEUE,
-	SI_TIMER,
-	SI_ASYNCIO,
-	SI_MESGQ,
-	ILL_ILLOPC,
-	ILL_ILLOPN,
-	ILL_ILLADR,
-	ILL_ILLTRP,
-	ILL_PRVOPC,
-	ILL_PRVREG,
-	ILL_COPROC,
-	ILL_BADSTK,
-	FPE_INTDIV,
-	FPE_INTOVF,
-	FPE_FLTDIV,
-	FPE_FLTOVF,
-	FPE_FLTUND,
-	FPE_FLTRES,
-	FPE_FLTINV,
-	FPE_FLTSUB,
-	SEGV_MAPERR,
-	SEGV_ACCERR,
-	BUS_ADRALN,
-	BUS_ADRERR,
-	BUS_OBJERR,
-	TRAP_BRKPT,
-	TRAP_TRACE,
-	CLD_EXITED,
-	CLD_KILLED,
-	CLD_DUMPED,
-	CLD_TRAPPED,
-	CLD_STOPPED,
-	CLD_CONTINUED,
-	POLL_IN,
-	POLL_OUT,
-	POLL_MSG,
-	POLL_ERR,
-	POLL_PRI,
-	POLL_HUP
-};
-
-extern int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
-    struct posix_sigaction *restrict oact);
-
-extern void (*posix_signal(int sig, void (*func)(int)))(int);
-extern int posix_raise(int sig);
-extern int posix_kill(posix_pid_t pid, int sig);
-extern int posix_killpg(posix_pid_t pid, int sig);
-
-extern void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message);
-extern void posix_psignal(int signum, const char *message);
-
-extern int posix_sigemptyset(posix_sigset_t *set);
-extern int posix_sigfillset(posix_sigset_t *set);
-extern int posix_sigaddset(posix_sigset_t *set, int signo);
-extern int posix_sigdelset(posix_sigset_t *set, int signo);
-extern int posix_sigismember(const posix_sigset_t *set, int signo);
-
-extern int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
-    posix_sigset_t *restrict oset);
-extern int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
-    posix_sigset_t *restrict oset);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define sig_atomic_t posix_sig_atomic_t
-	#define sigset_t posix_sigset_t
-	#define sigval posix_sigval
-	#ifndef sigevent
-		#define sigevent posix_sigevent
-	#endif
-	#define mcontext_t posix_mcontext_t
-	#define ucontext_t posix_ucontext_t
-	#define stack_t posix_stack_t
-	#define siginfo_t posix_siginfo_t
-
-	#define sigaction posix_sigaction
-
-	#define signal posix_signal
-	#define raise posix_raise
-	#define kill posix_kill
-	#define killpg posix_killpg
-
-	#define psiginfo posix_psiginfo
-	#define psignal posix_psignal
-
-	#define sigemptyset posix_sigemptyset
-	#define sigfillset posix_sigfillset
-	#define sigaddset posix_sigaddset
-	#define sigdelset posix_sigdelset
-	#define sigismember posix_sigismember
-
-	#define pthread_sigmask posix_thread_sigmask
-	#define sigprocmask posix_sigprocmask
-#endif
-
-#endif /* POSIX_SIGNAL_H_ */
-
-/** @}
- */
Index: uspace/lib/posix/source/ctype.c
===================================================================
--- uspace/lib/posix/source/ctype.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/ctype.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Character classification.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "posix/ctype.h"
+
+/**
+ * Checks whether character is a hexadecimal digit.
+ *
+ * @param c Character to inspect.
+ * @return Non-zero if character match the definition, zero otherwise.
+ */
+int posix_isxdigit(int c)
+{
+	return isdigit(c) ||
+	    (c >= 'a' && c <= 'f') ||
+	    (c >= 'A' && c <= 'F');
+}
+
+/**
+ * Checks whether character is a word separator.
+ *
+ * @param c Character to inspect.
+ * @return Non-zero if character match the definition, zero otherwise.
+ */
+int posix_isblank(int c)
+{
+	return c == ' ' || c == '\t';
+}
+
+/**
+ * Checks whether character is a control character.
+ *
+ * @param c Character to inspect.
+ * @return Non-zero if character match the definition, zero otherwise.
+ */
+int posix_iscntrl(int c)
+{
+	return c < 0x20 || c == 0x7E;
+}
+
+/**
+ * Checks whether character is any printing character except space.
+ *
+ * @param c Character to inspect.
+ * @return Non-zero if character match the definition, zero otherwise.
+ */
+int posix_isgraph(int c)
+{
+	return posix_isprint(c) && c != ' ';
+}
+
+/**
+ * Checks whether character is a printing character.
+ *
+ * @param c Character to inspect.
+ * @return Non-zero if character match the definition, zero otherwise.
+ */
+int posix_isprint(int c)
+{
+	return posix_isascii(c) && !posix_iscntrl(c);
+}
+
+/**
+ * Checks whether character is a punctuation.
+ *
+ * @param c Character to inspect.
+ * @return Non-zero if character match the definition, zero otherwise.
+ */
+int posix_ispunct(int c)
+{
+	return !isspace(c) && !isalnum(c) && posix_isprint(c);
+}
+
+/**
+ * Checks whether character is ASCII. (obsolete)
+ *
+ * @param c Character to inspect.
+ * @return Non-zero if character match the definition, zero otherwise.
+ */
+int posix_isascii(int c)
+{
+	return c >= 0 && c < 128;
+}
+
+/**
+ * Converts argument to a 7-bit ASCII character. (obsolete)
+ *
+ * @param c Character to convert.
+ * @return Coverted character.
+ */
+int posix_toascii(int c)
+{
+	return c & 0x7F;
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/errno.c
===================================================================
--- uspace/lib/posix/source/errno.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/errno.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file System error numbers.
+ */
+
+#include "posix/errno.h"
+
+#include "posix/stdlib.h"
+#include "libc/fibril.h"
+
+static fibril_local int _posix_errno;
+
+int *__posix_errno(void)
+{
+	if (*__errno() != 0) {
+		_posix_errno = abs(*__errno());
+		*__errno() = 0;
+	}
+	return &_posix_errno;
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/fcntl.c
===================================================================
--- uspace/lib/posix/source/fcntl.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/fcntl.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file File control.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "internal/common.h"
+#include "posix/fcntl.h"
+
+#include "libc/unistd.h"
+#include "libc/vfs/vfs.h"
+#include "posix/errno.h"
+
+/**
+ * Performs set of operations on the opened files.
+ *
+ * @param fd File descriptor of the opened file.
+ * @param cmd Operation to carry out.
+ * @return Non-negative on success. Might have special meaning corresponding
+ *     to the requested operation.
+ */
+int posix_fcntl(int fd, int cmd, ...)
+{
+	int flags;
+
+	switch (cmd) {
+	case F_DUPFD:
+	case F_DUPFD_CLOEXEC:
+		/* VFS currently does not provide the functionality to duplicate
+		 * opened file descriptor. */
+		// FIXME: implement this once dup() is available
+		errno = ENOTSUP;
+		return -1;
+	case F_GETFD:
+		/* FD_CLOEXEC is not supported. There are no other flags. */
+		return 0;
+	case F_SETFD:
+		/* FD_CLOEXEC is not supported. Ignore arguments and report success. */
+		return 0;
+	case F_GETFL:
+		/* File status flags (i.e. O_APPEND) are currently private to the
+		 * VFS server so it cannot be easily retrieved. */
+		flags = 0;
+		/* File access flags are currently not supported for file descriptors.
+		 * Provide full access. */
+		flags |= O_RDWR;
+		return flags;
+	case F_SETFL:
+		/* File access flags are currently not supported for file descriptors.
+		 * Ignore arguments and report success. */
+		return 0;
+	case F_GETOWN:
+	case F_SETOWN:
+	case F_GETLK:
+	case F_SETLK:
+	case F_SETLKW:
+		/* Signals (SIGURG) and file locks are not supported. */
+		errno = ENOTSUP;
+		return -1;
+	default:
+		/* Unknown command */
+		errno = EINVAL;
+		return -1;
+	}
+}
+
+/**
+ * Open, possibly create, a file.
+ *
+ * @param pathname Path to the file.
+ * @param flags Access mode flags.
+ */
+int posix_open(const char *pathname, int flags, ...)
+{
+	mode_t mode = 0;
+	if ((flags & O_CREAT) > 0) {
+		va_list args;
+		va_start(args, flags);
+		mode = va_arg(args, mode_t);
+		va_end(args);
+	}
+
+	int rc = open(pathname, flags, mode);
+	if (rc < 0) {
+		errno = -rc;
+		rc = -1;
+	}
+
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/fnmatch.c
===================================================================
--- uspace/lib/posix/source/fnmatch.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/fnmatch.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,716 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Filename-matching.
+ */
+
+/* This file contains an implementation of the fnmatch() pattern matching
+ * function. There is more code than necessary to account for the possibility
+ * of adding POSIX-like locale support to the system in the future. Functions
+ * that are only necessary for locale support currently simply use single
+ * characters for "collation elements". 
+ * When (or if) locales are properly implemented, extending this implementation
+ * will be fairly straightforward.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "posix/stdbool.h"
+#include "posix/ctype.h"
+#include "posix/string.h"
+#include "posix/stdlib.h"
+#include "posix/assert.h"
+
+#include "internal/common.h"
+#include "posix/fnmatch.h"
+
+/* Returned by _match... functions. */
+#define INVALID_PATTERN -1
+
+/* Type for collating element, simple identity with characters now,
+ * but may be extended for better locale support.
+ */
+typedef int coll_elm_t;
+
+/** Return value indicating that the element in question
+ * is not valid in the current locale. (That is, if locales are supported.)
+ */
+#define COLL_ELM_INVALID -1
+
+/**
+ * Get collating element matching a string.
+ *
+ * @param str String representation of the element.
+ * @return Matching collating element or COLL_ELM_INVALID.
+ */
+static coll_elm_t _coll_elm_get(const char* str)
+{
+	if (str[0] == '\0' || str[1] != '\0') {
+		return COLL_ELM_INVALID;
+	}
+	return str[0];
+}
+
+/**
+ * Get collating element matching a single character.
+ *
+ * @param c Character representation of the element.
+ * @return Matching collating element.
+ */
+static coll_elm_t _coll_elm_char(int c)
+{
+	return c;
+}
+
+/**
+ * Match collating element with a beginning of a string.
+ *
+ * @param elm Collating element to match.
+ * @param str String which beginning should match the element.
+ * @return 0 if the element doesn't match, or the number of characters matched.
+ */
+static int _coll_elm_match(coll_elm_t elm, const char *str)
+{
+	return elm == *str;
+}
+
+/**
+ * Checks whether a string begins with a collating element in the given range.
+ * Ordering depends on the locale (if locales are supported).
+ *
+ * @param first First element of the range.
+ * @param second Last element of the range.
+ * @param str String to match.
+ * @return 0 if there is no match, or the number of characters matched.
+ */
+static int _coll_elm_between(coll_elm_t first, coll_elm_t second,
+    const char *str)
+{
+	return *str >= first && *str <= second;
+}
+
+/**
+ * Read a string delimited by [? and ?].
+ *
+ * @param pattern Pointer to the string to read from. Its position is moved
+ *    to the first character after the closing ].
+ * @param seq The character on the inside of brackets.
+ * @param buf Read buffer.
+ * @param buf_sz Read buffer's size. If the buffer is not large enough for
+ *    the entire string, the string is cut with no error indication.
+ * @param flags Flags modifying the behavior.
+ * @return True on success, false if the pattern is invalid.
+ */
+static bool _get_delimited(
+    const char **pattern, int seq,
+    char *buf, size_t buf_sz, int flags)
+{
+	const bool noescape = (flags & FNM_NOESCAPE) != 0;
+	const bool pathname = (flags & FNM_PATHNAME) != 0;
+
+	const char *p = *pattern;
+	assert(p[0] == '[' && p[1] == seq /* Caller should ensure this. */);
+	p += 2;
+
+	while (true) {
+		if (*p == seq && *(p + 1) == ']') {
+			/* String properly ended, return. */
+			*pattern = p + 2;
+			*buf = '\0';
+			return true;
+		}
+		if (!noescape && *p == '\\') {
+			p++;
+		}
+		if (*p == '\0') {
+			/* String not ended properly, invalid pattern. */
+			return false;
+		}
+		if (pathname && *p == '/') {
+			/* Slash in a pathname pattern is invalid. */
+			return false;
+		}
+		if (buf_sz > 1) {
+			/* Only add to the buffer if there is space. */
+			*buf = *p;
+			buf++;
+			buf_sz--;
+		}
+		p++;
+	}
+}
+
+/************** CHARACTER CLASSES ****************/
+
+#define MAX_CLASS_OR_COLL_LEN 6
+
+struct _char_class {
+	const char *name;
+	int (*func) (int);
+};
+
+/* List of supported character classes. */
+static const struct _char_class _char_classes[] = {
+	{ "alnum", isalnum },
+	{ "alpha", isalpha },
+	{ "blank", posix_isblank },
+	{ "cntrl", posix_iscntrl },
+	{ "digit", isdigit },
+	{ "graph", posix_isgraph },
+	{ "lower", islower },
+	{ "print", posix_isprint },
+	{ "punct", posix_ispunct },
+	{ "space", isspace },
+	{ "upper", isupper },
+	{ "xdigit", posix_isxdigit }
+};
+
+/**
+ * Compare function for binary search in the _char_classes array.
+ * 
+ * @param key Key of the searched element.
+ * @param elem Element of _char_classes array.
+ * @return Ordering indicator (-1 less than, 0 equal, 1 greater than).
+ */
+static int _class_compare(const void *key, const void *elem)
+{
+	const struct _char_class *class = elem;
+	return posix_strcmp((const char *) key, class->name);
+}
+
+/**
+ * Returns whether the given character belongs to the specified character class.
+ * 
+ * @param cname Name of the character class.
+ * @param c Character.
+ * @return True if the character belongs to the class, false otherwise.
+ */
+static bool _is_in_class (const char *cname, int c)
+{
+	/* Search for class in the array of supported character classes. */
+	const struct _char_class *class = posix_bsearch(cname, _char_classes,
+	    sizeof(_char_classes) / sizeof(struct _char_class),
+	    sizeof(struct _char_class), _class_compare);
+
+	if (class == NULL) {
+		/* No such class supported - treat as an empty class. */
+		return false;
+	} else {
+		/* Class matched. */
+		return class->func(c);
+	}
+}
+
+/**
+ * Tries to parse an initial part of the pattern as a character class pattern,
+ * and if successful, matches the beginning of the given string against the class.
+ * 
+ * @param pattern Pointer to the pattern to match. Must begin with a class
+ *    specifier and is repositioned to the first character after the specifier
+ *    if successful.
+ * @param str String to match.
+ * @param flags Flags modifying the behavior (see fnmatch()).
+ * @return INVALID_PATTERN if the pattern doesn't start with a valid class
+ *    specifier, 0 if the beginning of the matched string doesn't belong
+ *    to the class, or positive number of characters matched.
+ */
+static int _match_char_class(const char **pattern, const char *str, int flags)
+{
+	char class[MAX_CLASS_OR_COLL_LEN + 1];
+
+	if (!_get_delimited(pattern, ':', class, sizeof(class), flags)) {
+		return INVALID_PATTERN;
+	}
+
+	return _is_in_class(class, *str);
+}
+
+/************** END CHARACTER CLASSES ****************/
+
+/**
+ * Reads the next collating element in the pattern, taking into account
+ * locale (if supported) and flags (see fnmatch()).
+ * 
+ * @param pattern Pattern.
+ * @param flags Flags given to fnmatch().
+ * @return Collating element on success,
+ *     or COLL_ELM_INVALID if the pattern is invalid.
+ */
+static coll_elm_t _next_coll_elm(const char **pattern, int flags)
+{
+	assert(pattern != NULL);
+	assert(*pattern != NULL);
+	assert(**pattern != '\0');
+
+	const char *p = *pattern;
+	const bool noescape = (flags & FNM_NOESCAPE) != 0;
+	const bool pathname = (flags & FNM_PATHNAME) != 0;
+
+	if (*p == '[') {
+		if (*(p + 1) == '.') {
+			char buf[MAX_CLASS_OR_COLL_LEN + 1];
+			if (!_get_delimited(pattern, '.', buf, sizeof(buf), flags)) {
+				return COLL_ELM_INVALID;
+			}
+			return _coll_elm_get(buf);
+		}
+
+		if (*(p + 1) == '=') {
+			char buf[MAX_CLASS_OR_COLL_LEN + 1];
+			if (!_get_delimited(pattern, '=', buf, sizeof(buf), flags)) {
+				return COLL_ELM_INVALID;
+			}
+			return _coll_elm_get(buf);
+		}
+	}
+
+	if (!noescape && *p == '\\') {
+		p++;
+		if (*p == '\0') {
+			*pattern = p;
+			return COLL_ELM_INVALID;
+		}
+	}
+	if (pathname && *p == '/') {
+		return COLL_ELM_INVALID;
+	}
+	
+	*pattern = p + 1;
+	return _coll_elm_char(*p);
+}
+
+/**
+ * Matches the beginning of the given string against a bracket expression
+ * the pattern begins with.
+ * 
+ * @param pattern Pointer to the beginning of a bracket expression in a pattern.
+ *     On success, the pointer is moved to the first character after the
+ *     bracket expression.
+ * @param str Unmatched part of the string.
+ * @param flags Flags given to fnmatch().
+ * @return INVALID_PATTERN if the pattern is invalid, 0 if there is no match
+ *     or the number of matched characters on success.
+ */
+static int _match_bracket_expr(const char **pattern, const char *str, int flags)
+{
+	const bool pathname = (flags & FNM_PATHNAME) != 0;
+	const bool special_period = (flags & FNM_PERIOD) != 0;
+	const char *p = *pattern;
+	bool negative = false;
+	int matched = 0;
+
+	#define _matched(match) { \
+		int _match = match; \
+		if (_match < 0) { \
+			/* Invalid pattern */ \
+			return _match; \
+		} else if (matched == 0 && _match > 0) { \
+			/* First match */ \
+			matched = _match; \
+		} \
+	}
+
+	assert(*p == '[');  /* calling code should ensure this */
+	p++;
+
+	if (*str == '\0' || (pathname && *str == '/') ||
+	    (pathname && special_period && *str == '.' && *(str - 1) == '/')) {
+		/* No bracket expression matches end of string,
+		 * slash in pathname match or initial period with FNM_PERIOD
+		 * option.
+		 */
+		return 0;
+	}
+
+	if (*p == '^' || *p == '!') {
+		negative = true;
+		p++;
+	}
+
+	if (*p == ']') {
+		/* When ']' is first, treat it as a normal character. */
+		_matched(*str == ']');
+		p++;
+	}
+	
+	coll_elm_t current_elm = COLL_ELM_INVALID;
+	
+	while (*p != ']') {
+		if (*p == '-' && *(p + 1) != ']' &&
+		    current_elm != COLL_ELM_INVALID) {
+			/* Range expression. */
+			p++;
+			coll_elm_t end_elm = _next_coll_elm(&p, flags);
+			if (end_elm == COLL_ELM_INVALID) {
+				return INVALID_PATTERN;
+			}
+			_matched(_coll_elm_between(current_elm, end_elm, str));
+			continue;
+		}
+	
+		if (*p == '[' && *(p + 1) == ':') {
+			current_elm = COLL_ELM_INVALID;
+			_matched(_match_char_class(&p, str, flags));
+			continue;
+		}
+		
+		current_elm = _next_coll_elm(&p, flags);
+		if (current_elm == COLL_ELM_INVALID) {
+			return INVALID_PATTERN;
+		}
+		_matched(_coll_elm_match(current_elm, str));
+	}
+
+	/* No error occured - update pattern pointer. */
+	*pattern = p + 1;
+
+	if (matched == 0) {
+		/* No match found */
+		return negative;
+	} else {
+		/* Matched 'match' characters. */
+		return negative ? 0 : matched;
+	}
+
+	#undef _matched
+}
+
+/**
+ * Matches a portion of the pattern containing no asterisks (*) against
+ * the given string.
+ * 
+ * @param pattern Pointer to the unmatched portion of the pattern.
+ *     On success, the pointer is moved to the first asterisk, or to the
+ *     terminating nul character, whichever occurs first.
+ * @param string Pointer to the input string. On success, the pointer is moved
+ *     to the first character that wasn't explicitly matched.
+ * @param flags Flags given to fnmatch().
+ * @return True if the entire subpattern matched. False otherwise.
+ */
+static bool _partial_match(const char **pattern, const char **string, int flags)
+{
+	/* Only a single *-delimited subpattern is matched here.
+	 * So in this function, '*' is understood as the end of pattern.
+	 */
+
+	const bool pathname = (flags & FNM_PATHNAME) != 0;
+	const bool special_period = (flags & FNM_PERIOD) != 0;
+	const bool noescape = (flags & FNM_NOESCAPE) != 0;
+	const bool leading_dir = (flags & FNM_LEADING_DIR) != 0;
+
+	const char *s = *string;
+	const char *p = *pattern;
+
+	while (*p != '*') {
+		/* Bracket expression. */
+		if (*p == '[') {
+			int matched = _match_bracket_expr(&p, s, flags);
+			if (matched == 0) {
+				/* Doesn't match. */
+				return false;
+			}
+			if (matched != INVALID_PATTERN) {
+				s += matched;
+				continue;
+			}
+
+			assert(matched == INVALID_PATTERN);
+			/* Fall through to match [ as an ordinary character. */
+		}
+
+		/* Wildcard match. */
+		if (*p == '?') {
+			if (*s == '\0') {
+				/* No character to match. */
+				return false;
+			}
+			if (pathname && *s == '/') {
+				/* Slash must be matched explicitly. */
+				return false;
+			}
+			if (special_period && pathname &&
+			    *s == '.' && *(s - 1) == '/') {
+				/* Initial period must be matched explicitly. */
+				return false;
+			}
+			
+			/* None of the above, match anything else. */
+			p++;
+			s++;
+			continue;
+		}
+
+		if (!noescape && *p == '\\') {
+			/* Escaped character. */
+			p++;
+		}
+
+		if (*p == '\0') {
+			/* End of pattern, must match end of string or
+			 * an end of subdirectory name (optional).
+			 */
+
+			if (*s == '\0' || (leading_dir && *s == '/')) {
+				break;
+			}
+
+			return false;
+		}
+
+		if (*p == *s) {
+			/* Exact match. */
+			p++;
+			s++;
+			continue;
+		}
+
+		/* Nothing matched. */
+		return false;
+	}
+
+	/* Entire sub-pattern matched. */
+	
+	/* postconditions */
+	assert(*p == '\0' || *p == '*');
+	assert(*p != '\0' || *s == '\0' || (leading_dir && *s == '/'));
+	
+	*pattern = p;
+	*string = s;
+	return true;
+}
+
+/**
+ * Match string against a pattern.
+ * 
+ * @param pattern Pattern.
+ * @param string String to match.
+ * @param flags Flags given to fnmatch().
+ * @return True if the string matched the pattern, false otherwise.
+ */
+static bool _full_match(const char *pattern, const char *string, int flags)
+{
+	const bool pathname = (flags & FNM_PATHNAME) != 0;
+	const bool special_period = (flags & FNM_PERIOD) != 0;
+	const bool leading_dir = (flags & FNM_LEADING_DIR) != 0;
+
+	if (special_period && *string == '.') {
+		/* Initial dot must be matched by an explicit dot in pattern. */
+		if (*pattern != '.') {
+			return false;
+		}
+		pattern++;
+		string++;
+	}
+
+	if (*pattern != '*') {
+		if (!_partial_match(&pattern, &string, flags)) {
+			/* The initial match must succeed. */
+			return false;
+		}
+	}
+
+	while (*pattern != '\0') {
+		assert(*pattern == '*');
+		pattern++;
+
+		bool matched = false;
+
+		const char *end;
+		if (pathname && special_period &&
+		    *string == '.' && *(string - 1) == '/') {
+			end = string;
+		} else {
+			end = gnu_strchrnul(string, pathname ? '/' : '\0');
+		}
+
+		/* Try to match every possible offset. */
+		while (string <= end) {
+			if (_partial_match(&pattern, &string, flags)) {
+				matched = true;
+				break;
+			}
+			string++;
+		}
+
+		if (matched) {
+			continue;
+		}
+
+		return false;
+	}
+
+	return *string == '\0' || (leading_dir && *string == '/');
+}
+
+/**
+ * Transform the entire string to lowercase.
+ * 
+ * @param s Input string.
+ * @return Newly allocated copy of the input string with all uppercase
+ *     characters folded to their lowercase variants.
+ */
+static char *_casefold(const char *s)
+{
+	assert(s != NULL);
+	char *result = posix_strdup(s);
+	for (char *i = result; *i != '\0'; ++i) {
+		*i = tolower(*i);
+	}
+	return result;
+}
+
+/**
+ * Filename pattern matching.
+ *
+ * @param pattern Pattern to match the string against.
+ * @param string Matched string.
+ * @param flags Flags altering the matching of special characters
+ *     (mainly for dot and slash).
+ * @return Zero if the string matches the pattern, FNM_NOMATCH otherwise.
+ */
+int posix_fnmatch(const char *pattern, const char *string, int flags)
+{
+	assert(pattern != NULL);
+	assert(string != NULL);
+
+	// TODO: don't fold everything in advance, but only when needed
+
+	if ((flags & FNM_CASEFOLD) != 0) {
+		/* Just fold the entire pattern and string. */
+		pattern = _casefold(pattern);
+		string = _casefold(string);
+	}
+
+	bool result = _full_match(pattern, string, flags);
+
+	if ((flags & FNM_CASEFOLD) != 0) {
+		if (pattern) {
+			free((char *) pattern);
+		}
+		if (string) {
+			free((char *) string);
+		}
+	}
+
+	return result ? 0 : FNM_NOMATCH;
+}
+
+// FIXME: put the testcases to the app/tester after fnmatch is included into libc
+
+#if 0
+
+#include <stdio.h>
+
+void __posix_fnmatch_test()
+{
+	int fail = 0;
+
+	#undef assert
+	#define assert(x) { if (x) printf("SUCCESS: "#x"\n"); else { printf("FAILED: "#x"\n"); fail++; } }
+	#define match(s1, s2, flags) assert(posix_fnmatch(s1, s2, flags) == 0)
+	#define nomatch(s1, s2, flags) assert(posix_fnmatch(s1, s2, flags) == FNM_NOMATCH)
+
+	assert(FNM_PATHNAME == FNM_FILE_NAME);
+	match("", "", 0);
+	match("*", "hello", 0);
+	match("hello", "hello", 0);
+	match("hello*", "hello", 0);
+	nomatch("hello?", "hello", 0);
+	match("*hello", "prdel hello", 0);
+	match("he[sl]lo", "hello", 0);
+	match("he[sl]lo", "heslo", 0);
+	nomatch("he[sl]lo", "heblo", 0);
+	nomatch("he[^sl]lo", "hello", 0);
+	nomatch("he[^sl]lo", "heslo", 0);
+	match("he[^sl]lo", "heblo", 0);
+	nomatch("he[!sl]lo", "hello", 0);
+	nomatch("he[!sl]lo", "heslo", 0);
+	match("he[!sl]lo", "heblo", 0);
+	match("al*[c-t]a*vis*ta", "alheimer talir jehovista", 0);
+	match("al*[c-t]a*vis*ta", "alfons had jehovista", 0);
+	match("[a-ce-z]", "a", 0);
+	match("[a-ce-z]", "c", 0);
+	nomatch("[a-ce-z]", "d", 0);
+	match("[a-ce-z]", "e", 0);
+	match("[a-ce-z]", "z", 0);
+	nomatch("[^a-ce-z]", "a", 0);
+	nomatch("[^a-ce-z]", "c", 0);
+	match("[^a-ce-z]", "d", 0);
+	nomatch("[^a-ce-z]", "e", 0);
+	nomatch("[^a-ce-z]", "z", 0);
+	match("helen??", "helenos", 0);
+	match("****booo****", "booo", 0);
+	
+	match("hello[[:space:]]world", "hello world", 0);
+	nomatch("hello[[:alpha:]]world", "hello world", 0);
+	
+	match("/hoooo*", "/hooooooo/hooo", 0);
+	nomatch("/hoooo*", "/hooooooo/hooo", FNM_PATHNAME);
+	nomatch("/hoooo*/", "/hooooooo/hooo", FNM_PATHNAME);
+	match("/hoooo*/*", "/hooooooo/hooo", FNM_PATHNAME);
+	match("/hoooo*/hooo", "/hooooooo/hooo", FNM_PATHNAME);
+	match("/hoooo*", "/hooooooo/hooo", FNM_PATHNAME | FNM_LEADING_DIR);
+	nomatch("/hoooo*/", "/hooooooo/hooo", FNM_PATHNAME | FNM_LEADING_DIR);
+	nomatch("/hoooo", "/hooooooo/hooo", FNM_LEADING_DIR);
+	match("/hooooooo", "/hooooooo/hooo", FNM_LEADING_DIR);
+	
+	match("*", "hell", 0);
+	match("*?", "hell", 0);
+	match("?*?", "hell", 0);
+	match("?*??", "hell", 0);
+	match("??*??", "hell", 0);
+	nomatch("???*??", "hell", 0);
+	
+	nomatch("", "hell", 0);
+	nomatch("?", "hell", 0);
+	nomatch("??", "hell", 0);
+	nomatch("???", "hell", 0);
+	match("????", "hell", 0);
+	
+	match("*", "h.ello", FNM_PERIOD);
+	match("*", "h.ello", FNM_PATHNAME | FNM_PERIOD);
+	nomatch("*", ".hello", FNM_PERIOD);
+	match("h?ello", "h.ello", FNM_PERIOD);
+	nomatch("?hello", ".hello", FNM_PERIOD);
+	match("/home/user/.*", "/home/user/.hello", FNM_PATHNAME | FNM_PERIOD);
+	match("/home/user/*", "/home/user/.hello", FNM_PERIOD);
+	nomatch("/home/user/*", "/home/user/.hello", FNM_PATHNAME | FNM_PERIOD);
+
+	nomatch("HeLlO", "hello", 0);
+	match("HeLlO", "hello", FNM_CASEFOLD);
+
+	printf("Failed: %d\n", fail);
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/posix/source/getopt.c
===================================================================
--- uspace/lib/posix/source/getopt.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/getopt.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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 libposix
+ * @{
+ */
+/** @file Command line argument parsing.
+ */
+#define LIBPOSIX_INTERNAL
+
+#include "internal/common.h"
+#include "libc/getopt.h"
+#include "posix/getopt.h"
+
+
+int posix_getopt_long(int argc, char * const argv[],
+    const char *opt_string, const struct option *long_opts, int *long_index)
+{
+	int rc = getopt_long(argc, argv, opt_string, long_opts, long_index);
+	posix_optarg = (char *) optarg;
+	return rc;
+}
+
+int posix_getopt(int argc, char * const argv[], const char *opt_string)
+{
+	int rc = getopt(argc, argv, opt_string);
+	posix_optarg = (char *) optarg;
+	return rc;
+}
Index: uspace/lib/posix/source/internal/common.h
===================================================================
--- uspace/lib/posix/source/internal/common.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/internal/common.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Helper definitions common for all libposix files.
+ */
+
+#ifndef LIBPOSIX_COMMON_H_
+#define LIBPOSIX_COMMON_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define not_implemented() (fprintf(stderr, \
+    "Function %s() in file %s at line %d is not implemented\n", \
+    __func__, __FILE__, __LINE__), abort())
+
+/* A little helper macro to avoid typing this over and over. */
+#define errnify(func, ...) ({ \
+	int rc = func(__VA_ARGS__); \
+	if (rc < 0) { \
+		errno = -rc; \
+		rc = -1; \
+	} \
+	rc; \
+})
+
+#endif /* LIBPOSIX_COMMON_H_ */
+
+/** @}
+ */
Index: uspace/lib/posix/source/locale.c
===================================================================
--- uspace/lib/posix/source/locale.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/locale.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Locale-specific definitions.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "internal/common.h"
+#include "posix/locale.h"
+
+#include "posix/errno.h"
+#include "posix/limits.h"
+#include "posix/string.h"
+
+/* Just a very basic dummy implementation.
+ * This should allow code using locales to work properly, but doesn't provide
+ * any localization functionality.
+ * Should be extended/rewritten when or if HelenOS supports locales natively.
+ */
+
+struct __posix_locale {
+	int _dummy;
+};
+
+const struct posix_lconv C_LOCALE = {
+	.currency_symbol = (char *) "",
+	.decimal_point = (char *) ".",
+	.frac_digits = CHAR_MAX,
+	.grouping = (char *) "",
+	.int_curr_symbol = (char *) "",
+	.int_frac_digits = CHAR_MAX,
+	.int_n_cs_precedes = CHAR_MAX,
+	.int_n_sep_by_space = CHAR_MAX,
+	.int_n_sign_posn = CHAR_MAX,
+	.int_p_cs_precedes = CHAR_MAX,
+	.int_p_sep_by_space = CHAR_MAX,
+	.int_p_sign_posn = CHAR_MAX,
+	.mon_decimal_point = (char *) "",
+	.mon_grouping = (char *) "",
+	.mon_thousands_sep = (char *) "",
+	.negative_sign = (char *) "",
+	.n_cs_precedes = CHAR_MAX,
+	.n_sep_by_space = CHAR_MAX,
+	.n_sign_posn = CHAR_MAX,
+	.positive_sign = (char *) "",
+	.p_cs_precedes = CHAR_MAX,
+	.p_sep_by_space = CHAR_MAX,
+	.p_sign_posn = CHAR_MAX,
+	.thousands_sep = (char *) ""
+};
+
+/**
+ * Set program locale.
+ * 
+ * @param category What category to set.
+ * @param locale Locale name.
+ * @return Original locale name on success, NULL on failure.
+ */
+char *posix_setlocale(int category, const char *locale)
+{
+	// TODO
+	if (locale == NULL || *locale == '\0' ||
+	    posix_strcmp(locale, "C") == 0) {
+		return (char *) "C";
+	}
+	return NULL;
+}
+
+/**
+ * Return locale-specific information.
+ * 
+ * @return Information about the current locale.
+ */
+struct posix_lconv *posix_localeconv(void)
+{
+	// TODO
+	return (struct posix_lconv *) &C_LOCALE;
+}
+
+/**
+ * Duplicate locale object.
+ * 
+ * @param locobj Object to duplicate.
+ * @return Duplicated object.
+ */
+posix_locale_t posix_duplocale(posix_locale_t locobj)
+{
+	if (locobj == NULL) {
+		errno = EINVAL;
+		return NULL;
+	}
+	posix_locale_t copy = malloc(sizeof(struct __posix_locale));
+	if (copy == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	memcpy(copy, locobj, sizeof(struct __posix_locale));
+	return copy;
+}
+
+/**
+ * Free locale object.
+ * 
+ * @param locobj Object to free.
+ */
+void posix_freelocale(posix_locale_t locobj)
+{
+	if (locobj) {
+		free(locobj);
+	}
+}
+
+/**
+ * Create or modify a locale object.
+ * 
+ * @param category_mask Mask of categories to be set or modified.
+ * @param locale Locale to be used.
+ * @param base Object to modify. 0 if new object is to be created.
+ * @return The new/modified locale object.
+ */
+posix_locale_t posix_newlocale(int category_mask, const char *locale,
+    posix_locale_t base)
+{
+	if (locale == NULL ||
+	    (category_mask & LC_ALL_MASK) != category_mask) {
+		errno = EINVAL;
+		return NULL;
+	}
+	// TODO
+	posix_locale_t new = malloc(sizeof(struct __posix_locale));
+	if (new == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	if (base != NULL) {
+		posix_freelocale(base);
+	}
+	return new;
+}
+
+/**
+ * Set locale for the current thread.
+ * 
+ * @param newloc Locale to use.
+ * @return The previously set locale or LC_GLOBAL_LOCALE
+ */
+posix_locale_t posix_uselocale(posix_locale_t newloc)
+{
+	// TODO
+	return LC_GLOBAL_LOCALE;
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/math.c
===================================================================
--- uspace/lib/posix/source/math.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/math.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Mathematical operations.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "internal/common.h"
+#include "posix/math.h"
+
+/**
+ * 
+ * @param x
+ * @param exp
+ * @return
+ */
+double posix_ldexp(double x, int exp)
+{
+	// TODO: low priority, just a compile-time dependency of binutils
+	not_implemented();
+}
+
+/**
+ * 
+ * @param num
+ * @param exp
+ * @return
+ */
+double posix_frexp(double num, int *exp)
+{
+	// TODO: low priority, just a compile-time dependency of binutils
+	not_implemented();
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/pwd.c
===================================================================
--- uspace/lib/posix/source/pwd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/pwd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Password handling.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "posix/stdbool.h"
+#include "posix/pwd.h"
+#include "posix/string.h"
+#include "posix/errno.h"
+#include "posix/assert.h"
+
+static bool entry_read = false;
+
+/* dummy user account */
+static const struct posix_passwd dummy_pwd = {
+	.pw_name = (char *) "user",
+	.pw_uid = 0,
+	.pw_gid = 0,
+	.pw_dir = (char *) "/",
+	.pw_shell = (char *) "/app/bdsh"
+};
+
+/**
+ * Retrieve next broken-down entry from the user database.
+ *
+ * Since HelenOS doesn't have user accounts, this always returns
+ * the same made-up entry.
+ *
+ * @return Next user database entry or NULL if not possible. Since HelenOS
+ *     doesn't have user accounts, this always returns the same made-up entry.
+ */
+struct posix_passwd *posix_getpwent(void)
+{
+	if (entry_read) {
+		return NULL;
+	}
+
+	entry_read = true;
+	return (struct posix_passwd *) &dummy_pwd;
+}
+
+/**
+ * Rewind the user list.
+ */
+void posix_setpwent(void)
+{
+	entry_read = false;
+}
+
+/**
+ * Ends enumerating and releases all resources. (Noop)
+ */
+void posix_endpwent(void)
+{
+	/* noop */
+}
+
+/**
+ * Find an entry by name.
+ *
+ * @param name Name of the entry.
+ * @return Either found entry or NULL if no such entry exists.
+ */
+struct posix_passwd *posix_getpwnam(const char *name)
+{
+	assert(name != NULL);
+
+	if (posix_strcmp(name, "user") != 0) {
+		return NULL;
+	}
+
+	return (struct posix_passwd *) &dummy_pwd;
+}
+
+/**
+ * Find an entry by name, thread safely.
+ *
+ * @param name Name of the entry.
+ * @param pwd Original structure.
+ * @param buffer Buffer for the strings referenced from the result structure.
+ * @param bufsize Length of the buffer.
+ * @param result Where to store updated structure.
+ * @return Zero on success (either found or not found, but without an error),
+ *     non-zero error number if error occured.
+ */
+int posix_getpwnam_r(const char *name, struct posix_passwd *pwd,
+    char *buffer, size_t bufsize, struct posix_passwd **result)
+{
+	assert(name != NULL);
+	assert(pwd != NULL);
+	assert(buffer != NULL);
+	assert(result != NULL);
+	
+	if (posix_strcmp(name, "user") != 0) {
+		*result = NULL;
+		return 0;
+	}
+	
+	return posix_getpwuid_r(0, pwd, buffer, bufsize, result);
+}
+
+/**
+ * Find an entry by UID.
+ *
+ * @param uid UID of the entry.
+ * @return Either found entry or NULL if no such entry exists.
+ */
+struct posix_passwd *posix_getpwuid(posix_uid_t uid)
+{
+	if (uid != 0) {
+		return NULL;
+	}
+
+	return (struct posix_passwd *) &dummy_pwd;
+}
+
+/**
+ * Find an entry by UID, thread safely.
+ *
+ * @param uid UID of the entry.
+ * @param pwd Original structure.
+ * @param buffer Buffer for the strings referenced from the result structure.
+ * @param bufsize Length of the buffer.
+ * @param result Where to store updated structure.
+ * @return Zero on success (either found or not found, but without an error),
+ *     non-zero error number if error occured.
+ */
+int posix_getpwuid_r(posix_uid_t uid, struct posix_passwd *pwd,
+    char *buffer, size_t bufsize, struct posix_passwd **result)
+{
+	assert(pwd != NULL);
+	assert(buffer != NULL);
+	assert(result != NULL);
+	
+	static const char bf[] = { 'u', 's', 'e', 'r', '\0',
+	    '/', '\0', 'b', 'd', 's', 'h', '\0' };
+	
+	if (uid != 0) {
+		*result = NULL;
+		return 0;
+	}
+	if (bufsize < sizeof(bf)) {
+		*result = NULL;
+		return ERANGE;
+	}
+
+	memcpy(buffer, bf, sizeof(bf));
+
+	pwd->pw_name = (char *) bf;
+	pwd->pw_uid = 0;
+	pwd->pw_gid = 0;
+	pwd->pw_dir = (char *) bf + 5;
+	pwd->pw_shell = (char *) bf + 7;
+	*result = (struct posix_passwd *) pwd;
+
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/signal.c
===================================================================
--- uspace/lib/posix/source/signal.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/signal.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,566 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Signal handling.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "posix/signal.h"
+#include "internal/common.h"
+#include "posix/limits.h"
+#include "posix/stdlib.h"
+#include "posix/string.h"
+#include "posix/errno.h"
+
+#include "libc/fibril_synch.h"
+#include "libc/task.h"
+
+/* This file implements a fairly dumb and incomplete "simulation" of
+ * POSIX signals. Since HelenOS doesn't support signals and mostly doesn't
+ * have any equivalent functionality, most of the signals are useless. The
+ * main purpose of this implementation is thus to help port applications using
+ * signals with minimal modification, but if the application uses signals for
+ * anything non-trivial, it's quite probable it won't work properly even if
+ * it builds without problems.
+ */
+
+/* Used to serialize signal handling. */
+static FIBRIL_MUTEX_INITIALIZE(_signal_mutex);
+
+static LIST_INITIALIZE(_signal_queue);
+
+static posix_sigset_t _signal_mask = 0;
+
+#define DEFAULT_HANDLER { .sa_handler = SIG_DFL, \
+    .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL }
+
+/* Actions associated with each signal number. */
+static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = {
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
+	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER
+};
+
+/**
+ * Default signal handler. Executes the default action for each signal,
+ * as reasonable within HelenOS.
+ *
+ * @param signo Signal number.
+ */
+void __posix_default_signal_handler(int signo)
+{
+	switch (signo) {
+	case SIGABRT:
+		abort();
+	case SIGQUIT:
+		fprintf(stderr, "Quit signal raised. Exiting.\n");
+		exit(EXIT_FAILURE);
+	case SIGINT:
+		fprintf(stderr, "Interrupt signal caught. Exiting.\n");
+		exit(EXIT_FAILURE);
+	case SIGTERM:
+		fprintf(stderr, "Termination signal caught. Exiting.\n");
+		exit(EXIT_FAILURE);
+	case SIGSTOP:
+		fprintf(stderr, "Stop signal caught, but unsupported. Ignoring.\n");
+		break;
+	case SIGKILL:
+		/* This will only occur when raise or similar is called. */
+		/* Commit suicide. */
+		task_kill(task_get_id());
+		
+		/* Should not be reached. */
+		abort();
+	case SIGFPE:
+	case SIGBUS:
+	case SIGILL:
+	case SIGSEGV:
+		posix_psignal(signo, "Hardware exception raised by user code");
+		abort();
+	case SIGSYS:
+	case SIGXCPU:
+	case SIGXFSZ:
+	case SIGTRAP:
+	case SIGHUP:
+	case SIGPIPE:
+	case SIGPOLL:
+	case SIGURG:
+	case SIGTSTP:
+	case SIGTTIN:
+	case SIGTTOU:
+		posix_psignal(signo, "Unsupported signal caught");
+		abort();
+	case SIGCHLD:
+	case SIGUSR1:
+	case SIGUSR2:
+	case SIGALRM:
+	case SIGVTALRM:
+	case SIGPROF:
+	case SIGCONT:
+		/* ignored */
+		break;
+	}
+}
+
+/**
+ * Just an empty function to get an unique pointer value for comparison.
+ *
+ * @param signo Signal number.
+ */
+void __posix_hold_signal_handler(int signo)
+{
+	/* Nothing */
+}
+
+/**
+ * Empty function to be used as ignoring handler.
+ * 
+ * @param signo Signal number.
+ */
+void __posix_ignore_signal_handler(int signo)
+{
+	/* Nothing */
+}
+
+/**
+ * Clear the signal set.
+ * 
+ * @param set Pointer to the signal set.
+ * @return Always returns zero.
+ */
+int posix_sigemptyset(posix_sigset_t *set)
+{
+	assert(set != NULL);
+
+	*set = 0;
+	return 0;
+}
+
+/**
+ * Fill the signal set (i.e. add all signals).
+ * 
+ * @param set Pointer to the signal set.
+ * @return Always returns zero.
+ */
+int posix_sigfillset(posix_sigset_t *set)
+{
+	assert(set != NULL);
+
+	*set = UINT32_MAX;
+	return 0;
+}
+
+/**
+ * Add a signal to the set.
+ * 
+ * @param set Pointer to the signal set.
+ * @param signo Signal number to add.
+ * @return Always returns zero.
+ */
+int posix_sigaddset(posix_sigset_t *set, int signo)
+{
+	assert(set != NULL);
+
+	*set |= (1 << signo);
+	return 0;
+}
+
+/**
+ * Delete a signal from the set.
+ * 
+ * @param set Pointer to the signal set.
+ * @param signo Signal number to remove.
+ * @return Always returns zero.
+ */
+int posix_sigdelset(posix_sigset_t *set, int signo)
+{
+	assert(set != NULL);
+
+	*set &= ~(1 << signo);
+	return 0;
+}
+
+/**
+ * Inclusion test for a signal set.
+ * 
+ * @param set Pointer to the signal set.
+ * @param signo Signal number to query.
+ * @return 1 if the signal is in the set, 0 otherwise.
+ */
+int posix_sigismember(const posix_sigset_t *set, int signo)
+{
+	assert(set != NULL);
+	
+	return (*set & (1 << signo)) != 0;
+}
+
+/**
+ * Unsafe variant of the sigaction() function.
+ * Doesn't do any checking of its arguments and
+ * does not deal with thread-safety.
+ * 
+ * @param sig
+ * @param act
+ * @param oact
+ */
+static void _sigaction_unsafe(int sig, const struct posix_sigaction *restrict act,
+    struct posix_sigaction *restrict oact)
+{
+	if (oact != NULL) {
+		memcpy(oact, &_signal_actions[sig],
+		    sizeof(struct posix_sigaction));
+	}
+
+	if (act != NULL) {
+		memcpy(&_signal_actions[sig], act,
+		    sizeof(struct posix_sigaction));
+	}
+}
+
+/**
+ * Sets a new action for the given signal number.
+ * 
+ * @param sig Signal number to set action for.
+ * @param act If not NULL, contents of this structure are
+ *     used as the new action for the signal.
+ * @param oact If not NULL, the original action associated with the signal
+ *     is stored in the structure pointer to. 
+ * @return -1 with errno set on failure, 0 on success.
+ */
+int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
+    struct posix_sigaction *restrict oact)
+{
+	if (sig > _TOP_SIGNAL || (act != NULL &&
+	    (sig == SIGKILL || sig == SIGSTOP))) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (sig > _TOP_CATCHABLE_SIGNAL) {
+		posix_psignal(sig,
+		    "WARNING: registering handler for a partially"
+		    " or fully unsupported signal. This handler may only be"
+		    " invoked by the raise() function, which may not be what"
+		    " the application developer intended");
+	}
+
+	fibril_mutex_lock(&_signal_mutex);
+	_sigaction_unsafe(sig, act, oact);
+	fibril_mutex_unlock(&_signal_mutex);
+
+	return 0;
+}
+
+/**
+ * Sets a new handler for the given signal number.
+ * 
+ * @param sig Signal number to set handler for.
+ * @param func Handler function.
+ * @return SIG_ERR on failure, original handler on success.
+ */
+void (*posix_signal(int sig, void (*func)(int)))(int)
+{
+	struct posix_sigaction new = {
+		.sa_handler = func,
+		.sa_mask = 0,
+		.sa_flags = 0,
+		.sa_sigaction = NULL
+	};
+	struct posix_sigaction old;
+	if (posix_sigaction(sig, func == NULL ? NULL : &new, &old) == 0) {
+		return old.sa_handler;
+	} else {
+		return SIG_ERR;
+	}
+}
+
+typedef struct {
+	link_t link;
+	int signo;
+	posix_siginfo_t siginfo;
+} signal_queue_item;
+
+/**
+ * Queue blocked signal.
+ *
+ * @param signo Signal number.
+ * @param siginfo Additional information about the signal.
+ */
+static void _queue_signal(int signo, posix_siginfo_t *siginfo)
+{
+	assert(signo >= 0 && signo <= _TOP_SIGNAL);
+	assert(siginfo != NULL);
+	
+	signal_queue_item *item = malloc(sizeof(signal_queue_item));
+	link_initialize(&(item->link));
+	item->signo = signo;
+	memcpy(&item->siginfo, siginfo, sizeof(posix_siginfo_t));
+	list_append(&(item->link), &_signal_queue);
+}
+
+
+/**
+ * Executes an action associated with the given signal.
+ *
+ * @param signo Signal number.
+ * @param siginfo Additional information about the circumstances of this raise.
+ * @return 0 if the action has been successfully executed. -1 if the signal is
+ *     blocked.
+ */
+static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
+{
+	assert(signo >= 0 && signo <= _TOP_SIGNAL);
+	assert(siginfo != NULL);
+
+	fibril_mutex_lock(&_signal_mutex);
+
+	struct posix_sigaction action = _signal_actions[signo];
+
+	if (posix_sigismember(&_signal_mask, signo) ||
+	    action.sa_handler == SIG_HOLD) {
+		_queue_signal(signo, siginfo);
+		fibril_mutex_unlock(&_signal_mutex);
+		return -1;
+	}
+
+	/* Modifying signal mask is unnecessary,
+	 * signal handling is serialized.
+	 */
+
+	if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) {
+		_signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER;
+	}
+
+	if (action.sa_flags & SA_SIGINFO) {
+		assert(action.sa_sigaction != NULL);
+		action.sa_sigaction(signo, siginfo, NULL);
+	} else {
+		assert(action.sa_handler != NULL);
+		action.sa_handler(signo);
+	}
+
+	fibril_mutex_unlock(&_signal_mutex);
+
+	return 0;
+}
+
+/**
+ * Raise all unblocked previously queued signals.
+ */
+static void _dequeue_unblocked_signals()
+{
+	link_t *iterator = _signal_queue.head.next;
+	link_t *next;
+	
+	while (iterator != &(_signal_queue).head) {
+		next = iterator->next;
+		
+		signal_queue_item *item =
+		    list_get_instance(iterator, signal_queue_item, link);
+		
+		if (!posix_sigismember(&_signal_mask, item->signo) &&
+		    _signal_actions[item->signo].sa_handler != SIG_HOLD) {
+			list_remove(&(item->link));
+			_raise_sigaction(item->signo, &(item->siginfo));
+			free(item);
+		}
+		
+		iterator = next;
+	}
+}
+
+/**
+ * Raise a signal for the calling process.
+ * 
+ * @param sig Signal number.
+ * @return -1 with errno set on failure, 0 on success.
+ */
+int posix_raise(int sig)
+{
+	if (sig >= 0 && sig <= _TOP_SIGNAL) {
+		posix_siginfo_t siginfo = {
+			.si_signo = sig,
+			.si_code = SI_USER
+		};
+		return _raise_sigaction(sig, &siginfo);
+	} else {
+		errno = EINVAL;
+		return -1;
+	}
+}
+
+/**
+ * Raises a signal for a selected process.
+ * 
+ * @param pid PID of the process for which the signal shall be raised.
+ * @param signo Signal to raise.
+ * @return -1 with errno set on failure (possible errors include unsupported
+ *     action, invalid signal number, lack of permissions, etc.), 0 on success.
+ */
+int posix_kill(posix_pid_t pid, int signo)
+{
+	if (pid < 1) {
+		// TODO
+		errno = ENOTSUP;
+		return -1;
+	}
+
+	if (signo > _TOP_SIGNAL) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (pid == (posix_pid_t) task_get_id()) {
+		return posix_raise(signo);
+	}
+
+	switch (signo) {
+	case SIGKILL:
+		task_kill(pid);
+		break;
+	default:
+		/* Nothing else supported yet. */
+		errno = ENOTSUP;
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * Send a signal to a process group. Always fails at the moment because of
+ * lack of this functionality in HelenOS.
+ * 
+ * @param pid PID of the process group.
+ * @param sig Signal number.
+ * @return -1 on failure, 0 on success (see kill()).
+ */
+int posix_killpg(posix_pid_t pid, int sig)
+{
+	assert(pid > 1);
+	return posix_kill(-pid, sig);
+}
+
+/**
+ * Outputs information about the signal to the standard error stream.
+ * 
+ * @param pinfo SigInfo struct to write.
+ * @param message String to output alongside human-readable signal description.
+ */
+void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message)
+{
+	assert(pinfo != NULL);
+	posix_psignal(pinfo->si_signo, message);
+	// TODO: print si_code
+}
+
+/**
+ * Outputs information about the signal to the standard error stream.
+ * 
+ * @param signum Signal number.
+ * @param message String to output alongside human-readable signal description.
+ */
+void posix_psignal(int signum, const char *message)
+{
+	char *sigmsg = posix_strsignal(signum);
+	if (message == NULL || *message == '\0') {
+		fprintf(stderr, "%s\n", sigmsg);
+	} else {
+		fprintf(stderr, "%s: %s\n", message, sigmsg);
+	}
+}
+
+/**
+ * Manipulate the signal mask of the calling thread.
+ * 
+ * @param how What to do with the mask.
+ * @param set Signal set to work with.
+ * @param oset If not NULL, the original signal mask is coppied here.
+ * @return 0 success, errorcode on failure.
+ */
+int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
+    posix_sigset_t *restrict oset)
+{
+	fibril_mutex_lock(&_signal_mutex);
+
+	if (oset != NULL) {
+		*oset = _signal_mask;
+	}
+	if (set != NULL) {
+		switch (how) {
+		case SIG_BLOCK:
+			_signal_mask |= *set;
+			break;
+		case SIG_UNBLOCK:
+			_signal_mask &= ~*set;
+			break;
+		case SIG_SETMASK:
+			_signal_mask = *set;
+			break;
+		default:
+			fibril_mutex_unlock(&_signal_mutex);
+			return EINVAL;
+		}
+	}
+	
+	_dequeue_unblocked_signals();
+
+	fibril_mutex_unlock(&_signal_mutex);
+
+	return 0;
+}
+
+/**
+ * Manipulate the signal mask of the process.
+ * 
+ * @param how What to do with the mask.
+ * @param set Signal set to work with.
+ * @param oset If not NULL, the original signal mask is coppied here.
+ * @return 0 on success, -1 with errno set on failure.
+ */
+int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
+    posix_sigset_t *restrict oset)
+{
+	int result = posix_thread_sigmask(how, set, oset);
+	if (result != 0) {
+		errno = result;
+		return -1;
+	}
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/stdio.c
===================================================================
--- uspace/lib/posix/source/stdio.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/stdio.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,808 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Standard buffered input/output.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+/* Has to be first. */
+#include "posix/stdbool.h"
+
+#include "internal/common.h"
+#include "posix/stdio.h"
+
+#include "posix/assert.h"
+#include "posix/errno.h"
+#include "posix/stdlib.h"
+#include "posix/string.h"
+#include "posix/sys/types.h"
+#include "posix/unistd.h"
+
+#include "libc/stdio.h"
+#include "libc/io/printf_core.h"
+#include "libc/str.h"
+#include "libc/malloc.h"
+#include "libc/adt/list.h"
+#include "libc/sys/stat.h"
+
+
+/* not the best of solutions, but freopen and ungetc will eventually
+ * need to be implemented in libc anyway
+ */
+#include "../../c/generic/private/stdio.h"
+
+/** Clears the stream's error and end-of-file indicators.
+ *
+ * @param stream Stream whose indicators shall be cleared.
+ */
+void posix_clearerr(FILE *stream)
+{
+	stream->error = 0;
+	stream->eof = 0;
+}
+
+/**
+ * Generate a pathname for the controlling terminal.
+ *
+ * @param s Allocated buffer to which the pathname shall be put.
+ * @return Either s or static location filled with the requested pathname.
+ */
+char *posix_ctermid(char *s)
+{
+	/* Currently always returns an error value (empty string). */
+	// TODO: return a real terminal path
+
+	static char dummy_path[L_ctermid] = {'\0'};
+
+	if (s == NULL) {
+		return dummy_path;
+	}
+
+	s[0] = '\0';
+	return s;
+}
+
+/**
+ * Put a string on the stream.
+ * 
+ * @param s String to be written.
+ * @param stream Output stream.
+ * @return Non-negative on success, EOF on failure.
+ */
+int posix_fputs(const char *restrict s, FILE *restrict stream)
+{
+	int rc = fputs(s, stream);
+	if (rc == 0) {
+		return EOF;
+	} else {
+		return 0;
+	}
+}
+
+/**
+ * Push byte back into input stream.
+ * 
+ * @param c Byte to be pushed back.
+ * @param stream Stream to where the byte shall be pushed.
+ * @return Provided byte on success or EOF if not possible.
+ */
+int posix_ungetc(int c, FILE *stream)
+{
+	uint8_t b = (uint8_t) c;
+
+	bool can_unget =
+	    /* Provided character is legal. */
+	    c != EOF &&
+	    /* Stream is consistent. */
+	    !stream->error &&
+	    /* Stream is buffered. */
+	    stream->btype != _IONBF &&
+	    /* Last operation on the stream was a read operation. */
+	    stream->buf_state == _bs_read &&
+	    /* Stream buffer is already allocated (i.e. there was already carried
+	     * out either write or read operation on the stream). This is probably
+	     * redundant check but let's be safe. */
+	    stream->buf != NULL &&
+	    /* There is still space in the stream to retreat. POSIX demands the
+	     * possibility to unget at least 1 character. It should be always
+	     * possible, assuming the last operation on the stream read at least 1
+	     * character, because the buffer is refilled in the lazily manner. */
+	    stream->buf_tail > stream->buf;
+
+	if (can_unget) {
+		--stream->buf_tail;
+		stream->buf_tail[0] = b;
+		stream->eof = false;
+		return (int) b;
+	} else {
+		return EOF;
+	}
+}
+
+/**
+ * Read a stream until the delimiter (or EOF) is encountered.
+ *
+ * @param lineptr Pointer to the output buffer in which there will be stored
+ *     nul-terminated string together with the delimiter (if encountered).
+ *     Will be resized if necessary.
+ * @param n Pointer to the size of the output buffer. Will be increased if
+ *     necessary.
+ * @param delimiter Delimiter on which to finish reading the stream.
+ * @param stream Input stream.
+ * @return Number of fetched characters (including delimiter if encountered)
+ *     or -1 on error (set in errno).
+ */
+ssize_t posix_getdelim(char **restrict lineptr, size_t *restrict n,
+    int delimiter, FILE *restrict stream)
+{
+	/* Check arguments for sanity. */
+	if (!lineptr || !n) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	size_t alloc_step = 80; /* Buffer size gain during reallocation. */
+	char *pos = *lineptr; /* Next free byte of the output buffer. */
+	size_t cnt = 0; /* Number of fetched characters. */
+	int c = fgetc(stream); /* Current input character. Might be EOF. */
+
+	do {
+		/* Mask EOF as NUL to terminate string. */
+		if (c == EOF) {
+			c = '\0';
+		}
+
+		/* Ensure there is still space left in the buffer. */
+		if (pos == *lineptr + *n) {
+			*lineptr = realloc(*lineptr, *n + alloc_step);
+			if (*lineptr) {
+				pos = *lineptr + *n;
+				*n += alloc_step;
+			} else {
+				errno = ENOMEM;
+				return -1;
+			}
+		}
+
+		/* Store the fetched character. */
+		*pos = c;
+
+		/* Fetch the next character according to the current character. */
+		if (c != '\0') {
+			++pos;
+			++cnt;
+			if (c == delimiter) {
+				/* Delimiter was just stored. Provide EOF as the next
+				 * character - it will be masked as NUL and output string
+				 * will be properly terminated. */
+				c = EOF;
+			} else {
+				/* Neither delimiter nor EOF were encountered. Just fetch
+				 * the next character from the stream. */
+				c = fgetc(stream);
+			}
+		}
+	} while (c != '\0');
+
+	if (errno == EOK && cnt > 0) {
+		return cnt;
+	} else {
+		/* Either some error occured or the stream was already at EOF. */
+		return -1;
+	}
+}
+
+/**
+ * Read a stream until the newline (or EOF) is encountered.
+ * 
+ * @param lineptr Pointer to the output buffer in which there will be stored
+ *     nul-terminated string together with the delimiter (if encountered).
+ *     Will be resized if necessary.
+ * @param n Pointer to the size of the output buffer. Will be increased if
+ *     necessary.
+ * @param stream Input stream.
+ * @return Number of fetched characters (including newline if encountered)
+ *     or -1 on error (set in errno).
+ */
+ssize_t posix_getline(char **restrict lineptr, size_t *restrict n,
+    FILE *restrict stream)
+{
+	return posix_getdelim(lineptr, n, '\n', stream);
+}
+
+/**
+ * Reopen a file stream.
+ * 
+ * @param filename Pathname of a file to be reopened or NULL for changing
+ *     the mode of the stream.
+ * @param mode Mode to be used for reopening the file or changing current
+ *     mode of the stream.
+ * @param stream Current stream associated with the opened file.
+ * @return On success, either a stream of the reopened file or the provided
+ *     stream with a changed mode. NULL otherwise.
+ */
+FILE *posix_freopen(const char *restrict filename, 
+    const char *restrict mode, FILE *restrict stream)
+{
+	assert(mode != NULL);
+	assert(stream != NULL);
+	
+	if (filename == NULL) {
+		/* POSIX allows this to be imlementation-defined. HelenOS currently
+		 * does not support changing the mode. */
+		// FIXME: handle mode change once it is supported
+		return stream;
+	}
+	
+	/* Open a new stream. */
+	FILE* new = fopen(filename, mode);
+	if (new == NULL) {
+		fclose(stream);
+		/* errno was set by fopen() */
+		return NULL;
+	}
+	
+	/* Close the original stream without freeing it (ignoring errors). */
+	if (stream->buf != NULL) {
+		fflush(stream);
+	}
+	if (stream->sess != NULL) {
+		async_hangup(stream->sess);
+	}
+	if (stream->fd >= 0) {
+		close(stream->fd);
+	}
+	list_remove(&stream->link);
+	
+	/* Move the new stream to the original location. */
+	memcpy(stream, new, sizeof (FILE));
+	free(new);
+	
+	/* Update references in the file list. */
+	stream->link.next->prev = &stream->link;
+	stream->link.prev->next = &stream->link;
+	
+	return stream;
+}
+
+/**
+ * Write error messages to standard error.
+ *
+ * @param s Error message.
+ */
+void posix_perror(const char *s)
+{
+	if (s == NULL || s[0] == '\0') {
+		fprintf(stderr, "%s\n", posix_strerror(errno));
+	} else {
+		fprintf(stderr, "%s: %s\n", s, posix_strerror(errno));
+	}
+}
+
+struct _posix_fpos {
+	off64_t offset;
+};
+
+/** Restores stream a to position previously saved with fgetpos().
+ *
+ * @param stream Stream to restore
+ * @param pos Position to restore
+ * @return Zero on success, non-zero (with errno set) on failure
+ */
+int posix_fsetpos(FILE *stream, const posix_fpos_t *pos)
+{
+	return fseek(stream, pos->offset, SEEK_SET);
+}
+
+/** Saves the stream's position for later use by fsetpos().
+ *
+ * @param stream Stream to save
+ * @param pos Place to store the position
+ * @return Zero on success, non-zero (with errno set) on failure
+ */
+int posix_fgetpos(FILE *restrict stream, posix_fpos_t *restrict pos)
+{
+	off64_t ret = ftell(stream);
+	if (ret != -1) {
+		pos->offset = ret;
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+/**
+ * Reposition a file-position indicator in a stream.
+ * 
+ * @param stream Stream to seek in.
+ * @param offset Direction and amount of bytes to seek.
+ * @param whence From where to seek.
+ * @return Zero on success, -1 otherwise.
+ */
+int posix_fseek(FILE *stream, long offset, int whence)
+{
+	return fseek(stream, (off64_t) offset, whence);
+}
+
+/**
+ * Reposition a file-position indicator in a stream.
+ * 
+ * @param stream Stream to seek in.
+ * @param offset Direction and amount of bytes to seek.
+ * @param whence From where to seek.
+ * @return Zero on success, -1 otherwise.
+ */
+int posix_fseeko(FILE *stream, posix_off_t offset, int whence)
+{
+	return fseek(stream, (off64_t) offset, whence);
+}
+
+/**
+ * Discover current file offset in a stream.
+ * 
+ * @param stream Stream for which the offset shall be retrieved.
+ * @return Current offset or -1 if not possible.
+ */
+long posix_ftell(FILE *stream)
+{
+	return (long) ftell(stream);
+}
+
+/**
+ * Discover current file offset in a stream.
+ * 
+ * @param stream Stream for which the offset shall be retrieved.
+ * @return Current offset or -1 if not possible.
+ */
+posix_off_t posix_ftello(FILE *stream)
+{
+	return (posix_off_t) ftell(stream);
+}
+
+/**
+ * Discard prefetched data or write unwritten data.
+ * 
+ * @param stream Stream that shall be flushed.
+ * @return Zero on success, EOF on failure.
+ */
+int posix_fflush(FILE *stream)
+{
+	int rc = fflush(stream);
+	if (rc < 0) {
+		errno = -rc;
+		return EOF;
+	} else {
+		return 0;
+	}
+}
+
+/**
+ * Print formatted output to the opened file.
+ *
+ * @param fildes File descriptor of the opened file.
+ * @param format Format description.
+ * @return Either the number of printed characters or negative value on error.
+ */
+int posix_dprintf(int fildes, const char *restrict format, ...)
+{
+	va_list list;
+	va_start(list, format);
+	int result = posix_vdprintf(fildes, format, list);
+	va_end(list);
+	return result;
+}
+
+/**
+ * Write ordinary string to the opened file.
+ *
+ * @param str String to be written.
+ * @param size Size of the string (in bytes)..
+ * @param fd File descriptor of the opened file.
+ * @return The number of written characters.
+ */
+static int _dprintf_str_write(const char *str, size_t size, void *fd)
+{
+	ssize_t wr = write(*(int *) fd, str, size);
+	return str_nlength(str, wr);
+}
+
+/**
+ * Write wide string to the opened file.
+ * 
+ * @param str String to be written.
+ * @param size Size of the string (in bytes).
+ * @param fd File descriptor of the opened file.
+ * @return The number of written characters.
+ */
+static int _dprintf_wstr_write(const wchar_t *str, size_t size, void *fd)
+{
+	size_t offset = 0;
+	size_t chars = 0;
+	size_t sz;
+	char buf[4];
+	
+	while (offset < size) {
+		sz = 0;
+		if (chr_encode(str[chars], buf, &sz, sizeof(buf)) != EOK) {
+			break;
+		}
+		
+		if (write(*(int *) fd, buf, sz) != (ssize_t) sz) {
+			break;
+		}
+		
+		chars++;
+		offset += sizeof(wchar_t);
+	}
+	
+	return chars;
+}
+
+/**
+ * Print formatted output to the opened file.
+ * 
+ * @param fildes File descriptor of the opened file.
+ * @param format Format description.
+ * @param ap Print arguments.
+ * @return Either the number of printed characters or negative value on error.
+ */
+int posix_vdprintf(int fildes, const char *restrict format, va_list ap)
+{
+	printf_spec_t spec = {
+		.str_write = _dprintf_str_write,
+		.wstr_write = _dprintf_wstr_write,
+		.data = &fildes
+	};
+	
+	return printf_core(format, &spec, ap);
+}
+
+/**
+ * Print formatted output to the string.
+ * 
+ * @param s Output string.
+ * @param format Format description.
+ * @return Either the number of printed characters (excluding null byte) or
+ *     negative value on error.
+ */
+int posix_sprintf(char *s, const char *restrict format, ...)
+{
+	va_list list;
+	va_start(list, format);
+	int result = posix_vsprintf(s, format, list);
+	va_end(list);
+	return result;
+}
+
+/**
+ * Print formatted output to the string.
+ * 
+ * @param s Output string.
+ * @param format Format description.
+ * @param ap Print arguments.
+ * @return Either the number of printed characters (excluding null byte) or
+ *     negative value on error.
+ */
+int posix_vsprintf(char *s, const char *restrict format, va_list ap)
+{
+	return vsnprintf(s, STR_NO_LIMIT, format, ap);
+}
+
+/**
+ * Convert formatted input from the stream.
+ * 
+ * @param stream Input stream.
+ * @param format Format description.
+ * @return The number of converted output items or EOF on failure.
+ */
+int posix_fscanf(FILE *restrict stream, const char *restrict format, ...)
+{
+	va_list list;
+	va_start(list, format);
+	int result = posix_vfscanf(stream, format, list);
+	va_end(list);
+	return result;
+}
+
+/**
+ * Convert formatted input from the standard input.
+ * 
+ * @param format Format description.
+ * @return The number of converted output items or EOF on failure.
+ */
+int posix_scanf(const char *restrict format, ...)
+{
+	va_list list;
+	va_start(list, format);
+	int result = posix_vscanf(format, list);
+	va_end(list);
+	return result;
+}
+
+/**
+ * Convert formatted input from the standard input.
+ * 
+ * @param format Format description.
+ * @param arg Output items.
+ * @return The number of converted output items or EOF on failure.
+ */
+int posix_vscanf(const char *restrict format, va_list arg)
+{
+	return posix_vfscanf(stdin, format, arg);
+}
+
+/**
+ * Convert formatted input from the string.
+ * 
+ * @param s Input string.
+ * @param format Format description.
+ * @return The number of converted output items or EOF on failure.
+ */
+int posix_sscanf(const char *restrict s, const char *restrict format, ...)
+{
+	va_list list;
+	va_start(list, format);
+	int result = posix_vsscanf(s, format, list);
+	va_end(list);
+	return result;
+}
+
+/**
+ * Acquire file stream for the thread.
+ *
+ * @param file File stream to lock.
+ */
+void posix_flockfile(FILE *file)
+{
+	/* dummy */
+}
+
+/**
+ * Acquire file stream for the thread (non-blocking).
+ *
+ * @param file File stream to lock.
+ * @return Zero for success and non-zero if the lock cannot be acquired.
+ */
+int posix_ftrylockfile(FILE *file)
+{
+	/* dummy */
+	return 0;
+}
+
+/**
+ * Relinquish the ownership of the locked file stream.
+ *
+ * @param file File stream to unlock.
+ */
+void posix_funlockfile(FILE *file)
+{
+	/* dummy */
+}
+
+/**
+ * Get a byte from a stream (thread-unsafe).
+ *
+ * @param stream Input file stream.
+ * @return Either read byte or EOF.
+ */
+int posix_getc_unlocked(FILE *stream)
+{
+	return getc(stream);
+}
+
+/**
+ * Get a byte from the standard input stream (thread-unsafe).
+ *
+ * @return Either read byte or EOF.
+ */
+int posix_getchar_unlocked(void)
+{
+	return getchar();
+}
+
+/**
+ * Put a byte on a stream (thread-unsafe).
+ *
+ * @param c Byte to output.
+ * @param stream Output file stream.
+ * @return Either written byte or EOF.
+ */
+int posix_putc_unlocked(int c, FILE *stream)
+{
+	return putc(c, stream);
+}
+
+/**
+ * Put a byte on the standard output stream (thread-unsafe).
+ * 
+ * @param c Byte to output.
+ * @return Either written byte or EOF.
+ */
+int posix_putchar_unlocked(int c)
+{
+	return putchar(c);
+}
+
+/**
+ * Remove a file or directory.
+ *
+ * @param path Pathname of the file that shall be removed.
+ * @return Zero on success, -1 (with errno set) otherwise.
+ */
+int posix_remove(const char *path)
+{
+	struct stat st;
+	int rc = stat(path, &st);
+	
+	if (rc != EOK) {
+		errno = -rc;
+		return -1;
+	}
+	
+	if (st.is_directory) {
+		rc = rmdir(path);
+	} else {
+		rc = unlink(path);
+	}
+	
+	if (rc != EOK) {
+		errno = -rc;
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * Rename a file or directory.
+ *
+ * @param old Old pathname.
+ * @param new New pathname.
+ * @return Zero on success, -1 (with errno set) otherwise.
+ */
+int posix_rename(const char *old, const char *new)
+{
+	return errnify(rename, old, new);
+}
+
+/**
+ * Get a unique temporary file name (obsolete).
+ *
+ * @param s Buffer for the file name. Must be at least L_tmpnam bytes long.
+ * @return The value of s on success, NULL on failure.
+ */
+char *posix_tmpnam(char *s)
+{
+	assert(L_tmpnam >= posix_strlen("/tmp/tnXXXXXX"));
+	
+	static char buffer[L_tmpnam + 1];
+	if (s == NULL) {
+		s = buffer;
+	}
+	
+	posix_strcpy(s, "/tmp/tnXXXXXX");
+	posix_mktemp(s);
+	
+	if (*s == '\0') {
+		/* Errno set by mktemp(). */
+		return NULL;
+	}
+	
+	return s;
+}
+
+/**
+ * Get an unique temporary file name with additional constraints (obsolete).
+ *
+ * @param dir Path to directory, where the file should be created.
+ * @param pfx Optional prefix up to 5 characters long.
+ * @return Newly allocated unique path for temporary file. NULL on failure.
+ */
+char *posix_tempnam(const char *dir, const char *pfx)
+{
+	/* Sequence number of the filename. */
+	static int seq = 0;
+	
+	size_t dir_len = posix_strlen(dir);
+	if (dir[dir_len - 1] == '/') {
+		dir_len--;
+	}
+	
+	size_t pfx_len = posix_strlen(pfx);
+	if (pfx_len > 5) {
+		pfx_len = 5;
+	}
+	
+	char *result = malloc(dir_len + /* slash*/ 1 +
+	    pfx_len + /* three-digit seq */ 3 + /* .tmp */ 4 + /* nul */ 1);
+	
+	if (result == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	char *res_ptr = result;
+	posix_strncpy(res_ptr, dir, dir_len);
+	res_ptr += dir_len;
+	posix_strncpy(res_ptr, pfx, pfx_len);
+	res_ptr += pfx_len;
+	
+	for (; seq < 1000; ++seq) {
+		snprintf(res_ptr, 8, "%03d.tmp", seq);
+		
+		int orig_errno = errno;
+		errno = 0;
+		/* Check if the file exists. */
+		if (posix_access(result, F_OK) == -1) {
+			if (errno == ENOENT) {
+				errno = orig_errno;
+				break;
+			} else {
+				/* errno set by access() */
+				return NULL;
+			}
+		}
+	}
+	
+	if (seq == 1000) {
+		free(result);
+		errno = EINVAL;
+		return NULL;
+	}
+	
+	return result;
+}
+
+/**
+ * Create and open an unique temporary file.
+ * The file is automatically removed when the stream is closed.
+ *
+ * @param dir Path to directory, where the file should be created.
+ * @param pfx Optional prefix up to 5 characters long.
+ * @return Newly allocated unique path for temporary file. NULL on failure.
+ */
+FILE *posix_tmpfile(void)
+{
+	char filename[] = "/tmp/tfXXXXXX";
+	int fd = posix_mkstemp(filename);
+	if (fd == -1) {
+		/* errno set by mkstemp(). */
+		return NULL;
+	}
+	
+	/* Unlink the created file, so that it's removed on close(). */
+	posix_unlink(filename);
+	return fdopen(fd, "w+");
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/stdio/scanf.c
===================================================================
--- uspace/lib/posix/source/stdio/scanf.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/stdio/scanf.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1339 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Implementation of the scanf backend.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+/* Must be first. */
+#include "posix/stdbool.h"
+
+#include "posix/assert.h"
+#include "posix/errno.h"
+
+#include "posix/stdio.h"
+#include "posix/stdlib.h"
+#include "posix/stddef.h"
+#include "posix/string.h"
+#include "posix/ctype.h"
+#include "posix/sys/types.h"
+
+#include "../internal/common.h"
+#include "libc/malloc.h"
+
+/** Unified data type for possible data sources for scanf. */
+typedef union __data_source {
+	FILE *stream; /**< Input file stream. */
+	const char *string; /**< Input string. */
+} _data_source;
+
+/** Internal state of the input provider. */
+enum {
+	/** Partly constructed but not yet functional. */
+	_PROV_CONSTRUCTED,
+	/** Ready to serve any request. */
+	_PROV_READY,
+	/** Cursor is temporarily lent to the external entity. No action is
+	  * possible until the cursor is returned.  */
+	_PROV_CURSOR_LENT,
+};
+
+/** Universal abstraction over data input for scanf. */
+typedef struct __input_provider {
+	/** Source of data elements. */
+	_data_source source;
+	/** How many elements was already processed. */
+	int consumed;
+	/** How many elements was already fetched from the source. */
+	int fetched;
+	/** Elements are fetched from the source in batches (e.g. by getline())
+	  * to allow using strtol/strtod family even on streams. */
+	char *window;
+	/** Size of the current window. */
+	size_t window_size;
+	/** Points to the next element to be processed inside the current window. */
+	const char *cursor;
+	/** Internal state of the provider. */
+	int state;
+
+	/** Take control over data source. Finish initialization of the internal
+	  * structures (e.g. allocation of window). */
+	void (*capture)(struct __input_provider *);
+	/** Get a single element from the source and update the internal structures
+	  * accordingly (e.g. greedy update of the window). Return -1 if the
+	  * element cannot be obtained. */
+	int (*pop)(struct __input_provider *);
+	/** Undo the most recent not-undone pop operation. Might be necesarry to
+	  * flush current window and seek data source backwards. Return 0 if the
+	  * pop history is exhausted, non-zero on success. */
+	int (*undo)(struct __input_provider *);
+	/** Lend the cursor to the caller.  */
+	const char * (*borrow_cursor)(struct __input_provider *);
+	/** Take control over possibly incremented cursor and update the internal
+	  * structures if necessary. */
+	void (*return_cursor)(struct __input_provider *, const char *);
+	/** Release the control over the source. That is, synchronize any
+	  * fetched but non-consumed elements (e.g. by seeking) and destruct
+	  * internal structures (e.g. window deallocation). */
+	void (*release)(struct __input_provider *);
+} _input_provider;
+
+/** @see __input_provider */
+static void _capture_stream(_input_provider *self)
+{
+	assert(self->source.stream);
+	assert(self->state == _PROV_CONSTRUCTED);
+	/* Caller could already pre-allocated the window. */
+	assert((self->window == NULL && self->window_size == 0) ||
+	    (self->window && self->window_size > 0));
+
+	/* Initialize internal structures. */
+	self->consumed = 0;
+	ssize_t fetched = posix_getline(
+	    &self->window, &self->window_size, self->source.stream);
+	if (fetched != -1) {
+		self->fetched = fetched;
+		self->cursor = self->window;
+	} else {
+		/* EOF encountered. */
+		self->fetched = 0;
+		self->cursor = NULL;
+	}
+	self->state = _PROV_READY;
+}
+
+/** @see __input_provider */
+static void _capture_string(_input_provider *self)
+{
+	assert(self->source.string);
+	assert(self->state == _PROV_CONSTRUCTED);
+
+	/* Initialize internal structures. */
+	self->consumed = 0;
+	self->fetched = posix_strlen(self->source.string);
+	self->window = (char *) self->source.string;
+	self->window_size = self->fetched + 1;
+	self->cursor = self->window;
+	self->state = _PROV_READY;
+}
+
+/** @see __input_provider */
+static int _pop_stream(_input_provider *self)
+{
+	assert(self->state == _PROV_READY);
+
+	if (self->cursor) {
+		int c = *self->cursor;
+		++self->consumed;
+		++self->cursor;
+		/* Do we need to fetch a new line from the source? */
+		if (*self->cursor == '\0') {
+			ssize_t fetched = posix_getline(&self->window,
+			    &self->window_size, self->source.stream);
+			if (fetched != -1) {
+				self->fetched += fetched;
+				self->cursor = self->window;
+			} else {
+				/* EOF encountered. */
+				self->cursor = NULL;
+			}
+		}
+		return c;
+	} else {
+		/* Already at EOF. */
+		return -1;
+	}
+}
+
+/** @see __input_provider */
+static int _pop_string(_input_provider *self)
+{
+	assert(self->state == _PROV_READY);
+
+	if (*self->cursor != '\0') {
+		int c = *self->cursor;
+		++self->consumed;
+		++self->cursor;
+		return c;
+	} else {
+		/* String depleted. */
+		return -1;
+	}
+}
+
+/** @see __input_provider */
+static int _undo_stream(_input_provider *self)
+{
+	assert(self->state == _PROV_READY);
+
+	if (self->consumed == 0) {
+		/* Undo history exhausted. */
+		return 0;
+	}
+
+	if (!self->cursor || self->window == self->cursor) {
+		/* Complex case. Either at EOF (cursor == NULL) or there is no more
+		 * place to retreat to inside the window. Seek the source backwards
+		 * and flush the window. Regarding the scanf, this could happend only
+		 * when matching unbounded string (%s) or unbounded scanset (%[) not
+		 * containing newline, while at the same time newline is the character
+		 * that breaks the matching process. */
+		int rc = posix_fseek(
+		    self->source.stream, -1, SEEK_CUR);
+		if (rc == -1) {
+			/* Seek failed.  */
+			return 0;
+		}
+		ssize_t fetched = posix_getline(&self->window,
+		    &self->window_size, self->source.stream);
+		if (fetched != -1) {
+			assert(fetched == 1);
+			self->fetched = self->consumed + 1;
+			self->cursor = self->window;
+		} else {
+			/* Stream is broken. */
+			return 0;
+		}
+	} else {
+		/* Simple case. Still inside window. */
+		--self->cursor;
+	}
+	--self->consumed;
+	return 1; /* Success. */
+}
+
+/** @see __input_provider */
+static int _undo_string(_input_provider *self)
+{
+	assert(self->state == _PROV_READY);
+
+	if (self->consumed > 0) {
+		--self->consumed;
+		--self->cursor;
+	} else {
+		/* Undo history exhausted. */
+		return 0;
+	}
+	return 1; /* Success. */
+}
+
+/** @see __input_provider */
+static const char *_borrow_cursor_universal(_input_provider *self)
+{
+	assert(self->state == _PROV_READY);
+
+	self->state = _PROV_CURSOR_LENT;
+	return self->cursor;
+}
+
+/** @see __input_provider */
+static void _return_cursor_stream(_input_provider *self, const char *cursor)
+{
+	assert(self->state == _PROV_CURSOR_LENT);
+
+	/* Check how much of the window did external entity consumed. */
+	self->consumed += cursor - self->cursor;
+	self->cursor = cursor;
+	if (*self->cursor == '\0') {
+		/* Window was completely consumed, fetch new data. */
+		ssize_t fetched = posix_getline(&self->window,
+		    &self->window_size, self->source.stream);
+		if (fetched != -1) {
+			self->fetched += fetched;
+			self->cursor = self->window;
+		} else {
+			/* EOF encountered. */
+			self->cursor = NULL;
+		}
+	}
+	self->state = _PROV_READY;
+}
+
+/** @see __input_provider */
+static void _return_cursor_string(_input_provider *self, const char *cursor)
+{
+	assert(self->state == _PROV_CURSOR_LENT);
+
+	/* Check how much of the window did external entity consumed. */
+	self->consumed += cursor - self->cursor;
+	self->cursor = cursor;
+	self->state = _PROV_READY;
+}
+
+/** @see __input_provider */
+static void _release_stream(_input_provider *self)
+{
+	assert(self->state == _PROV_READY);
+	assert(self->consumed >= self->fetched);
+
+	/* Try to correct the difference between the stream position and what was
+	 * actually consumed. If it is not possible, continue anyway. */
+	posix_fseek(self->source.stream, self->consumed - self->fetched, SEEK_CUR);
+
+	/* Destruct internal structures. */
+	self->fetched = 0;
+	self->cursor = NULL;
+	if (self->window) {
+		free(self->window);
+		self->window = NULL;
+	}
+	self->window_size = 0;
+	self->state = _PROV_CONSTRUCTED;
+}
+
+/** @see __input_provider */
+static void _release_string(_input_provider *self)
+{
+	assert(self->state == _PROV_READY);
+
+	/* Destruct internal structures. */
+	self->fetched = 0;
+	self->cursor = NULL;
+	self->window = NULL;
+	self->window_size = 0;
+	self->state = _PROV_CONSTRUCTED;
+}
+
+/** Length modifier values. */
+enum {
+	LMOD_NONE,
+	LMOD_hh,
+	LMOD_h,
+	LMOD_l,
+	LMOD_ll,
+	LMOD_j,
+	LMOD_z,
+	LMOD_t,
+	LMOD_L,
+	LMOD_p, /* Reserved for %p conversion. */
+};
+
+/**
+ * Decides whether provided characters specify length modifier. If so, the
+ * recognized modifier is stored through provider pointer.
+ *
+ * @param c Candidate on the length modifier.
+ * @param _c Next character (might be NUL).
+ * @param modifier Pointer to the modifier value.
+ * @return Whether the modifier was recognized or not.
+ */
+static inline int is_length_mod(int c, int _c, int *modifier)
+{
+	assert(modifier);
+
+	switch (c) {
+	case 'h':
+		/* Check whether the modifier was not already recognized. */
+		if (*modifier == LMOD_NONE) {
+			*modifier = _c == 'h' ? LMOD_hh : LMOD_h;
+		} else {
+			/* Format string is invalid. Notify the caller. */
+			*modifier = LMOD_NONE;
+		}
+		return 1;
+	case 'l':
+		if (*modifier == LMOD_NONE) {
+			*modifier = _c == 'l' ? LMOD_ll : LMOD_l;
+		} else {
+			*modifier = LMOD_NONE;
+		}
+		return 1;
+	case 'j':
+		*modifier = *modifier == LMOD_NONE ? LMOD_j : LMOD_NONE;
+		return 1;
+	case 'z':
+		*modifier = *modifier == LMOD_NONE ? LMOD_z : LMOD_NONE;
+		return 1;
+	case 't':
+		*modifier = *modifier == LMOD_NONE ? LMOD_t : LMOD_NONE;
+		return 1;
+	case 'L':
+		*modifier = *modifier == LMOD_NONE ? LMOD_L : LMOD_NONE;
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+/**
+ * Decides whether provided character specifies integer conversion. If so, the
+ * semantics of the conversion is stored through provided pointers..
+ * 
+ * @param c Candidate on the integer conversion.
+ * @param is_unsigned Pointer to store whether the conversion is signed or not.
+ * @param base Pointer to store the base of the integer conversion.
+ * @return Whether the conversion was recognized or not.
+ */
+static inline int is_int_conv(int c, bool *is_unsigned, int *base)
+{
+	assert(is_unsigned && base);
+
+	switch (c) {
+	case 'd':
+		*is_unsigned = false;
+		*base = 10;
+		return 1;
+	case 'i':
+		*is_unsigned = false;
+		*base = 0;
+		return 1;
+	case 'o':
+		*is_unsigned = true;
+		*base = 8;
+		return 1;
+	case 'u':
+		*is_unsigned = true;
+		*base = 10;
+		return 1;
+	case 'p': /* According to POSIX, %p modifier is implementation defined but
+			   * must correspond to its printf counterpart. */
+	case 'x':
+	case 'X':
+		*is_unsigned = true;
+		*base = 16;
+		return 1;
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+/**
+ * Decides whether provided character specifies conversion of the floating
+ * point number.
+ *
+ * @param c Candidate on the floating point conversion.
+ * @return Whether the conversion was recognized or not.
+ */
+static inline int is_float_conv(int c)
+{
+	switch (c) {
+	case 'a':
+	case 'A':
+	case 'e':
+	case 'E':
+	case 'f':
+	case 'F':
+	case 'g':
+	case 'G':
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+/**
+ * Decides whether provided character specifies conversion of the character
+ * sequence.
+ *
+ * @param c Candidate on the character sequence conversion.
+ * @param modifier Pointer to store length modifier for wide chars.
+ * @return Whether the conversion was recognized or not.
+ */
+static inline int is_seq_conv(int c, int *modifier)
+{
+	assert(modifier);
+	
+	switch (c) {
+	case 'S':
+		*modifier = LMOD_l;
+		/* fallthrough */
+	case 's':
+		return 1;
+	case 'C':
+		*modifier = LMOD_l;
+		/* fallthrough */
+	case 'c':
+		return 1;
+	case '[':
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+/**
+ * Backend for the whole family of scanf functions. Uses input provider
+ * to abstract over differences between strings and streams. Should be
+ * POSIX compliant (apart from the not supported stuff).
+ *
+ * NOT SUPPORTED: locale (see strtold), wide chars, numbered output arguments
+ * 
+ * @param in Input provider.
+ * @param fmt Format description.
+ * @param arg Output arguments.
+ * @return The number of converted output items or EOF on failure.
+ */
+static inline int _internal_scanf(
+    _input_provider *in, const char *restrict fmt, va_list arg)
+{
+	int c = -1;
+	int converted_cnt = 0;
+	bool converting = false;
+	bool matching_failure = false;
+
+	bool assign_supress = false;
+	bool assign_alloc = false;
+	long width = -1;
+	int length_mod = LMOD_NONE;
+	bool int_conv_unsigned = false;
+	int int_conv_base = 0;
+
+	/* Buffers allocated by scanf for optional 'm' specifier must be remembered
+	 * to deallocaate them in case of an error. Because each of those buffers
+	 * corresponds to one of the argument from va_list, there is an upper bound
+	 * on the number of those arguments. In case of C99, this uppper bound is
+	 * 127 arguments. */
+	char *buffers[127];
+	for (int i = 0; i < 127; ++i) {
+		buffers[i] = NULL;
+	}
+	int next_unused_buffer_idx = 0;
+
+	in->capture(in);
+
+	/* Interpret format string. Control shall prematurely jump from the cycle
+	 * on input failure, matching failure or illegal format string. In order
+	 * to keep error reporting simple enough and to keep input consistent,
+	 * error condition shall be always manifested as jump from the cycle,
+	 * not function return. Format string pointer shall be updated specifically
+	 * for each sub-case (i.e. there shall be no loop-wide increment).*/
+	while (*fmt) {
+
+		if (converting) {
+
+			/* Processing inside conversion specifier. Either collect optional
+			 * parameters or execute the conversion. When the conversion
+			 * is successfully completed, increment conversion count and switch
+			 * back to normal mode. */
+			if (*fmt == '*') {
+				/* Assignment-supression (optional). */
+				if (assign_supress) {
+					/* Already set. Illegal format string. */
+					break;
+				}
+				assign_supress = true;
+				++fmt;
+			} else if (*fmt == 'm') {
+				/* Assignment-allocation (optional). */
+				if (assign_alloc) {
+					/* Already set. Illegal format string. */
+					break;
+				}
+				assign_alloc = true;
+				++fmt;
+			} else if (*fmt == '$') {
+				/* Reference to numbered output argument. */
+				// TODO
+				not_implemented();
+			} else if (isdigit(*fmt)) {
+				/* Maximum field length (optional). */
+				if (width != -1) {
+					/* Already set. Illegal format string. */
+					break;
+				}
+				char *fmt_new = NULL;
+				width = posix_strtol(fmt, &fmt_new, 10);
+				if (width != 0) {
+					fmt = fmt_new;
+				} else {
+					/* Since POSIX requires width to be non-zero, it is
+					 * sufficient to interpret zero width as error without
+					 * referring to errno. */
+					break;
+				}
+			} else if (is_length_mod(*fmt, *(fmt + 1), &length_mod)) {
+				/* Length modifier (optional). */
+				if (length_mod == LMOD_NONE) {
+					/* Already set. Illegal format string. The actual detection
+					 * is carried out in the is_length_mod(). */
+					break;
+				}
+				if (length_mod == LMOD_hh || length_mod == LMOD_ll) {
+					/* Modifier was two characters long. */
+					++fmt;
+				}
+				++fmt;
+			} else if (is_int_conv(*fmt, &int_conv_unsigned, &int_conv_base)) {
+				/* Integer conversion. */
+
+				/* Check sanity of optional parts of conversion specifier. */
+				if (assign_alloc || length_mod == LMOD_L) {
+					/* Illegal format string. */
+					break;
+				}
+
+				/* Conversion of the integer with %p specifier needs special
+				 * handling, because it is not allowed to have arbitrary
+				 * length modifier.  */
+				if (*fmt == 'p') {
+					if (length_mod == LMOD_NONE) {
+						length_mod = LMOD_p;
+					} else {
+						/* Already set. Illegal format string. */
+						break;
+					}
+				}
+
+				/* First consume any white spaces, so we can borrow cursor
+				 * from the input provider. This way, the cursor will either
+				 * point to the non-white space while the input will be
+				 * prefetched up to the newline (which is suitable for strtol),
+				 * or the input will be at EOF. */
+				do {
+					c = in->pop(in);
+				} while (isspace(c));
+
+				/* After skipping the white spaces, can we actually continue? */
+				if (c == -1) {
+					/* Input failure. */
+					break;
+				} else {
+					/* Everything is OK, just undo the last pop, so the cursor
+					 * can be borrowed. */
+					in->undo(in);
+				}
+
+				const char *cur_borrowed = NULL;
+				const char *cur_limited = NULL;
+				char *cur_updated = NULL;
+
+				/* Borrow the cursor. Until it is returned to the provider
+				 * we cannot jump from the cycle, because it would leave
+				 * the input inconsistent. */
+				cur_borrowed = in->borrow_cursor(in);
+
+				/* If the width is limited, the cursor horizont must be
+				 * decreased accordingly. Otherwise the strtol could read more
+				 * than allowed by width. */
+				if (width != -1) {
+					cur_limited = posix_strndup(cur_borrowed, width);
+				} else {
+					cur_limited = cur_borrowed;
+				}
+				cur_updated = (char *) cur_limited;
+
+				long long sres = 0;
+				unsigned long long ures = 0;
+				errno = 0; /* Reset errno to recognize error later. */
+				/* Try to convert the integer. */
+				if (int_conv_unsigned) {
+					ures = posix_strtoull(cur_limited, &cur_updated, int_conv_base);
+				} else {
+					sres = posix_strtoll(cur_limited, &cur_updated, int_conv_base);
+				}
+
+				/* Update the cursor so it can be returned to the provider. */
+				cur_borrowed += cur_updated - cur_limited;
+				if (width != -1 && cur_limited != NULL) {
+					/* Deallocate duplicated part of the cursor view. */
+					free(cur_limited);
+				}
+				cur_limited = NULL;
+				cur_updated = NULL;
+				/* Return the cursor to the provider. Input consistency is again
+				 * the job of the provider, so we can report errors from
+				 * now on. */
+				in->return_cursor(in, cur_borrowed);
+				cur_borrowed = NULL;
+
+				/* Check whether the conversion was successful. */
+				if (errno != EOK) {
+					matching_failure = true;
+					break;
+				}
+
+				/* If not supressed, assign the converted integer into
+				 * the next output argument. */
+				if (!assign_supress) {
+					if (int_conv_unsigned) {
+						switch (length_mod) {
+						case LMOD_hh: ; /* Label cannot be part of declaration. */
+							unsigned char *phh = va_arg(arg, unsigned char *);
+							*phh = (unsigned char) ures;
+							break;
+						case LMOD_h: ;
+							unsigned short *ph = va_arg(arg, unsigned short *);
+							*ph = (unsigned short) ures;
+							break;
+						case LMOD_NONE: ;
+							unsigned *pdef = va_arg(arg, unsigned *);
+							*pdef = (unsigned) ures;
+							break;
+						case LMOD_l: ;
+							unsigned long *pl = va_arg(arg, unsigned long *);
+							*pl = (unsigned long) ures;
+							break;
+						case LMOD_ll: ;
+							unsigned long long *pll = va_arg(arg, unsigned long long *);
+							*pll = (unsigned long long) ures;
+							break;
+						case LMOD_j: ;
+							posix_uintmax_t *pj = va_arg(arg, posix_uintmax_t *);
+							*pj = (posix_uintmax_t) ures;
+							break;
+						case LMOD_z: ;
+							size_t *pz = va_arg(arg, size_t *);
+							*pz = (size_t) ures;
+							break;
+						case LMOD_t: ;
+							// XXX: What is unsigned counterpart of the ptrdiff_t?
+							size_t *pt = va_arg(arg, size_t *);
+							*pt = (size_t) ures;
+							break;
+						case LMOD_p: ;
+							void **pp = va_arg(arg, void **);
+							*pp = (void *) (uintptr_t) ures;
+							break;
+						default:
+							assert(false);
+						}
+					} else {
+						switch (length_mod) {
+						case LMOD_hh: ; /* Label cannot be part of declaration. */
+							signed char *phh = va_arg(arg, signed char *);
+							*phh = (signed char) sres;
+							break;
+						case LMOD_h: ;
+							short *ph = va_arg(arg, short *);
+							*ph = (short) sres;
+							break;
+						case LMOD_NONE: ;
+							int *pdef = va_arg(arg, int *);
+							*pdef = (int) sres;
+							break;
+						case LMOD_l: ;
+							long *pl = va_arg(arg, long *);
+							*pl = (long) sres;
+							break;
+						case LMOD_ll: ;
+							long long *pll = va_arg(arg, long long *);
+							*pll = (long long) sres;
+							break;
+						case LMOD_j: ;
+							posix_intmax_t *pj = va_arg(arg, posix_intmax_t *);
+							*pj = (posix_intmax_t) sres;
+							break;
+						case LMOD_z: ;
+							ssize_t *pz = va_arg(arg, ssize_t *);
+							*pz = (ssize_t) sres;
+							break;
+						case LMOD_t: ;
+							posix_ptrdiff_t *pt = va_arg(arg, posix_ptrdiff_t *);
+							*pt = (posix_ptrdiff_t) sres;
+							break;
+						default:
+							assert(false);
+						}
+					}
+					++converted_cnt;
+				}
+
+				converting = false;
+				++fmt;
+			} else if (is_float_conv(*fmt)) {
+				/* Floating point number conversion. */
+
+				/* Check sanity of optional parts of conversion specifier. */
+				if (assign_alloc) {
+					/* Illegal format string. */
+					break;
+				}
+				if (length_mod != LMOD_NONE &&
+				    length_mod != LMOD_l &&
+				    length_mod != LMOD_L) {
+					/* Illegal format string. */
+					break;
+				}
+
+				/* First consume any white spaces, so we can borrow cursor
+				 * from the input provider. This way, the cursor will either
+				 * point to the non-white space while the input will be
+				 * prefetched up to the newline (which is suitable for strtof),
+				 * or the input will be at EOF. */
+				do {
+					c = in->pop(in);
+				} while (isspace(c));
+
+				/* After skipping the white spaces, can we actually continue? */
+				if (c == -1) {
+					/* Input failure. */
+					break;
+				} else {
+					/* Everything is OK, just undo the last pop, so the cursor
+					 * can be borrowed. */
+					in->undo(in);
+				}
+
+				const char *cur_borrowed = NULL;
+				const char *cur_limited = NULL;
+				char *cur_updated = NULL;
+
+				/* Borrow the cursor. Until it is returned to the provider
+				 * we cannot jump from the cycle, because it would leave
+				 * the input inconsistent. */
+				cur_borrowed = in->borrow_cursor(in);
+
+				/* If the width is limited, the cursor horizont must be
+				 * decreased accordingly. Otherwise the strtof could read more
+				 * than allowed by width. */
+				if (width != -1) {
+					cur_limited = posix_strndup(cur_borrowed, width);
+				} else {
+					cur_limited = cur_borrowed;
+				}
+				cur_updated = (char *) cur_limited;
+
+				float fres = 0.0;
+				double dres = 0.0;
+				long double ldres = 0.0;
+				errno = 0; /* Reset errno to recognize error later. */
+				/* Try to convert the floating point nubmer. */
+				switch (length_mod) {
+				case LMOD_NONE:
+					fres = posix_strtof(cur_limited, &cur_updated);
+					break;
+				case LMOD_l:
+					dres = posix_strtod(cur_limited, &cur_updated);
+					break;
+				case LMOD_L:
+					ldres = posix_strtold(cur_limited, &cur_updated);
+					break;
+				default:
+					assert(false);
+				}
+
+				/* Update the cursor so it can be returned to the provider. */
+				cur_borrowed += cur_updated - cur_limited;
+				if (width != -1 && cur_limited != NULL) {
+					/* Deallocate duplicated part of the cursor view. */
+					free(cur_limited);
+				}
+				cur_limited = NULL;
+				cur_updated = NULL;
+				/* Return the cursor to the provider. Input consistency is again
+				 * the job of the provider, so we can report errors from
+				 * now on. */
+				in->return_cursor(in, cur_borrowed);
+				cur_borrowed = NULL;
+
+				/* Check whether the conversion was successful. */
+				if (errno != EOK) {
+					matching_failure = true;
+					break;
+				}
+
+				/* If nto supressed, assign the converted floating point number
+				 * into the next output argument. */
+				if (!assign_supress) {
+					switch (length_mod) {
+					case LMOD_NONE: ; /* Label cannot be part of declaration. */
+						float *pf = va_arg(arg, float *);
+						*pf = fres;
+						break;
+					case LMOD_l: ;
+						double *pd = va_arg(arg, double *);
+						*pd = dres;
+						break;
+					case LMOD_L: ;
+						long double *pld = va_arg(arg, long double *);
+						*pld = ldres;
+						break;
+					default:
+						assert(false);
+					}
+					++converted_cnt;
+				}
+
+				converting = false;
+				++fmt;
+			} else if (is_seq_conv(*fmt, &length_mod)) {
+				/* Character sequence conversion. */
+				
+				/* Check sanity of optional parts of conversion specifier. */
+				if (length_mod != LMOD_NONE &&
+				    length_mod != LMOD_l) {
+					/* Illegal format string. */
+					break;
+				}
+
+				if (length_mod == LMOD_l) {
+					/* Wide chars not supported. */
+					// TODO
+					not_implemented();
+				}
+
+				int term_size = 1; /* Size of the terminator (0 or 1)). */
+				if (*fmt == 'c') {
+					term_size = 0;
+					width = width == -1 ? 1 : width;
+				}
+
+				if (*fmt == 's') {
+					/* Skip white spaces. */
+					do {
+						c = in->pop(in);
+					} while (isspace(c));
+				} else {
+					/* Fetch a single character. */
+					c = in->pop(in);
+				}
+
+				/* Check whether there is still input to read. */
+				if (c == -1) {
+					/* Input failure. */
+					break;
+				}
+
+				/* Prepare scanset. */
+				char terminate_on[256];
+				for (int i = 0; i < 256; ++i) {
+					terminate_on[i] = 0;
+				}
+				if (*fmt == 'c') {
+					++fmt;
+				} else if (*fmt == 's') {
+					terminate_on[' '] = 1;
+					terminate_on['\n'] = 1;
+					terminate_on['\t'] = 1;
+					terminate_on['\f'] = 1;
+					terminate_on['\r'] = 1;
+					terminate_on['\v'] = 1;
+					++fmt;
+				} else {
+					assert(*fmt == '[');
+					bool not = false;
+					bool dash = false;
+					++fmt;
+					/* Check for negation. */
+					if (*fmt == '^') {
+						not = true;
+						++fmt;
+					}
+					/* Check for escape sequences. */
+					if (*fmt == '-' || *fmt == ']') {
+						terminate_on[(int) *fmt] = 1;
+						++fmt;
+					}
+					/* Check for ordinary characters and ranges. */
+					while (*fmt != '\0' && *fmt != ']') {
+						if (dash) {
+							for (char chr = *(fmt - 2); chr <= *fmt; ++chr) {
+								terminate_on[(int) chr] = 1;
+							}
+							dash = false;
+						} else if (*fmt == '-') {
+							dash = true;
+						} else {
+							terminate_on[(int) *fmt] = 1;
+						}
+						++fmt;
+					}
+					/* Check for escape sequence. */
+					if (dash == true) {
+						terminate_on['-'] = 1;
+					}
+					/* Check whether the specifier was correctly terminated.*/
+					if (*fmt == '\0') {
+						/* Illegal format string. */
+						break;
+					} else {
+						++fmt;
+					}
+					/* Inverse the scanset if necessary. */
+					if (not == false) {
+						for (int i = 0; i < 256; ++i) {
+							terminate_on[i] = terminate_on[i] ? 0 : 1;
+						}
+					}
+				}
+
+				char * buf = NULL;
+				size_t buf_size = 0;
+				char * cur = NULL;
+				size_t alloc_step = 80; /* Buffer size gain during reallocation. */
+				int my_buffer_idx = 0;
+
+				/* Retrieve the buffer into which popped characters
+				 * will be stored. */
+				if (!assign_supress) {
+					if (assign_alloc) {
+						/* We must allocate our own buffer. */
+						buf_size =
+						    width == -1 ? alloc_step : (size_t) width + term_size;
+						buf = malloc(buf_size);
+						if (!buf) {
+							/* No memory. */
+							break;
+						}
+						my_buffer_idx = next_unused_buffer_idx;
+						++next_unused_buffer_idx;
+						buffers[my_buffer_idx] = buf;
+						cur = buf;
+					} else {
+						/* Caller provided its buffer. */
+						buf = va_arg(arg, char *);
+						cur = buf;
+						buf_size =
+						    width == -1 ? SIZE_MAX : (size_t) width + term_size;
+					}
+				}
+
+				/* Match the string. The next character is already popped. */
+				while ((width == -1 || width > 0) && c != -1 && !terminate_on[c]) {
+
+					/* Check whether the buffer is still sufficiently large. */
+					if (!assign_supress) {
+						/* Always reserve space for the null terminator. */
+						if (cur == buf + buf_size - term_size) {
+							/* Buffer size must be increased. */
+							buf = realloc(buf, buf_size + alloc_step);
+							if (buf) {
+								buffers[my_buffer_idx] = buf;
+								cur = buf + buf_size - term_size;
+								buf_size += alloc_step;
+							} else {
+								/* Break just from this tight loop. Errno will
+								 * be checked after it. */
+								break;
+							}
+						}
+						/* Store the input character. */
+						*cur = c;
+					}
+
+					width = width == -1 ? -1 : width - 1;
+					++cur;
+					c = in->pop(in);
+				}
+				if (errno == ENOMEM) {
+					/* No memory. */
+					break;
+				}
+				if (c != -1) {
+					/* There is still more input, so undo the last pop. */
+					in->undo(in);
+				}
+
+				/* Check for failures. */
+				if (cur == buf) {
+					/* Matching failure. Input failure was already checked
+					 * earlier. */
+					matching_failure = true;
+					if (!assign_supress && assign_alloc) {
+						/* Roll back. */
+						free(buf);
+						buffers[my_buffer_idx] = NULL;
+						--next_unused_buffer_idx;
+					}
+					break;
+				}
+
+				/* Store the terminator. */
+				if (!assign_supress && term_size > 0) {
+					/* Space for the terminator was reserved. */
+					*cur = '\0';
+				}
+
+				/* Store the result if not already stored. */
+				if (!assign_supress) {
+					if (assign_alloc) {
+						char **pbuf = va_arg(arg, char **);
+						*pbuf = buf;
+					}
+					++converted_cnt;
+				}
+				
+				converting = false;
+				/* Format string pointer already incremented. */
+			} else if (*fmt == 'n') {
+				/* Report the number of consumed bytes so far. */
+
+				/* Sanity check. */
+				bool sane =
+				    width == -1 &&
+				    length_mod == LMOD_NONE &&
+				    assign_alloc == false &&
+				    assign_supress == false;
+
+				if (sane) {
+					int *pi = va_arg(arg, int *);
+					*pi = in->consumed;
+				} else {
+					/* Illegal format string. */
+					break;
+				}
+
+				/* This shall not be counted as conversion. */
+				converting = false;
+				++fmt;
+			} else {
+				/* Illegal format string. */
+				break;
+			}
+			
+		} else {
+
+			/* Processing outside conversion specifier. Either skip white
+			 * spaces or match characters one by one. If conversion specifier
+			 * is detected, switch to coversion mode. */
+			if (isspace(*fmt)) {
+				/* Skip white spaces in the format string. */
+				while (isspace(*fmt)) {
+					++fmt;
+				}
+				/* Skip white spaces in the input. */
+				do {
+					c = in->pop(in);
+				} while (isspace(c));
+				if (c != -1) {
+					/* Input is not at EOF, so undo the last pop operation. */
+					in->undo(in);
+				}
+			} else if (*fmt == '%' && *(fmt + 1) != '%') {
+				/* Conversion specifier detected. Switch modes. */
+				converting = true;
+				/* Reset the conversion context. */
+				assign_supress = false;
+				assign_alloc = false;
+				width = -1;
+				length_mod = LMOD_NONE;
+				int_conv_unsigned = false;
+				int_conv_base = 0;
+				++fmt;
+			} else {
+				/* One by one matching. */
+				if (*fmt == '%') {
+					/* Escape sequence detected. */
+					++fmt;
+					assert(*fmt == '%');
+				}
+				c = in->pop(in);
+				if (c == -1) {
+					/* Input failure. */
+					break;
+				} else if (c != *fmt) {
+					/* Matching failure. */
+					in->undo(in);
+					matching_failure = true;
+					break;
+				} else {
+					++fmt;
+				}
+			}
+			
+		}
+
+	}
+
+	in->release(in);
+
+	/* This somewhat complicated return value decision is required by POSIX. */
+	int rc;
+	if (matching_failure) {
+		rc = converted_cnt;
+	} else {
+		if (errno == EOK) {
+			rc = converted_cnt > 0 ? converted_cnt : EOF;
+		} else {
+			rc = EOF;
+		}
+	}
+	if (rc == EOF) {
+		/* Caller will not know how many arguments were successfully converted,
+		 * so the deallocation of buffers is our responsibility. */
+		for (int i = 0; i < next_unused_buffer_idx; ++i) {
+			free(buffers[i]);
+			buffers[i] = NULL;
+		}
+		next_unused_buffer_idx = 0;
+	}
+	return rc;
+}
+
+/**
+ * Convert formatted input from the stream.
+ *
+ * @param stream Input stream.
+ * @param format Format description.
+ * @param arg Output items.
+ * @return The number of converted output items or EOF on failure.
+ */
+int posix_vfscanf(
+    FILE *restrict stream, const char *restrict format, va_list arg)
+{
+	_input_provider provider = {
+	    { 0 }, 0, 0, NULL, 0, NULL, _PROV_CONSTRUCTED,
+	    _capture_stream, _pop_stream, _undo_stream,
+	    _borrow_cursor_universal, _return_cursor_stream, _release_stream
+	};
+	provider.source.stream = stream;
+	return _internal_scanf(&provider, format, arg);
+}
+
+/**
+ * Convert formatted input from the string.
+ *
+ * @param s Input string.
+ * @param format Format description.
+ * @param arg Output items.
+ * @return The number of converted output items or EOF on failure.
+ */
+int posix_vsscanf(
+    const char *restrict s, const char *restrict format, va_list arg)
+{
+	_input_provider provider = {
+	    { 0 }, 0, 0, NULL, 0, NULL, _PROV_CONSTRUCTED,
+	    _capture_string, _pop_string, _undo_string,
+	    _borrow_cursor_universal, _return_cursor_string, _release_string
+	};
+	provider.source.string = s;
+	return _internal_scanf(&provider, format, arg);
+}
+
+// FIXME: put the testcases to the app/tester after scanf is included into libc
+
+#if 0
+
+//#include <stdio.h>
+//#include <malloc.h>
+//#include <string.h>
+
+#define test_val(fmt, exp_val, act_val) \
+	if (exp_val == act_val) { \
+		printf("succ, expected "fmt", actual "fmt"\n", exp_val, act_val); \
+	} else { \
+		printf("fail, expected "fmt", actual "fmt"\n", exp_val, act_val); \
+		++fail; \
+	}
+
+#define test_str(fmt, exp_str, act_str) \
+	if (posix_strcmp(exp_str, act_str) == 0) { \
+		printf("succ, expected "fmt", actual "fmt"\n", exp_str, act_str); \
+	} else { \
+		printf("fail, expected "fmt", actual "fmt"\n", exp_str, act_str); \
+		++fail; \
+	}
+
+void __posix_scanf_test(void);
+void __posix_scanf_test(void)
+{
+	int fail = 0;
+
+	int ret;
+
+	unsigned char uhh;
+	signed char shh;
+	unsigned short uh;
+	short sh;
+	unsigned udef;
+	int sdef;
+	unsigned long ul;
+	long sl;
+	unsigned long long ull;
+	long long sll;
+	void *p;
+	
+	float f;
+	double d;
+	long double ld;
+
+	char str[20];
+	char seq[20];
+	char scanset[20];
+
+	char *pstr;
+	char *pseq;
+	char *pscanset;
+	
+	ret = posix_sscanf(
+	    "\n j tt % \t -121314 98765 aqw 0765 0x77 0xABCDEF88 -99 884",
+	    " j tt %%%3hhd%1hhu%3hd %3hu%u aqw%n %lo%llx %p %li %lld",
+	    &shh, &uhh, &sh, &uh, &udef, &sdef, &ul, &ull, &p, &sl, &sll);
+	test_val("%d", -12, shh);
+	test_val("%u", 1, uhh);
+	test_val("%d", 314, sh);
+	test_val("%u", 987, uh);
+	test_val("%u", 65, udef);
+	test_val("%d", 28, sdef);
+	test_val("%lo", (unsigned long) 0765, ul);
+	test_val("%llx", (unsigned long long) 0x77, ull);
+	test_val("%p", (void *) 0xABCDEF88, p);
+	test_val("%ld", (long) -99, sl);
+	test_val("%lld", (long long) 884, sll);
+	test_val("%d", 10, ret);
+
+	ret = posix_sscanf(
+	    "\n \t\t1.0 -0x555.AP10 1234.5678e12",
+	    "%f %lf %Lf",
+	    &f, &d, &ld);
+	test_val("%f", 1.0, f);
+	test_val("%lf", (double) -0x555.AP10, d);
+	test_val("%Lf", (long double) 1234.5678e12, ld);
+	test_val("%d", 3, ret);
+	 
+	ret = posix_sscanf(
+	    "\n\n\thello world    \n",
+	    "%5s %ms",
+	    str, &pstr);
+	test_str("%s", "hello", str);
+	test_str("%s", "world", pstr);
+	test_val("%d", 2, ret);
+	free(pstr);
+
+	ret = posix_sscanf(
+	    "\n\n\thello world    \n",
+	    " %5c %mc",
+	    seq, &pseq);
+	seq[5] = '\0';
+	pseq[1] = '\0';
+	test_str("%s", "hello", seq);
+	test_str("%s", "w", pseq);
+	test_val("%d", 2, ret);
+	free(pseq);
+
+	ret = posix_sscanf(
+	    "\n\n\th-e-l-l-o world-]    \n",
+	    " %9[-eh-o] %m[^]-]",
+	    scanset, &pscanset);
+	test_str("%s", "h-e-l-l-o", scanset);
+	test_str("%s", "world", pscanset);
+	test_val("%d", 2, ret);
+	free(pscanset);
+
+	printf("Failed: %d\n", fail);
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/posix/source/stdlib.c
===================================================================
--- uspace/lib/posix/source/stdlib.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/stdlib.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Standard library definitions.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "internal/common.h"
+#include "posix/stdlib.h"
+
+#include "posix/errno.h"
+#include "posix/fcntl.h"
+#include "posix/limits.h"
+#include "posix/string.h"
+#include "posix/sys/stat.h"
+#include "posix/unistd.h"
+
+#include "libc/sort.h"
+#include "libc/str.h"
+#include "libc/vfs/vfs.h"
+#include "libc/stats.h"
+
+/**
+ * 
+ * @param array
+ * @param count
+ * @param size
+ * @param compare
+ */
+int posix_atexit(void (*func)(void))
+{
+	// TODO: low priority, just a compile-time dependency of binutils
+	not_implemented();
+}
+
+/**
+ * Integer absolute value.
+ * 
+ * @param i Input value.
+ * @return Absolute value of the parameter.
+ */
+int posix_abs(int i)
+{
+	return i < 0 ? -i : i;
+}
+
+/**
+ * Long integer absolute value.
+ * 
+ * @param i Input value.
+ * @return Absolute value of the parameter.
+ */
+long posix_labs(long i)
+{
+	return i < 0 ? -i : i;
+}
+
+/**
+ * Long long integer absolute value.
+ * 
+ * @param i Input value.
+ * @return Absolute value of the parameter.
+ */
+long long posix_llabs(long long i)
+{
+	return i < 0 ? -i : i;
+}
+
+/**
+ * Compute the quotient and remainder of an integer division.
+ *
+ * @param numer Numerator.
+ * @param denom Denominator.
+ * @return Quotient and remainder packed into structure.
+ */
+posix_div_t posix_div(int numer, int denom)
+{
+	return (posix_div_t) { .quot = numer / denom, .rem = numer % denom };
+}
+
+/**
+ * Compute the quotient and remainder of a long integer division.
+ *
+ * @param numer Numerator.
+ * @param denom Denominator.
+ * @return Quotient and remainder packed into structure.
+ */
+posix_ldiv_t posix_ldiv(long numer, long denom)
+{
+	return (posix_ldiv_t) { .quot = numer / denom, .rem = numer % denom };
+}
+
+/**
+ * Compute the quotient and remainder of a long long integer division.
+ *
+ * @param numer Numerator.
+ * @param denom Denominator.
+ * @return Quotient and remainder packed into structure.
+ */
+posix_lldiv_t posix_lldiv(long long numer, long long denom)
+{
+	return (posix_lldiv_t) { .quot = numer / denom, .rem = numer % denom };
+}
+
+/**
+ * Private helper function that serves as a compare function for qsort().
+ *
+ * @param elem1 First element to compare.
+ * @param elem2 Second element to compare.
+ * @param compare Comparison function without userdata parameter.
+ * @return Relative ordering of the elements.
+ */
+static int sort_compare_wrapper(void *elem1, void *elem2, void *userdata)
+{
+	int (*compare)(const void *, const void *) = userdata;
+	int ret = compare(elem1, elem2);
+	
+	/* Native qsort internals expect this. */
+	if (ret < 0) {
+		return -1;
+	} else if (ret > 0) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+/**
+ * Array sorting utilizing the quicksort algorithm.
+ *
+ * @param array Array of elements to sort.
+ * @param count Number of elements in the array.
+ * @param size Width of each element.
+ * @param compare Decides relative ordering of two elements.
+ */
+void posix_qsort(void *array, size_t count, size_t size,
+    int (*compare)(const void *, const void *))
+{
+	/* Implemented in libc with one extra argument. */
+	qsort(array, count, size, sort_compare_wrapper, compare);
+}
+
+/**
+ * Binary search in a sorted array.
+ *
+ * @param key Object to search for.
+ * @param base Pointer to the first element of the array.
+ * @param nmemb Number of elements in the array.
+ * @param size Size of each array element.
+ * @param compar Comparison function.
+ * @return Pointer to a matching element, or NULL if none can be found.
+ */
+void *posix_bsearch(const void *key, const void *base,
+    size_t nmemb, size_t size, int (*compar)(const void *, const void *))
+{
+	while (nmemb > 0) {
+		const void *middle = base + (nmemb / 2) * size;
+		int cmp = compar(key, middle);
+		if (cmp == 0) {
+			return (void *) middle;
+		}
+		if (middle == base) {
+			/* There is just one member left to check and it
+			 * didn't match the key. Avoid infinite loop.
+			 */
+			break;
+		}
+		if (cmp < 0) {
+			nmemb = nmemb / 2;
+		} else if (cmp > 0) {
+			nmemb = nmemb - (nmemb / 2);
+			base = middle;
+		}
+	}
+	
+	return NULL;
+}
+
+/**
+ * Retrieve a value of the given environment variable.
+ *
+ * Since HelenOS doesn't support env variables at the moment,
+ * this function always returns NULL.
+ *
+ * @param name Name of the variable.
+ * @return Value of the variable or NULL if such variable does not exist.
+ */
+char *posix_getenv(const char *name)
+{
+	return NULL;
+}
+
+/**
+ * 
+ * @param name
+ * @param resolved
+ * @return
+ */
+int posix_putenv(char *string)
+{
+	// TODO: low priority, just a compile-time dependency of binutils
+	not_implemented();
+}
+
+/**
+ * Issue a command.
+ *
+ * @param string String to be passed to a command interpreter or NULL.
+ * @return Termination status of the command if the command is not NULL,
+ *     otherwise indicate whether there is a command interpreter (non-zero)
+ *     or not (zero).
+ */
+int posix_system(const char *string) {
+	// TODO: does nothing at the moment
+	return 0;
+}
+
+/**
+ * Resolve absolute pathname.
+ * 
+ * @param name Pathname to be resolved.
+ * @param resolved Either buffer for the resolved absolute pathname or NULL.
+ * @return On success, either resolved (if it was not NULL) or pointer to the
+ *     newly allocated buffer containing the absolute pathname (if resolved was
+ *     NULL). Otherwise NULL.
+ *
+ */
+char *posix_realpath(const char *restrict name, char *restrict resolved)
+{
+	#ifndef PATH_MAX
+		assert(resolved == NULL);
+	#endif
+	
+	if (name == NULL) {
+		errno = EINVAL;
+		return NULL;
+	}
+	
+	// TODO: symlink resolution
+	
+	/* Function absolutize is implemented in libc and declared in vfs.h.
+	 * No more processing is required as HelenOS doesn't have symlinks
+	 * so far (as far as I can tell), although this function will need
+	 * to be updated when that support is implemented.
+	 */
+	char* absolute = absolutize(name, NULL);
+	
+	if (absolute == NULL) {
+		/* POSIX requires some specific errnos to be set
+		 * for some cases, but there is no way to find out from
+		 * absolutize().
+		 */
+		errno = EINVAL;
+		return NULL;
+	}
+	
+	if (resolved == NULL) {
+		return absolute;
+	} else {
+		#ifdef PATH_MAX
+			str_cpy(resolved, PATH_MAX, absolute);
+		#endif
+		free(absolute);
+		return resolved;
+	}
+}
+
+/**
+ * Converts a string representation of a floating-point number to
+ * its native representation. See posix_strtold().
+ *
+ * @param nptr String representation of a floating-point number.
+ * @return Double-precision number resulting from the string conversion.
+ */
+double posix_atof(const char *nptr)
+{
+	return posix_strtod(nptr, NULL);
+}
+
+/**
+ * Converts a string representation of a floating-point number to
+ * its native representation. See posix_strtold().
+ *
+ * @param nptr String representation of a floating-point number.
+ * @param endptr Pointer to the final part of the string which
+ *     was not used for conversion.
+ * @return Single-precision number resulting from the string conversion.
+ */
+float posix_strtof(const char *restrict nptr, char **restrict endptr)
+{
+	return (float) posix_strtold(nptr, endptr);
+}
+
+/**
+ * Converts a string representation of a floating-point number to
+ * its native representation. See posix_strtold().
+ *
+ * @param nptr String representation of a floating-point number.
+ * @param endptr Pointer to the final part of the string which
+ *     was not used for conversion.
+ * @return Double-precision number resulting from the string conversion.
+ */
+double posix_strtod(const char *restrict nptr, char **restrict endptr)
+{
+	return (double) posix_strtold(nptr, endptr);
+}
+
+/**
+ * Allocate memory chunk.
+ *
+ * @param size Size of the chunk to allocate.
+ * @return Either pointer to the allocated chunk or NULL if not possible.
+ */
+void *posix_malloc(size_t size)
+{
+	return malloc(size);
+}
+
+/**
+ * Allocate memory for an array of elements.
+ *
+ * @param nelem Number of elements in the array.
+ * @param elsize Size of each element.
+ * @return Either pointer to the allocated array or NULL if not possible.
+ */
+void *posix_calloc(size_t nelem, size_t elsize)
+{
+	return calloc(nelem, elsize);
+}
+
+/**
+ * Reallocate memory chunk to a new size.
+ *
+ * @param ptr Memory chunk to reallocate. Might be NULL.
+ * @param size Size of the reallocated chunk. Might be zero.
+ * @return Either NULL or the pointer to the newly reallocated chunk.
+ */
+void *posix_realloc(void *ptr, size_t size)
+{
+	if (ptr != NULL && size == 0) {
+		/* Native realloc does not handle this special case. */
+		free(ptr);
+		return NULL;
+	} else {
+		return realloc(ptr, size);
+	}
+}
+
+/**
+ * Free allocated memory chunk.
+ *
+ * @param ptr Memory chunk to be freed.
+ */
+void posix_free(void *ptr)
+{
+	if (ptr) {
+		free(ptr);
+	}
+}
+
+/**
+ * Creates and opens an unique temporary file from template.
+ *
+ * @param tmpl Template. Last six characters must be XXXXXX.
+ * @return The opened file descriptor or -1 on error.
+ */
+int posix_mkstemp(char *tmpl)
+{
+	int fd = -1;
+	
+	char *tptr = tmpl + posix_strlen(tmpl) - 6;
+	
+	while (fd < 0) {
+		if (*posix_mktemp(tmpl) == '\0') {
+			/* Errno set by mktemp(). */
+			return -1;
+		}
+		
+		fd = open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+		
+		if (fd == -1) {
+			/* Restore template to it's original state. */
+			snprintf(tptr, 7, "XXXXXX");
+		}
+	}
+	
+	return fd;
+}
+
+/**
+ * Creates an unique temporary file name from template.
+ *
+ * @param tmpl Template. Last six characters must be XXXXXX.
+ * @return The value of tmpl. The template is modified in place.
+ *    If no temporary file name can be created, template is
+ *    reduced to an empty string.
+ */
+char *posix_mktemp(char *tmpl)
+{
+	int tmpl_len = posix_strlen(tmpl);
+	if (tmpl_len < 6) {
+		errno = EINVAL;
+		*tmpl = '\0';
+		return tmpl;
+	}
+	
+	char *tptr = tmpl + tmpl_len - 6;
+	if (posix_strcmp(tptr, "XXXXXX") != 0) {
+		errno = EINVAL;
+		*tmpl = '\0';
+		return tmpl;
+	}
+	
+	static int seq = 0;
+	
+	for (; seq < 1000000; ++seq) {
+		snprintf(tptr, 7, "%06d", seq);
+		
+		int orig_errno = errno;
+		errno = 0;
+		/* Check if the file exists. */
+		if (posix_access(tmpl, F_OK) == -1) {
+			if (errno == ENOENT) {
+				errno = orig_errno;
+				break;
+			} else {
+				/* errno set by access() */
+				*tmpl = '\0';
+				return tmpl;
+			}
+		}
+	}
+	
+	if (seq == 10000000) {
+		errno = EEXIST;
+		*tmpl = '\0';
+		return tmpl;
+	}
+	
+	return tmpl;
+}
+
+/**
+ * Get system load average statistics.
+ *
+ * @param loadavg Array where the load averages shall be placed.
+ * @param nelem Maximum number of elements to be placed into the array.
+ * @return Number of elements placed into the array on success, -1 otherwise.
+ */
+int bsd_getloadavg(double loadavg[], int nelem)
+{
+	assert(nelem > 0);
+	
+	size_t count;
+	load_t *loads = stats_get_load(&count);
+	
+	if (loads == NULL) {
+		return -1;
+	}
+	
+	if (((size_t) nelem) < count) {
+		count = nelem;
+	}
+	
+	for (size_t i = 0; i < count; ++i) {
+		loadavg[i] = (double) loads[i];
+	}
+	
+	free(loads);
+	return count;
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/stdlib/strtol.c
===================================================================
--- uspace/lib/posix/source/stdlib/strtol.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/stdlib/strtol.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Backend for integer conversions.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "../internal/common.h"
+#include "posix/stdlib.h"
+
+#include "posix/ctype.h"
+#include "posix/errno.h"
+#include "posix/inttypes.h"
+#include "posix/limits.h"
+
+#define intmax_t posix_intmax_t
+#define uintmax_t posix_uintmax_t
+
+/**
+ * Decides whether a digit belongs to a particular base.
+ *
+ * @param c Character representation of the digit.
+ * @param base Base against which the digit shall be tested.
+ * @return True if the digit belongs to the base, false otherwise.
+ */
+static inline bool is_digit_in_base(int c, int base)
+{
+	if (base <= 10) {
+		return c >= '0' && c < '0' + base;
+	} else {
+		return isdigit(c) ||
+		    (tolower(c) >= 'a' && tolower(c) < ('a' + base - 10));
+	}
+}
+
+/**
+ * Derive a digit from its character representation.
+ *
+ * @param c Character representation of the digit.
+ * @return Digit value represented by an integer.
+ */
+static inline int digit_value(int c)
+{
+	if (c <= '9') {
+		return c - '0';
+	} else {
+		return 10 + tolower(c) - 'a';
+	}
+}
+
+/**
+ * Generic function for parsing an integer from it's string representation.
+ * Different variants differ in lower and upper bounds.
+ * The parsed string returned by this function is always positive, sign
+ * information is provided via a dedicated parameter.
+ *
+ * @param nptr Input string.
+ * @param endptr If non-NULL, *endptr is set to the position of the first
+ *     unrecognized character. If no digit has been parsed, value of
+ *     nptr is stored there (regardless of any skipped characters at the
+ *     beginning).
+ * @param base Expected base of the string representation. If 0, base is
+ *    determined to be decimal, octal or hexadecimal using the same rules
+ *    as C syntax. Otherwise, value must be between 2 and 36, inclusive.
+ * @param min_value Lower bound for the resulting conversion.
+ * @param max_value Upper bound for the resulting conversion.
+ * @param out_negative Either NULL for unsigned conversion or a pointer to the
+ *     bool variable into which shall be placed the negativity of the resulting
+ *     converted value.
+ * @return The absolute value of the parsed value, or the closest in-range value
+ *     if the parsed value is out of range. If the input is invalid, zero is
+ *     returned and errno is set to EINVAL.
+ */
+static inline uintmax_t internal_strtol(
+    const char *restrict nptr, char **restrict endptr, int base,
+    const intmax_t min_value, const uintmax_t max_value,
+    bool *restrict out_negative)
+{
+	if (nptr == NULL) {
+		errno = EINVAL;
+		return 0;
+	}
+	
+	if (base < 0 || base == 1 || base > 36) {
+		errno = EINVAL;
+		return 0;
+	}
+	
+	/* The maximal absolute value that can be returned in this run.
+	 * Depends on sign.
+	 */
+	uintmax_t real_max_value = max_value;
+	
+	/* Current index in the input string. */
+	size_t i = 0;
+	bool negative = false;
+	
+	/* Skip whitespace. */
+	while (isspace(nptr[i])) {
+		i++;
+	}
+	
+	/* Parse sign. */
+	switch (nptr[i]) {
+	case '-':
+		negative = true;
+		
+		/* The strange computation is are there to avoid a corner case
+		 * where -min_value can't be represented in intmax_t.
+		 * (I'm not exactly sure what the semantics are in such a
+		 *  case, but this should be safe for any case.)
+		 */
+		real_max_value = (min_value == 0)
+		    ? 0
+		    :(((uintmax_t) -(min_value + 1)) + 1);
+		
+		/* fallthrough */
+	case '+':
+		i++;
+	}
+	
+	/* Figure out the base. */
+	switch (base) {
+	case 0:
+		if (nptr[i] == '0') {
+			if (tolower(nptr[i + 1]) == 'x') {
+				/* 0x... is hex. */
+				base = 16;
+				i += 2;
+			} else {
+				/* 0... is octal. */
+				base = 8;
+			}
+		} else {
+			/* Anything else is decimal by default. */
+			base = 10;
+		}
+		break;
+	case 16:
+		/* Allow hex number to be prefixed with "0x". */
+		if (nptr[i] == '0' && tolower(nptr[i + 1]) == 'x') {
+			i += 2;
+		}
+		break;
+	}
+	
+	if (!is_digit_in_base(nptr[i], base)) {
+		/* No digits to parse, invalid input. */
+		
+		errno = EINVAL;
+		if (endptr != NULL) {
+			*endptr = (char *) nptr;
+		}
+		return 0;
+	}
+	
+	/* Maximal value to which a digit can be added without a risk
+	 * of overflow.
+	 */
+	uintmax_t max_safe_value = (real_max_value - base + 1) / base;
+	
+	uintmax_t result = 0;
+	
+	if (real_max_value == 0) {
+		/* Special case when a negative number is parsed as
+		 * unsigned integer. Only -0 is accepted.
+		 */
+		
+		while (is_digit_in_base(nptr[i], base)) {
+			if (nptr[i] != '0') {
+				errno = ERANGE;
+				result = 0;
+			}
+			i++;
+		}
+	}
+	
+	while (is_digit_in_base(nptr[i], base)) {
+		int digit = digit_value(nptr[i]);
+		
+		if (result > max_safe_value) {
+			/* corner case, check for overflow */
+			
+			uintmax_t boundary = (real_max_value - digit) / base;
+			
+			if (result > boundary) {
+				/* overflow */
+				errno = ERANGE;
+				result = real_max_value;
+				break;
+			}
+		}
+		
+		result = result * base + digit;
+		i++;
+	}
+	
+	if (endptr != NULL) {
+		/* Move the pointer to the end of the number,
+		 * in case it isn't there already.
+		 */
+		while (is_digit_in_base(nptr[i], base)) {
+			i++;
+		}
+		
+		*endptr = (char *) &nptr[i];
+	}
+	if (out_negative != NULL) {
+		*out_negative = negative;
+	}
+	return result;
+}
+
+/**
+ * Convert a string to an integer.
+ *
+ * @param nptr Input string.
+ * @return Result of the conversion.
+ */
+int posix_atoi(const char *nptr)
+{
+	bool neg = false;
+	uintmax_t result =
+	    internal_strtol(nptr, NULL, 10, INT_MIN, INT_MAX, &neg);
+
+	return (neg ? ((int) -result) : (int) result);
+}
+
+/**
+ * Convert a string to a long integer.
+ *
+ * @param nptr Input string.
+ * @return Result of the conversion.
+ */
+long posix_atol(const char *nptr)
+{
+	bool neg = false;
+	uintmax_t result =
+	    internal_strtol(nptr, NULL, 10, LONG_MIN, LONG_MAX, &neg);
+
+	return (neg ? ((long) -result) : (long) result);
+}
+
+/**
+ * Convert a string to a long long integer.
+ *
+ * @param nptr Input string.
+ * @return Result of the conversion.
+ */
+long long posix_atoll(const char *nptr)
+{
+	bool neg = false;
+	uintmax_t result =
+	    internal_strtol(nptr, NULL, 10, LLONG_MIN, LLONG_MAX, &neg);
+
+	return (neg ? ((long long) -result) : (long long) result);
+}
+
+/**
+ * Convert a string to a long integer.
+ *
+ * @param nptr Input string.
+ * @param endptr Pointer to the final part of the string which
+ *     was not used for conversion.
+ * @param base Expected base of the string representation.
+ * @return Result of the conversion.
+ */
+long posix_strtol(const char *restrict nptr, char **restrict endptr, int base)
+{
+	bool neg = false;
+	uintmax_t result =
+	    internal_strtol(nptr, endptr, base, LONG_MIN, LONG_MAX, &neg);
+
+	return (neg ? ((long) -result) : ((long) result));
+}
+
+/**
+ * Convert a string to a long long integer.
+ *
+ * @param nptr Input string.
+ * @param endptr Pointer to the final part of the string which
+ *     was not used for conversion.
+ * @param base Expected base of the string representation.
+ * @return Result of the conversion.
+ */
+long long posix_strtoll(
+    const char *restrict nptr, char **restrict endptr, int base)
+{
+	bool neg = false;
+	uintmax_t result =
+	    internal_strtol(nptr, endptr, base, LLONG_MIN, LLONG_MAX, &neg);
+
+	return (neg ? ((long long) -result) : (long long) result);
+}
+
+/**
+ * Convert a string to a largest signed integer type.
+ *
+ * @param nptr Input string.
+ * @param endptr Pointer to the final part of the string which
+ *     was not used for conversion.
+ * @param base Expected base of the string representation.
+ * @return Result of the conversion.
+ */
+intmax_t posix_strtoimax(
+    const char *restrict nptr, char **restrict endptr, int base)
+{
+	bool neg = false;
+	uintmax_t result =
+	    internal_strtol(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX, &neg);
+
+	return (neg ? ((intmax_t) -result) : (intmax_t) result);
+}
+
+/**
+ * Convert a string to an unsigned long integer.
+ *
+ * @param nptr Input string.
+ * @param endptr Pointer to the final part of the string which
+ *     was not used for conversion.
+ * @param base Expected base of the string representation.
+ * @return Result of the conversion.
+ */
+unsigned long posix_strtoul(
+    const char *restrict nptr, char **restrict endptr, int base)
+{
+	uintmax_t result =
+	    internal_strtol(nptr, endptr, base, 0, ULONG_MAX, NULL);
+
+	return (unsigned long) result;
+}
+
+/**
+ * Convert a string to an unsigned long long integer.
+ *
+ * @param nptr Input string.
+ * @param endptr Pointer to the final part of the string which
+ *     was not used for conversion.
+ * @param base Expected base of the string representation.
+ * @return Result of the conversion.
+ */
+unsigned long long posix_strtoull(
+    const char *restrict nptr, char **restrict endptr, int base)
+{
+	uintmax_t result =
+	    internal_strtol(nptr, endptr, base, 0, ULLONG_MAX, NULL);
+
+	return (unsigned long long) result;
+}
+
+/**
+ * Convert a string to a largest unsigned integer type.
+ *
+ * @param nptr Input string.
+ * @param endptr Pointer to the final part of the string which
+ *     was not used for conversion.
+ * @param base Expected base of the string representation.
+ * @return Result of the conversion.
+ */
+uintmax_t posix_strtoumax(
+    const char *restrict nptr, char **restrict endptr, int base)
+{
+	uintmax_t result =
+	    internal_strtol(nptr, endptr, base, 0, UINTMAX_MAX, NULL);
+
+	return result;
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/stdlib/strtold.c
===================================================================
--- uspace/lib/posix/source/stdlib/strtold.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/stdlib/strtold.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Backend for floating point conversions.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+/* Must be first. */
+#include "posix/stdbool.h"
+
+#include "../internal/common.h"
+#include "posix/stdlib.h"
+
+#include "posix/assert.h"
+#include "posix/ctype.h"
+#include "posix/stdint.h"
+#include "posix/strings.h"
+#include "posix/errno.h"
+#include "posix/limits.h"
+
+#include "posix/float.h"
+
+#ifndef HUGE_VALL
+	#define HUGE_VALL (+1.0l / +0.0l)
+#endif
+
+#ifndef abs
+	#define abs(x) (((x) < 0) ? -(x) : (x))
+#endif
+
+/* If the constants are not defined, use double precision as default. */
+#ifndef LDBL_MANT_DIG
+	#define LDBL_MANT_DIG 53
+#endif
+#ifndef LDBL_MAX_EXP
+	#define LDBL_MAX_EXP 1024
+#endif
+#ifndef LDBL_MIN_EXP
+	#define LDBL_MIN_EXP (-1021)
+#endif
+#ifndef LDBL_DIG
+	#define LDBL_DIG 15
+#endif
+#ifndef LDBL_MIN
+	#define LDBL_MIN 2.2250738585072014E-308
+#endif
+
+/* power functions ************************************************************/
+
+#if LDBL_MAX_EXP >= 16384
+const int MAX_POW5 = 12;
+#else
+const int MAX_POW5 = 8;
+#endif
+
+/* The value at index i is approximately 5**(2**i). */
+long double pow5[] = {
+	0x5p0l,
+	0x19p0l,
+	0x271p0l,
+	0x5F5E1p0l,
+	0x2386F26FC1p0l,
+	0x4EE2D6D415B85ACEF81p0l,
+	0x184F03E93FF9F4DAA797ED6E38ED6p36l,
+	0x127748F9301D319BF8CDE66D86D62p185l,
+	0x154FDD7F73BF3BD1BBB77203731FDp482l,
+#if LDBL_MAX_EXP >= 16384
+	0x1C633415D4C1D238D98CAB8A978A0p1076l,
+	0x192ECEB0D02EA182ECA1A7A51E316p2265l,
+	0x13D1676BB8A7ABBC94E9A519C6535p4643l,
+	0x188C0A40514412F3592982A7F0094p9398l,
+#endif
+};
+
+#if LDBL_MAX_EXP >= 16384
+const int MAX_POW2 = 15;
+#else
+const int MAX_POW2 = 9;
+#endif
+
+/* Powers of two. */
+long double pow2[] = {
+	0x1P1l,
+	0x1P2l,
+	0x1P4l,
+	0x1P8l,
+	0x1P16l,
+	0x1P32l,
+	0x1P64l,
+	0x1P128l,
+	0x1P256l,
+	0x1P512l,
+#if LDBL_MAX_EXP >= 16384
+	0x1P1024l,
+	0x1P2048l,
+	0x1P4096l,
+	0x1P8192l,
+#endif
+};
+
+/**
+ * Multiplies a number by a power of five.
+ * The result may be inexact and may not be the best possible approximation.
+ *
+ * @param mant Number to be multiplied.
+ * @param exp Base 5 exponent.
+ * @return mant multiplied by 5**exp
+ */
+static long double mul_pow5(long double mant, int exp)
+{
+	if (mant == 0.0l || mant == HUGE_VALL) {
+		return mant;
+	}
+	
+	if (abs(exp) >> (MAX_POW5 + 1) != 0) {
+		/* Too large exponent. */
+		errno = ERANGE;
+		return exp < 0 ? LDBL_MIN : HUGE_VALL;
+	}
+	
+	if (exp < 0) {
+		exp = abs(exp);
+		for (int bit = 0; bit <= MAX_POW5; ++bit) {
+			/* Multiply by powers of five bit-by-bit. */
+			if (((exp >> bit) & 1) != 0) {
+				mant /= pow5[bit];
+				if (mant == 0.0l) {
+					/* Underflow. */
+					mant = LDBL_MIN;
+					errno = ERANGE;
+					break;
+				}
+			}
+		}
+	} else {
+		for (int bit = 0; bit <= MAX_POW5; ++bit) {
+			/* Multiply by powers of five bit-by-bit. */
+			if (((exp >> bit) & 1) != 0) {
+				mant *= pow5[bit];
+				if (mant == HUGE_VALL) {
+					/* Overflow. */
+					errno = ERANGE;
+					break;
+				}
+			}
+		}
+	}
+	
+	return mant;
+}
+
+/**
+ * Multiplies a number by a power of two. This is always exact.
+ *
+ * @param mant Number to be multiplied.
+ * @param exp Base 2 exponent.
+ * @return mant multiplied by 2**exp.
+ */
+static long double mul_pow2(long double mant, int exp)
+{
+	if (mant == 0.0l || mant == HUGE_VALL) {
+		return mant;
+	}
+	
+	if (exp > LDBL_MAX_EXP || exp < LDBL_MIN_EXP) {
+		errno = ERANGE;
+		return exp < 0 ? LDBL_MIN : HUGE_VALL;
+	}
+	
+	if (exp < 0) {
+		exp = abs(exp);
+		for (int i = 0; i <= MAX_POW2; ++i) {
+			if (((exp >> i) & 1) != 0) {
+				mant /= pow2[i];
+				if (mant == 0.0l) {
+					mant = LDBL_MIN;
+					errno = ERANGE;
+					break;
+				}
+			}
+		}
+	} else {
+		for (int i = 0; i <= MAX_POW2; ++i) {
+			if (((exp >> i) & 1) != 0) {
+				mant *= pow2[i];
+				if (mant == HUGE_VALL) {
+					errno = ERANGE;
+					break;
+				}
+			}
+		}
+	}
+	
+	return mant;
+}
+
+/* end power functions ********************************************************/
+
+
+
+/**
+ * Convert decimal string representation of the floating point number.
+ * Function expects the string pointer to be already pointed at the first
+ * digit (i.e. leading optional sign was already consumed by the caller).
+ * 
+ * @param sptr Pointer to the storage of the string pointer. Upon successful
+ *     conversion, the string pointer is updated to point to the first
+ *     unrecognized character.
+ * @return An approximate representation of the input floating-point number.
+ */
+static long double parse_decimal(const char **sptr)
+{
+	assert(sptr != NULL);
+	assert (*sptr != NULL);
+	
+	const int DEC_BASE = 10;
+	const char DECIMAL_POINT = '.';
+	const char EXPONENT_MARK = 'e';
+	
+	const char *str = *sptr;
+	long double significand = 0;
+	long exponent = 0;
+	
+	/* number of digits parsed so far */
+	int parsed_digits = 0;
+	bool after_decimal = false;
+	
+	while (isdigit(*str) || (!after_decimal && *str == DECIMAL_POINT)) {
+		if (*str == DECIMAL_POINT) {
+			after_decimal = true;
+			str++;
+			continue;
+		}
+		
+		if (parsed_digits == 0 && *str == '0') {
+			/* Nothing, just skip leading zeros. */
+		} else if (parsed_digits < LDBL_DIG) {
+			significand = significand * DEC_BASE + (*str - '0');
+			parsed_digits++;
+		} else {
+			exponent++;
+		}
+		
+		if (after_decimal) {
+			/* Decrement exponent if we are parsing the fractional part. */
+			exponent--;
+		}
+		
+		str++;
+	}
+	
+	/* exponent */
+	if (tolower(*str) == EXPONENT_MARK) {
+		str++;
+		
+		/* Returns MIN/MAX value on error, which is ok. */
+		long exp = strtol(str, (char **) &str, DEC_BASE);
+		
+		if (exponent > 0 && exp > LONG_MAX - exponent) {
+			exponent = LONG_MAX;
+		} else if (exponent < 0 && exp < LONG_MIN - exponent) {
+			exponent = LONG_MIN;
+		} else {
+			exponent += exp;
+		}
+	}
+	
+	*sptr = str;
+	
+	/* Return multiplied by a power of ten. */
+	return mul_pow2(mul_pow5(significand, exponent), exponent);
+}
+
+/**
+ * Derive a hexadecimal digit from its character representation.
+ * 
+ * @param ch Character representation of the hexadecimal digit.
+ * @return Digit value represented by an integer.
+ */
+static inline int hex_value(char ch)
+{
+	if (ch <= '9') {
+		return ch - '0';
+	} else {
+		return 10 + tolower(ch) - 'a';
+	}
+}
+
+/**
+ * Convert hexadecimal string representation of the floating point number.
+ * Function expects the string pointer to be already pointed at the first
+ * digit (i.e. leading optional sign and 0x prefix were already consumed
+ * by the caller).
+ *
+ * @param sptr Pointer to the storage of the string pointer. Upon successful
+ *     conversion, the string pointer is updated to point to the first
+ *     unrecognized character.
+ * @return Representation of the input floating-point number.
+ */
+static long double parse_hexadecimal(const char **sptr)
+{
+	assert(sptr != NULL && *sptr != NULL);
+	
+	const int DEC_BASE = 10;
+	const int HEX_BASE = 16;
+	const char DECIMAL_POINT = '.';
+	const char EXPONENT_MARK = 'p';
+	
+	const char *str = *sptr;
+	long double significand = 0;
+	long exponent = 0;
+	
+	/* number of bits parsed so far */
+	int parsed_bits = 0;
+	bool after_decimal = false;
+	
+	while (posix_isxdigit(*str) || (!after_decimal && *str == DECIMAL_POINT)) {
+		if (*str == DECIMAL_POINT) {
+			after_decimal = true;
+			str++;
+			continue;
+		}
+		
+		if (parsed_bits == 0 && *str == '0') {
+			/* Nothing, just skip leading zeros. */
+		} else if (parsed_bits <= LDBL_MANT_DIG) {
+			significand = significand * HEX_BASE + hex_value(*str);
+			parsed_bits += 4;
+		} else {
+			exponent += 4;
+		}
+		
+		if (after_decimal) {
+			exponent -= 4;
+		}
+		
+		str++;
+	}
+	
+	/* exponent */
+	if (tolower(*str) == EXPONENT_MARK) {
+		str++;
+		
+		/* Returns MIN/MAX value on error, which is ok. */
+		long exp = strtol(str, (char **) &str, DEC_BASE);
+		
+		if (exponent > 0 && exp > LONG_MAX - exponent) {
+			exponent = LONG_MAX;
+		} else if (exponent < 0 && exp < LONG_MIN - exponent) {
+			exponent = LONG_MIN;
+		} else {
+			exponent += exp;
+		}
+	}
+	
+	*sptr = str;
+	
+	/* Return multiplied by a power of two. */
+	return mul_pow2(significand, exponent);
+}
+
+/**
+ * Converts a string representation of a floating-point number to
+ * its native representation. Largely POSIX compliant, except for
+ * locale differences (always uses '.' at the moment) and rounding.
+ * Decimal strings are NOT guaranteed to be correctly rounded. This function
+ * should return a good enough approximation for most purposes but if you
+ * depend on a precise conversion, use hexadecimal representation.
+ * Hexadecimal strings are currently always rounded towards zero, regardless
+ * of the current rounding mode.
+ *
+ * @param nptr Input string.
+ * @param endptr If non-NULL, *endptr is set to the position of the first
+ *     unrecognized character.
+ * @return An approximate representation of the input floating-point number.
+ */
+long double posix_strtold(const char *restrict nptr, char **restrict endptr)
+{
+	assert(nptr != NULL);
+	
+	const int RADIX = '.';
+	
+	/* minus sign */
+	bool negative = false;
+	/* current position in the string */
+	int i = 0;
+	
+	/* skip whitespace */
+	while (isspace(nptr[i])) {
+		i++;
+	}
+	
+	/* parse sign */
+	switch (nptr[i]) {
+	case '-':
+		negative = true;
+		/* fallthrough */
+	case '+':
+		i++;
+	}
+	
+	/* check for NaN */
+	if (posix_strncasecmp(&nptr[i], "nan", 3) == 0) {
+		// FIXME: return NaN
+		// TODO: handle the parenthesised case
+		
+		if (endptr != NULL) {
+			*endptr = (char *) nptr;
+		}
+		errno = EINVAL;
+		return 0;
+	}
+	
+	/* check for Infinity */
+	if (posix_strncasecmp(&nptr[i], "inf", 3) == 0) {
+		i += 3;
+		if (posix_strncasecmp(&nptr[i], "inity", 5) == 0) {
+			i += 5;
+		}
+		
+		if (endptr != NULL) {
+			*endptr = (char *) &nptr[i];
+		}
+		return negative ? -HUGE_VALL : +HUGE_VALL;
+	}
+
+	/* check for a hex number */
+	if (nptr[i] == '0' && tolower(nptr[i + 1]) == 'x' &&
+	    (posix_isxdigit(nptr[i + 2]) ||
+	    (nptr[i + 2] == RADIX && posix_isxdigit(nptr[i + 3])))) {
+		i += 2;
+		
+		const char *ptr = &nptr[i];
+		/* this call sets errno if appropriate. */
+		long double result = parse_hexadecimal(&ptr);
+		if (endptr != NULL) {
+			*endptr = (char *) ptr;
+		}
+		return negative ? -result : result;
+	}
+	
+	/* check for a decimal number */
+	if (isdigit(nptr[i]) || (nptr[i] == RADIX && isdigit(nptr[i + 1]))) {
+		const char *ptr = &nptr[i];
+		/* this call sets errno if appropriate. */
+		long double result = parse_decimal(&ptr);
+		if (endptr != NULL) {
+			*endptr = (char *) ptr;
+		}
+		return negative ? -result : result;
+	}
+	
+	/* nothing to parse */
+	if (endptr != NULL) {
+		*endptr = (char *) nptr;
+	}
+	errno = EINVAL;
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/string.c
===================================================================
--- uspace/lib/posix/source/string.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/string.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,754 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file String manipulation.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "internal/common.h"
+#include "posix/string.h"
+
+#include "posix/assert.h"
+#include "posix/errno.h"
+#include "posix/limits.h"
+#include "posix/stdlib.h"
+#include "posix/signal.h"
+
+#include "libc/str_error.h"
+
+/**
+ * The same as strpbrk, except it returns pointer to the nul terminator
+ * if no occurence is found.
+ *
+ * @param s1 String in which to look for the bytes.
+ * @param s2 String of bytes to look for.
+ * @return Pointer to the found byte on success, pointer to the
+ *     string terminator otherwise.
+ */
+static char *strpbrk_null(const char *s1, const char *s2)
+{
+	while (!posix_strchr(s2, *s1)) {
+		++s1;
+	}
+	
+	return (char *) s1;
+}
+
+/**
+ * Copy a string.
+ *
+ * @param dest Destination pre-allocated buffer.
+ * @param src Source string to be copied.
+ * @return Pointer to the destination buffer.
+ */
+char *posix_strcpy(char *restrict dest, const char *restrict src)
+{
+	posix_stpcpy(dest, src);
+	return dest;
+}
+
+/**
+ * Copy fixed length string.
+ *
+ * @param dest Destination pre-allocated buffer.
+ * @param src Source string to be copied.
+ * @param n Number of bytes to be stored into destination buffer.
+ * @return Pointer to the destination buffer.
+ */
+char *posix_strncpy(char *restrict dest, const char *restrict src, size_t n)
+{
+	posix_stpncpy(dest, src, n);
+	return dest;
+}
+
+/**
+ * Copy a string.
+ *
+ * @param dest Destination pre-allocated buffer.
+ * @param src Source string to be copied.
+ * @return Pointer to the nul character in the destination string.
+ */
+char *posix_stpcpy(char *restrict dest, const char *restrict src)
+{
+	assert(dest != NULL);
+	assert(src != NULL);
+
+	for (size_t i = 0; ; ++i) {
+		dest[i] = src[i];
+		
+		if (src[i] == '\0') {
+			/* pointer to the terminating nul character */
+			return &dest[i];
+		}
+	}
+	
+	/* unreachable */
+	return NULL;
+}
+
+/**
+ * Copy fixed length string.
+ *
+ * @param dest Destination pre-allocated buffer.
+ * @param src Source string to be copied.
+ * @param n Number of bytes to be stored into destination buffer.
+ * @return Pointer to the first written nul character or &dest[n].
+ */
+char *posix_stpncpy(char *restrict dest, const char *restrict src, size_t n)
+{
+	assert(dest != NULL);
+	assert(src != NULL);
+
+	for (size_t i = 0; i < n; ++i) {
+		dest[i] = src[i];
+	
+		/* the standard requires that nul characters
+		 * are appended to the length of n, in case src is shorter
+		 */
+		if (src[i] == '\0') {
+			char *result = &dest[i];
+			for (++i; i < n; ++i) {
+				dest[i] = '\0';
+			}
+			return result;
+		}
+	}
+	
+	return &dest[n];
+}
+
+/**
+ * Concatenate two strings.
+ *
+ * @param dest String to which src shall be appended.
+ * @param src String to be appended after dest.
+ * @return Pointer to destination buffer.
+ */
+char *posix_strcat(char *restrict dest, const char *restrict src)
+{
+	assert(dest != NULL);
+	assert(src != NULL);
+
+	posix_strcpy(posix_strchr(dest, '\0'), src);
+	return dest;
+}
+
+/**
+ * Concatenate a string with part of another.
+ *
+ * @param dest String to which part of src shall be appended.
+ * @param src String whose part shall be appended after dest.
+ * @param n Number of bytes to append after dest.
+ * @return Pointer to destination buffer.
+ */
+char *posix_strncat(char *restrict dest, const char *restrict src, size_t n)
+{
+	assert(dest != NULL);
+	assert(src != NULL);
+
+	char *zeroptr = posix_strncpy(posix_strchr(dest, '\0'), src, n);
+	/* strncpy doesn't append the nul terminator, so we do it here */
+	zeroptr[n] = '\0';
+	return dest;
+}
+
+/**
+ * Copy limited number of bytes in memory.
+ *
+ * @param dest Destination buffer.
+ * @param src Source buffer.
+ * @param c Character after which the copying shall stop.
+ * @param n Number of bytes that shall be copied if not stopped earlier by c.
+ * @return Pointer to the first byte after c in dest if found, NULL otherwise.
+ */
+void *posix_memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
+{
+	assert(dest != NULL);
+	assert(src != NULL);
+	
+	unsigned char* bdest = dest;
+	const unsigned char* bsrc = src;
+	
+	for (size_t i = 0; i < n; ++i) {
+		bdest[i] = bsrc[i];
+	
+		if (bsrc[i] == (unsigned char) c) {
+			/* pointer to the next byte */
+			return &bdest[i + 1];
+		}
+	}
+	
+	return NULL;
+}
+
+/**
+ * Duplicate a string.
+ *
+ * @param s String to be duplicated.
+ * @return Newly allocated copy of the string.
+ */
+char *posix_strdup(const char *s)
+{
+	return posix_strndup(s, SIZE_MAX);
+}
+
+/**
+ * Duplicate a specific number of bytes from a string.
+ *
+ * @param s String to be duplicated.
+ * @param n Maximum length of the resulting string..
+ * @return Newly allocated string copy of length at most n.
+ */
+char *posix_strndup(const char *s, size_t n)
+{
+	assert(s != NULL);
+
+	size_t len = posix_strnlen(s, n);
+	char *dup = malloc(len + 1);
+	if (dup == NULL) {
+		return NULL;
+	}
+
+	memcpy(dup, s, len);
+	dup[len] = '\0';
+
+	return dup;
+}
+
+/**
+ * Compare bytes in memory.
+ *
+ * @param mem1 First area of memory to be compared.
+ * @param mem2 Second area of memory to be compared.
+ * @param n Maximum number of bytes to be compared.
+ * @return Difference of the first pair of inequal bytes,
+ *     or 0 if areas have the same content.
+ */
+int posix_memcmp(const void *mem1, const void *mem2, size_t n)
+{
+	assert(mem1 != NULL);
+	assert(mem2 != NULL);
+
+	const unsigned char *s1 = mem1;
+	const unsigned char *s2 = mem2;
+	
+	for (size_t i = 0; i < n; ++i) {
+		if (s1[i] != s2[i]) {
+			return s1[i] - s2[i];
+		}
+	}
+	
+	return 0;
+}
+
+/**
+ * Compare two strings.
+ *
+ * @param s1 First string to be compared.
+ * @param s2 Second string to be compared.
+ * @return Difference of the first pair of inequal characters,
+ *     or 0 if strings have the same content.
+ */
+int posix_strcmp(const char *s1, const char *s2)
+{
+	assert(s1 != NULL);
+	assert(s2 != NULL);
+
+	return posix_strncmp(s1, s2, STR_NO_LIMIT);
+}
+
+/**
+ * Compare part of two strings.
+ *
+ * @param s1 First string to be compared.
+ * @param s2 Second string to be compared.
+ * @param n Maximum number of characters to be compared.
+ * @return Difference of the first pair of inequal characters,
+ *     or 0 if strings have the same content.
+ */
+int posix_strncmp(const char *s1, const char *s2, size_t n)
+{
+	assert(s1 != NULL);
+	assert(s2 != NULL);
+
+	for (size_t i = 0; i < n; ++i) {
+		if (s1[i] != s2[i]) {
+			return s1[i] - s2[i];
+		}
+		if (s1[i] == '\0') {
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Find byte in memory.
+ *
+ * @param mem Memory area in which to look for the byte.
+ * @param c Byte to look for.
+ * @param n Maximum number of bytes to be inspected.
+ * @return Pointer to the specified byte on success,
+ *     NULL pointer otherwise.
+ */
+void *posix_memchr(const void *mem, int c, size_t n)
+{
+	assert(mem != NULL);
+	
+	const unsigned char *s = mem;
+	
+	for (size_t i = 0; i < n; ++i) {
+		if (s[i] == (unsigned char) c) {
+			return (void *) &s[i];
+		}
+	}
+	return NULL;
+}
+
+/**
+ * Scan string for a first occurence of a character.
+ *
+ * @param s String in which to look for the character.
+ * @param c Character to look for.
+ * @return Pointer to the specified character on success,
+ *     NULL pointer otherwise.
+ */
+char *posix_strchr(const char *s, int c)
+{
+	assert(s != NULL);
+	
+	char *res = gnu_strchrnul(s, c);
+	return (*res == c) ? res : NULL;
+}
+
+/**
+ * Scan string for a last occurence of a character.
+ *
+ * @param s String in which to look for the character.
+ * @param c Character to look for.
+ * @return Pointer to the specified character on success,
+ *     NULL pointer otherwise.
+ */
+char *posix_strrchr(const char *s, int c)
+{
+	assert(s != NULL);
+	
+	const char *ptr = posix_strchr(s, '\0');
+	
+	/* the same as in strchr, except it loops in reverse direction */
+	while (*ptr != (char) c) {
+		if (ptr == s) {
+			return NULL;
+		}
+
+		ptr--;
+	}
+
+	return (char *) ptr;
+}
+
+/**
+ * Scan string for a first occurence of a character.
+ *
+ * @param s String in which to look for the character.
+ * @param c Character to look for.
+ * @return Pointer to the specified character on success, pointer to the
+ *     string terminator otherwise.
+ */
+char *gnu_strchrnul(const char *s, int c)
+{
+	assert(s != NULL);
+	
+	while (*s != c && *s != '\0') {
+		s++;
+	}
+	
+	return (char *) s;
+}
+
+/**
+ * Scan a string for a first occurence of one of provided bytes.
+ *
+ * @param s1 String in which to look for the bytes.
+ * @param s2 String of bytes to look for.
+ * @return Pointer to the found byte on success,
+ *     NULL pointer otherwise.
+ */
+char *posix_strpbrk(const char *s1, const char *s2)
+{
+	assert(s1 != NULL);
+	assert(s2 != NULL);
+
+	char *ptr = strpbrk_null(s1, s2);
+	return (*ptr == '\0') ? NULL : ptr;
+}
+
+/**
+ * Get the length of a complementary substring.
+ *
+ * @param s1 String that shall be searched for complementary prefix.
+ * @param s2 String of bytes that shall not occur in the prefix.
+ * @return Length of the prefix.
+ */
+size_t posix_strcspn(const char *s1, const char *s2)
+{
+	assert(s1 != NULL);
+	assert(s2 != NULL);
+
+	char *ptr = strpbrk_null(s1, s2);
+	return (size_t) (ptr - s1);
+}
+
+/**
+ * Get length of a substring.
+ *
+ * @param s1 String that shall be searched for prefix.
+ * @param s2 String of bytes that the prefix must consist of.
+ * @return Length of the prefix.
+ */
+size_t posix_strspn(const char *s1, const char *s2)
+{
+	assert(s1 != NULL);
+	assert(s2 != NULL);
+
+	const char *ptr;
+	for (ptr = s1; *ptr != '\0'; ++ptr) {
+		if (!posix_strchr(s2, *ptr)) {
+			break;
+		}
+	}
+	return ptr - s1;
+}
+
+/**
+ * Find a substring. Uses Knuth-Morris-Pratt algorithm.
+ *
+ * @param s1 String in which to look for a substring.
+ * @param s2 Substring to look for.
+ * @return Pointer to the first character of the substring in s1, or NULL if
+ *     not found.
+ */
+char *posix_strstr(const char *haystack, const char *needle)
+{
+	assert(haystack != NULL);
+	assert(needle != NULL);
+	
+	/* Special case - needle is an empty string. */
+	if (needle[0] == '\0') {
+		return (char *) haystack;
+	}
+	
+	/* Preprocess needle. */
+	size_t nlen = posix_strlen(needle);
+	size_t prefix_table[nlen + 1];
+	
+	{
+		size_t i = 0;
+		ssize_t j = -1;
+		
+		prefix_table[i] = j;
+		
+		while (i < nlen) {
+			while (j >= 0 && needle[i] != needle[j]) {
+				j = prefix_table[j];
+			}
+			i++; j++;
+			prefix_table[i] = j;
+		}
+	}
+	
+	/* Search needle using the precomputed table. */
+	size_t npos = 0;
+	
+	for (size_t hpos = 0; haystack[hpos] != '\0'; ++hpos) {
+		while (npos != 0 && haystack[hpos] != needle[npos]) {
+			npos = prefix_table[npos];
+		}
+		
+		if (haystack[hpos] == needle[npos]) {
+			npos++;
+			
+			if (npos == nlen) {
+				return (char *) (haystack + hpos - nlen + 1);
+			}
+		}
+	}
+	
+	return NULL;
+}
+
+/**
+ * String comparison using collating information.
+ *
+ * Currently ignores locale and just calls strcmp.
+ *
+ * @param s1 First string to be compared.
+ * @param s2 Second string to be compared.
+ * @return Difference of the first pair of inequal characters,
+ *     or 0 if strings have the same content.
+ */
+int posix_strcoll(const char *s1, const char *s2)
+{
+	assert(s1 != NULL);
+	assert(s2 != NULL);
+
+	return posix_strcmp(s1, s2);
+}
+
+/**
+ * Transform a string in such a way that the resulting string yields the same
+ * results when passed to the strcmp as if the original string is passed to
+ * the strcoll.
+ *
+ * Since strcoll is equal to strcmp here, this just makes a copy.
+ *
+ * @param s1 Transformed string.
+ * @param s2 Original string.
+ * @param n Maximum length of the transformed string.
+ * @return Length of the transformed string.
+ */
+size_t posix_strxfrm(char *restrict s1, const char *restrict s2, size_t n)
+{
+	assert(s1 != NULL || n == 0);
+	assert(s2 != NULL);
+
+	size_t len = posix_strlen(s2);
+
+	if (n > len) {
+		posix_strcpy(s1, s2);
+	}
+
+	return len;
+}
+
+/**
+ * Get error message string.
+ *
+ * @param errnum Error code for which to obtain human readable string.
+ * @return Error message.
+ */
+char *posix_strerror(int errnum)
+{
+	static const char *error_msgs[] = {
+		[E2BIG] = "[E2BIG] Argument list too long",
+		[EACCES] = "[EACCES] Permission denied",
+		[EADDRINUSE] = "[EADDRINUSE] Address in use",
+		[EADDRNOTAVAIL] = "[EADDRNOTAVAIL] Address not available",
+		[EAFNOSUPPORT] = "[EAFNOSUPPORT] Address family not supported",
+		[EAGAIN] = "[EAGAIN] Resource unavailable, try again",
+		[EALREADY] = "[EALREADY] Connection already in progress",
+		[EBADF] = "[EBADF] Bad file descriptor",
+		[EBADMSG] = "[EBADMSG] Bad message",
+		[EBUSY] = "[EBUSY] Device or resource busy",
+		[ECANCELED] = "[ECANCELED] Operation canceled",
+		[ECHILD] = "[ECHILD] No child processes",
+		[ECONNABORTED] = "[ECONNABORTED] Connection aborted",
+		[ECONNREFUSED] = "[ECONNREFUSED] Connection refused",
+		[ECONNRESET] = "[ECONNRESET] Connection reset",
+		[EDEADLK] = "[EDEADLK] Resource deadlock would occur",
+		[EDESTADDRREQ] = "[EDESTADDRREQ] Destination address required",
+		[EDOM] = "[EDOM] Mathematics argument out of domain of function",
+		[EDQUOT] = "[EDQUOT] Reserved",
+		[EEXIST] = "[EEXIST] File exists",
+		[EFAULT] = "[EFAULT] Bad address",
+		[EFBIG] = "[EFBIG] File too large",
+		[EHOSTUNREACH] = "[EHOSTUNREACH] Host is unreachable",
+		[EIDRM] = "[EIDRM] Identifier removed",
+		[EILSEQ] = "[EILSEQ] Illegal byte sequence",
+		[EINPROGRESS] = "[EINPROGRESS] Operation in progress",
+		[EINTR] = "[EINTR] Interrupted function",
+		[EINVAL] = "[EINVAL] Invalid argument",
+		[EIO] = "[EIO] I/O error",
+		[EISCONN] = "[EISCONN] Socket is connected",
+		[EISDIR] = "[EISDIR] Is a directory",
+		[ELOOP] = "[ELOOP] Too many levels of symbolic links",
+		[EMFILE] = "[EMFILE] File descriptor value too large",
+		[EMLINK] = "[EMLINK] Too many links",
+		[EMSGSIZE] = "[EMSGSIZE] Message too large",
+		[EMULTIHOP] = "[EMULTIHOP] Reserved",
+		[ENAMETOOLONG] = "[ENAMETOOLONG] Filename too long",
+		[ENETDOWN] = "[ENETDOWN] Network is down",
+		[ENETRESET] = "[ENETRESET] Connection aborted by network",
+		[ENETUNREACH] = "[ENETUNREACH] Network unreachable",
+		[ENFILE] = "[ENFILE] Too many files open in system",
+		[ENOBUFS] = "[ENOBUFS] No buffer space available",
+		[ENODATA] = "[ENODATA] No message is available on the STREAM head read queue",
+		[ENODEV] = "[ENODEV] No such device",
+		[ENOENT] = "[ENOENT] No such file or directory",
+		[ENOEXEC] = "[ENOEXEC] Executable file format error",
+		[ENOLCK] = "[ENOLCK] No locks available",
+		[ENOLINK] = "[ENOLINK] Reserved",
+		[ENOMEM] = "[ENOMEM] Not enough space",
+		[ENOMSG] = "[ENOMSG] No message of the desired type",
+		[ENOPROTOOPT] = "[ENOPROTOOPT] Protocol not available",
+		[ENOSPC] = "[ENOSPC] No space left on device",
+		[ENOSR] = "[ENOSR] No STREAM resources.",
+		[ENOSTR] = "[ENOSTR] Not a STREAM",
+		[ENOSYS] = "[ENOSYS] Function not supported",
+		[ENOTCONN] = "[ENOTCONN] The socket is not connected",
+		[ENOTDIR] = "[ENOTDIR] Not a directory",
+		[ENOTEMPTY] = "[ENOTEMPTY] Directory not empty",
+		[ENOTRECOVERABLE] = "[ENOTRECOVERABLE] State not recoverable",
+		[ENOTSOCK] = "[ENOTSOCK] Not a socket",
+		[ENOTSUP] = "[ENOTSUP] Not supported",
+		[ENOTTY] = "[ENOTTY] Inappropriate I/O control operation",
+		[ENXIO] = "[ENXIO] No such device or address",
+		[EOPNOTSUPP] = "[EOPNOTSUPP] Operation not supported",
+		[EOVERFLOW] = "[EOVERFLOW] Value too large to be stored in data type",
+		[EOWNERDEAD] = "[EOWNERDEAD] Previous owned died",
+		[EPERM] = "[EPERM] Operation not permitted",
+		[EPIPE] = "[EPIPE] Broken pipe",
+		[EPROTO] = "[EPROTO] Protocol error",
+		[EPROTONOSUPPORT] = "[EPROTONOSUPPORT] Protocol not supported",
+		[EPROTOTYPE] = "[EPROTOTYPE] Protocol wrong type for socket",
+		[ERANGE] = "[ERANGE] Result too large",
+		[EROFS] = "[EROFS] Read-only file system",
+		[ESPIPE] = "[ESPIPE] Invalid seek",
+		[ESRCH] = "[ESRCH] No such process",
+		[ESTALE] = "[ESTALE] Reserved",
+		[ETIME] = "[ETIME] Stream ioctl() timeout",
+		[ETIMEDOUT] = "[ETIMEDOUT] Connection timed out",
+		[ETXTBSY] = "[ETXTBSY] Text file busy",
+		[EWOULDBLOCK] = "[EWOULDBLOCK] Operation would block",
+		[EXDEV] = "[EXDEV] Cross-device link",
+	};
+
+	return (char *) error_msgs[posix_abs(errnum)];
+}
+
+/**
+ * Get error message string.
+ *
+ * @param errnum Error code for which to obtain human readable string.
+ * @param buf Buffer to store a human readable string to.
+ * @param bufsz Size of buffer pointed to by buf.
+ * @return Zero on success, errno otherwise.
+ */
+int posix_strerror_r(int errnum, char *buf, size_t bufsz)
+{
+	assert(buf != NULL);
+	
+	char *errstr = posix_strerror(errnum);
+	
+	if (posix_strlen(errstr) + 1 > bufsz) {
+		return ERANGE;
+	} else {
+		posix_strcpy(buf, errstr);
+	}
+
+	return 0;
+}
+
+/**
+ * Get length of the string.
+ *
+ * @param s String which length shall be determined.
+ * @return Length of the string.
+ */
+size_t posix_strlen(const char *s)
+{
+	assert(s != NULL);
+	
+	return (size_t) (posix_strchr(s, '\0') - s);
+}
+
+/**
+ * Get limited length of the string.
+ *
+ * @param s String which length shall be determined.
+ * @param n Maximum number of bytes that can be examined to determine length.
+ * @return The lower of either string length or n limit.
+ */
+size_t posix_strnlen(const char *s, size_t n)
+{
+	assert(s != NULL);
+	
+	for (size_t sz = 0; sz < n; ++sz) {
+		
+		if (s[sz] == '\0') {
+			return sz;
+		}
+	}
+	
+	return n;
+}
+
+/**
+ * Get description of a signal.
+ *
+ * @param signum Signal number.
+ * @return Human readable signal description.
+ */
+char *posix_strsignal(int signum)
+{
+	static const char *const sigstrings[] = {
+		[SIGABRT] = "SIGABRT (Process abort signal)",
+		[SIGALRM] = "SIGALRM (Alarm clock)",
+		[SIGBUS] = "SIGBUS (Access to an undefined portion of a memory object)",
+		[SIGCHLD] = "SIGCHLD (Child process terminated, stopped, or continued)",
+		[SIGCONT] = "SIGCONT (Continue executing, if stopped)",
+		[SIGFPE] = "SIGFPE (Erroneous arithmetic operation)",
+		[SIGHUP] = "SIGHUP (Hangup)",
+		[SIGILL] = "SIGILL (Illegal instruction)",
+		[SIGINT] = "SIGINT (Terminal interrupt signal)",
+		[SIGKILL] = "SIGKILL (Kill process)",
+		[SIGPIPE] = "SIGPIPE (Write on a pipe with no one to read it)",
+		[SIGQUIT] = "SIGQUIT (Terminal quit signal)",
+		[SIGSEGV] = "SIGSEGV (Invalid memory reference)",
+		[SIGSTOP] = "SIGSTOP (Stop executing)",
+		[SIGTERM] = "SIGTERM (Termination signal)",
+		[SIGTSTP] = "SIGTSTP (Terminal stop signal)",
+		[SIGTTIN] = "SIGTTIN (Background process attempting read)",
+		[SIGTTOU] = "SIGTTOU (Background process attempting write)",
+		[SIGUSR1] = "SIGUSR1 (User-defined signal 1)",
+		[SIGUSR2] = "SIGUSR2 (User-defined signal 2)",
+		[SIGPOLL] = "SIGPOLL (Pollable event)",
+		[SIGPROF] = "SIGPROF (Profiling timer expired)",
+		[SIGSYS] = "SIGSYS (Bad system call)",
+		[SIGTRAP] = "SIGTRAP (Trace/breakpoint trap)",
+		[SIGURG] = "SIGURG (High bandwidth data is available at a socket)",
+		[SIGVTALRM] = "SIGVTALRM (Virtual timer expired)",
+		[SIGXCPU] = "SIGXCPU (CPU time limit exceeded)",
+		[SIGXFSZ] = "SIGXFSZ (File size limit exceeded)"
+	};
+
+	if (signum <= _TOP_SIGNAL) {
+		return (char *) sigstrings[signum];
+	}
+
+	return (char *) "ERROR, Invalid signal number";
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/strings.c
===================================================================
--- uspace/lib/posix/source/strings.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/strings.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Additional string manipulation.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "internal/common.h"
+#include "posix/strings.h"
+
+#include "posix/string.h"
+#include "posix/ctype.h"
+
+#include "libc/mem.h"
+
+/**
+ * Find first set bit (beginning with the least significant bit).
+ *
+ * @param i Integer in which to look for the first set bit.
+ * @return Index of first set bit. Bits are numbered starting at one.
+ */
+int posix_ffs(int i)
+{
+	if (i == 0) {
+		return 0;
+	}
+
+	int result = 0;
+
+	// XXX: assumes at most 32-bit int
+	if (!(i & 0xFFFF)) {
+		result |= 16;
+		i >>= 16;
+	}
+	if (!(i & 0xFF)) {
+		result |= 8;
+		i >>= 8;
+	}
+	if (!(i & 0xF)) {
+		result |= 4;
+		i >>= 4;
+	}
+	if (!(i & 0x3)) {
+		result |= 2;
+		i >>= 2;
+	}
+	if (!(i & 0x1)) {
+		result |= 1;
+	}
+
+	return result + 1;
+}
+
+/**
+ * Compare two strings (case-insensitive).
+ *
+ * @param s1 First string to be compared.
+ * @param s2 Second string to be compared.
+ * @return Difference of the first pair of inequal characters,
+ *     or 0 if strings have the same content.
+ */
+int posix_strcasecmp(const char *s1, const char *s2)
+{
+	return posix_strncasecmp(s1, s2, STR_NO_LIMIT);
+}
+
+/**
+ * Compare part of two strings (case-insensitive).
+ *
+ * @param s1 First string to be compared.
+ * @param s2 Second string to be compared.
+ * @param n Maximum number of characters to be compared.
+ * @return Difference of the first pair of inequal characters,
+ *     or 0 if strings have the same content.
+ */
+int posix_strncasecmp(const char *s1, const char *s2, size_t n)
+{
+	for (size_t i = 0; i < n; ++i) {
+		int cmp = tolower(s1[i]) - tolower(s2[i]);
+		if (cmp != 0) {
+			return cmp;
+		}
+		
+		if (s1[i] == 0) {
+			return 0;
+		}
+	}
+	
+	return 0;
+}
+
+/**
+ * Compare two memory areas.
+ *
+ * @param mem1 Pointer to the first area to compare.
+ * @param mem2 Pointer to the second area to compare.
+ * @param n Common size of both areas.
+ * @return If n is 0, return zero. If the areas match, return
+ *     zero. Otherwise return non-zero.
+ */
+int posix_bcmp(const void *mem1, const void *mem2, size_t n)
+{
+	return bcmp(mem1, mem2, n);
+}
+
+/**
+ * Copy bytes in memory with overlapping areas.
+ *
+ * @param src Source area.
+ * @param dest Destination area.
+ * @param n Number of bytes to copy.
+ */
+void posix_bcopy(const void *src, void *dest, size_t n)
+{
+	/* Note that memmove has different order of arguments. */
+	memmove(dest, src, n);
+}
+
+/**
+ * Reset bytes in memory area to zero.
+ *
+ * @param mem Memory area to be zeroed.
+ * @param n Number of bytes to reset.
+ */
+void posix_bzero(void *mem, size_t n)
+{
+	bzero(mem, n);
+}
+
+/**
+ * Scan string for a first occurence of a character.
+ *
+ * @param s String in which to look for the character.
+ * @param c Character to look for.
+ * @return Pointer to the specified character on success,
+ *     NULL pointer otherwise.
+ */
+char *posix_index(const char *s, int c)
+{
+	return posix_strchr(s, c);
+}
+
+/**
+ * Scan string for a last occurence of a character.
+ *
+ * @param s String in which to look for the character.
+ * @param c Character to look for.
+ * @return Pointer to the specified character on success,
+ *     NULL pointer otherwise.
+ */
+char *posix_rindex(const char *s, int c)
+{
+	return posix_strrchr(s, c);
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/sys/stat.c
===================================================================
--- uspace/lib/posix/source/sys/stat.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/sys/stat.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file File status handling.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "../internal/common.h"
+#include "posix/sys/stat.h"
+#include "libc/sys/stat.h"
+
+#include "posix/errno.h"
+#include "libc/mem.h"
+
+/**
+ * Convert HelenOS stat struct into POSIX stat struct (if possible).
+ *
+ * @param dest POSIX stat struct.
+ * @param src HelenOS stat struct.
+ */
+static void stat_to_posix(struct posix_stat *dest, struct stat *src)
+{
+	memset(dest, 0, sizeof(struct posix_stat));
+	
+	dest->st_dev = src->service;
+	dest->st_ino = src->index;
+	
+	/* HelenOS doesn't support permissions, so we set them all */
+	dest->st_mode = S_IRWXU | S_IRWXG | S_IRWXO;
+	if (src->is_file) {
+		dest->st_mode |= S_IFREG;
+	}
+	if (src->is_directory) {
+		dest->st_mode |= S_IFDIR;
+	}
+	
+	dest->st_nlink = src->lnkcnt;
+	dest->st_size = src->size;
+}
+
+/**
+ * Retrieve file status for file associated with file descriptor.
+ *
+ * @param fd File descriptor of the opened file.
+ * @param st Status structure to be filled with information.
+ * @return Zero on success, -1 otherwise.
+ */
+int posix_fstat(int fd, struct posix_stat *st)
+{
+	struct stat hst;
+	int rc = fstat(fd, &hst);
+	if (rc < 0) {
+		/* fstat() returns negative error code instead of using errno. */
+		errno = -rc;
+		return -1;
+	}
+	stat_to_posix(st, &hst);
+	return 0;
+}
+
+/**
+ * Retrieve file status for symbolic link.
+ * 
+ * @param path Path to the symbolic link.
+ * @param st Status structure to be filled with information.
+ * @return Zero on success, -1 otherwise.
+ */
+int posix_lstat(const char *restrict path, struct posix_stat *restrict st)
+{
+	/* There are currently no symbolic links in HelenOS. */
+	return posix_stat(path, st);
+}
+
+/**
+ * Retrieve file status for regular file (or symbolic link target).
+ *
+ * @param path Path to the file/link.
+ * @param st Status structure to be filled with information.
+ * @return Zero on success, -1 otherwise.
+ */
+int posix_stat(const char *restrict path, struct posix_stat *restrict st)
+{
+	struct stat hst;
+	int rc = stat(path, &hst);
+	if (rc < 0) {
+		/* stat() returns negative error code instead of using errno. */
+		errno = -rc;
+		return -1;
+	}
+	stat_to_posix(st, &hst);
+	return 0;
+}
+
+/**
+ * Change permission bits for the file if possible.
+ * 
+ * @param path Path to the file.
+ * @param mode Permission bits to be set.
+ * @return Zero on success, -1 otherwise.
+ */
+int posix_chmod(const char *path, mode_t mode)
+{
+	/* HelenOS doesn't support permissions, return success. */
+	return 0;
+}
+
+/**
+ * Set the file mode creation mask of the process.
+ * 
+ * @param mask Set permission bits are cleared in the related creation
+ *     functions. Non-permission bits are ignored.
+ * @return Previous file mode creation mask.
+ */
+mode_t posix_umask(mode_t mask)
+{
+	/* HelenOS doesn't support permissions, return empty mask. */
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/sys/wait.c
===================================================================
--- uspace/lib/posix/source/sys/wait.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/sys/wait.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Support for waiting.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "../internal/common.h"
+#include "posix/sys/wait.h"
+
+#include "libc/task.h"
+#include "posix/assert.h"
+#include "posix/errno.h"
+#include "posix/limits.h"
+#include "posix/signal.h"
+
+int __posix_wifexited(int status) {
+	return status != INT_MIN;
+}
+
+int __posix_wexitstatus(int status) {
+	assert(__posix_wifexited(status));
+	return status;
+}
+
+int __posix_wifsignaled(int status) {
+	return status == INT_MIN;
+}
+
+int __posix_wtermsig(int status) {
+	assert(__posix_wifsignaled(status));
+	/* There is no way to distinguish reason
+	 * for unexpected termination at the moment.
+	 */
+	return SIGABRT;
+}
+
+/**
+ * Wait for any child process to stop or terminate.
+ * 
+ * @param stat_ptr Location of the final status code of the child process.
+ * @return ID of the child process for which status is reported,
+ *     -1 on signal interrupt, (pid_t)-1 otherwise.
+ */
+posix_pid_t posix_wait(int *stat_ptr)
+{
+	/* HelenOS does not support this. */
+	errno = ENOSYS;
+	return (posix_pid_t) -1;
+}
+
+/**
+ * Wait for a child process to stop or terminate.
+ * 
+ * @param pid What child process shall the caller wait for. See POSIX manual
+ *     for details.
+ * @param stat_ptr Location of the final status code of the child process.
+ * @param options Constraints of the waiting. See POSIX manual for details.
+ * @return ID of the child process for which status is reported,
+ *     -1 on signal interrupt, 0 if non-blocking wait is requested but there is
+ *     no child process whose status can be reported, (pid_t)-1 otherwise.
+ */
+posix_pid_t posix_waitpid(posix_pid_t pid, int *stat_ptr, int options)
+{
+	assert(stat_ptr != NULL);
+	assert(options == 0 /* None of the options are supported. */);
+	
+	task_exit_t texit;
+	int retval;
+	
+	int rc = task_wait((task_id_t) pid, &texit, &retval);
+	
+	if (rc < 0) {
+		/* Unable to retrieve status. */
+		errno = -rc;
+		return (posix_pid_t) -1;
+	}
+	
+	if (texit == TASK_EXIT_NORMAL) {
+		// FIXME: relies on application not returning this value
+		assert(retval != INT_MIN);
+		*stat_ptr = retval;
+	} else {
+		/* Reserve the lowest value for unexpected termination. */
+		*stat_ptr = INT_MIN;
+	}
+	
+	return pid;
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/time.c
===================================================================
--- uspace/lib/posix/source/time.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/time.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * Copyright (c) 2011 Jiri Zarevucky
+ * 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 libposix
+ * @{
+ */
+/** @file Time measurement support.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+/* Must be first. */
+#include "posix/stdbool.h"
+
+#include "internal/common.h"
+#include "posix/time.h"
+
+#include "posix/ctype.h"
+#include "posix/errno.h"
+#include "posix/signal.h"
+#include "posix/assert.h"
+
+#include "libc/malloc.h"
+#include "libc/task.h"
+#include "libc/stats.h"
+#include "libc/sys/time.h"
+
+// TODO: test everything in this file
+
+/* In some places in this file, phrase "normalized broken-down time" is used.
+ * This means time broken down to components (year, month, day, hour, min, sec),
+ * in which every component is in its proper bounds. Non-normalized time could
+ * e.g. be 2011-54-5 29:13:-5, which would semantically mean start of year 2011
+ * + 53 months + 4 days + 29 hours + 13 minutes - 5 seconds.
+ */
+
+int posix_daylight;
+long posix_timezone;
+char *posix_tzname[2];
+
+/**
+ * Set timezone conversion information.
+ */
+void posix_tzset(void)
+{
+	// TODO: read environment
+	posix_tzname[0] = (char *) "GMT";
+	posix_tzname[1] = (char *) "GMT";
+	posix_daylight = 0;
+	posix_timezone = 0;
+}
+
+/**
+ * Converts a time value to a broken-down UTC time.
+ * 
+ * @param timer Time to convert.
+ * @param result Structure to store the result to.
+ * @return Value of result on success, NULL on overflow.
+ */
+struct tm *posix_gmtime_r(const time_t *restrict timer,
+    struct tm *restrict result)
+{
+	int rc = time_utc2tm(*timer, result);
+	if (rc != EOK) {
+		errno = rc;
+		return NULL;
+	}
+
+	return result;
+}
+
+/**
+ * Converts a time value to a broken-down UTC time.
+ * (non reentrant version)
+ *
+ * @param timep  Time to convert
+ * @return       Pointer to a statically allocated structure that stores
+ *               the result, NULL in case of error.
+ */
+struct tm *posix_gmtime(const time_t *restrict timep)
+{
+	static struct tm result;
+
+	return posix_gmtime_r(timep, &result);
+}
+
+/**
+ * Converts a time value to a broken-down local time.
+ * 
+ * @param timer Time to convert.
+ * @param result Structure to store the result to.
+ * @return Value of result on success, NULL on overflow.
+ */
+struct tm *posix_localtime_r(const time_t *restrict timer,
+    struct tm *restrict result)
+{
+	// TODO: deal with timezone
+	// currently assumes system and all times are in GMT
+	return posix_gmtime_r(timer, result);
+}
+
+/**
+ * Converts a time value to a broken-down local time.
+ * (non reentrant version)
+ *
+ * @param timep    Time to convert.
+ * @return         Pointer to a statically allocated structure that stores
+ *                 the result, NULL in case of error.
+ */
+struct tm *posix_localtime(const time_t *restrict timep)
+{
+	static struct tm result;
+
+	return posix_localtime_r(timep, &result);
+}
+
+/**
+ * Converts broken-down time to a string in format
+ * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
+ *
+ * @param timeptr Broken-down time structure.
+ * @param buf Buffer to store string to, must be at least ASCTIME_BUF_LEN
+ *     bytes long.
+ * @return Value of buf.
+ */
+char *posix_asctime_r(const struct tm *restrict timeptr,
+    char *restrict buf)
+{
+	time_tm2str(timeptr, buf);
+	return buf;
+}
+
+/**
+ * Convers broken-down time to a string in format
+ * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
+ * (non reentrant version)
+ *
+ * @param timeptr    Broken-down time structure.
+ * @return           Pointer to a statically allocated buffer that stores
+ *                   the result, NULL in case of error.
+ */
+char *posix_asctime(const struct tm *restrict timeptr)
+{
+	static char buf[ASCTIME_BUF_LEN];
+
+	return posix_asctime_r(timeptr, buf);
+}
+
+/**
+ * Converts the calendar time to a string in format
+ * "Sun Jan 1 00:00:00 1970\n" (Obsolete)
+ * 
+ * @param timer Time to convert.
+ * @param buf Buffer to store string to. Must be at least ASCTIME_BUF_LEN
+ *     bytes long.
+ * @return Pointer to buf on success, NULL on failure.
+ */
+char *posix_ctime_r(const time_t *timer, char *buf)
+{
+	int r = time_local2str(*timer, buf);
+	if (r != EOK) {
+		errno = r;
+		return NULL;
+	}
+
+	return buf;
+}
+
+/**
+ * Converts the calendar time to a string in format
+ * "Sun Jan 1 00:00:00 1970\n" (Obsolete)
+ * (non reentrant version)
+ *
+ * @param timep    Time to convert.
+ * @return         Pointer to a statically allocated buffer that stores
+ *                 the result, NULL in case of error.
+ */
+char *posix_ctime(const time_t *timep)
+{
+	static char buf[ASCTIME_BUF_LEN];
+
+	return posix_ctime_r(timep, buf);
+}
+
+/**
+ * Get clock resolution. Only CLOCK_REALTIME is supported.
+ *
+ * @param clock_id Clock ID.
+ * @param res Pointer to the variable where the resolution is to be written.
+ * @return 0 on success, -1 with errno set on failure.
+ */
+int posix_clock_getres(posix_clockid_t clock_id, struct posix_timespec *res)
+{
+	assert(res != NULL);
+
+	switch (clock_id) {
+		case CLOCK_REALTIME:
+			res->tv_sec = 0;
+			res->tv_nsec = 1000; /* Microsecond resolution. */
+			return 0;
+		default:
+			errno = EINVAL;
+			return -1;
+	}
+}
+
+/**
+ * Get time. Only CLOCK_REALTIME is supported.
+ * 
+ * @param clock_id ID of the clock to query.
+ * @param tp Pointer to the variable where the time is to be written.
+ * @return 0 on success, -1 with errno on failure.
+ */
+int posix_clock_gettime(posix_clockid_t clock_id, struct posix_timespec *tp)
+{
+	assert(tp != NULL);
+
+	switch (clock_id) {
+		case CLOCK_REALTIME:
+			;
+			struct timeval tv;
+			gettimeofday(&tv, NULL);
+			tp->tv_sec = tv.tv_sec;
+			tp->tv_nsec = tv.tv_usec * 1000;
+			return 0;
+		default:
+			errno = EINVAL;
+			return -1;
+	}
+}
+
+/**
+ * Set time on a specified clock. As HelenOS doesn't support this yet,
+ * this function always fails.
+ * 
+ * @param clock_id ID of the clock to set.
+ * @param tp Time to set.
+ * @return 0 on success, -1 with errno on failure.
+ */
+int posix_clock_settime(posix_clockid_t clock_id,
+    const struct posix_timespec *tp)
+{
+	assert(tp != NULL);
+
+	switch (clock_id) {
+		case CLOCK_REALTIME:
+			// TODO: setting clock
+			// FIXME: HelenOS doesn't actually support hardware
+			//        clock yet
+			errno = EPERM;
+			return -1;
+		default:
+			errno = EINVAL;
+			return -1;
+	}
+}
+
+/**
+ * Sleep on a specified clock.
+ * 
+ * @param clock_id ID of the clock to sleep on (only CLOCK_REALTIME supported).
+ * @param flags Flags (none supported).
+ * @param rqtp Sleep time.
+ * @param rmtp Remaining time is written here if sleep is interrupted.
+ * @return 0 on success, -1 with errno set on failure.
+ */
+int posix_clock_nanosleep(posix_clockid_t clock_id, int flags,
+    const struct posix_timespec *rqtp, struct posix_timespec *rmtp)
+{
+	assert(rqtp != NULL);
+	assert(rmtp != NULL);
+
+	switch (clock_id) {
+		case CLOCK_REALTIME:
+			// TODO: interruptible sleep
+			if (rqtp->tv_sec != 0) {
+				sleep(rqtp->tv_sec);
+			}
+			if (rqtp->tv_nsec != 0) {
+				usleep(rqtp->tv_nsec / 1000);
+			}
+			return 0;
+		default:
+			errno = EINVAL;
+			return -1;
+	}
+}
+
+/**
+ * Get CPU time used since the process invocation.
+ *
+ * @return Consumed CPU cycles by this process or -1 if not available.
+ */
+posix_clock_t posix_clock(void)
+{
+	posix_clock_t total_cycles = -1;
+	stats_task_t *task_stats = stats_get_task(task_get_id());
+	if (task_stats) {
+		total_cycles = (posix_clock_t) (task_stats->kcycles +
+		    task_stats->ucycles);
+		free(task_stats);
+		task_stats = 0;
+	}
+
+	return total_cycles;
+}
+
+/** @}
+ */
Index: uspace/lib/posix/source/unistd.c
===================================================================
--- uspace/lib/posix/source/unistd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/posix/source/unistd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2011 Jiri Zarevucky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 libposix
+ * @{
+ */
+/** @file Miscellaneous standard definitions.
+ */
+
+#define LIBPOSIX_INTERNAL
+
+#include "internal/common.h"
+#include "posix/unistd.h"
+
+#include "posix/errno.h"
+#include "posix/string.h"
+#include "posix/fcntl.h"
+
+#include "libc/task.h"
+#include "libc/stats.h"
+#include "libc/malloc.h"
+
+/* Array of environment variable strings (NAME=VALUE). */
+char **posix_environ = NULL;
+char *posix_optarg;
+
+/**
+ * Get current user name.
+ *
+ * @return User name (static) string or NULL if not found.
+ */
+char *posix_getlogin(void)
+{
+	/* There is currently no support for user accounts in HelenOS. */
+	return (char *) "user";
+}
+
+/**
+ * Get current user name.
+ *
+ * @param name Pointer to a user supplied buffer.
+ * @param namesize Length of the buffer.
+ * @return Zero on success, error code otherwise.
+ */
+int posix_getlogin_r(char *name, size_t namesize)
+{
+	/* There is currently no support for user accounts in HelenOS. */
+	if (namesize >= 5) {
+		posix_strcpy(name, (char *) "user");
+		return 0;
+	} else {
+		errno = ERANGE;
+		return -1;
+	}
+}
+
+/**
+ * Test whether open file descriptor is associated with a terminal.
+ *
+ * @param fd Open file descriptor to test.
+ * @return Boolean result of the test.
+ */
+int posix_isatty(int fd)
+{
+	// TODO
+	/* Always returns false, because there is no easy way to find
+	 * out under HelenOS. */
+	return 0;
+}
+
+/**
+ * Get the pathname of the current working directory.
+ *
+ * @param buf Buffer into which the pathname shall be put.
+ * @param size Size of the buffer.
+ * @return Buffer pointer on success, NULL on failure.
+ */
+char *posix_getcwd(char *buf, size_t size)
+{
+	/* Native getcwd() does not set any errno despite the fact that general
+	 * usage pattern of this function depends on it (caller is repeatedly
+	 * guessing the required size of the buffer by checking for ERANGE on
+	 * failure). */
+	if (size == 0) {
+		errno = EINVAL;
+		return NULL;
+	}
+	
+	/* Save the original value to comply with the "no modification on
+	 * success" semantics.
+	 */
+	int orig_errno = errno;
+	errno = EOK;
+	
+	char *ret = getcwd(buf, size);
+	if (ret == NULL) {
+		/* Check errno to avoid shadowing other possible errors. */
+		if (errno == EOK) {
+			errno = ERANGE;
+		}
+	} else {
+		/* Success, restore previous errno value. */
+		errno = orig_errno;
+	}
+	
+	return ret;
+}
+
+/**
+ * Change the current working directory.
+ *
+ * @param path New working directory.
+ */
+int posix_chdir(const char *path)
+{
+	return errnify(chdir, path);
+}
+
+/**
+ * Determine the page size of the current run of the process.
+ *
+ * @return Page size of the process.
+ */
+int posix_getpagesize(void)
+{
+	return getpagesize();
+}
+
+/**
+ * Get the process ID of the calling process.
+ *
+ * @return Process ID.
+ */
+posix_pid_t posix_getpid(void)
+{
+	return task_get_id();
+}
+
+/**
+ * Get the real user ID of the calling process.
+ *
+ * @return User ID.
+ */
+posix_uid_t posix_getuid(void)
+{
+	/* There is currently no support for user accounts in HelenOS. */
+	return 0;
+}
+
+/**
+ * Get the real group ID of the calling process.
+ * 
+ * @return Group ID.
+ */
+posix_gid_t posix_getgid(void)
+{
+	/* There is currently no support for user accounts in HelenOS. */
+	return 0;
+}
+
+/**
+ * Close a file.
+ *
+ * @param fildes File descriptor of the opened file.
+ * @return 0 on success, -1 on error.
+ */
+int posix_close(int fildes)
+{
+	return errnify(close, fildes);
+}
+
+/**
+ * Read from a file.
+ *
+ * @param fildes File descriptor of the opened file.
+ * @param buf Buffer to which the read bytes shall be stored.
+ * @param nbyte Upper limit on the number of read bytes.
+ * @return Number of read bytes on success, -1 otherwise.
+ */
+ssize_t posix_read(int fildes, void *buf, size_t nbyte)
+{
+	return errnify(read, fildes, buf, nbyte);
+}
+
+/**
+ * Write to a file.
+ *
+ * @param fildes File descriptor of the opened file.
+ * @param buf Buffer to write.
+ * @param nbyte Size of the buffer.
+ * @return Number of written bytes on success, -1 otherwise.
+ */
+ssize_t posix_write(int fildes, const void *buf, size_t nbyte)
+{
+	return errnify(write, fildes, buf, nbyte);
+}
+
+/**
+ * Requests outstanding data to be written to the underlying storage device.
+ *
+ * @param fildes File descriptor of the opened file.
+ * @return Zero on success, -1 otherwise.
+ */
+int posix_fsync(int fildes)
+{
+	return errnify(fsync, fildes);
+}
+
+/**
+ * Truncate a file to a specified length.
+ *
+ * @param fildes File descriptor of the opened file.
+ * @param length New length of the file.
+ * @return Zero on success, -1 otherwise.
+ */
+int posix_ftruncate(int fildes, posix_off_t length)
+{
+	return errnify(ftruncate, fildes, (aoff64_t) length);
+}
+
+/**
+ * Remove a directory.
+ *
+ * @param path Directory pathname.
+ * @return Zero on success, -1 otherwise.
+ */
+int posix_rmdir(const char *path)
+{
+	return errnify(rmdir, path);
+}
+
+/**
+ * Remove a link to a file.
+ * 
+ * @param path File pathname.
+ * @return Zero on success, -1 otherwise.
+ */
+int posix_unlink(const char *path)
+{
+	return errnify(unlink, path);
+}
+
+/**
+ * Duplicate an open file descriptor.
+ *
+ * @param fildes File descriptor to be duplicated.
+ * @return On success, new file descriptor for the same file, otherwise -1.
+ */
+int posix_dup(int fildes)
+{
+	return posix_fcntl(fildes, F_DUPFD, 0);
+}
+
+/**
+ * Duplicate an open file descriptor.
+ * 
+ * @param fildes File descriptor to be duplicated.
+ * @param fildes2 File descriptor to be paired with the same file description
+ *     as is paired fildes.
+ * @return fildes2 on success, -1 otherwise.
+ */
+int posix_dup2(int fildes, int fildes2)
+{
+	return errnify(dup2, fildes, fildes2);
+}
+
+/**
+ * Determine accessibility of a file.
+ *
+ * @param path File to check accessibility for.
+ * @param amode Either check for existence or intended access mode.
+ * @return Zero on success, -1 otherwise.
+ */
+int posix_access(const char *path, int amode)
+{
+	if (amode == F_OK || (amode & (X_OK | W_OK | R_OK))) {
+		/* HelenOS doesn't support permissions, permission checks
+		 * are equal to existence check.
+		 *
+		 * Check file existence by attempting to open it.
+		 */
+		int fd = open(path, O_RDONLY);
+		if (fd < 0) {
+			errno = -fd;
+			return -1;
+		}
+		close(fd);
+		return 0;
+	} else {
+		/* Invalid amode argument. */
+		errno = EINVAL;
+		return -1;
+	}
+}
+
+/**
+ * Get configurable system variables.
+ * 
+ * @param name Variable name.
+ * @return Variable value.
+ */
+long posix_sysconf(int name)
+{
+	long clk_tck = 0;
+	size_t cpu_count = 0;
+	stats_cpu_t *cpu_stats = stats_get_cpus(&cpu_count);
+	if (cpu_stats && cpu_count > 0) {
+		clk_tck = ((long) cpu_stats[0].frequency_mhz) * 1000000L;
+	}
+	if (cpu_stats) {
+		free(cpu_stats);
+		cpu_stats = 0;
+	}
+
+	long phys_pages = 0;
+	long avphys_pages = 0;
+	stats_physmem_t *mem_stats = stats_get_physmem();
+	if (mem_stats) {
+		phys_pages = (long) (mem_stats->total / getpagesize());
+		avphys_pages = (long) (mem_stats->free / getpagesize());
+		free(mem_stats);
+		mem_stats = 0;
+	}
+
+	switch (name) {
+	case _SC_PHYS_PAGES:
+		return phys_pages;
+	case _SC_AVPHYS_PAGES:
+		return avphys_pages;
+	case _SC_PAGESIZE:
+		return getpagesize();
+	case _SC_CLK_TCK:
+		return clk_tck;
+	default:
+		errno = EINVAL;
+		return -1;
+	}
+}
+
+/**
+ * 
+ * @param path
+ * @param name
+ * @return
+ */
+long posix_pathconf(const char *path, int name)
+{
+	// TODO: low priority, just a compile-time dependency of binutils
+	not_implemented();
+}
+
+/**
+ * 
+ * @return
+ */
+posix_pid_t posix_fork(void)
+{
+	// TODO: low priority, just a compile-time dependency of binutils
+	not_implemented();
+}
+
+/**
+ * 
+ * @param path
+ * @param argv
+ * @return
+ */
+int posix_execv(const char *path, char *const argv[])
+{
+	// TODO: low priority, just a compile-time dependency of binutils
+	not_implemented();
+}
+
+/**
+ * 
+ * @param file
+ * @param argv
+ * @return
+ */
+int posix_execvp(const char *file, char *const argv[])
+{
+	// TODO: low priority, just a compile-time dependency of binutils
+	not_implemented();
+}
+
+/**
+ * 
+ * @param fildes
+ * @return
+ */
+int posix_pipe(int fildes[2])
+{
+	// TODO: low priority, just a compile-time dependency of binutils
+	not_implemented();
+}
+
+/** @}
+ */
Index: pace/lib/posix/stdbool.h
===================================================================
--- uspace/lib/posix/stdbool.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,55 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Boolean type and values.
- */
-
-#ifndef POSIX_STDBOOL_H_
-#define POSIX_STDBOOL_H_
-
-#ifdef LIBC_BOOL_H_
-
-#if (!defined(POSIX_STDIO_H_)) && \
-    (!defined(POSIX_STDLIB_H_)) && \
-    (!defined(POSIX_STRING_H_))
-	#error "You can't include bool.h and stdbool.h at the same time."
-#endif
-
-#endif /* LIBC_BOOL_H */
-
-#define LIBC_BOOL_H_
-
-#define bool _Bool
-#define true 1
-#define false 0
-#define __bool_true_false_are_defined 1
-
-#endif /* POSIX_STDBOOL_H_ */
Index: pace/lib/posix/stddef.h
===================================================================
--- uspace/lib/posix/stddef.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,55 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Standard type definitions.
- */
-
-#ifndef POSIX_STDDEF_H_
-#define POSIX_STDDEF_H_
-
-#include "libc/stddef.h"
-
-#ifndef NULL
-	#define NULL  ((void *) 0)
-#endif
-
-#define offsetof(type,member) ((size_t) &(((type *) 0)->member))
-
-typedef ssize_t posix_ptrdiff_t;
-
-#ifndef LIBPOSIX_INTERNAL
-	#define ptrdiff_t posix_ptrdiff_t
-#endif
-
-#endif /* POSIX_STDDEF_H_ */
-
-/** @}
- */
Index: pace/lib/posix/stdint.h
===================================================================
--- uspace/lib/posix/stdint.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,113 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Integer types.
- */
-
-#ifndef POSIX_STDINT_H_
-#define POSIX_STDINT_H_
-
-#include "libc/stdint.h"
-
-#undef INT8_MAX
-#undef INT8_MIN
-#define INT8_MAX  127
-#define INT8_MIN  (-128)
-
-#undef UINT8_MAX
-#undef UINT8_MIN
-#define UINT8_MAX  255
-#define UINT8_MIN  0
-
-#undef INT16_MAX
-#undef INT16_MIN
-#define INT16_MAX  32767
-#define INT16_MIN  (-32768)
-
-#undef UINT16_MAX
-#undef UINT16_MIN
-#define UINT16_MAX  65535
-#define UINT16_MIN  0
-
-#undef INT32_MAX
-#undef INT32_MIN
-#define INT32_MAX  2147483647
-#define INT32_MIN  (-INT32_MAX - 1)
-
-#undef UINT32_MAX
-#undef UINT32_MIN
-#define UINT32_MAX  4294967295U
-#define UINT32_MIN  0U
-
-#undef INT64_MAX
-#undef INT64_MIN
-#define INT64_MAX  9223372036854775807LL
-#define INT64_MIN  (-INT64_MAX - 1LL)
-
-#undef UINT64_MAX
-#undef  UINT64_MIN
-#define UINT64_MAX  18446744073709551615ULL
-#define UINT64_MIN  0ULL
-
-#undef OFF64_MAX
-#undef OFF64_MIN
-#define OFF64_MAX  INT64_MAX
-#define OFF64_MIN  INT64_MIN
-
-#undef AOFF64_MAX
-#undef AOFF64_MIN
-#define AOFF64_MAX  UINT64_MAX
-#define AOFF64_MIN  UINT64_MIN
-
-#undef INTMAX_MIN
-#undef INTMAX_MAX
-#define INTMAX_MIN INT64_MIN
-#define INTMAX_MAX INT64_MAX
-
-#undef UINTMAX_MIN
-#undef UINTMAX_MAX
-#define UINTMAX_MIN UINT64_MIN
-#define UINTMAX_MAX UINT64_MAX
-
-#include "libc/sys/types.h"
-
-typedef int64_t posix_intmax_t;
-typedef uint64_t posix_uintmax_t;
-
-#ifndef LIBPOSIX_INTERNAL
-	#define intmax_t posix_intmax_t
-	#define uintmax_t posix_uintmax_t
-#endif
-
-#endif /* POSIX_STDINT_H_ */
-
-/** @}
- */
Index: pace/lib/posix/stdio.c
===================================================================
--- uspace/lib/posix/stdio.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,807 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Standard buffered input/output.
- */
-
-#define LIBPOSIX_INTERNAL
-
-/* Has to be first. */
-#include "stdbool.h"
-
-#include "internal/common.h"
-#include "stdio.h"
-
-#include "assert.h"
-#include "errno.h"
-#include "stdlib.h"
-#include "string.h"
-#include "sys/types.h"
-#include "unistd.h"
-
-#include "libc/io/printf_core.h"
-#include "libc/str.h"
-#include "libc/malloc.h"
-#include "libc/adt/list.h"
-#include "libc/sys/stat.h"
-
-
-/* not the best of solutions, but freopen and ungetc will eventually
- * need to be implemented in libc anyway
- */
-#include "../c/generic/private/stdio.h"
-
-/** Clears the stream's error and end-of-file indicators.
- *
- * @param stream Stream whose indicators shall be cleared.
- */
-void posix_clearerr(FILE *stream)
-{
-	stream->error = 0;
-	stream->eof = 0;
-}
-
-/**
- * Generate a pathname for the controlling terminal.
- *
- * @param s Allocated buffer to which the pathname shall be put.
- * @return Either s or static location filled with the requested pathname.
- */
-char *posix_ctermid(char *s)
-{
-	/* Currently always returns an error value (empty string). */
-	// TODO: return a real terminal path
-
-	static char dummy_path[L_ctermid] = {'\0'};
-
-	if (s == NULL) {
-		return dummy_path;
-	}
-
-	s[0] = '\0';
-	return s;
-}
-
-/**
- * Put a string on the stream.
- * 
- * @param s String to be written.
- * @param stream Output stream.
- * @return Non-negative on success, EOF on failure.
- */
-int posix_fputs(const char *restrict s, FILE *restrict stream)
-{
-	int rc = fputs(s, stream);
-	if (rc == 0) {
-		return EOF;
-	} else {
-		return 0;
-	}
-}
-
-/**
- * Push byte back into input stream.
- * 
- * @param c Byte to be pushed back.
- * @param stream Stream to where the byte shall be pushed.
- * @return Provided byte on success or EOF if not possible.
- */
-int posix_ungetc(int c, FILE *stream)
-{
-	uint8_t b = (uint8_t) c;
-
-	bool can_unget =
-	    /* Provided character is legal. */
-	    c != EOF &&
-	    /* Stream is consistent. */
-	    !stream->error &&
-	    /* Stream is buffered. */
-	    stream->btype != _IONBF &&
-	    /* Last operation on the stream was a read operation. */
-	    stream->buf_state == _bs_read &&
-	    /* Stream buffer is already allocated (i.e. there was already carried
-	     * out either write or read operation on the stream). This is probably
-	     * redundant check but let's be safe. */
-	    stream->buf != NULL &&
-	    /* There is still space in the stream to retreat. POSIX demands the
-	     * possibility to unget at least 1 character. It should be always
-	     * possible, assuming the last operation on the stream read at least 1
-	     * character, because the buffer is refilled in the lazily manner. */
-	    stream->buf_tail > stream->buf;
-
-	if (can_unget) {
-		--stream->buf_tail;
-		stream->buf_tail[0] = b;
-		stream->eof = false;
-		return (int) b;
-	} else {
-		return EOF;
-	}
-}
-
-/**
- * Read a stream until the delimiter (or EOF) is encountered.
- *
- * @param lineptr Pointer to the output buffer in which there will be stored
- *     nul-terminated string together with the delimiter (if encountered).
- *     Will be resized if necessary.
- * @param n Pointer to the size of the output buffer. Will be increased if
- *     necessary.
- * @param delimiter Delimiter on which to finish reading the stream.
- * @param stream Input stream.
- * @return Number of fetched characters (including delimiter if encountered)
- *     or -1 on error (set in errno).
- */
-ssize_t posix_getdelim(char **restrict lineptr, size_t *restrict n,
-    int delimiter, FILE *restrict stream)
-{
-	/* Check arguments for sanity. */
-	if (!lineptr || !n) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	size_t alloc_step = 80; /* Buffer size gain during reallocation. */
-	char *pos = *lineptr; /* Next free byte of the output buffer. */
-	size_t cnt = 0; /* Number of fetched characters. */
-	int c = fgetc(stream); /* Current input character. Might be EOF. */
-
-	do {
-		/* Mask EOF as NUL to terminate string. */
-		if (c == EOF) {
-			c = '\0';
-		}
-
-		/* Ensure there is still space left in the buffer. */
-		if (pos == *lineptr + *n) {
-			*lineptr = realloc(*lineptr, *n + alloc_step);
-			if (*lineptr) {
-				pos = *lineptr + *n;
-				*n += alloc_step;
-			} else {
-				errno = ENOMEM;
-				return -1;
-			}
-		}
-
-		/* Store the fetched character. */
-		*pos = c;
-
-		/* Fetch the next character according to the current character. */
-		if (c != '\0') {
-			++pos;
-			++cnt;
-			if (c == delimiter) {
-				/* Delimiter was just stored. Provide EOF as the next
-				 * character - it will be masked as NUL and output string
-				 * will be properly terminated. */
-				c = EOF;
-			} else {
-				/* Neither delimiter nor EOF were encountered. Just fetch
-				 * the next character from the stream. */
-				c = fgetc(stream);
-			}
-		}
-	} while (c != '\0');
-
-	if (errno == EOK && cnt > 0) {
-		return cnt;
-	} else {
-		/* Either some error occured or the stream was already at EOF. */
-		return -1;
-	}
-}
-
-/**
- * Read a stream until the newline (or EOF) is encountered.
- * 
- * @param lineptr Pointer to the output buffer in which there will be stored
- *     nul-terminated string together with the delimiter (if encountered).
- *     Will be resized if necessary.
- * @param n Pointer to the size of the output buffer. Will be increased if
- *     necessary.
- * @param stream Input stream.
- * @return Number of fetched characters (including newline if encountered)
- *     or -1 on error (set in errno).
- */
-ssize_t posix_getline(char **restrict lineptr, size_t *restrict n,
-    FILE *restrict stream)
-{
-	return posix_getdelim(lineptr, n, '\n', stream);
-}
-
-/**
- * Reopen a file stream.
- * 
- * @param filename Pathname of a file to be reopened or NULL for changing
- *     the mode of the stream.
- * @param mode Mode to be used for reopening the file or changing current
- *     mode of the stream.
- * @param stream Current stream associated with the opened file.
- * @return On success, either a stream of the reopened file or the provided
- *     stream with a changed mode. NULL otherwise.
- */
-FILE *posix_freopen(const char *restrict filename, 
-    const char *restrict mode, FILE *restrict stream)
-{
-	assert(mode != NULL);
-	assert(stream != NULL);
-	
-	if (filename == NULL) {
-		/* POSIX allows this to be imlementation-defined. HelenOS currently
-		 * does not support changing the mode. */
-		// FIXME: handle mode change once it is supported
-		return stream;
-	}
-	
-	/* Open a new stream. */
-	FILE* new = fopen(filename, mode);
-	if (new == NULL) {
-		fclose(stream);
-		/* errno was set by fopen() */
-		return NULL;
-	}
-	
-	/* Close the original stream without freeing it (ignoring errors). */
-	if (stream->buf != NULL) {
-		fflush(stream);
-	}
-	if (stream->sess != NULL) {
-		async_hangup(stream->sess);
-	}
-	if (stream->fd >= 0) {
-		close(stream->fd);
-	}
-	list_remove(&stream->link);
-	
-	/* Move the new stream to the original location. */
-	memcpy(stream, new, sizeof (FILE));
-	free(new);
-	
-	/* Update references in the file list. */
-	stream->link.next->prev = &stream->link;
-	stream->link.prev->next = &stream->link;
-	
-	return stream;
-}
-
-/**
- * Write error messages to standard error.
- *
- * @param s Error message.
- */
-void posix_perror(const char *s)
-{
-	if (s == NULL || s[0] == '\0') {
-		fprintf(stderr, "%s\n", posix_strerror(errno));
-	} else {
-		fprintf(stderr, "%s: %s\n", s, posix_strerror(errno));
-	}
-}
-
-struct _posix_fpos {
-	off64_t offset;
-};
-
-/** Restores stream a to position previously saved with fgetpos().
- *
- * @param stream Stream to restore
- * @param pos Position to restore
- * @return Zero on success, non-zero (with errno set) on failure
- */
-int posix_fsetpos(FILE *stream, const posix_fpos_t *pos)
-{
-	return fseek(stream, pos->offset, SEEK_SET);
-}
-
-/** Saves the stream's position for later use by fsetpos().
- *
- * @param stream Stream to save
- * @param pos Place to store the position
- * @return Zero on success, non-zero (with errno set) on failure
- */
-int posix_fgetpos(FILE *restrict stream, posix_fpos_t *restrict pos)
-{
-	off64_t ret = ftell(stream);
-	if (ret != -1) {
-		pos->offset = ret;
-		return 0;
-	} else {
-		return -1;
-	}
-}
-
-/**
- * Reposition a file-position indicator in a stream.
- * 
- * @param stream Stream to seek in.
- * @param offset Direction and amount of bytes to seek.
- * @param whence From where to seek.
- * @return Zero on success, -1 otherwise.
- */
-int posix_fseek(FILE *stream, long offset, int whence)
-{
-	return fseek(stream, (off64_t) offset, whence);
-}
-
-/**
- * Reposition a file-position indicator in a stream.
- * 
- * @param stream Stream to seek in.
- * @param offset Direction and amount of bytes to seek.
- * @param whence From where to seek.
- * @return Zero on success, -1 otherwise.
- */
-int posix_fseeko(FILE *stream, posix_off_t offset, int whence)
-{
-	return fseek(stream, (off64_t) offset, whence);
-}
-
-/**
- * Discover current file offset in a stream.
- * 
- * @param stream Stream for which the offset shall be retrieved.
- * @return Current offset or -1 if not possible.
- */
-long posix_ftell(FILE *stream)
-{
-	return (long) ftell(stream);
-}
-
-/**
- * Discover current file offset in a stream.
- * 
- * @param stream Stream for which the offset shall be retrieved.
- * @return Current offset or -1 if not possible.
- */
-posix_off_t posix_ftello(FILE *stream)
-{
-	return (posix_off_t) ftell(stream);
-}
-
-/**
- * Discard prefetched data or write unwritten data.
- * 
- * @param stream Stream that shall be flushed.
- * @return Zero on success, EOF on failure.
- */
-int posix_fflush(FILE *stream)
-{
-	int rc = fflush(stream);
-	if (rc < 0) {
-		errno = -rc;
-		return EOF;
-	} else {
-		return 0;
-	}
-}
-
-/**
- * Print formatted output to the opened file.
- *
- * @param fildes File descriptor of the opened file.
- * @param format Format description.
- * @return Either the number of printed characters or negative value on error.
- */
-int posix_dprintf(int fildes, const char *restrict format, ...)
-{
-	va_list list;
-	va_start(list, format);
-	int result = posix_vdprintf(fildes, format, list);
-	va_end(list);
-	return result;
-}
-
-/**
- * Write ordinary string to the opened file.
- *
- * @param str String to be written.
- * @param size Size of the string (in bytes)..
- * @param fd File descriptor of the opened file.
- * @return The number of written characters.
- */
-static int _dprintf_str_write(const char *str, size_t size, void *fd)
-{
-	ssize_t wr = write(*(int *) fd, str, size);
-	return str_nlength(str, wr);
-}
-
-/**
- * Write wide string to the opened file.
- * 
- * @param str String to be written.
- * @param size Size of the string (in bytes).
- * @param fd File descriptor of the opened file.
- * @return The number of written characters.
- */
-static int _dprintf_wstr_write(const wchar_t *str, size_t size, void *fd)
-{
-	size_t offset = 0;
-	size_t chars = 0;
-	size_t sz;
-	char buf[4];
-	
-	while (offset < size) {
-		sz = 0;
-		if (chr_encode(str[chars], buf, &sz, sizeof(buf)) != EOK) {
-			break;
-		}
-		
-		if (write(*(int *) fd, buf, sz) != (ssize_t) sz) {
-			break;
-		}
-		
-		chars++;
-		offset += sizeof(wchar_t);
-	}
-	
-	return chars;
-}
-
-/**
- * Print formatted output to the opened file.
- * 
- * @param fildes File descriptor of the opened file.
- * @param format Format description.
- * @param ap Print arguments.
- * @return Either the number of printed characters or negative value on error.
- */
-int posix_vdprintf(int fildes, const char *restrict format, va_list ap)
-{
-	printf_spec_t spec = {
-		.str_write = _dprintf_str_write,
-		.wstr_write = _dprintf_wstr_write,
-		.data = &fildes
-	};
-	
-	return printf_core(format, &spec, ap);
-}
-
-/**
- * Print formatted output to the string.
- * 
- * @param s Output string.
- * @param format Format description.
- * @return Either the number of printed characters (excluding null byte) or
- *     negative value on error.
- */
-int posix_sprintf(char *s, const char *restrict format, ...)
-{
-	va_list list;
-	va_start(list, format);
-	int result = posix_vsprintf(s, format, list);
-	va_end(list);
-	return result;
-}
-
-/**
- * Print formatted output to the string.
- * 
- * @param s Output string.
- * @param format Format description.
- * @param ap Print arguments.
- * @return Either the number of printed characters (excluding null byte) or
- *     negative value on error.
- */
-int posix_vsprintf(char *s, const char *restrict format, va_list ap)
-{
-	return vsnprintf(s, STR_NO_LIMIT, format, ap);
-}
-
-/**
- * Convert formatted input from the stream.
- * 
- * @param stream Input stream.
- * @param format Format description.
- * @return The number of converted output items or EOF on failure.
- */
-int posix_fscanf(FILE *restrict stream, const char *restrict format, ...)
-{
-	va_list list;
-	va_start(list, format);
-	int result = posix_vfscanf(stream, format, list);
-	va_end(list);
-	return result;
-}
-
-/**
- * Convert formatted input from the standard input.
- * 
- * @param format Format description.
- * @return The number of converted output items or EOF on failure.
- */
-int posix_scanf(const char *restrict format, ...)
-{
-	va_list list;
-	va_start(list, format);
-	int result = posix_vscanf(format, list);
-	va_end(list);
-	return result;
-}
-
-/**
- * Convert formatted input from the standard input.
- * 
- * @param format Format description.
- * @param arg Output items.
- * @return The number of converted output items or EOF on failure.
- */
-int posix_vscanf(const char *restrict format, va_list arg)
-{
-	return posix_vfscanf(stdin, format, arg);
-}
-
-/**
- * Convert formatted input from the string.
- * 
- * @param s Input string.
- * @param format Format description.
- * @return The number of converted output items or EOF on failure.
- */
-int posix_sscanf(const char *restrict s, const char *restrict format, ...)
-{
-	va_list list;
-	va_start(list, format);
-	int result = posix_vsscanf(s, format, list);
-	va_end(list);
-	return result;
-}
-
-/**
- * Acquire file stream for the thread.
- *
- * @param file File stream to lock.
- */
-void posix_flockfile(FILE *file)
-{
-	/* dummy */
-}
-
-/**
- * Acquire file stream for the thread (non-blocking).
- *
- * @param file File stream to lock.
- * @return Zero for success and non-zero if the lock cannot be acquired.
- */
-int posix_ftrylockfile(FILE *file)
-{
-	/* dummy */
-	return 0;
-}
-
-/**
- * Relinquish the ownership of the locked file stream.
- *
- * @param file File stream to unlock.
- */
-void posix_funlockfile(FILE *file)
-{
-	/* dummy */
-}
-
-/**
- * Get a byte from a stream (thread-unsafe).
- *
- * @param stream Input file stream.
- * @return Either read byte or EOF.
- */
-int posix_getc_unlocked(FILE *stream)
-{
-	return getc(stream);
-}
-
-/**
- * Get a byte from the standard input stream (thread-unsafe).
- *
- * @return Either read byte or EOF.
- */
-int posix_getchar_unlocked(void)
-{
-	return getchar();
-}
-
-/**
- * Put a byte on a stream (thread-unsafe).
- *
- * @param c Byte to output.
- * @param stream Output file stream.
- * @return Either written byte or EOF.
- */
-int posix_putc_unlocked(int c, FILE *stream)
-{
-	return putc(c, stream);
-}
-
-/**
- * Put a byte on the standard output stream (thread-unsafe).
- * 
- * @param c Byte to output.
- * @return Either written byte or EOF.
- */
-int posix_putchar_unlocked(int c)
-{
-	return putchar(c);
-}
-
-/**
- * Remove a file or directory.
- *
- * @param path Pathname of the file that shall be removed.
- * @return Zero on success, -1 (with errno set) otherwise.
- */
-int posix_remove(const char *path)
-{
-	struct stat st;
-	int rc = stat(path, &st);
-	
-	if (rc != EOK) {
-		errno = -rc;
-		return -1;
-	}
-	
-	if (st.is_directory) {
-		rc = rmdir(path);
-	} else {
-		rc = unlink(path);
-	}
-	
-	if (rc != EOK) {
-		errno = -rc;
-		return -1;
-	}
-	return 0;
-}
-
-/**
- * Rename a file or directory.
- *
- * @param old Old pathname.
- * @param new New pathname.
- * @return Zero on success, -1 (with errno set) otherwise.
- */
-int posix_rename(const char *old, const char *new)
-{
-	return errnify(rename, old, new);
-}
-
-/**
- * Get a unique temporary file name (obsolete).
- *
- * @param s Buffer for the file name. Must be at least L_tmpnam bytes long.
- * @return The value of s on success, NULL on failure.
- */
-char *posix_tmpnam(char *s)
-{
-	assert(L_tmpnam >= posix_strlen("/tmp/tnXXXXXX"));
-	
-	static char buffer[L_tmpnam + 1];
-	if (s == NULL) {
-		s = buffer;
-	}
-	
-	posix_strcpy(s, "/tmp/tnXXXXXX");
-	posix_mktemp(s);
-	
-	if (*s == '\0') {
-		/* Errno set by mktemp(). */
-		return NULL;
-	}
-	
-	return s;
-}
-
-/**
- * Get an unique temporary file name with additional constraints (obsolete).
- *
- * @param dir Path to directory, where the file should be created.
- * @param pfx Optional prefix up to 5 characters long.
- * @return Newly allocated unique path for temporary file. NULL on failure.
- */
-char *posix_tempnam(const char *dir, const char *pfx)
-{
-	/* Sequence number of the filename. */
-	static int seq = 0;
-	
-	size_t dir_len = posix_strlen(dir);
-	if (dir[dir_len - 1] == '/') {
-		dir_len--;
-	}
-	
-	size_t pfx_len = posix_strlen(pfx);
-	if (pfx_len > 5) {
-		pfx_len = 5;
-	}
-	
-	char *result = malloc(dir_len + /* slash*/ 1 +
-	    pfx_len + /* three-digit seq */ 3 + /* .tmp */ 4 + /* nul */ 1);
-	
-	if (result == NULL) {
-		errno = ENOMEM;
-		return NULL;
-	}
-	
-	char *res_ptr = result;
-	posix_strncpy(res_ptr, dir, dir_len);
-	res_ptr += dir_len;
-	posix_strncpy(res_ptr, pfx, pfx_len);
-	res_ptr += pfx_len;
-	
-	for (; seq < 1000; ++seq) {
-		snprintf(res_ptr, 8, "%03d.tmp", seq);
-		
-		int orig_errno = errno;
-		errno = 0;
-		/* Check if the file exists. */
-		if (posix_access(result, F_OK) == -1) {
-			if (errno == ENOENT) {
-				errno = orig_errno;
-				break;
-			} else {
-				/* errno set by access() */
-				return NULL;
-			}
-		}
-	}
-	
-	if (seq == 1000) {
-		free(result);
-		errno = EINVAL;
-		return NULL;
-	}
-	
-	return result;
-}
-
-/**
- * Create and open an unique temporary file.
- * The file is automatically removed when the stream is closed.
- *
- * @param dir Path to directory, where the file should be created.
- * @param pfx Optional prefix up to 5 characters long.
- * @return Newly allocated unique path for temporary file. NULL on failure.
- */
-FILE *posix_tmpfile(void)
-{
-	char filename[] = "/tmp/tfXXXXXX";
-	int fd = posix_mkstemp(filename);
-	if (fd == -1) {
-		/* errno set by mkstemp(). */
-		return NULL;
-	}
-	
-	/* Unlink the created file, so that it's removed on close(). */
-	posix_unlink(filename);
-	return fdopen(fd, "w+");
-}
-
-/** @}
- */
Index: pace/lib/posix/stdio.h
===================================================================
--- uspace/lib/posix/stdio.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,190 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Standard buffered input/output.
- */
-
-#ifndef POSIX_STDIO_H_
-#define POSIX_STDIO_H_
-
-#include "stddef.h"
-#include "unistd.h"
-#include "libc/stdio.h"
-#include "sys/types.h"
-#include "libc/stdarg.h"
-#include "limits.h"
-
-/* Identifying the Terminal */
-#undef L_ctermid
-#define L_ctermid PATH_MAX
-extern char *posix_ctermid(char *s);
-
-/* Error Recovery */
-extern void posix_clearerr(FILE *stream);
-
-/* Input/Output */
-#undef putc
-#define putc fputc
-extern int posix_fputs(const char *restrict s, FILE *restrict stream);
-#undef getc
-#define getc fgetc
-extern int posix_ungetc(int c, FILE *stream);
-extern ssize_t posix_getdelim(char **restrict lineptr, size_t *restrict n,
-    int delimiter, FILE *restrict stream);
-extern ssize_t posix_getline(char **restrict lineptr, size_t *restrict n,
-    FILE *restrict stream);
-
-/* Opening Streams */
-extern FILE *posix_freopen(const char *restrict filename,
-    const char *restrict mode, FILE *restrict stream);
-
-/* Error Messages */
-extern void posix_perror(const char *s);
-
-/* File Positioning */
-typedef struct _posix_fpos posix_fpos_t;
-extern int posix_fsetpos(FILE *stream, const posix_fpos_t *pos);
-extern int posix_fgetpos(FILE *restrict stream, posix_fpos_t *restrict pos);
-extern int posix_fseek(FILE *stream, long offset, int whence);
-extern int posix_fseeko(FILE *stream, posix_off_t offset, int whence);
-extern long posix_ftell(FILE *stream);
-extern posix_off_t posix_ftello(FILE *stream);
-
-/* Flushing Buffers */
-extern int posix_fflush(FILE *stream);
-
-/* Formatted Output */
-extern int posix_dprintf(int fildes, const char *restrict format, ...)
-    PRINTF_ATTRIBUTE(2, 3);
-extern int posix_vdprintf(int fildes, const char *restrict format, va_list ap);
-extern int posix_sprintf(char *restrict s, const char *restrict format, ...)
-    PRINTF_ATTRIBUTE(2, 3);
-extern int posix_vsprintf(char *restrict s, const char *restrict format, va_list ap);
-
-/* Formatted Input */
-extern int posix_fscanf(
-    FILE *restrict stream, const char *restrict format, ...);
-extern int posix_vfscanf(
-    FILE *restrict stream, const char *restrict format, va_list arg);
-extern int posix_scanf(const char *restrict format, ...);
-extern int posix_vscanf(const char *restrict format, va_list arg);
-extern int posix_sscanf(
-    const char *restrict s, const char *restrict format, ...);
-extern int posix_vsscanf(
-    const char *restrict s, const char *restrict format, va_list arg);
-
-/* File Locking */
-extern void posix_flockfile(FILE *file);
-extern int posix_ftrylockfile(FILE *file);
-extern void posix_funlockfile(FILE *file);
-extern int posix_getc_unlocked(FILE *stream);
-extern int posix_getchar_unlocked(void);
-extern int posix_putc_unlocked(int c, FILE *stream);
-extern int posix_putchar_unlocked(int c);
-
-/* Deleting Files */
-extern int posix_remove(const char *path);
-
-/* Renaming Files */
-extern int posix_rename(const char *old, const char *new);
-
-/* Temporary Files */
-#undef L_tmpnam
-#define L_tmpnam PATH_MAX
-extern char *posix_tmpnam(char *s);
-extern char *posix_tempnam(const char *dir, const char *pfx);
-extern FILE *posix_tmpfile(void);
-
-#ifndef LIBPOSIX_INTERNAL
-	/* DEBUG macro does not belong to POSIX stdio.h. Its unconditional
-	 * definition in the native stdio.h causes unexpected behaviour of
-	 * applications which uses their own DEBUG macro (e.g. debugging
-	 * output is printed even if not desirable). */
-	#undef DEBUG
-
-	#define ctermid posix_ctermid
-
-	#define clearerr posix_clearerr
-
-	#define fputs posix_fputs
-	#define ungetc posix_ungetc
-	#define getdelim posix_getdelim
-	#define getline posix_getline
-
-	#define freopen posix_freopen
-
-	#define perror posix_perror
-
-	#define fpos_t posix_fpos_t
-	#define fsetpos posix_fsetpos
-	#define fgetpos posix_fgetpos
-	#define fseek posix_fseek
-	#define fseeko posix_fseeko
-	#define ftell posix_ftell
-	#define ftello posix_ftello
-
-	#define fflush posix_fflush
-
-	#define dprintf posix_dprintf
-	#define vdprintf posix_vdprintf
-	#define sprintf posix_sprintf
-	#define vsprintf posix_vsprintf
-
-	#define fscanf posix_fscanf
-	#define vfscanf posix_vfscanf
-	#define vscanf posix_vscanf
-	#define scanf posix_scanf
-	#define sscanf posix_sscanf
-	#define vsscanf posix_vsscanf
-
-	#define flockfile posix_flockfile
-	#define ftrylockfile posix_ftrylockfile
-	#define funlockfile posix_funlockfile
-
-	#define getc_unlocked posix_getc_unlocked
-	#define getchar_unlocked posix_getchar_unlocked
-	#define putc_unlocked posix_putc_unlocked
-	#define putchar_unlocked posix_putchar_unlocked
-
-	#define remove posix_remove
-
-	#define rename posix_rename
-
-	#define tmpnam posix_tmpnam
-	#define tempnam posix_tempnam
-	#define tmpfile posix_tmpfile
-#endif
-
-#endif /* POSIX_STDIO_H_ */
-
-/** @}
- */
Index: pace/lib/posix/stdio/scanf.c
===================================================================
--- uspace/lib/posix/stdio/scanf.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,1339 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Implementation of the scanf backend.
- */
-
-#define LIBPOSIX_INTERNAL
-
-/* Must be first. */
-#include "../stdbool.h"
-
-#include "../assert.h"
-#include "../errno.h"
-
-#include "../stdio.h"
-#include "../stdlib.h"
-#include "../stddef.h"
-#include "../string.h"
-#include "../ctype.h"
-#include "../sys/types.h"
-
-#include "../internal/common.h"
-#include "../libc/malloc.h"
-
-/** Unified data type for possible data sources for scanf. */
-typedef union __data_source {
-	FILE *stream; /**< Input file stream. */
-	const char *string; /**< Input string. */
-} _data_source;
-
-/** Internal state of the input provider. */
-enum {
-	/** Partly constructed but not yet functional. */
-	_PROV_CONSTRUCTED,
-	/** Ready to serve any request. */
-	_PROV_READY,
-	/** Cursor is temporarily lent to the external entity. No action is
-	  * possible until the cursor is returned.  */
-	_PROV_CURSOR_LENT,
-};
-
-/** Universal abstraction over data input for scanf. */
-typedef struct __input_provider {
-	/** Source of data elements. */
-	_data_source source;
-	/** How many elements was already processed. */
-	int consumed;
-	/** How many elements was already fetched from the source. */
-	int fetched;
-	/** Elements are fetched from the source in batches (e.g. by getline())
-	  * to allow using strtol/strtod family even on streams. */
-	char *window;
-	/** Size of the current window. */
-	size_t window_size;
-	/** Points to the next element to be processed inside the current window. */
-	const char *cursor;
-	/** Internal state of the provider. */
-	int state;
-
-	/** Take control over data source. Finish initialization of the internal
-	  * structures (e.g. allocation of window). */
-	void (*capture)(struct __input_provider *);
-	/** Get a single element from the source and update the internal structures
-	  * accordingly (e.g. greedy update of the window). Return -1 if the
-	  * element cannot be obtained. */
-	int (*pop)(struct __input_provider *);
-	/** Undo the most recent not-undone pop operation. Might be necesarry to
-	  * flush current window and seek data source backwards. Return 0 if the
-	  * pop history is exhausted, non-zero on success. */
-	int (*undo)(struct __input_provider *);
-	/** Lend the cursor to the caller.  */
-	const char * (*borrow_cursor)(struct __input_provider *);
-	/** Take control over possibly incremented cursor and update the internal
-	  * structures if necessary. */
-	void (*return_cursor)(struct __input_provider *, const char *);
-	/** Release the control over the source. That is, synchronize any
-	  * fetched but non-consumed elements (e.g. by seeking) and destruct
-	  * internal structures (e.g. window deallocation). */
-	void (*release)(struct __input_provider *);
-} _input_provider;
-
-/** @see __input_provider */
-static void _capture_stream(_input_provider *self)
-{
-	assert(self->source.stream);
-	assert(self->state == _PROV_CONSTRUCTED);
-	/* Caller could already pre-allocated the window. */
-	assert((self->window == NULL && self->window_size == 0) ||
-	    (self->window && self->window_size > 0));
-
-	/* Initialize internal structures. */
-	self->consumed = 0;
-	ssize_t fetched = posix_getline(
-	    &self->window, &self->window_size, self->source.stream);
-	if (fetched != -1) {
-		self->fetched = fetched;
-		self->cursor = self->window;
-	} else {
-		/* EOF encountered. */
-		self->fetched = 0;
-		self->cursor = NULL;
-	}
-	self->state = _PROV_READY;
-}
-
-/** @see __input_provider */
-static void _capture_string(_input_provider *self)
-{
-	assert(self->source.string);
-	assert(self->state == _PROV_CONSTRUCTED);
-
-	/* Initialize internal structures. */
-	self->consumed = 0;
-	self->fetched = posix_strlen(self->source.string);
-	self->window = (char *) self->source.string;
-	self->window_size = self->fetched + 1;
-	self->cursor = self->window;
-	self->state = _PROV_READY;
-}
-
-/** @see __input_provider */
-static int _pop_stream(_input_provider *self)
-{
-	assert(self->state == _PROV_READY);
-
-	if (self->cursor) {
-		int c = *self->cursor;
-		++self->consumed;
-		++self->cursor;
-		/* Do we need to fetch a new line from the source? */
-		if (*self->cursor == '\0') {
-			ssize_t fetched = posix_getline(&self->window,
-			    &self->window_size, self->source.stream);
-			if (fetched != -1) {
-				self->fetched += fetched;
-				self->cursor = self->window;
-			} else {
-				/* EOF encountered. */
-				self->cursor = NULL;
-			}
-		}
-		return c;
-	} else {
-		/* Already at EOF. */
-		return -1;
-	}
-}
-
-/** @see __input_provider */
-static int _pop_string(_input_provider *self)
-{
-	assert(self->state == _PROV_READY);
-
-	if (*self->cursor != '\0') {
-		int c = *self->cursor;
-		++self->consumed;
-		++self->cursor;
-		return c;
-	} else {
-		/* String depleted. */
-		return -1;
-	}
-}
-
-/** @see __input_provider */
-static int _undo_stream(_input_provider *self)
-{
-	assert(self->state == _PROV_READY);
-
-	if (self->consumed == 0) {
-		/* Undo history exhausted. */
-		return 0;
-	}
-
-	if (!self->cursor || self->window == self->cursor) {
-		/* Complex case. Either at EOF (cursor == NULL) or there is no more
-		 * place to retreat to inside the window. Seek the source backwards
-		 * and flush the window. Regarding the scanf, this could happend only
-		 * when matching unbounded string (%s) or unbounded scanset (%[) not
-		 * containing newline, while at the same time newline is the character
-		 * that breaks the matching process. */
-		int rc = posix_fseek(
-		    self->source.stream, -1, SEEK_CUR);
-		if (rc == -1) {
-			/* Seek failed.  */
-			return 0;
-		}
-		ssize_t fetched = posix_getline(&self->window,
-		    &self->window_size, self->source.stream);
-		if (fetched != -1) {
-			assert(fetched == 1);
-			self->fetched = self->consumed + 1;
-			self->cursor = self->window;
-		} else {
-			/* Stream is broken. */
-			return 0;
-		}
-	} else {
-		/* Simple case. Still inside window. */
-		--self->cursor;
-	}
-	--self->consumed;
-	return 1; /* Success. */
-}
-
-/** @see __input_provider */
-static int _undo_string(_input_provider *self)
-{
-	assert(self->state == _PROV_READY);
-
-	if (self->consumed > 0) {
-		--self->consumed;
-		--self->cursor;
-	} else {
-		/* Undo history exhausted. */
-		return 0;
-	}
-	return 1; /* Success. */
-}
-
-/** @see __input_provider */
-static const char *_borrow_cursor_universal(_input_provider *self)
-{
-	assert(self->state == _PROV_READY);
-
-	self->state = _PROV_CURSOR_LENT;
-	return self->cursor;
-}
-
-/** @see __input_provider */
-static void _return_cursor_stream(_input_provider *self, const char *cursor)
-{
-	assert(self->state == _PROV_CURSOR_LENT);
-
-	/* Check how much of the window did external entity consumed. */
-	self->consumed += cursor - self->cursor;
-	self->cursor = cursor;
-	if (*self->cursor == '\0') {
-		/* Window was completely consumed, fetch new data. */
-		ssize_t fetched = posix_getline(&self->window,
-		    &self->window_size, self->source.stream);
-		if (fetched != -1) {
-			self->fetched += fetched;
-			self->cursor = self->window;
-		} else {
-			/* EOF encountered. */
-			self->cursor = NULL;
-		}
-	}
-	self->state = _PROV_READY;
-}
-
-/** @see __input_provider */
-static void _return_cursor_string(_input_provider *self, const char *cursor)
-{
-	assert(self->state == _PROV_CURSOR_LENT);
-
-	/* Check how much of the window did external entity consumed. */
-	self->consumed += cursor - self->cursor;
-	self->cursor = cursor;
-	self->state = _PROV_READY;
-}
-
-/** @see __input_provider */
-static void _release_stream(_input_provider *self)
-{
-	assert(self->state == _PROV_READY);
-	assert(self->consumed >= self->fetched);
-
-	/* Try to correct the difference between the stream position and what was
-	 * actually consumed. If it is not possible, continue anyway. */
-	posix_fseek(self->source.stream, self->consumed - self->fetched, SEEK_CUR);
-
-	/* Destruct internal structures. */
-	self->fetched = 0;
-	self->cursor = NULL;
-	if (self->window) {
-		free(self->window);
-		self->window = NULL;
-	}
-	self->window_size = 0;
-	self->state = _PROV_CONSTRUCTED;
-}
-
-/** @see __input_provider */
-static void _release_string(_input_provider *self)
-{
-	assert(self->state == _PROV_READY);
-
-	/* Destruct internal structures. */
-	self->fetched = 0;
-	self->cursor = NULL;
-	self->window = NULL;
-	self->window_size = 0;
-	self->state = _PROV_CONSTRUCTED;
-}
-
-/** Length modifier values. */
-enum {
-	LMOD_NONE,
-	LMOD_hh,
-	LMOD_h,
-	LMOD_l,
-	LMOD_ll,
-	LMOD_j,
-	LMOD_z,
-	LMOD_t,
-	LMOD_L,
-	LMOD_p, /* Reserved for %p conversion. */
-};
-
-/**
- * Decides whether provided characters specify length modifier. If so, the
- * recognized modifier is stored through provider pointer.
- *
- * @param c Candidate on the length modifier.
- * @param _c Next character (might be NUL).
- * @param modifier Pointer to the modifier value.
- * @return Whether the modifier was recognized or not.
- */
-static inline int is_length_mod(int c, int _c, int *modifier)
-{
-	assert(modifier);
-
-	switch (c) {
-	case 'h':
-		/* Check whether the modifier was not already recognized. */
-		if (*modifier == LMOD_NONE) {
-			*modifier = _c == 'h' ? LMOD_hh : LMOD_h;
-		} else {
-			/* Format string is invalid. Notify the caller. */
-			*modifier = LMOD_NONE;
-		}
-		return 1;
-	case 'l':
-		if (*modifier == LMOD_NONE) {
-			*modifier = _c == 'l' ? LMOD_ll : LMOD_l;
-		} else {
-			*modifier = LMOD_NONE;
-		}
-		return 1;
-	case 'j':
-		*modifier = *modifier == LMOD_NONE ? LMOD_j : LMOD_NONE;
-		return 1;
-	case 'z':
-		*modifier = *modifier == LMOD_NONE ? LMOD_z : LMOD_NONE;
-		return 1;
-	case 't':
-		*modifier = *modifier == LMOD_NONE ? LMOD_t : LMOD_NONE;
-		return 1;
-	case 'L':
-		*modifier = *modifier == LMOD_NONE ? LMOD_L : LMOD_NONE;
-		return 1;
-	default:
-		return 0;
-	}
-}
-
-/**
- * Decides whether provided character specifies integer conversion. If so, the
- * semantics of the conversion is stored through provided pointers..
- * 
- * @param c Candidate on the integer conversion.
- * @param is_unsigned Pointer to store whether the conversion is signed or not.
- * @param base Pointer to store the base of the integer conversion.
- * @return Whether the conversion was recognized or not.
- */
-static inline int is_int_conv(int c, bool *is_unsigned, int *base)
-{
-	assert(is_unsigned && base);
-
-	switch (c) {
-	case 'd':
-		*is_unsigned = false;
-		*base = 10;
-		return 1;
-	case 'i':
-		*is_unsigned = false;
-		*base = 0;
-		return 1;
-	case 'o':
-		*is_unsigned = true;
-		*base = 8;
-		return 1;
-	case 'u':
-		*is_unsigned = true;
-		*base = 10;
-		return 1;
-	case 'p': /* According to POSIX, %p modifier is implementation defined but
-			   * must correspond to its printf counterpart. */
-	case 'x':
-	case 'X':
-		*is_unsigned = true;
-		*base = 16;
-		return 1;
-		return 1;
-	default:
-		return 0;
-	}
-}
-
-/**
- * Decides whether provided character specifies conversion of the floating
- * point number.
- *
- * @param c Candidate on the floating point conversion.
- * @return Whether the conversion was recognized or not.
- */
-static inline int is_float_conv(int c)
-{
-	switch (c) {
-	case 'a':
-	case 'A':
-	case 'e':
-	case 'E':
-	case 'f':
-	case 'F':
-	case 'g':
-	case 'G':
-		return 1;
-	default:
-		return 0;
-	}
-}
-
-/**
- * Decides whether provided character specifies conversion of the character
- * sequence.
- *
- * @param c Candidate on the character sequence conversion.
- * @param modifier Pointer to store length modifier for wide chars.
- * @return Whether the conversion was recognized or not.
- */
-static inline int is_seq_conv(int c, int *modifier)
-{
-	assert(modifier);
-	
-	switch (c) {
-	case 'S':
-		*modifier = LMOD_l;
-		/* fallthrough */
-	case 's':
-		return 1;
-	case 'C':
-		*modifier = LMOD_l;
-		/* fallthrough */
-	case 'c':
-		return 1;
-	case '[':
-		return 1;
-	default:
-		return 0;
-	}
-}
-
-/**
- * Backend for the whole family of scanf functions. Uses input provider
- * to abstract over differences between strings and streams. Should be
- * POSIX compliant (apart from the not supported stuff).
- *
- * NOT SUPPORTED: locale (see strtold), wide chars, numbered output arguments
- * 
- * @param in Input provider.
- * @param fmt Format description.
- * @param arg Output arguments.
- * @return The number of converted output items or EOF on failure.
- */
-static inline int _internal_scanf(
-    _input_provider *in, const char *restrict fmt, va_list arg)
-{
-	int c = -1;
-	int converted_cnt = 0;
-	bool converting = false;
-	bool matching_failure = false;
-
-	bool assign_supress = false;
-	bool assign_alloc = false;
-	long width = -1;
-	int length_mod = LMOD_NONE;
-	bool int_conv_unsigned = false;
-	int int_conv_base = 0;
-
-	/* Buffers allocated by scanf for optional 'm' specifier must be remembered
-	 * to deallocaate them in case of an error. Because each of those buffers
-	 * corresponds to one of the argument from va_list, there is an upper bound
-	 * on the number of those arguments. In case of C99, this uppper bound is
-	 * 127 arguments. */
-	char *buffers[127];
-	for (int i = 0; i < 127; ++i) {
-		buffers[i] = NULL;
-	}
-	int next_unused_buffer_idx = 0;
-
-	in->capture(in);
-
-	/* Interpret format string. Control shall prematurely jump from the cycle
-	 * on input failure, matching failure or illegal format string. In order
-	 * to keep error reporting simple enough and to keep input consistent,
-	 * error condition shall be always manifested as jump from the cycle,
-	 * not function return. Format string pointer shall be updated specifically
-	 * for each sub-case (i.e. there shall be no loop-wide increment).*/
-	while (*fmt) {
-
-		if (converting) {
-
-			/* Processing inside conversion specifier. Either collect optional
-			 * parameters or execute the conversion. When the conversion
-			 * is successfully completed, increment conversion count and switch
-			 * back to normal mode. */
-			if (*fmt == '*') {
-				/* Assignment-supression (optional). */
-				if (assign_supress) {
-					/* Already set. Illegal format string. */
-					break;
-				}
-				assign_supress = true;
-				++fmt;
-			} else if (*fmt == 'm') {
-				/* Assignment-allocation (optional). */
-				if (assign_alloc) {
-					/* Already set. Illegal format string. */
-					break;
-				}
-				assign_alloc = true;
-				++fmt;
-			} else if (*fmt == '$') {
-				/* Reference to numbered output argument. */
-				// TODO
-				not_implemented();
-			} else if (isdigit(*fmt)) {
-				/* Maximum field length (optional). */
-				if (width != -1) {
-					/* Already set. Illegal format string. */
-					break;
-				}
-				char *fmt_new = NULL;
-				width = posix_strtol(fmt, &fmt_new, 10);
-				if (width != 0) {
-					fmt = fmt_new;
-				} else {
-					/* Since POSIX requires width to be non-zero, it is
-					 * sufficient to interpret zero width as error without
-					 * referring to errno. */
-					break;
-				}
-			} else if (is_length_mod(*fmt, *(fmt + 1), &length_mod)) {
-				/* Length modifier (optional). */
-				if (length_mod == LMOD_NONE) {
-					/* Already set. Illegal format string. The actual detection
-					 * is carried out in the is_length_mod(). */
-					break;
-				}
-				if (length_mod == LMOD_hh || length_mod == LMOD_ll) {
-					/* Modifier was two characters long. */
-					++fmt;
-				}
-				++fmt;
-			} else if (is_int_conv(*fmt, &int_conv_unsigned, &int_conv_base)) {
-				/* Integer conversion. */
-
-				/* Check sanity of optional parts of conversion specifier. */
-				if (assign_alloc || length_mod == LMOD_L) {
-					/* Illegal format string. */
-					break;
-				}
-
-				/* Conversion of the integer with %p specifier needs special
-				 * handling, because it is not allowed to have arbitrary
-				 * length modifier.  */
-				if (*fmt == 'p') {
-					if (length_mod == LMOD_NONE) {
-						length_mod = LMOD_p;
-					} else {
-						/* Already set. Illegal format string. */
-						break;
-					}
-				}
-
-				/* First consume any white spaces, so we can borrow cursor
-				 * from the input provider. This way, the cursor will either
-				 * point to the non-white space while the input will be
-				 * prefetched up to the newline (which is suitable for strtol),
-				 * or the input will be at EOF. */
-				do {
-					c = in->pop(in);
-				} while (isspace(c));
-
-				/* After skipping the white spaces, can we actually continue? */
-				if (c == -1) {
-					/* Input failure. */
-					break;
-				} else {
-					/* Everything is OK, just undo the last pop, so the cursor
-					 * can be borrowed. */
-					in->undo(in);
-				}
-
-				const char *cur_borrowed = NULL;
-				const char *cur_limited = NULL;
-				char *cur_updated = NULL;
-
-				/* Borrow the cursor. Until it is returned to the provider
-				 * we cannot jump from the cycle, because it would leave
-				 * the input inconsistent. */
-				cur_borrowed = in->borrow_cursor(in);
-
-				/* If the width is limited, the cursor horizont must be
-				 * decreased accordingly. Otherwise the strtol could read more
-				 * than allowed by width. */
-				if (width != -1) {
-					cur_limited = posix_strndup(cur_borrowed, width);
-				} else {
-					cur_limited = cur_borrowed;
-				}
-				cur_updated = (char *) cur_limited;
-
-				long long sres = 0;
-				unsigned long long ures = 0;
-				errno = 0; /* Reset errno to recognize error later. */
-				/* Try to convert the integer. */
-				if (int_conv_unsigned) {
-					ures = posix_strtoull(cur_limited, &cur_updated, int_conv_base);
-				} else {
-					sres = posix_strtoll(cur_limited, &cur_updated, int_conv_base);
-				}
-
-				/* Update the cursor so it can be returned to the provider. */
-				cur_borrowed += cur_updated - cur_limited;
-				if (width != -1 && cur_limited != NULL) {
-					/* Deallocate duplicated part of the cursor view. */
-					free(cur_limited);
-				}
-				cur_limited = NULL;
-				cur_updated = NULL;
-				/* Return the cursor to the provider. Input consistency is again
-				 * the job of the provider, so we can report errors from
-				 * now on. */
-				in->return_cursor(in, cur_borrowed);
-				cur_borrowed = NULL;
-
-				/* Check whether the conversion was successful. */
-				if (errno != EOK) {
-					matching_failure = true;
-					break;
-				}
-
-				/* If not supressed, assign the converted integer into
-				 * the next output argument. */
-				if (!assign_supress) {
-					if (int_conv_unsigned) {
-						switch (length_mod) {
-						case LMOD_hh: ; /* Label cannot be part of declaration. */
-							unsigned char *phh = va_arg(arg, unsigned char *);
-							*phh = (unsigned char) ures;
-							break;
-						case LMOD_h: ;
-							unsigned short *ph = va_arg(arg, unsigned short *);
-							*ph = (unsigned short) ures;
-							break;
-						case LMOD_NONE: ;
-							unsigned *pdef = va_arg(arg, unsigned *);
-							*pdef = (unsigned) ures;
-							break;
-						case LMOD_l: ;
-							unsigned long *pl = va_arg(arg, unsigned long *);
-							*pl = (unsigned long) ures;
-							break;
-						case LMOD_ll: ;
-							unsigned long long *pll = va_arg(arg, unsigned long long *);
-							*pll = (unsigned long long) ures;
-							break;
-						case LMOD_j: ;
-							posix_uintmax_t *pj = va_arg(arg, posix_uintmax_t *);
-							*pj = (posix_uintmax_t) ures;
-							break;
-						case LMOD_z: ;
-							size_t *pz = va_arg(arg, size_t *);
-							*pz = (size_t) ures;
-							break;
-						case LMOD_t: ;
-							// XXX: What is unsigned counterpart of the ptrdiff_t?
-							size_t *pt = va_arg(arg, size_t *);
-							*pt = (size_t) ures;
-							break;
-						case LMOD_p: ;
-							void **pp = va_arg(arg, void **);
-							*pp = (void *) (uintptr_t) ures;
-							break;
-						default:
-							assert(false);
-						}
-					} else {
-						switch (length_mod) {
-						case LMOD_hh: ; /* Label cannot be part of declaration. */
-							signed char *phh = va_arg(arg, signed char *);
-							*phh = (signed char) sres;
-							break;
-						case LMOD_h: ;
-							short *ph = va_arg(arg, short *);
-							*ph = (short) sres;
-							break;
-						case LMOD_NONE: ;
-							int *pdef = va_arg(arg, int *);
-							*pdef = (int) sres;
-							break;
-						case LMOD_l: ;
-							long *pl = va_arg(arg, long *);
-							*pl = (long) sres;
-							break;
-						case LMOD_ll: ;
-							long long *pll = va_arg(arg, long long *);
-							*pll = (long long) sres;
-							break;
-						case LMOD_j: ;
-							posix_intmax_t *pj = va_arg(arg, posix_intmax_t *);
-							*pj = (posix_intmax_t) sres;
-							break;
-						case LMOD_z: ;
-							ssize_t *pz = va_arg(arg, ssize_t *);
-							*pz = (ssize_t) sres;
-							break;
-						case LMOD_t: ;
-							posix_ptrdiff_t *pt = va_arg(arg, posix_ptrdiff_t *);
-							*pt = (posix_ptrdiff_t) sres;
-							break;
-						default:
-							assert(false);
-						}
-					}
-					++converted_cnt;
-				}
-
-				converting = false;
-				++fmt;
-			} else if (is_float_conv(*fmt)) {
-				/* Floating point number conversion. */
-
-				/* Check sanity of optional parts of conversion specifier. */
-				if (assign_alloc) {
-					/* Illegal format string. */
-					break;
-				}
-				if (length_mod != LMOD_NONE &&
-				    length_mod != LMOD_l &&
-				    length_mod != LMOD_L) {
-					/* Illegal format string. */
-					break;
-				}
-
-				/* First consume any white spaces, so we can borrow cursor
-				 * from the input provider. This way, the cursor will either
-				 * point to the non-white space while the input will be
-				 * prefetched up to the newline (which is suitable for strtof),
-				 * or the input will be at EOF. */
-				do {
-					c = in->pop(in);
-				} while (isspace(c));
-
-				/* After skipping the white spaces, can we actually continue? */
-				if (c == -1) {
-					/* Input failure. */
-					break;
-				} else {
-					/* Everything is OK, just undo the last pop, so the cursor
-					 * can be borrowed. */
-					in->undo(in);
-				}
-
-				const char *cur_borrowed = NULL;
-				const char *cur_limited = NULL;
-				char *cur_updated = NULL;
-
-				/* Borrow the cursor. Until it is returned to the provider
-				 * we cannot jump from the cycle, because it would leave
-				 * the input inconsistent. */
-				cur_borrowed = in->borrow_cursor(in);
-
-				/* If the width is limited, the cursor horizont must be
-				 * decreased accordingly. Otherwise the strtof could read more
-				 * than allowed by width. */
-				if (width != -1) {
-					cur_limited = posix_strndup(cur_borrowed, width);
-				} else {
-					cur_limited = cur_borrowed;
-				}
-				cur_updated = (char *) cur_limited;
-
-				float fres = 0.0;
-				double dres = 0.0;
-				long double ldres = 0.0;
-				errno = 0; /* Reset errno to recognize error later. */
-				/* Try to convert the floating point nubmer. */
-				switch (length_mod) {
-				case LMOD_NONE:
-					fres = posix_strtof(cur_limited, &cur_updated);
-					break;
-				case LMOD_l:
-					dres = posix_strtod(cur_limited, &cur_updated);
-					break;
-				case LMOD_L:
-					ldres = posix_strtold(cur_limited, &cur_updated);
-					break;
-				default:
-					assert(false);
-				}
-
-				/* Update the cursor so it can be returned to the provider. */
-				cur_borrowed += cur_updated - cur_limited;
-				if (width != -1 && cur_limited != NULL) {
-					/* Deallocate duplicated part of the cursor view. */
-					free(cur_limited);
-				}
-				cur_limited = NULL;
-				cur_updated = NULL;
-				/* Return the cursor to the provider. Input consistency is again
-				 * the job of the provider, so we can report errors from
-				 * now on. */
-				in->return_cursor(in, cur_borrowed);
-				cur_borrowed = NULL;
-
-				/* Check whether the conversion was successful. */
-				if (errno != EOK) {
-					matching_failure = true;
-					break;
-				}
-
-				/* If nto supressed, assign the converted floating point number
-				 * into the next output argument. */
-				if (!assign_supress) {
-					switch (length_mod) {
-					case LMOD_NONE: ; /* Label cannot be part of declaration. */
-						float *pf = va_arg(arg, float *);
-						*pf = fres;
-						break;
-					case LMOD_l: ;
-						double *pd = va_arg(arg, double *);
-						*pd = dres;
-						break;
-					case LMOD_L: ;
-						long double *pld = va_arg(arg, long double *);
-						*pld = ldres;
-						break;
-					default:
-						assert(false);
-					}
-					++converted_cnt;
-				}
-
-				converting = false;
-				++fmt;
-			} else if (is_seq_conv(*fmt, &length_mod)) {
-				/* Character sequence conversion. */
-				
-				/* Check sanity of optional parts of conversion specifier. */
-				if (length_mod != LMOD_NONE &&
-				    length_mod != LMOD_l) {
-					/* Illegal format string. */
-					break;
-				}
-
-				if (length_mod == LMOD_l) {
-					/* Wide chars not supported. */
-					// TODO
-					not_implemented();
-				}
-
-				int term_size = 1; /* Size of the terminator (0 or 1)). */
-				if (*fmt == 'c') {
-					term_size = 0;
-					width = width == -1 ? 1 : width;
-				}
-
-				if (*fmt == 's') {
-					/* Skip white spaces. */
-					do {
-						c = in->pop(in);
-					} while (isspace(c));
-				} else {
-					/* Fetch a single character. */
-					c = in->pop(in);
-				}
-
-				/* Check whether there is still input to read. */
-				if (c == -1) {
-					/* Input failure. */
-					break;
-				}
-
-				/* Prepare scanset. */
-				char terminate_on[256];
-				for (int i = 0; i < 256; ++i) {
-					terminate_on[i] = 0;
-				}
-				if (*fmt == 'c') {
-					++fmt;
-				} else if (*fmt == 's') {
-					terminate_on[' '] = 1;
-					terminate_on['\n'] = 1;
-					terminate_on['\t'] = 1;
-					terminate_on['\f'] = 1;
-					terminate_on['\r'] = 1;
-					terminate_on['\v'] = 1;
-					++fmt;
-				} else {
-					assert(*fmt == '[');
-					bool not = false;
-					bool dash = false;
-					++fmt;
-					/* Check for negation. */
-					if (*fmt == '^') {
-						not = true;
-						++fmt;
-					}
-					/* Check for escape sequences. */
-					if (*fmt == '-' || *fmt == ']') {
-						terminate_on[(int) *fmt] = 1;
-						++fmt;
-					}
-					/* Check for ordinary characters and ranges. */
-					while (*fmt != '\0' && *fmt != ']') {
-						if (dash) {
-							for (char chr = *(fmt - 2); chr <= *fmt; ++chr) {
-								terminate_on[(int) chr] = 1;
-							}
-							dash = false;
-						} else if (*fmt == '-') {
-							dash = true;
-						} else {
-							terminate_on[(int) *fmt] = 1;
-						}
-						++fmt;
-					}
-					/* Check for escape sequence. */
-					if (dash == true) {
-						terminate_on['-'] = 1;
-					}
-					/* Check whether the specifier was correctly terminated.*/
-					if (*fmt == '\0') {
-						/* Illegal format string. */
-						break;
-					} else {
-						++fmt;
-					}
-					/* Inverse the scanset if necessary. */
-					if (not == false) {
-						for (int i = 0; i < 256; ++i) {
-							terminate_on[i] = terminate_on[i] ? 0 : 1;
-						}
-					}
-				}
-
-				char * buf = NULL;
-				size_t buf_size = 0;
-				char * cur = NULL;
-				size_t alloc_step = 80; /* Buffer size gain during reallocation. */
-				int my_buffer_idx = 0;
-
-				/* Retrieve the buffer into which popped characters
-				 * will be stored. */
-				if (!assign_supress) {
-					if (assign_alloc) {
-						/* We must allocate our own buffer. */
-						buf_size =
-						    width == -1 ? alloc_step : (size_t) width + term_size;
-						buf = malloc(buf_size);
-						if (!buf) {
-							/* No memory. */
-							break;
-						}
-						my_buffer_idx = next_unused_buffer_idx;
-						++next_unused_buffer_idx;
-						buffers[my_buffer_idx] = buf;
-						cur = buf;
-					} else {
-						/* Caller provided its buffer. */
-						buf = va_arg(arg, char *);
-						cur = buf;
-						buf_size =
-						    width == -1 ? SIZE_MAX : (size_t) width + term_size;
-					}
-				}
-
-				/* Match the string. The next character is already popped. */
-				while ((width == -1 || width > 0) && c != -1 && !terminate_on[c]) {
-
-					/* Check whether the buffer is still sufficiently large. */
-					if (!assign_supress) {
-						/* Always reserve space for the null terminator. */
-						if (cur == buf + buf_size - term_size) {
-							/* Buffer size must be increased. */
-							buf = realloc(buf, buf_size + alloc_step);
-							if (buf) {
-								buffers[my_buffer_idx] = buf;
-								cur = buf + buf_size - term_size;
-								buf_size += alloc_step;
-							} else {
-								/* Break just from this tight loop. Errno will
-								 * be checked after it. */
-								break;
-							}
-						}
-						/* Store the input character. */
-						*cur = c;
-					}
-
-					width = width == -1 ? -1 : width - 1;
-					++cur;
-					c = in->pop(in);
-				}
-				if (errno == ENOMEM) {
-					/* No memory. */
-					break;
-				}
-				if (c != -1) {
-					/* There is still more input, so undo the last pop. */
-					in->undo(in);
-				}
-
-				/* Check for failures. */
-				if (cur == buf) {
-					/* Matching failure. Input failure was already checked
-					 * earlier. */
-					matching_failure = true;
-					if (!assign_supress && assign_alloc) {
-						/* Roll back. */
-						free(buf);
-						buffers[my_buffer_idx] = NULL;
-						--next_unused_buffer_idx;
-					}
-					break;
-				}
-
-				/* Store the terminator. */
-				if (!assign_supress && term_size > 0) {
-					/* Space for the terminator was reserved. */
-					*cur = '\0';
-				}
-
-				/* Store the result if not already stored. */
-				if (!assign_supress) {
-					if (assign_alloc) {
-						char **pbuf = va_arg(arg, char **);
-						*pbuf = buf;
-					}
-					++converted_cnt;
-				}
-				
-				converting = false;
-				/* Format string pointer already incremented. */
-			} else if (*fmt == 'n') {
-				/* Report the number of consumed bytes so far. */
-
-				/* Sanity check. */
-				bool sane =
-				    width == -1 &&
-				    length_mod == LMOD_NONE &&
-				    assign_alloc == false &&
-				    assign_supress == false;
-
-				if (sane) {
-					int *pi = va_arg(arg, int *);
-					*pi = in->consumed;
-				} else {
-					/* Illegal format string. */
-					break;
-				}
-
-				/* This shall not be counted as conversion. */
-				converting = false;
-				++fmt;
-			} else {
-				/* Illegal format string. */
-				break;
-			}
-			
-		} else {
-
-			/* Processing outside conversion specifier. Either skip white
-			 * spaces or match characters one by one. If conversion specifier
-			 * is detected, switch to coversion mode. */
-			if (isspace(*fmt)) {
-				/* Skip white spaces in the format string. */
-				while (isspace(*fmt)) {
-					++fmt;
-				}
-				/* Skip white spaces in the input. */
-				do {
-					c = in->pop(in);
-				} while (isspace(c));
-				if (c != -1) {
-					/* Input is not at EOF, so undo the last pop operation. */
-					in->undo(in);
-				}
-			} else if (*fmt == '%' && *(fmt + 1) != '%') {
-				/* Conversion specifier detected. Switch modes. */
-				converting = true;
-				/* Reset the conversion context. */
-				assign_supress = false;
-				assign_alloc = false;
-				width = -1;
-				length_mod = LMOD_NONE;
-				int_conv_unsigned = false;
-				int_conv_base = 0;
-				++fmt;
-			} else {
-				/* One by one matching. */
-				if (*fmt == '%') {
-					/* Escape sequence detected. */
-					++fmt;
-					assert(*fmt == '%');
-				}
-				c = in->pop(in);
-				if (c == -1) {
-					/* Input failure. */
-					break;
-				} else if (c != *fmt) {
-					/* Matching failure. */
-					in->undo(in);
-					matching_failure = true;
-					break;
-				} else {
-					++fmt;
-				}
-			}
-			
-		}
-
-	}
-
-	in->release(in);
-
-	/* This somewhat complicated return value decision is required by POSIX. */
-	int rc;
-	if (matching_failure) {
-		rc = converted_cnt;
-	} else {
-		if (errno == EOK) {
-			rc = converted_cnt > 0 ? converted_cnt : EOF;
-		} else {
-			rc = EOF;
-		}
-	}
-	if (rc == EOF) {
-		/* Caller will not know how many arguments were successfully converted,
-		 * so the deallocation of buffers is our responsibility. */
-		for (int i = 0; i < next_unused_buffer_idx; ++i) {
-			free(buffers[i]);
-			buffers[i] = NULL;
-		}
-		next_unused_buffer_idx = 0;
-	}
-	return rc;
-}
-
-/**
- * Convert formatted input from the stream.
- *
- * @param stream Input stream.
- * @param format Format description.
- * @param arg Output items.
- * @return The number of converted output items or EOF on failure.
- */
-int posix_vfscanf(
-    FILE *restrict stream, const char *restrict format, va_list arg)
-{
-	_input_provider provider = {
-	    { 0 }, 0, 0, NULL, 0, NULL, _PROV_CONSTRUCTED,
-	    _capture_stream, _pop_stream, _undo_stream,
-	    _borrow_cursor_universal, _return_cursor_stream, _release_stream
-	};
-	provider.source.stream = stream;
-	return _internal_scanf(&provider, format, arg);
-}
-
-/**
- * Convert formatted input from the string.
- *
- * @param s Input string.
- * @param format Format description.
- * @param arg Output items.
- * @return The number of converted output items or EOF on failure.
- */
-int posix_vsscanf(
-    const char *restrict s, const char *restrict format, va_list arg)
-{
-	_input_provider provider = {
-	    { 0 }, 0, 0, NULL, 0, NULL, _PROV_CONSTRUCTED,
-	    _capture_string, _pop_string, _undo_string,
-	    _borrow_cursor_universal, _return_cursor_string, _release_string
-	};
-	provider.source.string = s;
-	return _internal_scanf(&provider, format, arg);
-}
-
-// FIXME: put the testcases to the app/tester after scanf is included into libc
-
-#if 0
-
-//#include <stdio.h>
-//#include <malloc.h>
-//#include <string.h>
-
-#define test_val(fmt, exp_val, act_val) \
-	if (exp_val == act_val) { \
-		printf("succ, expected "fmt", actual "fmt"\n", exp_val, act_val); \
-	} else { \
-		printf("fail, expected "fmt", actual "fmt"\n", exp_val, act_val); \
-		++fail; \
-	}
-
-#define test_str(fmt, exp_str, act_str) \
-	if (posix_strcmp(exp_str, act_str) == 0) { \
-		printf("succ, expected "fmt", actual "fmt"\n", exp_str, act_str); \
-	} else { \
-		printf("fail, expected "fmt", actual "fmt"\n", exp_str, act_str); \
-		++fail; \
-	}
-
-void __posix_scanf_test(void);
-void __posix_scanf_test(void)
-{
-	int fail = 0;
-
-	int ret;
-
-	unsigned char uhh;
-	signed char shh;
-	unsigned short uh;
-	short sh;
-	unsigned udef;
-	int sdef;
-	unsigned long ul;
-	long sl;
-	unsigned long long ull;
-	long long sll;
-	void *p;
-	
-	float f;
-	double d;
-	long double ld;
-
-	char str[20];
-	char seq[20];
-	char scanset[20];
-
-	char *pstr;
-	char *pseq;
-	char *pscanset;
-	
-	ret = posix_sscanf(
-	    "\n j tt % \t -121314 98765 aqw 0765 0x77 0xABCDEF88 -99 884",
-	    " j tt %%%3hhd%1hhu%3hd %3hu%u aqw%n %lo%llx %p %li %lld",
-	    &shh, &uhh, &sh, &uh, &udef, &sdef, &ul, &ull, &p, &sl, &sll);
-	test_val("%d", -12, shh);
-	test_val("%u", 1, uhh);
-	test_val("%d", 314, sh);
-	test_val("%u", 987, uh);
-	test_val("%u", 65, udef);
-	test_val("%d", 28, sdef);
-	test_val("%lo", (unsigned long) 0765, ul);
-	test_val("%llx", (unsigned long long) 0x77, ull);
-	test_val("%p", (void *) 0xABCDEF88, p);
-	test_val("%ld", (long) -99, sl);
-	test_val("%lld", (long long) 884, sll);
-	test_val("%d", 10, ret);
-
-	ret = posix_sscanf(
-	    "\n \t\t1.0 -0x555.AP10 1234.5678e12",
-	    "%f %lf %Lf",
-	    &f, &d, &ld);
-	test_val("%f", 1.0, f);
-	test_val("%lf", (double) -0x555.AP10, d);
-	test_val("%Lf", (long double) 1234.5678e12, ld);
-	test_val("%d", 3, ret);
-	 
-	ret = posix_sscanf(
-	    "\n\n\thello world    \n",
-	    "%5s %ms",
-	    str, &pstr);
-	test_str("%s", "hello", str);
-	test_str("%s", "world", pstr);
-	test_val("%d", 2, ret);
-	free(pstr);
-
-	ret = posix_sscanf(
-	    "\n\n\thello world    \n",
-	    " %5c %mc",
-	    seq, &pseq);
-	seq[5] = '\0';
-	pseq[1] = '\0';
-	test_str("%s", "hello", seq);
-	test_str("%s", "w", pseq);
-	test_val("%d", 2, ret);
-	free(pseq);
-
-	ret = posix_sscanf(
-	    "\n\n\th-e-l-l-o world-]    \n",
-	    " %9[-eh-o] %m[^]-]",
-	    scanset, &pscanset);
-	test_str("%s", "h-e-l-l-o", scanset);
-	test_str("%s", "world", pscanset);
-	test_val("%d", 2, ret);
-	free(pscanset);
-
-	printf("Failed: %d\n", fail);
-}
-
-#endif
-
-/** @}
- */
Index: pace/lib/posix/stdlib.c
===================================================================
--- uspace/lib/posix/stdlib.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,504 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Standard library definitions.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "internal/common.h"
-#include "stdlib.h"
-
-#include "errno.h"
-#include "fcntl.h"
-#include "limits.h"
-#include "string.h"
-#include "sys/stat.h"
-#include "unistd.h"
-
-#include "libc/sort.h"
-#include "libc/str.h"
-#include "libc/vfs/vfs.h"
-#include "libc/stats.h"
-
-/**
- * 
- * @param array
- * @param count
- * @param size
- * @param compare
- */
-int posix_atexit(void (*func)(void))
-{
-	// TODO: low priority, just a compile-time dependency of binutils
-	not_implemented();
-}
-
-/**
- * Integer absolute value.
- * 
- * @param i Input value.
- * @return Absolute value of the parameter.
- */
-int posix_abs(int i)
-{
-	return i < 0 ? -i : i;
-}
-
-/**
- * Long integer absolute value.
- * 
- * @param i Input value.
- * @return Absolute value of the parameter.
- */
-long posix_labs(long i)
-{
-	return i < 0 ? -i : i;
-}
-
-/**
- * Long long integer absolute value.
- * 
- * @param i Input value.
- * @return Absolute value of the parameter.
- */
-long long posix_llabs(long long i)
-{
-	return i < 0 ? -i : i;
-}
-
-/**
- * Compute the quotient and remainder of an integer division.
- *
- * @param numer Numerator.
- * @param denom Denominator.
- * @return Quotient and remainder packed into structure.
- */
-posix_div_t posix_div(int numer, int denom)
-{
-	return (posix_div_t) { .quot = numer / denom, .rem = numer % denom };
-}
-
-/**
- * Compute the quotient and remainder of a long integer division.
- *
- * @param numer Numerator.
- * @param denom Denominator.
- * @return Quotient and remainder packed into structure.
- */
-posix_ldiv_t posix_ldiv(long numer, long denom)
-{
-	return (posix_ldiv_t) { .quot = numer / denom, .rem = numer % denom };
-}
-
-/**
- * Compute the quotient and remainder of a long long integer division.
- *
- * @param numer Numerator.
- * @param denom Denominator.
- * @return Quotient and remainder packed into structure.
- */
-posix_lldiv_t posix_lldiv(long long numer, long long denom)
-{
-	return (posix_lldiv_t) { .quot = numer / denom, .rem = numer % denom };
-}
-
-/**
- * Private helper function that serves as a compare function for qsort().
- *
- * @param elem1 First element to compare.
- * @param elem2 Second element to compare.
- * @param compare Comparison function without userdata parameter.
- * @return Relative ordering of the elements.
- */
-static int sort_compare_wrapper(void *elem1, void *elem2, void *userdata)
-{
-	int (*compare)(const void *, const void *) = userdata;
-	int ret = compare(elem1, elem2);
-	
-	/* Native qsort internals expect this. */
-	if (ret < 0) {
-		return -1;
-	} else if (ret > 0) {
-		return 1;
-	} else {
-		return 0;
-	}
-}
-
-/**
- * Array sorting utilizing the quicksort algorithm.
- *
- * @param array Array of elements to sort.
- * @param count Number of elements in the array.
- * @param size Width of each element.
- * @param compare Decides relative ordering of two elements.
- */
-void posix_qsort(void *array, size_t count, size_t size,
-    int (*compare)(const void *, const void *))
-{
-	/* Implemented in libc with one extra argument. */
-	qsort(array, count, size, sort_compare_wrapper, compare);
-}
-
-/**
- * Binary search in a sorted array.
- *
- * @param key Object to search for.
- * @param base Pointer to the first element of the array.
- * @param nmemb Number of elements in the array.
- * @param size Size of each array element.
- * @param compar Comparison function.
- * @return Pointer to a matching element, or NULL if none can be found.
- */
-void *posix_bsearch(const void *key, const void *base,
-    size_t nmemb, size_t size, int (*compar)(const void *, const void *))
-{
-	while (nmemb > 0) {
-		const void *middle = base + (nmemb / 2) * size;
-		int cmp = compar(key, middle);
-		if (cmp == 0) {
-			return (void *) middle;
-		}
-		if (middle == base) {
-			/* There is just one member left to check and it
-			 * didn't match the key. Avoid infinite loop.
-			 */
-			break;
-		}
-		if (cmp < 0) {
-			nmemb = nmemb / 2;
-		} else if (cmp > 0) {
-			nmemb = nmemb - (nmemb / 2);
-			base = middle;
-		}
-	}
-	
-	return NULL;
-}
-
-/**
- * Retrieve a value of the given environment variable.
- *
- * Since HelenOS doesn't support env variables at the moment,
- * this function always returns NULL.
- *
- * @param name Name of the variable.
- * @return Value of the variable or NULL if such variable does not exist.
- */
-char *posix_getenv(const char *name)
-{
-	return NULL;
-}
-
-/**
- * 
- * @param name
- * @param resolved
- * @return
- */
-int posix_putenv(char *string)
-{
-	// TODO: low priority, just a compile-time dependency of binutils
-	not_implemented();
-}
-
-/**
- * Issue a command.
- *
- * @param string String to be passed to a command interpreter or NULL.
- * @return Termination status of the command if the command is not NULL,
- *     otherwise indicate whether there is a command interpreter (non-zero)
- *     or not (zero).
- */
-int posix_system(const char *string) {
-	// TODO: does nothing at the moment
-	return 0;
-}
-
-/**
- * Resolve absolute pathname.
- * 
- * @param name Pathname to be resolved.
- * @param resolved Either buffer for the resolved absolute pathname or NULL.
- * @return On success, either resolved (if it was not NULL) or pointer to the
- *     newly allocated buffer containing the absolute pathname (if resolved was
- *     NULL). Otherwise NULL.
- *
- */
-char *posix_realpath(const char *restrict name, char *restrict resolved)
-{
-	#ifndef PATH_MAX
-		assert(resolved == NULL);
-	#endif
-	
-	if (name == NULL) {
-		errno = EINVAL;
-		return NULL;
-	}
-	
-	// TODO: symlink resolution
-	
-	/* Function absolutize is implemented in libc and declared in vfs.h.
-	 * No more processing is required as HelenOS doesn't have symlinks
-	 * so far (as far as I can tell), although this function will need
-	 * to be updated when that support is implemented.
-	 */
-	char* absolute = absolutize(name, NULL);
-	
-	if (absolute == NULL) {
-		/* POSIX requires some specific errnos to be set
-		 * for some cases, but there is no way to find out from
-		 * absolutize().
-		 */
-		errno = EINVAL;
-		return NULL;
-	}
-	
-	if (resolved == NULL) {
-		return absolute;
-	} else {
-		#ifdef PATH_MAX
-			str_cpy(resolved, PATH_MAX, absolute);
-		#endif
-		free(absolute);
-		return resolved;
-	}
-}
-
-/**
- * Converts a string representation of a floating-point number to
- * its native representation. See posix_strtold().
- *
- * @param nptr String representation of a floating-point number.
- * @return Double-precision number resulting from the string conversion.
- */
-double posix_atof(const char *nptr)
-{
-	return posix_strtod(nptr, NULL);
-}
-
-/**
- * Converts a string representation of a floating-point number to
- * its native representation. See posix_strtold().
- *
- * @param nptr String representation of a floating-point number.
- * @param endptr Pointer to the final part of the string which
- *     was not used for conversion.
- * @return Single-precision number resulting from the string conversion.
- */
-float posix_strtof(const char *restrict nptr, char **restrict endptr)
-{
-	return (float) posix_strtold(nptr, endptr);
-}
-
-/**
- * Converts a string representation of a floating-point number to
- * its native representation. See posix_strtold().
- *
- * @param nptr String representation of a floating-point number.
- * @param endptr Pointer to the final part of the string which
- *     was not used for conversion.
- * @return Double-precision number resulting from the string conversion.
- */
-double posix_strtod(const char *restrict nptr, char **restrict endptr)
-{
-	return (double) posix_strtold(nptr, endptr);
-}
-
-/**
- * Allocate memory chunk.
- *
- * @param size Size of the chunk to allocate.
- * @return Either pointer to the allocated chunk or NULL if not possible.
- */
-void *posix_malloc(size_t size)
-{
-	return malloc(size);
-}
-
-/**
- * Allocate memory for an array of elements.
- *
- * @param nelem Number of elements in the array.
- * @param elsize Size of each element.
- * @return Either pointer to the allocated array or NULL if not possible.
- */
-void *posix_calloc(size_t nelem, size_t elsize)
-{
-	return calloc(nelem, elsize);
-}
-
-/**
- * Reallocate memory chunk to a new size.
- *
- * @param ptr Memory chunk to reallocate. Might be NULL.
- * @param size Size of the reallocated chunk. Might be zero.
- * @return Either NULL or the pointer to the newly reallocated chunk.
- */
-void *posix_realloc(void *ptr, size_t size)
-{
-	if (ptr != NULL && size == 0) {
-		/* Native realloc does not handle this special case. */
-		free(ptr);
-		return NULL;
-	} else {
-		return realloc(ptr, size);
-	}
-}
-
-/**
- * Free allocated memory chunk.
- *
- * @param ptr Memory chunk to be freed.
- */
-void posix_free(void *ptr)
-{
-	if (ptr) {
-		free(ptr);
-	}
-}
-
-/**
- * Creates and opens an unique temporary file from template.
- *
- * @param tmpl Template. Last six characters must be XXXXXX.
- * @return The opened file descriptor or -1 on error.
- */
-int posix_mkstemp(char *tmpl)
-{
-	int fd = -1;
-	
-	char *tptr = tmpl + posix_strlen(tmpl) - 6;
-	
-	while (fd < 0) {
-		if (*posix_mktemp(tmpl) == '\0') {
-			/* Errno set by mktemp(). */
-			return -1;
-		}
-		
-		fd = open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
-		
-		if (fd == -1) {
-			/* Restore template to it's original state. */
-			snprintf(tptr, 7, "XXXXXX");
-		}
-	}
-	
-	return fd;
-}
-
-/**
- * Creates an unique temporary file name from template.
- *
- * @param tmpl Template. Last six characters must be XXXXXX.
- * @return The value of tmpl. The template is modified in place.
- *    If no temporary file name can be created, template is
- *    reduced to an empty string.
- */
-char *posix_mktemp(char *tmpl)
-{
-	int tmpl_len = posix_strlen(tmpl);
-	if (tmpl_len < 6) {
-		errno = EINVAL;
-		*tmpl = '\0';
-		return tmpl;
-	}
-	
-	char *tptr = tmpl + tmpl_len - 6;
-	if (posix_strcmp(tptr, "XXXXXX") != 0) {
-		errno = EINVAL;
-		*tmpl = '\0';
-		return tmpl;
-	}
-	
-	static int seq = 0;
-	
-	for (; seq < 1000000; ++seq) {
-		snprintf(tptr, 7, "%06d", seq);
-		
-		int orig_errno = errno;
-		errno = 0;
-		/* Check if the file exists. */
-		if (posix_access(tmpl, F_OK) == -1) {
-			if (errno == ENOENT) {
-				errno = orig_errno;
-				break;
-			} else {
-				/* errno set by access() */
-				*tmpl = '\0';
-				return tmpl;
-			}
-		}
-	}
-	
-	if (seq == 10000000) {
-		errno = EEXIST;
-		*tmpl = '\0';
-		return tmpl;
-	}
-	
-	return tmpl;
-}
-
-/**
- * Get system load average statistics.
- *
- * @param loadavg Array where the load averages shall be placed.
- * @param nelem Maximum number of elements to be placed into the array.
- * @return Number of elements placed into the array on success, -1 otherwise.
- */
-int bsd_getloadavg(double loadavg[], int nelem)
-{
-	assert(nelem > 0);
-	
-	size_t count;
-	load_t *loads = stats_get_load(&count);
-	
-	if (loads == NULL) {
-		return -1;
-	}
-	
-	if (((size_t) nelem) < count) {
-		count = nelem;
-	}
-	
-	for (size_t i = 0; i < count; ++i) {
-		loadavg[i] = (double) loads[i];
-	}
-	
-	free(loads);
-	return count;
-}
-
-/** @}
- */
Index: pace/lib/posix/stdlib.h
===================================================================
--- uspace/lib/posix/stdlib.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,172 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Standard library definitions.
- */
-
-#ifndef POSIX_STDLIB_H_
-#define POSIX_STDLIB_H_
-
-#include "libc/stdlib.h"
-
-#ifndef NULL
-	#define NULL  ((void *) 0)
-#endif
-
-/* Process Termination */
-#undef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#undef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#define _Exit exit
-extern int posix_atexit(void (*func)(void));
-
-/* Absolute Value */
-extern int posix_abs(int i);
-extern long posix_labs(long i);
-extern long long posix_llabs(long long i);
-
-/* Integer Division */
-
-typedef struct {
-	int quot, rem;
-} posix_div_t;
-
-typedef struct {
-	long quot, rem;
-} posix_ldiv_t;
-
-typedef struct {
-	long long quot, rem;
-} posix_lldiv_t;
-
-extern posix_div_t posix_div(int numer, int denom);
-extern posix_ldiv_t posix_ldiv(long numer, long denom);
-extern posix_lldiv_t posix_lldiv(long long numer, long long denom);
-
-/* Array Functions */
-extern void posix_qsort(void *array, size_t count, size_t size,
-    int (*compare)(const void *, const void *));
-extern void *posix_bsearch(const void *key, const void *base,
-    size_t nmemb, size_t size, int (*compar)(const void *, const void *));
-
-/* Environment Access */
-extern char *posix_getenv(const char *name);
-extern int posix_putenv(char *string);
-extern int posix_system(const char *string);
-
-/* Symbolic Links */
-extern char *posix_realpath(const char *restrict name, char *restrict resolved);
-
-/* Floating Point Conversion */
-extern double posix_atof(const char *nptr);
-extern float posix_strtof(const char *restrict nptr, char **restrict endptr);
-extern double posix_strtod(const char *restrict nptr, char **restrict endptr);
-extern long double posix_strtold(const char *restrict nptr, char **restrict endptr);
-
-/* Integer Conversion */
-extern int posix_atoi(const char *nptr);
-extern long int posix_atol(const char *nptr);
-extern long long int posix_atoll(const char *nptr);
-extern long int posix_strtol(const char *restrict nptr,
-    char **restrict endptr, int base);
-extern long long int posix_strtoll(const char *restrict nptr,
-    char **restrict endptr, int base);
-extern unsigned long int posix_strtoul(const char *restrict nptr,
-    char **restrict endptr, int base);
-extern unsigned long long int posix_strtoull(
-    const char *restrict nptr, char **restrict endptr, int base);
-
-/* Memory Allocation */
-extern void *posix_malloc(size_t size);
-extern void *posix_calloc(size_t nelem, size_t elsize);
-extern void *posix_realloc(void *ptr, size_t size);
-extern void posix_free(void *ptr);
-
-/* Temporary Files */
-extern int posix_mkstemp(char *tmpl);
-
-/* Legacy Declarations */
-extern char *posix_mktemp(char *tmpl);
-extern int bsd_getloadavg(double loadavg[], int nelem);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define atexit posix_atexit
-
-	#define abs posix_abs
-	#define labs posix_labs
-	#define llabs posix_llabs
-
-	#define div_t posix_div_t
-	#define ldiv_t posix_ldiv_t
-	#define lldiv_t posix_lldiv_t
-	#define div posix_div
-	#define ldiv posix_ldiv
-	#define lldiv posix_lldiv
-
-	#define qsort posix_qsort
-	#define bsearch posix_bsearch
-
-	#define getenv posix_getenv
-	#define putenv posix_putenv
-	#define system posix_system
-
-	#define realpath posix_realpath
-	
-	#define atof posix_atof
-	#define strtof posix_strtof
-	#define strtod posix_strtod
-	#define strtold posix_strtold
-	
-	#define atoi posix_atoi
-	#define atol posix_atol
-	#define atoll posix_atoll
-	#define strtol posix_strtol
-	#define strtoll posix_strtoll
-	#define strtoul posix_strtoul
-	#define strtoull posix_strtoull
-
-	#define malloc posix_malloc
-	#define calloc posix_calloc
-	#define realloc posix_realloc
-	#define free posix_free
-
-	#define mkstemp posix_mkstemp
-
-	#define mktemp posix_mktemp
-	#define getloadavg bsd_getloadavg
-#endif
-
-#endif  // POSIX_STDLIB_H_
-
-/** @}
- */
Index: pace/lib/posix/stdlib/strtol.c
===================================================================
--- uspace/lib/posix/stdlib/strtol.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,399 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Backend for integer conversions.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "../internal/common.h"
-#include "../stdlib.h"
-
-#include "../ctype.h"
-#include "../errno.h"
-#include "../inttypes.h"
-#include "../limits.h"
-
-#define intmax_t posix_intmax_t
-#define uintmax_t posix_uintmax_t
-
-/**
- * Decides whether a digit belongs to a particular base.
- *
- * @param c Character representation of the digit.
- * @param base Base against which the digit shall be tested.
- * @return True if the digit belongs to the base, false otherwise.
- */
-static inline bool is_digit_in_base(int c, int base)
-{
-	if (base <= 10) {
-		return c >= '0' && c < '0' + base;
-	} else {
-		return isdigit(c) ||
-		    (tolower(c) >= 'a' && tolower(c) < ('a' + base - 10));
-	}
-}
-
-/**
- * Derive a digit from its character representation.
- *
- * @param c Character representation of the digit.
- * @return Digit value represented by an integer.
- */
-static inline int digit_value(int c)
-{
-	if (c <= '9') {
-		return c - '0';
-	} else {
-		return 10 + tolower(c) - 'a';
-	}
-}
-
-/**
- * Generic function for parsing an integer from it's string representation.
- * Different variants differ in lower and upper bounds.
- * The parsed string returned by this function is always positive, sign
- * information is provided via a dedicated parameter.
- *
- * @param nptr Input string.
- * @param endptr If non-NULL, *endptr is set to the position of the first
- *     unrecognized character. If no digit has been parsed, value of
- *     nptr is stored there (regardless of any skipped characters at the
- *     beginning).
- * @param base Expected base of the string representation. If 0, base is
- *    determined to be decimal, octal or hexadecimal using the same rules
- *    as C syntax. Otherwise, value must be between 2 and 36, inclusive.
- * @param min_value Lower bound for the resulting conversion.
- * @param max_value Upper bound for the resulting conversion.
- * @param out_negative Either NULL for unsigned conversion or a pointer to the
- *     bool variable into which shall be placed the negativity of the resulting
- *     converted value.
- * @return The absolute value of the parsed value, or the closest in-range value
- *     if the parsed value is out of range. If the input is invalid, zero is
- *     returned and errno is set to EINVAL.
- */
-static inline uintmax_t internal_strtol(
-    const char *restrict nptr, char **restrict endptr, int base,
-    const intmax_t min_value, const uintmax_t max_value,
-    bool *restrict out_negative)
-{
-	if (nptr == NULL) {
-		errno = EINVAL;
-		return 0;
-	}
-	
-	if (base < 0 || base == 1 || base > 36) {
-		errno = EINVAL;
-		return 0;
-	}
-	
-	/* The maximal absolute value that can be returned in this run.
-	 * Depends on sign.
-	 */
-	uintmax_t real_max_value = max_value;
-	
-	/* Current index in the input string. */
-	size_t i = 0;
-	bool negative = false;
-	
-	/* Skip whitespace. */
-	while (isspace(nptr[i])) {
-		i++;
-	}
-	
-	/* Parse sign. */
-	switch (nptr[i]) {
-	case '-':
-		negative = true;
-		
-		/* The strange computation is are there to avoid a corner case
-		 * where -min_value can't be represented in intmax_t.
-		 * (I'm not exactly sure what the semantics are in such a
-		 *  case, but this should be safe for any case.)
-		 */
-		real_max_value = (min_value == 0)
-		    ? 0
-		    :(((uintmax_t) -(min_value + 1)) + 1);
-		
-		/* fallthrough */
-	case '+':
-		i++;
-	}
-	
-	/* Figure out the base. */
-	switch (base) {
-	case 0:
-		if (nptr[i] == '0') {
-			if (tolower(nptr[i + 1]) == 'x') {
-				/* 0x... is hex. */
-				base = 16;
-				i += 2;
-			} else {
-				/* 0... is octal. */
-				base = 8;
-			}
-		} else {
-			/* Anything else is decimal by default. */
-			base = 10;
-		}
-		break;
-	case 16:
-		/* Allow hex number to be prefixed with "0x". */
-		if (nptr[i] == '0' && tolower(nptr[i + 1]) == 'x') {
-			i += 2;
-		}
-		break;
-	}
-	
-	if (!is_digit_in_base(nptr[i], base)) {
-		/* No digits to parse, invalid input. */
-		
-		errno = EINVAL;
-		if (endptr != NULL) {
-			*endptr = (char *) nptr;
-		}
-		return 0;
-	}
-	
-	/* Maximal value to which a digit can be added without a risk
-	 * of overflow.
-	 */
-	uintmax_t max_safe_value = (real_max_value - base + 1) / base;
-	
-	uintmax_t result = 0;
-	
-	if (real_max_value == 0) {
-		/* Special case when a negative number is parsed as
-		 * unsigned integer. Only -0 is accepted.
-		 */
-		
-		while (is_digit_in_base(nptr[i], base)) {
-			if (nptr[i] != '0') {
-				errno = ERANGE;
-				result = 0;
-			}
-			i++;
-		}
-	}
-	
-	while (is_digit_in_base(nptr[i], base)) {
-		int digit = digit_value(nptr[i]);
-		
-		if (result > max_safe_value) {
-			/* corner case, check for overflow */
-			
-			uintmax_t boundary = (real_max_value - digit) / base;
-			
-			if (result > boundary) {
-				/* overflow */
-				errno = ERANGE;
-				result = real_max_value;
-				break;
-			}
-		}
-		
-		result = result * base + digit;
-		i++;
-	}
-	
-	if (endptr != NULL) {
-		/* Move the pointer to the end of the number,
-		 * in case it isn't there already.
-		 */
-		while (is_digit_in_base(nptr[i], base)) {
-			i++;
-		}
-		
-		*endptr = (char *) &nptr[i];
-	}
-	if (out_negative != NULL) {
-		*out_negative = negative;
-	}
-	return result;
-}
-
-/**
- * Convert a string to an integer.
- *
- * @param nptr Input string.
- * @return Result of the conversion.
- */
-int posix_atoi(const char *nptr)
-{
-	bool neg = false;
-	uintmax_t result =
-	    internal_strtol(nptr, NULL, 10, INT_MIN, INT_MAX, &neg);
-
-	return (neg ? ((int) -result) : (int) result);
-}
-
-/**
- * Convert a string to a long integer.
- *
- * @param nptr Input string.
- * @return Result of the conversion.
- */
-long posix_atol(const char *nptr)
-{
-	bool neg = false;
-	uintmax_t result =
-	    internal_strtol(nptr, NULL, 10, LONG_MIN, LONG_MAX, &neg);
-
-	return (neg ? ((long) -result) : (long) result);
-}
-
-/**
- * Convert a string to a long long integer.
- *
- * @param nptr Input string.
- * @return Result of the conversion.
- */
-long long posix_atoll(const char *nptr)
-{
-	bool neg = false;
-	uintmax_t result =
-	    internal_strtol(nptr, NULL, 10, LLONG_MIN, LLONG_MAX, &neg);
-
-	return (neg ? ((long long) -result) : (long long) result);
-}
-
-/**
- * Convert a string to a long integer.
- *
- * @param nptr Input string.
- * @param endptr Pointer to the final part of the string which
- *     was not used for conversion.
- * @param base Expected base of the string representation.
- * @return Result of the conversion.
- */
-long posix_strtol(const char *restrict nptr, char **restrict endptr, int base)
-{
-	bool neg = false;
-	uintmax_t result =
-	    internal_strtol(nptr, endptr, base, LONG_MIN, LONG_MAX, &neg);
-
-	return (neg ? ((long) -result) : ((long) result));
-}
-
-/**
- * Convert a string to a long long integer.
- *
- * @param nptr Input string.
- * @param endptr Pointer to the final part of the string which
- *     was not used for conversion.
- * @param base Expected base of the string representation.
- * @return Result of the conversion.
- */
-long long posix_strtoll(
-    const char *restrict nptr, char **restrict endptr, int base)
-{
-	bool neg = false;
-	uintmax_t result =
-	    internal_strtol(nptr, endptr, base, LLONG_MIN, LLONG_MAX, &neg);
-
-	return (neg ? ((long long) -result) : (long long) result);
-}
-
-/**
- * Convert a string to a largest signed integer type.
- *
- * @param nptr Input string.
- * @param endptr Pointer to the final part of the string which
- *     was not used for conversion.
- * @param base Expected base of the string representation.
- * @return Result of the conversion.
- */
-intmax_t posix_strtoimax(
-    const char *restrict nptr, char **restrict endptr, int base)
-{
-	bool neg = false;
-	uintmax_t result =
-	    internal_strtol(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX, &neg);
-
-	return (neg ? ((intmax_t) -result) : (intmax_t) result);
-}
-
-/**
- * Convert a string to an unsigned long integer.
- *
- * @param nptr Input string.
- * @param endptr Pointer to the final part of the string which
- *     was not used for conversion.
- * @param base Expected base of the string representation.
- * @return Result of the conversion.
- */
-unsigned long posix_strtoul(
-    const char *restrict nptr, char **restrict endptr, int base)
-{
-	uintmax_t result =
-	    internal_strtol(nptr, endptr, base, 0, ULONG_MAX, NULL);
-
-	return (unsigned long) result;
-}
-
-/**
- * Convert a string to an unsigned long long integer.
- *
- * @param nptr Input string.
- * @param endptr Pointer to the final part of the string which
- *     was not used for conversion.
- * @param base Expected base of the string representation.
- * @return Result of the conversion.
- */
-unsigned long long posix_strtoull(
-    const char *restrict nptr, char **restrict endptr, int base)
-{
-	uintmax_t result =
-	    internal_strtol(nptr, endptr, base, 0, ULLONG_MAX, NULL);
-
-	return (unsigned long long) result;
-}
-
-/**
- * Convert a string to a largest unsigned integer type.
- *
- * @param nptr Input string.
- * @param endptr Pointer to the final part of the string which
- *     was not used for conversion.
- * @param base Expected base of the string representation.
- * @return Result of the conversion.
- */
-uintmax_t posix_strtoumax(
-    const char *restrict nptr, char **restrict endptr, int base)
-{
-	uintmax_t result =
-	    internal_strtol(nptr, endptr, base, 0, UINTMAX_MAX, NULL);
-
-	return result;
-}
-
-/** @}
- */
Index: pace/lib/posix/stdlib/strtold.c
===================================================================
--- uspace/lib/posix/stdlib/strtold.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,491 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Backend for floating point conversions.
- */
-
-#define LIBPOSIX_INTERNAL
-
-/* Must be first. */
-#include "../stdbool.h"
-
-#include "../internal/common.h"
-#include "../stdlib.h"
-
-#include "../assert.h"
-#include "../ctype.h"
-#include "../stdint.h"
-#include "../strings.h"
-#include "../errno.h"
-#include "../limits.h"
-
-#include "../float.h"
-
-#ifndef HUGE_VALL
-	#define HUGE_VALL (+1.0l / +0.0l)
-#endif
-
-#ifndef abs
-	#define abs(x) (((x) < 0) ? -(x) : (x))
-#endif
-
-/* If the constants are not defined, use double precision as default. */
-#ifndef LDBL_MANT_DIG
-	#define LDBL_MANT_DIG 53
-#endif
-#ifndef LDBL_MAX_EXP
-	#define LDBL_MAX_EXP 1024
-#endif
-#ifndef LDBL_MIN_EXP
-	#define LDBL_MIN_EXP (-1021)
-#endif
-#ifndef LDBL_DIG
-	#define LDBL_DIG 15
-#endif
-#ifndef LDBL_MIN
-	#define LDBL_MIN 2.2250738585072014E-308
-#endif
-
-/* power functions ************************************************************/
-
-#if LDBL_MAX_EXP >= 16384
-const int MAX_POW5 = 12;
-#else
-const int MAX_POW5 = 8;
-#endif
-
-/* The value at index i is approximately 5**(2**i). */
-long double pow5[] = {
-	0x5p0l,
-	0x19p0l,
-	0x271p0l,
-	0x5F5E1p0l,
-	0x2386F26FC1p0l,
-	0x4EE2D6D415B85ACEF81p0l,
-	0x184F03E93FF9F4DAA797ED6E38ED6p36l,
-	0x127748F9301D319BF8CDE66D86D62p185l,
-	0x154FDD7F73BF3BD1BBB77203731FDp482l,
-#if LDBL_MAX_EXP >= 16384
-	0x1C633415D4C1D238D98CAB8A978A0p1076l,
-	0x192ECEB0D02EA182ECA1A7A51E316p2265l,
-	0x13D1676BB8A7ABBC94E9A519C6535p4643l,
-	0x188C0A40514412F3592982A7F0094p9398l,
-#endif
-};
-
-#if LDBL_MAX_EXP >= 16384
-const int MAX_POW2 = 15;
-#else
-const int MAX_POW2 = 9;
-#endif
-
-/* Powers of two. */
-long double pow2[] = {
-	0x1P1l,
-	0x1P2l,
-	0x1P4l,
-	0x1P8l,
-	0x1P16l,
-	0x1P32l,
-	0x1P64l,
-	0x1P128l,
-	0x1P256l,
-	0x1P512l,
-#if LDBL_MAX_EXP >= 16384
-	0x1P1024l,
-	0x1P2048l,
-	0x1P4096l,
-	0x1P8192l,
-#endif
-};
-
-/**
- * Multiplies a number by a power of five.
- * The result may be inexact and may not be the best possible approximation.
- *
- * @param mant Number to be multiplied.
- * @param exp Base 5 exponent.
- * @return mant multiplied by 5**exp
- */
-static long double mul_pow5(long double mant, int exp)
-{
-	if (mant == 0.0l || mant == HUGE_VALL) {
-		return mant;
-	}
-	
-	if (abs(exp) >> (MAX_POW5 + 1) != 0) {
-		/* Too large exponent. */
-		errno = ERANGE;
-		return exp < 0 ? LDBL_MIN : HUGE_VALL;
-	}
-	
-	if (exp < 0) {
-		exp = abs(exp);
-		for (int bit = 0; bit <= MAX_POW5; ++bit) {
-			/* Multiply by powers of five bit-by-bit. */
-			if (((exp >> bit) & 1) != 0) {
-				mant /= pow5[bit];
-				if (mant == 0.0l) {
-					/* Underflow. */
-					mant = LDBL_MIN;
-					errno = ERANGE;
-					break;
-				}
-			}
-		}
-	} else {
-		for (int bit = 0; bit <= MAX_POW5; ++bit) {
-			/* Multiply by powers of five bit-by-bit. */
-			if (((exp >> bit) & 1) != 0) {
-				mant *= pow5[bit];
-				if (mant == HUGE_VALL) {
-					/* Overflow. */
-					errno = ERANGE;
-					break;
-				}
-			}
-		}
-	}
-	
-	return mant;
-}
-
-/**
- * Multiplies a number by a power of two. This is always exact.
- *
- * @param mant Number to be multiplied.
- * @param exp Base 2 exponent.
- * @return mant multiplied by 2**exp.
- */
-static long double mul_pow2(long double mant, int exp)
-{
-	if (mant == 0.0l || mant == HUGE_VALL) {
-		return mant;
-	}
-	
-	if (exp > LDBL_MAX_EXP || exp < LDBL_MIN_EXP) {
-		errno = ERANGE;
-		return exp < 0 ? LDBL_MIN : HUGE_VALL;
-	}
-	
-	if (exp < 0) {
-		exp = abs(exp);
-		for (int i = 0; i <= MAX_POW2; ++i) {
-			if (((exp >> i) & 1) != 0) {
-				mant /= pow2[i];
-				if (mant == 0.0l) {
-					mant = LDBL_MIN;
-					errno = ERANGE;
-					break;
-				}
-			}
-		}
-	} else {
-		for (int i = 0; i <= MAX_POW2; ++i) {
-			if (((exp >> i) & 1) != 0) {
-				mant *= pow2[i];
-				if (mant == HUGE_VALL) {
-					errno = ERANGE;
-					break;
-				}
-			}
-		}
-	}
-	
-	return mant;
-}
-
-/* end power functions ********************************************************/
-
-
-
-/**
- * Convert decimal string representation of the floating point number.
- * Function expects the string pointer to be already pointed at the first
- * digit (i.e. leading optional sign was already consumed by the caller).
- * 
- * @param sptr Pointer to the storage of the string pointer. Upon successful
- *     conversion, the string pointer is updated to point to the first
- *     unrecognized character.
- * @return An approximate representation of the input floating-point number.
- */
-static long double parse_decimal(const char **sptr)
-{
-	assert(sptr != NULL);
-	assert (*sptr != NULL);
-	
-	const int DEC_BASE = 10;
-	const char DECIMAL_POINT = '.';
-	const char EXPONENT_MARK = 'e';
-	
-	const char *str = *sptr;
-	long double significand = 0;
-	long exponent = 0;
-	
-	/* number of digits parsed so far */
-	int parsed_digits = 0;
-	bool after_decimal = false;
-	
-	while (isdigit(*str) || (!after_decimal && *str == DECIMAL_POINT)) {
-		if (*str == DECIMAL_POINT) {
-			after_decimal = true;
-			str++;
-			continue;
-		}
-		
-		if (parsed_digits == 0 && *str == '0') {
-			/* Nothing, just skip leading zeros. */
-		} else if (parsed_digits < LDBL_DIG) {
-			significand = significand * DEC_BASE + (*str - '0');
-			parsed_digits++;
-		} else {
-			exponent++;
-		}
-		
-		if (after_decimal) {
-			/* Decrement exponent if we are parsing the fractional part. */
-			exponent--;
-		}
-		
-		str++;
-	}
-	
-	/* exponent */
-	if (tolower(*str) == EXPONENT_MARK) {
-		str++;
-		
-		/* Returns MIN/MAX value on error, which is ok. */
-		long exp = strtol(str, (char **) &str, DEC_BASE);
-		
-		if (exponent > 0 && exp > LONG_MAX - exponent) {
-			exponent = LONG_MAX;
-		} else if (exponent < 0 && exp < LONG_MIN - exponent) {
-			exponent = LONG_MIN;
-		} else {
-			exponent += exp;
-		}
-	}
-	
-	*sptr = str;
-	
-	/* Return multiplied by a power of ten. */
-	return mul_pow2(mul_pow5(significand, exponent), exponent);
-}
-
-/**
- * Derive a hexadecimal digit from its character representation.
- * 
- * @param ch Character representation of the hexadecimal digit.
- * @return Digit value represented by an integer.
- */
-static inline int hex_value(char ch)
-{
-	if (ch <= '9') {
-		return ch - '0';
-	} else {
-		return 10 + tolower(ch) - 'a';
-	}
-}
-
-/**
- * Convert hexadecimal string representation of the floating point number.
- * Function expects the string pointer to be already pointed at the first
- * digit (i.e. leading optional sign and 0x prefix were already consumed
- * by the caller).
- *
- * @param sptr Pointer to the storage of the string pointer. Upon successful
- *     conversion, the string pointer is updated to point to the first
- *     unrecognized character.
- * @return Representation of the input floating-point number.
- */
-static long double parse_hexadecimal(const char **sptr)
-{
-	assert(sptr != NULL && *sptr != NULL);
-	
-	const int DEC_BASE = 10;
-	const int HEX_BASE = 16;
-	const char DECIMAL_POINT = '.';
-	const char EXPONENT_MARK = 'p';
-	
-	const char *str = *sptr;
-	long double significand = 0;
-	long exponent = 0;
-	
-	/* number of bits parsed so far */
-	int parsed_bits = 0;
-	bool after_decimal = false;
-	
-	while (posix_isxdigit(*str) || (!after_decimal && *str == DECIMAL_POINT)) {
-		if (*str == DECIMAL_POINT) {
-			after_decimal = true;
-			str++;
-			continue;
-		}
-		
-		if (parsed_bits == 0 && *str == '0') {
-			/* Nothing, just skip leading zeros. */
-		} else if (parsed_bits <= LDBL_MANT_DIG) {
-			significand = significand * HEX_BASE + hex_value(*str);
-			parsed_bits += 4;
-		} else {
-			exponent += 4;
-		}
-		
-		if (after_decimal) {
-			exponent -= 4;
-		}
-		
-		str++;
-	}
-	
-	/* exponent */
-	if (tolower(*str) == EXPONENT_MARK) {
-		str++;
-		
-		/* Returns MIN/MAX value on error, which is ok. */
-		long exp = strtol(str, (char **) &str, DEC_BASE);
-		
-		if (exponent > 0 && exp > LONG_MAX - exponent) {
-			exponent = LONG_MAX;
-		} else if (exponent < 0 && exp < LONG_MIN - exponent) {
-			exponent = LONG_MIN;
-		} else {
-			exponent += exp;
-		}
-	}
-	
-	*sptr = str;
-	
-	/* Return multiplied by a power of two. */
-	return mul_pow2(significand, exponent);
-}
-
-/**
- * Converts a string representation of a floating-point number to
- * its native representation. Largely POSIX compliant, except for
- * locale differences (always uses '.' at the moment) and rounding.
- * Decimal strings are NOT guaranteed to be correctly rounded. This function
- * should return a good enough approximation for most purposes but if you
- * depend on a precise conversion, use hexadecimal representation.
- * Hexadecimal strings are currently always rounded towards zero, regardless
- * of the current rounding mode.
- *
- * @param nptr Input string.
- * @param endptr If non-NULL, *endptr is set to the position of the first
- *     unrecognized character.
- * @return An approximate representation of the input floating-point number.
- */
-long double posix_strtold(const char *restrict nptr, char **restrict endptr)
-{
-	assert(nptr != NULL);
-	
-	const int RADIX = '.';
-	
-	/* minus sign */
-	bool negative = false;
-	/* current position in the string */
-	int i = 0;
-	
-	/* skip whitespace */
-	while (isspace(nptr[i])) {
-		i++;
-	}
-	
-	/* parse sign */
-	switch (nptr[i]) {
-	case '-':
-		negative = true;
-		/* fallthrough */
-	case '+':
-		i++;
-	}
-	
-	/* check for NaN */
-	if (posix_strncasecmp(&nptr[i], "nan", 3) == 0) {
-		// FIXME: return NaN
-		// TODO: handle the parenthesised case
-		
-		if (endptr != NULL) {
-			*endptr = (char *) nptr;
-		}
-		errno = EINVAL;
-		return 0;
-	}
-	
-	/* check for Infinity */
-	if (posix_strncasecmp(&nptr[i], "inf", 3) == 0) {
-		i += 3;
-		if (posix_strncasecmp(&nptr[i], "inity", 5) == 0) {
-			i += 5;
-		}
-		
-		if (endptr != NULL) {
-			*endptr = (char *) &nptr[i];
-		}
-		return negative ? -HUGE_VALL : +HUGE_VALL;
-	}
-
-	/* check for a hex number */
-	if (nptr[i] == '0' && tolower(nptr[i + 1]) == 'x' &&
-	    (posix_isxdigit(nptr[i + 2]) ||
-	    (nptr[i + 2] == RADIX && posix_isxdigit(nptr[i + 3])))) {
-		i += 2;
-		
-		const char *ptr = &nptr[i];
-		/* this call sets errno if appropriate. */
-		long double result = parse_hexadecimal(&ptr);
-		if (endptr != NULL) {
-			*endptr = (char *) ptr;
-		}
-		return negative ? -result : result;
-	}
-	
-	/* check for a decimal number */
-	if (isdigit(nptr[i]) || (nptr[i] == RADIX && isdigit(nptr[i + 1]))) {
-		const char *ptr = &nptr[i];
-		/* this call sets errno if appropriate. */
-		long double result = parse_decimal(&ptr);
-		if (endptr != NULL) {
-			*endptr = (char *) ptr;
-		}
-		return negative ? -result : result;
-	}
-	
-	/* nothing to parse */
-	if (endptr != NULL) {
-		*endptr = (char *) nptr;
-	}
-	errno = EINVAL;
-	return 0;
-}
-
-/** @}
- */
Index: pace/lib/posix/string.c
===================================================================
--- uspace/lib/posix/string.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,754 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file String manipulation.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "internal/common.h"
-#include "string.h"
-
-#include "assert.h"
-#include "errno.h"
-#include "limits.h"
-#include "stdlib.h"
-#include "signal.h"
-
-#include "libc/str_error.h"
-
-/**
- * The same as strpbrk, except it returns pointer to the nul terminator
- * if no occurence is found.
- *
- * @param s1 String in which to look for the bytes.
- * @param s2 String of bytes to look for.
- * @return Pointer to the found byte on success, pointer to the
- *     string terminator otherwise.
- */
-static char *strpbrk_null(const char *s1, const char *s2)
-{
-	while (!posix_strchr(s2, *s1)) {
-		++s1;
-	}
-	
-	return (char *) s1;
-}
-
-/**
- * Copy a string.
- *
- * @param dest Destination pre-allocated buffer.
- * @param src Source string to be copied.
- * @return Pointer to the destination buffer.
- */
-char *posix_strcpy(char *restrict dest, const char *restrict src)
-{
-	posix_stpcpy(dest, src);
-	return dest;
-}
-
-/**
- * Copy fixed length string.
- *
- * @param dest Destination pre-allocated buffer.
- * @param src Source string to be copied.
- * @param n Number of bytes to be stored into destination buffer.
- * @return Pointer to the destination buffer.
- */
-char *posix_strncpy(char *restrict dest, const char *restrict src, size_t n)
-{
-	posix_stpncpy(dest, src, n);
-	return dest;
-}
-
-/**
- * Copy a string.
- *
- * @param dest Destination pre-allocated buffer.
- * @param src Source string to be copied.
- * @return Pointer to the nul character in the destination string.
- */
-char *posix_stpcpy(char *restrict dest, const char *restrict src)
-{
-	assert(dest != NULL);
-	assert(src != NULL);
-
-	for (size_t i = 0; ; ++i) {
-		dest[i] = src[i];
-		
-		if (src[i] == '\0') {
-			/* pointer to the terminating nul character */
-			return &dest[i];
-		}
-	}
-	
-	/* unreachable */
-	return NULL;
-}
-
-/**
- * Copy fixed length string.
- *
- * @param dest Destination pre-allocated buffer.
- * @param src Source string to be copied.
- * @param n Number of bytes to be stored into destination buffer.
- * @return Pointer to the first written nul character or &dest[n].
- */
-char *posix_stpncpy(char *restrict dest, const char *restrict src, size_t n)
-{
-	assert(dest != NULL);
-	assert(src != NULL);
-
-	for (size_t i = 0; i < n; ++i) {
-		dest[i] = src[i];
-	
-		/* the standard requires that nul characters
-		 * are appended to the length of n, in case src is shorter
-		 */
-		if (src[i] == '\0') {
-			char *result = &dest[i];
-			for (++i; i < n; ++i) {
-				dest[i] = '\0';
-			}
-			return result;
-		}
-	}
-	
-	return &dest[n];
-}
-
-/**
- * Concatenate two strings.
- *
- * @param dest String to which src shall be appended.
- * @param src String to be appended after dest.
- * @return Pointer to destination buffer.
- */
-char *posix_strcat(char *restrict dest, const char *restrict src)
-{
-	assert(dest != NULL);
-	assert(src != NULL);
-
-	posix_strcpy(posix_strchr(dest, '\0'), src);
-	return dest;
-}
-
-/**
- * Concatenate a string with part of another.
- *
- * @param dest String to which part of src shall be appended.
- * @param src String whose part shall be appended after dest.
- * @param n Number of bytes to append after dest.
- * @return Pointer to destination buffer.
- */
-char *posix_strncat(char *restrict dest, const char *restrict src, size_t n)
-{
-	assert(dest != NULL);
-	assert(src != NULL);
-
-	char *zeroptr = posix_strncpy(posix_strchr(dest, '\0'), src, n);
-	/* strncpy doesn't append the nul terminator, so we do it here */
-	zeroptr[n] = '\0';
-	return dest;
-}
-
-/**
- * Copy limited number of bytes in memory.
- *
- * @param dest Destination buffer.
- * @param src Source buffer.
- * @param c Character after which the copying shall stop.
- * @param n Number of bytes that shall be copied if not stopped earlier by c.
- * @return Pointer to the first byte after c in dest if found, NULL otherwise.
- */
-void *posix_memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
-{
-	assert(dest != NULL);
-	assert(src != NULL);
-	
-	unsigned char* bdest = dest;
-	const unsigned char* bsrc = src;
-	
-	for (size_t i = 0; i < n; ++i) {
-		bdest[i] = bsrc[i];
-	
-		if (bsrc[i] == (unsigned char) c) {
-			/* pointer to the next byte */
-			return &bdest[i + 1];
-		}
-	}
-	
-	return NULL;
-}
-
-/**
- * Duplicate a string.
- *
- * @param s String to be duplicated.
- * @return Newly allocated copy of the string.
- */
-char *posix_strdup(const char *s)
-{
-	return posix_strndup(s, SIZE_MAX);
-}
-
-/**
- * Duplicate a specific number of bytes from a string.
- *
- * @param s String to be duplicated.
- * @param n Maximum length of the resulting string..
- * @return Newly allocated string copy of length at most n.
- */
-char *posix_strndup(const char *s, size_t n)
-{
-	assert(s != NULL);
-
-	size_t len = posix_strnlen(s, n);
-	char *dup = malloc(len + 1);
-	if (dup == NULL) {
-		return NULL;
-	}
-
-	memcpy(dup, s, len);
-	dup[len] = '\0';
-
-	return dup;
-}
-
-/**
- * Compare bytes in memory.
- *
- * @param mem1 First area of memory to be compared.
- * @param mem2 Second area of memory to be compared.
- * @param n Maximum number of bytes to be compared.
- * @return Difference of the first pair of inequal bytes,
- *     or 0 if areas have the same content.
- */
-int posix_memcmp(const void *mem1, const void *mem2, size_t n)
-{
-	assert(mem1 != NULL);
-	assert(mem2 != NULL);
-
-	const unsigned char *s1 = mem1;
-	const unsigned char *s2 = mem2;
-	
-	for (size_t i = 0; i < n; ++i) {
-		if (s1[i] != s2[i]) {
-			return s1[i] - s2[i];
-		}
-	}
-	
-	return 0;
-}
-
-/**
- * Compare two strings.
- *
- * @param s1 First string to be compared.
- * @param s2 Second string to be compared.
- * @return Difference of the first pair of inequal characters,
- *     or 0 if strings have the same content.
- */
-int posix_strcmp(const char *s1, const char *s2)
-{
-	assert(s1 != NULL);
-	assert(s2 != NULL);
-
-	return posix_strncmp(s1, s2, STR_NO_LIMIT);
-}
-
-/**
- * Compare part of two strings.
- *
- * @param s1 First string to be compared.
- * @param s2 Second string to be compared.
- * @param n Maximum number of characters to be compared.
- * @return Difference of the first pair of inequal characters,
- *     or 0 if strings have the same content.
- */
-int posix_strncmp(const char *s1, const char *s2, size_t n)
-{
-	assert(s1 != NULL);
-	assert(s2 != NULL);
-
-	for (size_t i = 0; i < n; ++i) {
-		if (s1[i] != s2[i]) {
-			return s1[i] - s2[i];
-		}
-		if (s1[i] == '\0') {
-			break;
-		}
-	}
-
-	return 0;
-}
-
-/**
- * Find byte in memory.
- *
- * @param mem Memory area in which to look for the byte.
- * @param c Byte to look for.
- * @param n Maximum number of bytes to be inspected.
- * @return Pointer to the specified byte on success,
- *     NULL pointer otherwise.
- */
-void *posix_memchr(const void *mem, int c, size_t n)
-{
-	assert(mem != NULL);
-	
-	const unsigned char *s = mem;
-	
-	for (size_t i = 0; i < n; ++i) {
-		if (s[i] == (unsigned char) c) {
-			return (void *) &s[i];
-		}
-	}
-	return NULL;
-}
-
-/**
- * Scan string for a first occurence of a character.
- *
- * @param s String in which to look for the character.
- * @param c Character to look for.
- * @return Pointer to the specified character on success,
- *     NULL pointer otherwise.
- */
-char *posix_strchr(const char *s, int c)
-{
-	assert(s != NULL);
-	
-	char *res = gnu_strchrnul(s, c);
-	return (*res == c) ? res : NULL;
-}
-
-/**
- * Scan string for a last occurence of a character.
- *
- * @param s String in which to look for the character.
- * @param c Character to look for.
- * @return Pointer to the specified character on success,
- *     NULL pointer otherwise.
- */
-char *posix_strrchr(const char *s, int c)
-{
-	assert(s != NULL);
-	
-	const char *ptr = posix_strchr(s, '\0');
-	
-	/* the same as in strchr, except it loops in reverse direction */
-	while (*ptr != (char) c) {
-		if (ptr == s) {
-			return NULL;
-		}
-
-		ptr--;
-	}
-
-	return (char *) ptr;
-}
-
-/**
- * Scan string for a first occurence of a character.
- *
- * @param s String in which to look for the character.
- * @param c Character to look for.
- * @return Pointer to the specified character on success, pointer to the
- *     string terminator otherwise.
- */
-char *gnu_strchrnul(const char *s, int c)
-{
-	assert(s != NULL);
-	
-	while (*s != c && *s != '\0') {
-		s++;
-	}
-	
-	return (char *) s;
-}
-
-/**
- * Scan a string for a first occurence of one of provided bytes.
- *
- * @param s1 String in which to look for the bytes.
- * @param s2 String of bytes to look for.
- * @return Pointer to the found byte on success,
- *     NULL pointer otherwise.
- */
-char *posix_strpbrk(const char *s1, const char *s2)
-{
-	assert(s1 != NULL);
-	assert(s2 != NULL);
-
-	char *ptr = strpbrk_null(s1, s2);
-	return (*ptr == '\0') ? NULL : ptr;
-}
-
-/**
- * Get the length of a complementary substring.
- *
- * @param s1 String that shall be searched for complementary prefix.
- * @param s2 String of bytes that shall not occur in the prefix.
- * @return Length of the prefix.
- */
-size_t posix_strcspn(const char *s1, const char *s2)
-{
-	assert(s1 != NULL);
-	assert(s2 != NULL);
-
-	char *ptr = strpbrk_null(s1, s2);
-	return (size_t) (ptr - s1);
-}
-
-/**
- * Get length of a substring.
- *
- * @param s1 String that shall be searched for prefix.
- * @param s2 String of bytes that the prefix must consist of.
- * @return Length of the prefix.
- */
-size_t posix_strspn(const char *s1, const char *s2)
-{
-	assert(s1 != NULL);
-	assert(s2 != NULL);
-
-	const char *ptr;
-	for (ptr = s1; *ptr != '\0'; ++ptr) {
-		if (!posix_strchr(s2, *ptr)) {
-			break;
-		}
-	}
-	return ptr - s1;
-}
-
-/**
- * Find a substring. Uses Knuth-Morris-Pratt algorithm.
- *
- * @param s1 String in which to look for a substring.
- * @param s2 Substring to look for.
- * @return Pointer to the first character of the substring in s1, or NULL if
- *     not found.
- */
-char *posix_strstr(const char *haystack, const char *needle)
-{
-	assert(haystack != NULL);
-	assert(needle != NULL);
-	
-	/* Special case - needle is an empty string. */
-	if (needle[0] == '\0') {
-		return (char *) haystack;
-	}
-	
-	/* Preprocess needle. */
-	size_t nlen = posix_strlen(needle);
-	size_t prefix_table[nlen + 1];
-	
-	{
-		size_t i = 0;
-		ssize_t j = -1;
-		
-		prefix_table[i] = j;
-		
-		while (i < nlen) {
-			while (j >= 0 && needle[i] != needle[j]) {
-				j = prefix_table[j];
-			}
-			i++; j++;
-			prefix_table[i] = j;
-		}
-	}
-	
-	/* Search needle using the precomputed table. */
-	size_t npos = 0;
-	
-	for (size_t hpos = 0; haystack[hpos] != '\0'; ++hpos) {
-		while (npos != 0 && haystack[hpos] != needle[npos]) {
-			npos = prefix_table[npos];
-		}
-		
-		if (haystack[hpos] == needle[npos]) {
-			npos++;
-			
-			if (npos == nlen) {
-				return (char *) (haystack + hpos - nlen + 1);
-			}
-		}
-	}
-	
-	return NULL;
-}
-
-/**
- * String comparison using collating information.
- *
- * Currently ignores locale and just calls strcmp.
- *
- * @param s1 First string to be compared.
- * @param s2 Second string to be compared.
- * @return Difference of the first pair of inequal characters,
- *     or 0 if strings have the same content.
- */
-int posix_strcoll(const char *s1, const char *s2)
-{
-	assert(s1 != NULL);
-	assert(s2 != NULL);
-
-	return posix_strcmp(s1, s2);
-}
-
-/**
- * Transform a string in such a way that the resulting string yields the same
- * results when passed to the strcmp as if the original string is passed to
- * the strcoll.
- *
- * Since strcoll is equal to strcmp here, this just makes a copy.
- *
- * @param s1 Transformed string.
- * @param s2 Original string.
- * @param n Maximum length of the transformed string.
- * @return Length of the transformed string.
- */
-size_t posix_strxfrm(char *restrict s1, const char *restrict s2, size_t n)
-{
-	assert(s1 != NULL || n == 0);
-	assert(s2 != NULL);
-
-	size_t len = posix_strlen(s2);
-
-	if (n > len) {
-		posix_strcpy(s1, s2);
-	}
-
-	return len;
-}
-
-/**
- * Get error message string.
- *
- * @param errnum Error code for which to obtain human readable string.
- * @return Error message.
- */
-char *posix_strerror(int errnum)
-{
-	static const char *error_msgs[] = {
-		[E2BIG] = "[E2BIG] Argument list too long",
-		[EACCES] = "[EACCES] Permission denied",
-		[EADDRINUSE] = "[EADDRINUSE] Address in use",
-		[EADDRNOTAVAIL] = "[EADDRNOTAVAIL] Address not available",
-		[EAFNOSUPPORT] = "[EAFNOSUPPORT] Address family not supported",
-		[EAGAIN] = "[EAGAIN] Resource unavailable, try again",
-		[EALREADY] = "[EALREADY] Connection already in progress",
-		[EBADF] = "[EBADF] Bad file descriptor",
-		[EBADMSG] = "[EBADMSG] Bad message",
-		[EBUSY] = "[EBUSY] Device or resource busy",
-		[ECANCELED] = "[ECANCELED] Operation canceled",
-		[ECHILD] = "[ECHILD] No child processes",
-		[ECONNABORTED] = "[ECONNABORTED] Connection aborted",
-		[ECONNREFUSED] = "[ECONNREFUSED] Connection refused",
-		[ECONNRESET] = "[ECONNRESET] Connection reset",
-		[EDEADLK] = "[EDEADLK] Resource deadlock would occur",
-		[EDESTADDRREQ] = "[EDESTADDRREQ] Destination address required",
-		[EDOM] = "[EDOM] Mathematics argument out of domain of function",
-		[EDQUOT] = "[EDQUOT] Reserved",
-		[EEXIST] = "[EEXIST] File exists",
-		[EFAULT] = "[EFAULT] Bad address",
-		[EFBIG] = "[EFBIG] File too large",
-		[EHOSTUNREACH] = "[EHOSTUNREACH] Host is unreachable",
-		[EIDRM] = "[EIDRM] Identifier removed",
-		[EILSEQ] = "[EILSEQ] Illegal byte sequence",
-		[EINPROGRESS] = "[EINPROGRESS] Operation in progress",
-		[EINTR] = "[EINTR] Interrupted function",
-		[EINVAL] = "[EINVAL] Invalid argument",
-		[EIO] = "[EIO] I/O error",
-		[EISCONN] = "[EISCONN] Socket is connected",
-		[EISDIR] = "[EISDIR] Is a directory",
-		[ELOOP] = "[ELOOP] Too many levels of symbolic links",
-		[EMFILE] = "[EMFILE] File descriptor value too large",
-		[EMLINK] = "[EMLINK] Too many links",
-		[EMSGSIZE] = "[EMSGSIZE] Message too large",
-		[EMULTIHOP] = "[EMULTIHOP] Reserved",
-		[ENAMETOOLONG] = "[ENAMETOOLONG] Filename too long",
-		[ENETDOWN] = "[ENETDOWN] Network is down",
-		[ENETRESET] = "[ENETRESET] Connection aborted by network",
-		[ENETUNREACH] = "[ENETUNREACH] Network unreachable",
-		[ENFILE] = "[ENFILE] Too many files open in system",
-		[ENOBUFS] = "[ENOBUFS] No buffer space available",
-		[ENODATA] = "[ENODATA] No message is available on the STREAM head read queue",
-		[ENODEV] = "[ENODEV] No such device",
-		[ENOENT] = "[ENOENT] No such file or directory",
-		[ENOEXEC] = "[ENOEXEC] Executable file format error",
-		[ENOLCK] = "[ENOLCK] No locks available",
-		[ENOLINK] = "[ENOLINK] Reserved",
-		[ENOMEM] = "[ENOMEM] Not enough space",
-		[ENOMSG] = "[ENOMSG] No message of the desired type",
-		[ENOPROTOOPT] = "[ENOPROTOOPT] Protocol not available",
-		[ENOSPC] = "[ENOSPC] No space left on device",
-		[ENOSR] = "[ENOSR] No STREAM resources.",
-		[ENOSTR] = "[ENOSTR] Not a STREAM",
-		[ENOSYS] = "[ENOSYS] Function not supported",
-		[ENOTCONN] = "[ENOTCONN] The socket is not connected",
-		[ENOTDIR] = "[ENOTDIR] Not a directory",
-		[ENOTEMPTY] = "[ENOTEMPTY] Directory not empty",
-		[ENOTRECOVERABLE] = "[ENOTRECOVERABLE] State not recoverable",
-		[ENOTSOCK] = "[ENOTSOCK] Not a socket",
-		[ENOTSUP] = "[ENOTSUP] Not supported",
-		[ENOTTY] = "[ENOTTY] Inappropriate I/O control operation",
-		[ENXIO] = "[ENXIO] No such device or address",
-		[EOPNOTSUPP] = "[EOPNOTSUPP] Operation not supported",
-		[EOVERFLOW] = "[EOVERFLOW] Value too large to be stored in data type",
-		[EOWNERDEAD] = "[EOWNERDEAD] Previous owned died",
-		[EPERM] = "[EPERM] Operation not permitted",
-		[EPIPE] = "[EPIPE] Broken pipe",
-		[EPROTO] = "[EPROTO] Protocol error",
-		[EPROTONOSUPPORT] = "[EPROTONOSUPPORT] Protocol not supported",
-		[EPROTOTYPE] = "[EPROTOTYPE] Protocol wrong type for socket",
-		[ERANGE] = "[ERANGE] Result too large",
-		[EROFS] = "[EROFS] Read-only file system",
-		[ESPIPE] = "[ESPIPE] Invalid seek",
-		[ESRCH] = "[ESRCH] No such process",
-		[ESTALE] = "[ESTALE] Reserved",
-		[ETIME] = "[ETIME] Stream ioctl() timeout",
-		[ETIMEDOUT] = "[ETIMEDOUT] Connection timed out",
-		[ETXTBSY] = "[ETXTBSY] Text file busy",
-		[EWOULDBLOCK] = "[EWOULDBLOCK] Operation would block",
-		[EXDEV] = "[EXDEV] Cross-device link",
-	};
-
-	return (char *) error_msgs[posix_abs(errnum)];
-}
-
-/**
- * Get error message string.
- *
- * @param errnum Error code for which to obtain human readable string.
- * @param buf Buffer to store a human readable string to.
- * @param bufsz Size of buffer pointed to by buf.
- * @return Zero on success, errno otherwise.
- */
-int posix_strerror_r(int errnum, char *buf, size_t bufsz)
-{
-	assert(buf != NULL);
-	
-	char *errstr = posix_strerror(errnum);
-	
-	if (posix_strlen(errstr) + 1 > bufsz) {
-		return ERANGE;
-	} else {
-		posix_strcpy(buf, errstr);
-	}
-
-	return 0;
-}
-
-/**
- * Get length of the string.
- *
- * @param s String which length shall be determined.
- * @return Length of the string.
- */
-size_t posix_strlen(const char *s)
-{
-	assert(s != NULL);
-	
-	return (size_t) (posix_strchr(s, '\0') - s);
-}
-
-/**
- * Get limited length of the string.
- *
- * @param s String which length shall be determined.
- * @param n Maximum number of bytes that can be examined to determine length.
- * @return The lower of either string length or n limit.
- */
-size_t posix_strnlen(const char *s, size_t n)
-{
-	assert(s != NULL);
-	
-	for (size_t sz = 0; sz < n; ++sz) {
-		
-		if (s[sz] == '\0') {
-			return sz;
-		}
-	}
-	
-	return n;
-}
-
-/**
- * Get description of a signal.
- *
- * @param signum Signal number.
- * @return Human readable signal description.
- */
-char *posix_strsignal(int signum)
-{
-	static const char *const sigstrings[] = {
-		[SIGABRT] = "SIGABRT (Process abort signal)",
-		[SIGALRM] = "SIGALRM (Alarm clock)",
-		[SIGBUS] = "SIGBUS (Access to an undefined portion of a memory object)",
-		[SIGCHLD] = "SIGCHLD (Child process terminated, stopped, or continued)",
-		[SIGCONT] = "SIGCONT (Continue executing, if stopped)",
-		[SIGFPE] = "SIGFPE (Erroneous arithmetic operation)",
-		[SIGHUP] = "SIGHUP (Hangup)",
-		[SIGILL] = "SIGILL (Illegal instruction)",
-		[SIGINT] = "SIGINT (Terminal interrupt signal)",
-		[SIGKILL] = "SIGKILL (Kill process)",
-		[SIGPIPE] = "SIGPIPE (Write on a pipe with no one to read it)",
-		[SIGQUIT] = "SIGQUIT (Terminal quit signal)",
-		[SIGSEGV] = "SIGSEGV (Invalid memory reference)",
-		[SIGSTOP] = "SIGSTOP (Stop executing)",
-		[SIGTERM] = "SIGTERM (Termination signal)",
-		[SIGTSTP] = "SIGTSTP (Terminal stop signal)",
-		[SIGTTIN] = "SIGTTIN (Background process attempting read)",
-		[SIGTTOU] = "SIGTTOU (Background process attempting write)",
-		[SIGUSR1] = "SIGUSR1 (User-defined signal 1)",
-		[SIGUSR2] = "SIGUSR2 (User-defined signal 2)",
-		[SIGPOLL] = "SIGPOLL (Pollable event)",
-		[SIGPROF] = "SIGPROF (Profiling timer expired)",
-		[SIGSYS] = "SIGSYS (Bad system call)",
-		[SIGTRAP] = "SIGTRAP (Trace/breakpoint trap)",
-		[SIGURG] = "SIGURG (High bandwidth data is available at a socket)",
-		[SIGVTALRM] = "SIGVTALRM (Virtual timer expired)",
-		[SIGXCPU] = "SIGXCPU (CPU time limit exceeded)",
-		[SIGXFSZ] = "SIGXFSZ (File size limit exceeded)"
-	};
-
-	if (signum <= _TOP_SIGNAL) {
-		return (char *) sigstrings[signum];
-	}
-
-	return (char *) "ERROR, Invalid signal number";
-}
-
-/** @}
- */
Index: pace/lib/posix/string.h
===================================================================
--- uspace/lib/posix/string.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,155 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file String manipulation.
- */
-
-#ifndef POSIX_STRING_H_
-#define POSIX_STRING_H_
-
-#include <mem.h>
-#include <str.h>
-
-/* available in str.h
- *
- * char *strtok(char *restrict, const char *restrict);
- * char *strtok_r(char *restrict, const char *restrict, char **restrict);
- *
- * available in mem.h
- *
- * void *memset(void *, int, size_t);
- * void *memcpy(void *, const void *, size_t);
- * void *memmove(void *, const void *, size_t);
- *
- * TODO: not implemented due to missing locale support
- *
- * int      strcoll_l(const char *, const char *, locale_t);
- * char    *strerror_l(int, locale_t);
- * size_t   strxfrm_l(char *restrict, const char *restrict, size_t, locale_t);
- */
-
-#ifndef NULL
-	#define NULL  ((void *) 0)
-#endif
-
-/* Copying and Concatenation */
-extern char *posix_strcpy(char *restrict dest, const char *restrict src);
-extern char *posix_strncpy(char *restrict dest, const char *restrict src, size_t n);
-extern char *posix_stpcpy(char *restrict dest, const char *restrict src);
-extern char *posix_stpncpy(char *restrict dest, const char *restrict src, size_t n);
-extern char *posix_strcat(char *restrict dest, const char *restrict src);
-extern char *posix_strncat(char *restrict dest, const char *restrict src, size_t n);
-extern void *posix_memccpy(void *restrict dest, const void *restrict src, int c, size_t n);
-extern char *posix_strdup(const char *s);
-extern char *posix_strndup(const char *s, size_t n);
-
-/* String/Array Comparison */
-extern int posix_memcmp(const void *mem1, const void *mem2, size_t n);
-extern int posix_strcmp(const char *s1, const char *s2);
-extern int posix_strncmp(const char *s1, const char *s2, size_t n);
-
-/* Search Functions */
-extern void *posix_memchr(const void *mem, int c, size_t n);
-extern char *posix_strchr(const char *s, int c);
-extern char *posix_strrchr(const char *s, int c);
-extern char *gnu_strchrnul(const char *s, int c);
-extern char *posix_strpbrk(const char *s1, const char *s2);
-extern size_t posix_strcspn(const char *s1, const char *s2);
-extern size_t posix_strspn(const char *s1, const char *s2);
-extern char *posix_strstr(const char *haystack, const char *needle);
-
-/* Collation Functions */
-extern int posix_strcoll(const char *s1, const char *s2);
-extern size_t posix_strxfrm(char *restrict s1, const char *restrict s2, size_t n);
-
-/* Error Messages */
-extern char *posix_strerror(int errnum);
-extern int posix_strerror_r(int errnum, char *buf, size_t bufsz);
-
-/* String Length */
-extern size_t posix_strlen(const char *s);
-extern size_t posix_strnlen(const char *s, size_t n);
-
-/* Signal Messages */
-extern char *posix_strsignal(int signum);
-
-/* Legacy Declarations */
-#ifndef POSIX_STRINGS_H_
-extern int posix_ffs(int i);
-extern int posix_strcasecmp(const char *s1, const char *s2);
-extern int posix_strncasecmp(const char *s1, const char *s2, size_t n);
-#endif
-
-#ifndef LIBPOSIX_INTERNAL
-	#define strcpy posix_strcpy
-	#define strncpy posix_strncpy
-	#define stpcpy posix_stpcpy
-	#define stpncpy posix_stpncpy
-	#define strcat posix_strcat
-	#define strncat posix_strncat
-	#define memccpy posix_memccpy
-	#define strdup posix_strdup
-	#define strndup posix_strndup
-
-	#define memcmp posix_memcmp
-	#define strcmp posix_strcmp
-	#define strncmp posix_strncmp
-
-	#define memchr posix_memchr
-	#define strchr posix_strchr
-	#define strrchr posix_strrchr
-	#define strchrnul gnu_strchrnul
-	#define strpbrk posix_strpbrk
-	#define strcspn posix_strcspn
-	#define strspn posix_strspn
-	#define strstr posix_strstr
-
-	#define strcoll posix_strcoll
-	#define strxfrm posix_strxfrm
-
-	#define strerror posix_strerror
-	#define strerror_r posix_strerror_r
-
-	#define strlen posix_strlen
-	#define strnlen posix_strnlen
-
-	#define strsignal posix_strsignal
-
-	#define ffs posix_ffs
-	#define strcasecmp posix_strcasecmp
-	#define strncasecmp posix_strncasecmp
-#endif
-
-#endif  // POSIX_STRING_H_
-
-/** @}
- */
Index: pace/lib/posix/strings.c
===================================================================
--- uspace/lib/posix/strings.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,187 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Additional string manipulation.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "internal/common.h"
-#include "strings.h"
-
-#include "string.h"
-#include "ctype.h"
-
-#include "libc/mem.h"
-
-/**
- * Find first set bit (beginning with the least significant bit).
- *
- * @param i Integer in which to look for the first set bit.
- * @return Index of first set bit. Bits are numbered starting at one.
- */
-int posix_ffs(int i)
-{
-	if (i == 0) {
-		return 0;
-	}
-
-	int result = 0;
-
-	// XXX: assumes at most 32-bit int
-	if (!(i & 0xFFFF)) {
-		result |= 16;
-		i >>= 16;
-	}
-	if (!(i & 0xFF)) {
-		result |= 8;
-		i >>= 8;
-	}
-	if (!(i & 0xF)) {
-		result |= 4;
-		i >>= 4;
-	}
-	if (!(i & 0x3)) {
-		result |= 2;
-		i >>= 2;
-	}
-	if (!(i & 0x1)) {
-		result |= 1;
-	}
-
-	return result + 1;
-}
-
-/**
- * Compare two strings (case-insensitive).
- *
- * @param s1 First string to be compared.
- * @param s2 Second string to be compared.
- * @return Difference of the first pair of inequal characters,
- *     or 0 if strings have the same content.
- */
-int posix_strcasecmp(const char *s1, const char *s2)
-{
-	return posix_strncasecmp(s1, s2, STR_NO_LIMIT);
-}
-
-/**
- * Compare part of two strings (case-insensitive).
- *
- * @param s1 First string to be compared.
- * @param s2 Second string to be compared.
- * @param n Maximum number of characters to be compared.
- * @return Difference of the first pair of inequal characters,
- *     or 0 if strings have the same content.
- */
-int posix_strncasecmp(const char *s1, const char *s2, size_t n)
-{
-	for (size_t i = 0; i < n; ++i) {
-		int cmp = tolower(s1[i]) - tolower(s2[i]);
-		if (cmp != 0) {
-			return cmp;
-		}
-		
-		if (s1[i] == 0) {
-			return 0;
-		}
-	}
-	
-	return 0;
-}
-
-/**
- * Compare two memory areas.
- *
- * @param mem1 Pointer to the first area to compare.
- * @param mem2 Pointer to the second area to compare.
- * @param n Common size of both areas.
- * @return If n is 0, return zero. If the areas match, return
- *     zero. Otherwise return non-zero.
- */
-int posix_bcmp(const void *mem1, const void *mem2, size_t n)
-{
-	return bcmp(mem1, mem2, n);
-}
-
-/**
- * Copy bytes in memory with overlapping areas.
- *
- * @param src Source area.
- * @param dest Destination area.
- * @param n Number of bytes to copy.
- */
-void posix_bcopy(const void *src, void *dest, size_t n)
-{
-	/* Note that memmove has different order of arguments. */
-	memmove(dest, src, n);
-}
-
-/**
- * Reset bytes in memory area to zero.
- *
- * @param mem Memory area to be zeroed.
- * @param n Number of bytes to reset.
- */
-void posix_bzero(void *mem, size_t n)
-{
-	bzero(mem, n);
-}
-
-/**
- * Scan string for a first occurence of a character.
- *
- * @param s String in which to look for the character.
- * @param c Character to look for.
- * @return Pointer to the specified character on success,
- *     NULL pointer otherwise.
- */
-char *posix_index(const char *s, int c)
-{
-	return posix_strchr(s, c);
-}
-
-/**
- * Scan string for a last occurence of a character.
- *
- * @param s String in which to look for the character.
- * @param c Character to look for.
- * @return Pointer to the specified character on success,
- *     NULL pointer otherwise.
- */
-char *posix_rindex(const char *s, int c)
-{
-	return posix_strrchr(s, c);
-}
-
-/** @}
- */
Index: pace/lib/posix/strings.h
===================================================================
--- uspace/lib/posix/strings.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,80 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Additional string manipulation.
- */
-
-#ifndef POSIX_STRINGS_H_
-#define POSIX_STRINGS_H_
-
-/* Search Functions */
-#ifndef POSIX_STRING_H_
-extern int posix_ffs(int i);
-#endif
-
-/* String/Array Comparison */
-#ifndef POSIX_STRING_H_
-extern int posix_strcasecmp(const char *s1, const char *s2);
-extern int posix_strncasecmp(const char *s1, const char *s2, size_t n);
-#endif
-
-/* TODO: not implemented due to missing locale support
- *
- * int strcasecmp_l(const char *, const char *, locale_t);
- * int strncasecmp_l(const char *, const char *, size_t, locale_t);
- */
-
-/* Legacy Functions */
-extern int posix_bcmp(const void *mem1, const void *mem2, size_t n);
-extern void posix_bcopy(const void *src, void *dest, size_t n);
-extern void posix_bzero(void *mem, size_t n);
-extern char *posix_index(const char *s, int c);
-extern char *posix_rindex(const char *s, int c);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define ffs posix_ffs
-
-	#define strcasecmp posix_strcasecmp
-	#define strncasecmp posix_strncasecmp
-
-	#define bcmp posix_bcmp
-	#define bcopy posix_bcopy
-	#undef bzero
-	#define bzero posix_bzero
-	#define index posix_index
-	#define rindex posix_rindex
-#endif
-
-#endif  // POSIX_STRINGS_H_
-
-/** @}
- */
Index: pace/lib/posix/sys/mman.h
===================================================================
--- uspace/lib/posix/sys/mman.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,52 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Memory management declarations.
- */
-
-#ifndef POSIX_SYS_MMAN_H_
-#define POSIX_SYS_MMAN_H_
-
-#include "../libc/sys/mman.h"
-
-#undef PROT_NONE
-#undef PROT_READ
-#undef PROT_WRITE
-#undef PROT_EXEC
-#define PROT_NONE  0
-#define PROT_READ  PROTO_READ
-#define PROT_WRITE PROTO_WRITE
-#define PROT_EXEC  PROTO_EXEC
-
-#endif /* POSIX_SYS_MMAN_H_ */
-
-/** @}
- */
Index: pace/lib/posix/sys/stat.c
===================================================================
--- uspace/lib/posix/sys/stat.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,150 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file File status handling.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "../internal/common.h"
-#include "stat.h"
-
-#include "../errno.h"
-#include "../libc/mem.h"
-
-/**
- * Convert HelenOS stat struct into POSIX stat struct (if possible).
- *
- * @param dest POSIX stat struct.
- * @param src HelenOS stat struct.
- */
-static void stat_to_posix(struct posix_stat *dest, struct stat *src)
-{
-	memset(dest, 0, sizeof(struct posix_stat));
-	
-	dest->st_dev = src->service;
-	dest->st_ino = src->index;
-	
-	/* HelenOS doesn't support permissions, so we set them all */
-	dest->st_mode = S_IRWXU | S_IRWXG | S_IRWXO;
-	if (src->is_file) {
-		dest->st_mode |= S_IFREG;
-	}
-	if (src->is_directory) {
-		dest->st_mode |= S_IFDIR;
-	}
-	
-	dest->st_nlink = src->lnkcnt;
-	dest->st_size = src->size;
-}
-
-/**
- * Retrieve file status for file associated with file descriptor.
- *
- * @param fd File descriptor of the opened file.
- * @param st Status structure to be filled with information.
- * @return Zero on success, -1 otherwise.
- */
-int posix_fstat(int fd, struct posix_stat *st)
-{
-	struct stat hst;
-	int rc = fstat(fd, &hst);
-	if (rc < 0) {
-		/* fstat() returns negative error code instead of using errno. */
-		errno = -rc;
-		return -1;
-	}
-	stat_to_posix(st, &hst);
-	return 0;
-}
-
-/**
- * Retrieve file status for symbolic link.
- * 
- * @param path Path to the symbolic link.
- * @param st Status structure to be filled with information.
- * @return Zero on success, -1 otherwise.
- */
-int posix_lstat(const char *restrict path, struct posix_stat *restrict st)
-{
-	/* There are currently no symbolic links in HelenOS. */
-	return posix_stat(path, st);
-}
-
-/**
- * Retrieve file status for regular file (or symbolic link target).
- *
- * @param path Path to the file/link.
- * @param st Status structure to be filled with information.
- * @return Zero on success, -1 otherwise.
- */
-int posix_stat(const char *restrict path, struct posix_stat *restrict st)
-{
-	struct stat hst;
-	int rc = stat(path, &hst);
-	if (rc < 0) {
-		/* stat() returns negative error code instead of using errno. */
-		errno = -rc;
-		return -1;
-	}
-	stat_to_posix(st, &hst);
-	return 0;
-}
-
-/**
- * Change permission bits for the file if possible.
- * 
- * @param path Path to the file.
- * @param mode Permission bits to be set.
- * @return Zero on success, -1 otherwise.
- */
-int posix_chmod(const char *path, mode_t mode)
-{
-	/* HelenOS doesn't support permissions, return success. */
-	return 0;
-}
-
-/**
- * Set the file mode creation mask of the process.
- * 
- * @param mask Set permission bits are cleared in the related creation
- *     functions. Non-permission bits are ignored.
- * @return Previous file mode creation mask.
- */
-mode_t posix_umask(mode_t mask)
-{
-	/* HelenOS doesn't support permissions, return empty mask. */
-	return 0;
-}
-
-/** @}
- */
Index: pace/lib/posix/sys/stat.h
===================================================================
--- uspace/lib/posix/sys/stat.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,144 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file File status handling.
- */
-
-#ifndef POSIX_SYS_STAT_H_
-#define POSIX_SYS_STAT_H_
-
-#include "../libc/sys/stat.h"
-#include "types.h"
-#include "../time.h"
-
-/* values are the same as on Linux */
-
-#undef S_IFMT
-#undef S_IFSOCK
-#undef S_IFLNK
-#undef S_IFREG
-#undef S_IFBLK
-#undef S_IFDIR
-#undef S_IFCHR
-#undef S_IFIFO
-#define S_IFMT     0170000   /* all file types */
-#define S_IFSOCK   0140000   /* socket */
-#define S_IFLNK    0120000   /* symbolic link */
-#define S_IFREG    0100000   /* regular file */
-#define S_IFBLK    0060000   /* block device */
-#define S_IFDIR    0040000   /* directory */
-#define S_IFCHR    0020000   /* character device */
-#define S_IFIFO    0010000   /* FIFO */
-
-#undef S_ISUID
-#undef S_ISGID
-#undef S_ISVTX
-#define S_ISUID    0004000   /* SUID */
-#define S_ISGID    0002000   /* SGID */
-#define S_ISVTX    0001000   /* sticky */
-
-#undef S_IRWXU
-#undef S_IRUSR
-#undef S_IWUSR
-#undef S_IXUSR
-#define S_IRWXU    00700     /* owner permissions */
-#define S_IRUSR    00400
-#define S_IWUSR    00200
-#define S_IXUSR    00100
-
-#undef S_IRWXG
-#undef S_IRGRP
-#undef S_IWGRP
-#undef S_IXGRP
-#define S_IRWXG    00070     /* group permissions */
-#define S_IRGRP    00040
-#define S_IWGRP    00020
-#define S_IXGRP    00010
-
-#undef S_IRWXO
-#undef S_IROTH
-#undef S_IWOTH
-#undef S_IXOTH
-#define S_IRWXO    00007     /* other permissions */
-#define S_IROTH    00004
-#define S_IWOTH    00002
-#define S_IXOTH    00001
-
-#undef S_ISREG
-#undef S_ISDIR
-#undef S_ISCHR
-#undef S_ISBLK
-#undef S_ISFIFO
-#undef S_ISLNK
-#undef S_ISSOCK
-#define S_ISREG(m) ((m & S_IFREG) != 0)
-#define S_ISDIR(m) ((m & S_IFDIR) != 0)
-#define S_ISCHR(m) ((m & S_IFCHR) != 0)
-#define S_ISBLK(m) ((m & S_IFBLK) != 0)
-#define S_ISFIFO(m) ((m & S_IFIFO) != 0)
-#define S_ISLNK(m) ((m & S_IFLNK) != 0) /* symbolic link? (Not in POSIX.1-1996.) */
-#define S_ISSOCK(m) ((m & S_IFSOCK) != 0) /* socket? (Not in POSIX.1-1996.) */
-
-struct posix_stat {
-	posix_dev_t     st_dev;     /* ID of device containing file */
-	posix_ino_t     st_ino;     /* inode number */
-	mode_t          st_mode;    /* protection */
-	posix_nlink_t   st_nlink;   /* number of hard links */
-	posix_uid_t     st_uid;     /* user ID of owner */
-	posix_gid_t     st_gid;     /* group ID of owner */
-	posix_dev_t     st_rdev;    /* device ID (if special file) */
-	posix_off_t     st_size;    /* total size, in bytes */
-	posix_blksize_t st_blksize; /* blocksize for file system I/O */
-	posix_blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
-	time_t          st_atime;   /* time of last access */
-	time_t          st_mtime;   /* time of last modification */
-	time_t          st_ctime;   /* time of last status change */
-};
-
-extern int posix_fstat(int fd, struct posix_stat *st);
-extern int posix_lstat(const char *restrict path, struct posix_stat *restrict st);
-extern int posix_stat(const char *restrict path, struct posix_stat *restrict st);
-extern int posix_chmod(const char *path, mode_t mode);
-extern mode_t posix_umask(mode_t mask);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define fstat posix_fstat
-	#define lstat posix_lstat
-	#define stat posix_stat
-	#define chmod posix_chmod
-	#define umask posix_umask
-#endif
-
-#endif /* POSIX_SYS_STAT_H */
-
-/** @}
- */
Index: pace/lib/posix/sys/types.h
===================================================================
--- uspace/lib/posix/sys/types.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,78 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Data types definitions.
- */
-
-#ifndef POSIX_SYS_TYPES_H_
-#define POSIX_SYS_TYPES_H_
-
-#include "../libc/sys/types.h"
-
-typedef unsigned int posix_ino_t;
-typedef unsigned int posix_nlink_t;
-typedef unsigned int posix_uid_t;
-typedef unsigned int posix_gid_t;
-typedef off64_t posix_off_t;
-typedef long posix_blksize_t;
-typedef long posix_blkcnt_t;
-typedef int64_t posix_pid_t;
-typedef sysarg_t posix_dev_t;
-
-/* PThread Types */
-typedef struct posix_thread_attr posix_thread_attr_t;
-
-/* Clock Types */
-typedef long posix_clock_t;
-typedef int posix_clockid_t;
-
-#ifndef LIBPOSIX_INTERNAL
-	#define ino_t posix_ino_t
-	#define nlink_t posix_nlink_t
-	#define uid_t posix_uid_t
-	#define gid_t posix_gid_t
-	#define off_t posix_off_t
-	#define blksize_t posix_blksize_t
-	#define blkcnt_t posix_blkcnt_t
-	#define pid_t posix_pid_t
-	#define dev_t posix_dev_t
-	
-	#define pthread_attr_t posix_thread_attr_t
-	
-	#define clock_t posix_clock_t
-	#define clockid_t posix_clockid_t
-#endif
-
-#endif /* POSIX_SYS_TYPES_H_ */
-
-/** @}
- */
Index: pace/lib/posix/sys/wait.c
===================================================================
--- uspace/lib/posix/sys/wait.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,122 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Support for waiting.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "../internal/common.h"
-#include "wait.h"
-
-#include "../libc/task.h"
-#include "../assert.h"
-#include "../errno.h"
-#include "../limits.h"
-#include "../signal.h"
-
-int __posix_wifexited(int status) {
-	return status != INT_MIN;
-}
-
-int __posix_wexitstatus(int status) {
-	assert(__posix_wifexited(status));
-	return status;
-}
-
-int __posix_wifsignaled(int status) {
-	return status == INT_MIN;
-}
-
-int __posix_wtermsig(int status) {
-	assert(__posix_wifsignaled(status));
-	/* There is no way to distinguish reason
-	 * for unexpected termination at the moment.
-	 */
-	return SIGABRT;
-}
-
-/**
- * Wait for any child process to stop or terminate.
- * 
- * @param stat_ptr Location of the final status code of the child process.
- * @return ID of the child process for which status is reported,
- *     -1 on signal interrupt, (pid_t)-1 otherwise.
- */
-posix_pid_t posix_wait(int *stat_ptr)
-{
-	/* HelenOS does not support this. */
-	errno = ENOSYS;
-	return (posix_pid_t) -1;
-}
-
-/**
- * Wait for a child process to stop or terminate.
- * 
- * @param pid What child process shall the caller wait for. See POSIX manual
- *     for details.
- * @param stat_ptr Location of the final status code of the child process.
- * @param options Constraints of the waiting. See POSIX manual for details.
- * @return ID of the child process for which status is reported,
- *     -1 on signal interrupt, 0 if non-blocking wait is requested but there is
- *     no child process whose status can be reported, (pid_t)-1 otherwise.
- */
-posix_pid_t posix_waitpid(posix_pid_t pid, int *stat_ptr, int options)
-{
-	assert(stat_ptr != NULL);
-	assert(options == 0 /* None of the options are supported. */);
-	
-	task_exit_t texit;
-	int retval;
-	
-	int rc = task_wait((task_id_t) pid, &texit, &retval);
-	
-	if (rc < 0) {
-		/* Unable to retrieve status. */
-		errno = -rc;
-		return (posix_pid_t) -1;
-	}
-	
-	if (texit == TASK_EXIT_NORMAL) {
-		// FIXME: relies on application not returning this value
-		assert(retval != INT_MIN);
-		*stat_ptr = retval;
-	} else {
-		/* Reserve the lowest value for unexpected termination. */
-		*stat_ptr = INT_MIN;
-	}
-	
-	return pid;
-}
-
-/** @}
- */
Index: pace/lib/posix/sys/wait.h
===================================================================
--- uspace/lib/posix/sys/wait.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,65 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Support for waiting.
- */
-
-#ifndef POSIX_SYS_WAIT_H_
-#define POSIX_SYS_WAIT_H_
-
-#include "types.h"
-
-#undef WIFEXITED
-#undef WEXITSTATUS
-#undef WIFSIGNALED
-#undef WTERMSIG
-#define WIFEXITED(status) __posix_wifexited(status)
-#define WEXITSTATUS(status) __posix_wexitstatus(status)
-#define WIFSIGNALED(status) __posix_wifsignaled(status)
-#define WTERMSIG(status) __posix_wtermsig(status)
-
-extern int __posix_wifexited(int status);
-extern int __posix_wexitstatus(int status);
-extern int __posix_wifsignaled(int status);
-extern int __posix_wtermsig(int status);
-
-extern posix_pid_t posix_wait(int *stat_ptr);
-extern posix_pid_t posix_waitpid(posix_pid_t pid, int *stat_ptr, int options);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define wait posix_wait
-	#define waitpid posix_waitpid
-#endif
-
-#endif /* POSIX_SYS_WAIT_H_ */
-
-/** @}
- */
Index: pace/lib/posix/time.c
===================================================================
--- uspace/lib/posix/time.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,905 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Time measurement support.
- */
-
-#define LIBPOSIX_INTERNAL
-
-/* Must be first. */
-#include "stdbool.h"
-
-#include "internal/common.h"
-#include "time.h"
-
-#include "ctype.h"
-#include "errno.h"
-#include "signal.h"
-#include "assert.h"
-
-#include "libc/malloc.h"
-#include "libc/task.h"
-#include "libc/stats.h"
-#include "libc/sys/time.h"
-
-// TODO: test everything in this file
-
-/* In some places in this file, phrase "normalized broken-down time" is used.
- * This means time broken down to components (year, month, day, hour, min, sec),
- * in which every component is in its proper bounds. Non-normalized time could
- * e.g. be 2011-54-5 29:13:-5, which would semantically mean start of year 2011
- * + 53 months + 4 days + 29 hours + 13 minutes - 5 seconds.
- */
-
-
-
-/* Helper functions ***********************************************************/
-
-#define HOURS_PER_DAY (24)
-#define MINS_PER_HOUR (60)
-#define SECS_PER_MIN (60)
-#define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY)
-#define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
-#define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY)
-
-/**
- * Checks whether the year is a leap year.
- *
- * @param year Year since 1900 (e.g. for 1970, the value is 70).
- * @return true if year is a leap year, false otherwise
- */
-static bool _is_leap_year(time_t year)
-{
-	year += 1900;
-
-	if (year % 400 == 0)
-		return true;
-	if (year % 100 == 0)
-		return false;
-	if (year % 4 == 0)
-		return true;
-	return false;
-}
-
-/**
- * Returns how many days there are in the given month of the given year.
- * Note that year is only taken into account if month is February.
- *
- * @param year Year since 1900 (can be negative).
- * @param mon Month of the year. 0 for January, 11 for December.
- * @return Number of days in the specified month.
- */
-static int _days_in_month(time_t year, time_t mon)
-{
-	assert(mon >= 0 && mon <= 11);
-
-	static int month_days[] =
-		{ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
-	if (mon == 1) {
-		year += 1900;
-		/* february */
-		return _is_leap_year(year) ? 29 : 28;
-	} else {
-		return month_days[mon];
-	}
-}
-
-/**
- * For specified year, month and day of month, returns which day of that year
- * it is.
- *
- * For example, given date 2011-01-03, the corresponding expression is:
- *     _day_of_year(111, 0, 3) == 2
- *
- * @param year Year (year 1900 = 0, can be negative).
- * @param mon Month (January = 0).
- * @param mday Day of month (First day is 1).
- * @return Day of year (First day is 0).
- */
-static int _day_of_year(time_t year, time_t mon, time_t mday)
-{
-	static int mdays[] =
-	    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
-	static int leap_mdays[] =
-	    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
-
-	return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1;
-}
-
-/**
- * Integer division that rounds to negative infinity.
- * Used by some functions in this file.
- *
- * @param op1 Divident.
- * @param op2 Divisor.
- * @return Rounded quotient.
- */
-static time_t _floor_div(time_t op1, time_t op2)
-{
-	if (op1 >= 0 || op1 % op2 == 0) {
-		return op1 / op2;
-	} else {
-		return op1 / op2 - 1;
-	}
-}
-
-/**
- * Modulo that rounds to negative infinity.
- * Used by some functions in this file.
- *
- * @param op1 Divident.
- * @param op2 Divisor.
- * @return Remainder.
- */
-static time_t _floor_mod(time_t op1, time_t op2)
-{
-	int div = _floor_div(op1, op2);
-
-	/* (a / b) * b + a % b == a */
-	/* thus, a % b == a - (a / b) * b */
-
-	int result = op1 - div * op2;
-	
-	/* Some paranoid checking to ensure I didn't make a mistake here. */
-	assert(result >= 0);
-	assert(result < op2);
-	assert(div * op2 + result == op1);
-	
-	return result;
-}
-
-/**
- * Number of days since the Epoch.
- * Epoch is 1970-01-01, which is also equal to day 0.
- *
- * @param year Year (year 1900 = 0, may be negative).
- * @param mon Month (January = 0).
- * @param mday Day of month (first day = 1).
- * @return Number of days since the Epoch.
- */
-static time_t _days_since_epoch(time_t year, time_t mon, time_t mday)
-{
-	return (year - 70) * 365 + _floor_div(year - 69, 4) -
-	    _floor_div(year - 1, 100) + _floor_div(year + 299, 400) +
-	    _day_of_year(year, mon, mday);
-}
-
-/**
- * Seconds since the Epoch. see also _days_since_epoch().
- * 
- * @param tm Normalized broken-down time.
- * @return Number of seconds since the epoch, not counting leap seconds.
- */
-static time_t _secs_since_epoch(const struct posix_tm *tm)
-{
-	return _days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) *
-	    SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR +
-	    tm->tm_min * SECS_PER_MIN + tm->tm_sec;
-}
-
-/**
- * Which day of week the specified date is.
- * 
- * @param year Year (year 1900 = 0).
- * @param mon Month (January = 0).
- * @param mday Day of month (first = 1).
- * @return Day of week (Sunday = 0).
- */
-static int _day_of_week(time_t year, time_t mon, time_t mday)
-{
-	/* 1970-01-01 is Thursday */
-	return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7);
-}
-
-/**
- * Normalizes the broken-down time and optionally adds specified amount of
- * seconds.
- * 
- * @param tm Broken-down time to normalize.
- * @param sec_add Seconds to add.
- * @return 0 on success, -1 on overflow
- */
-static int _normalize_time(struct posix_tm *tm, time_t sec_add)
-{
-	// TODO: DST correction
-
-	/* Set initial values. */
-	time_t sec = tm->tm_sec + sec_add;
-	time_t min = tm->tm_min;
-	time_t hour = tm->tm_hour;
-	time_t day = tm->tm_mday - 1;
-	time_t mon = tm->tm_mon;
-	time_t year = tm->tm_year;
-
-	/* Adjust time. */
-	min += _floor_div(sec, SECS_PER_MIN);
-	sec = _floor_mod(sec, SECS_PER_MIN);
-	hour += _floor_div(min, MINS_PER_HOUR);
-	min = _floor_mod(min, MINS_PER_HOUR);
-	day += _floor_div(hour, HOURS_PER_DAY);
-	hour = _floor_mod(hour, HOURS_PER_DAY);
-
-	/* Adjust month. */
-	year += _floor_div(mon, 12);
-	mon = _floor_mod(mon, 12);
-
-	/* Now the difficult part - days of month. */
-	
-	/* First, deal with whole cycles of 400 years = 146097 days. */
-	year += _floor_div(day, 146097) * 400;
-	day = _floor_mod(day, 146097);
-	
-	/* Then, go in one year steps. */
-	if (mon <= 1) {
-		/* January and February. */
-		while (day > 365) {
-			day -= _is_leap_year(year) ? 366 : 365;
-			year++;
-		}
-	} else {
-		/* Rest of the year. */
-		while (day > 365) {
-			day -= _is_leap_year(year + 1) ? 366 : 365;
-			year++;
-		}
-	}
-	
-	/* Finally, finish it off month per month. */
-	while (day >= _days_in_month(year, mon)) {
-		day -= _days_in_month(year, mon);
-		mon++;
-		if (mon >= 12) {
-			mon -= 12;
-			year++;
-		}
-	}
-	
-	/* Calculate the remaining two fields. */
-	tm->tm_yday = _day_of_year(year, mon, day + 1);
-	tm->tm_wday = _day_of_week(year, mon, day + 1);
-	
-	/* And put the values back to the struct. */
-	tm->tm_sec = (int) sec;
-	tm->tm_min = (int) min;
-	tm->tm_hour = (int) hour;
-	tm->tm_mday = (int) day + 1;
-	tm->tm_mon = (int) mon;
-	
-	/* Casts to work around libc brain-damage. */
-	if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) {
-		tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX);
-		return -1;
-	}
-	
-	tm->tm_year = (int) year;
-	return 0;
-}
-
-/**
- * Which day the week-based year starts on, relative to the first calendar day.
- * E.g. if the year starts on December 31st, the return value is -1.
- *
- * @param Year since 1900.
- * @return Offset of week-based year relative to calendar year.
- */
-static int _wbyear_offset(int year)
-{
-	int start_wday = _day_of_week(year, 0, 1);
-	return _floor_mod(4 - start_wday, 7) - 3;
-}
-
-/**
- * Returns week-based year of the specified time.
- *
- * @param tm Normalized broken-down time.
- * @return Week-based year.
- */
-static int _wbyear(const struct posix_tm *tm)
-{
-	int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
-	if (day < 0) {
-		/* Last week of previous year. */
-		return tm->tm_year - 1;
-	}
-	if (day > 364 + _is_leap_year(tm->tm_year)) {
-		/* First week of next year. */
-		return tm->tm_year + 1;
-	}
-	/* All the other days are in the calendar year. */
-	return tm->tm_year;
-}
-
-/**
- * Week number of the year, assuming weeks start on sunday.
- * The first Sunday of January is the first day of week 1;
- * days in the new year before this are in week 0.
- *
- * @param tm Normalized broken-down time.
- * @return The week number (0 - 53).
- */
-static int _sun_week_number(const struct posix_tm *tm)
-{
-	int first_day = (7 - _day_of_week(tm->tm_year, 0, 1)) % 7;
-	return (tm->tm_yday - first_day + 7) / 7;
-}
-
-/**
- * Week number of the year, assuming weeks start on monday.
- * If the week containing January 1st has four or more days in the new year,
- * then it is considered week 1. Otherwise, it is the last week of the previous
- * year, and the next week is week 1. Both January 4th and the first Thursday
- * of January are always in week 1.
- *
- * @param tm Normalized broken-down time.
- * @return The week number (1 - 53).
- */
-static int _iso_week_number(const struct posix_tm *tm)
-{
-	int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
-	if (day < 0) {
-		/* Last week of previous year. */
-		return 53;
-	}
-	if (day > 364 + _is_leap_year(tm->tm_year)) {
-		/* First week of next year. */
-		return 1;
-	}
-	/* All the other days give correct answer. */
-	return (day / 7 + 1);
-}
-
-/**
- * Week number of the year, assuming weeks start on monday.
- * The first Monday of January is the first day of week 1;
- * days in the new year before this are in week 0. 
- *
- * @param tm Normalized broken-down time.
- * @return The week number (0 - 53).
- */
-static int _mon_week_number(const struct posix_tm *tm)
-{
-	int first_day = (1 - _day_of_week(tm->tm_year, 0, 1)) % 7;
-	return (tm->tm_yday - first_day + 7) / 7;
-}
-
-/******************************************************************************/
-
-int posix_daylight;
-long posix_timezone;
-char *posix_tzname[2];
-
-/**
- * Set timezone conversion information.
- */
-void posix_tzset(void)
-{
-	// TODO: read environment
-	posix_tzname[0] = (char *) "GMT";
-	posix_tzname[1] = (char *) "GMT";
-	posix_daylight = 0;
-	posix_timezone = 0;
-}
-
-/**
- * Calculate the difference between two times, in seconds.
- * 
- * @param time1 First time.
- * @param time0 Second time.
- * @return Time in seconds.
- */
-double posix_difftime(time_t time1, time_t time0)
-{
-	return (double) (time1 - time0);
-}
-
-/**
- * This function first normalizes the provided broken-down time
- * (moves all values to their proper bounds) and then tries to
- * calculate the appropriate time_t representation.
- *
- * @param tm Broken-down time.
- * @return time_t representation of the time, undefined value on overflow.
- */
-time_t posix_mktime(struct posix_tm *tm)
-{
-	// TODO: take DST flag into account
-	// TODO: detect overflow
-
-	_normalize_time(tm, 0);
-	return _secs_since_epoch(tm);
-}
-
-/**
- * Converts a time value to a broken-down UTC time.
- *
- * @param timer Time to convert.
- * @return Normalized broken-down time in UTC, NULL on overflow.
- */
-struct posix_tm *posix_gmtime(const time_t *timer)
-{
-	assert(timer != NULL);
-
-	static struct posix_tm result;
-	return posix_gmtime_r(timer, &result);
-}
-
-/**
- * Converts a time value to a broken-down UTC time.
- * 
- * @param timer Time to convert.
- * @param result Structure to store the result to.
- * @return Value of result on success, NULL on overflow.
- */
-struct posix_tm *posix_gmtime_r(const time_t *restrict timer,
-    struct posix_tm *restrict result)
-{
-	assert(timer != NULL);
-	assert(result != NULL);
-
-	/* Set result to epoch. */
-	result->tm_sec = 0;
-	result->tm_min = 0;
-	result->tm_hour = 0;
-	result->tm_mday = 1;
-	result->tm_mon = 0;
-	result->tm_year = 70; /* 1970 */
-
-	if (_normalize_time(result, *timer) == -1) {
-		errno = EOVERFLOW;
-		return NULL;
-	}
-
-	return result;
-}
-
-/**
- * Converts a time value to a broken-down local time.
- *
- * @param timer Time to convert.
- * @return Normalized broken-down time in local timezone, NULL on overflow.
- */
-struct posix_tm *posix_localtime(const time_t *timer)
-{
-	static struct posix_tm result;
-	return posix_localtime_r(timer, &result);
-}
-
-/**
- * Converts a time value to a broken-down local time.
- * 
- * @param timer Time to convert.
- * @param result Structure to store the result to.
- * @return Value of result on success, NULL on overflow.
- */
-struct posix_tm *posix_localtime_r(const time_t *restrict timer,
-    struct posix_tm *restrict result)
-{
-	// TODO: deal with timezone
-	// currently assumes system and all times are in GMT
-	return posix_gmtime_r(timer, result);
-}
-
-/**
- * Converts broken-down time to a string in format
- * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
- *
- * @param timeptr Broken-down time structure.
- * @return Pointer to a statically allocated string.
- */
-char *posix_asctime(const struct posix_tm *timeptr)
-{
-	static char buf[ASCTIME_BUF_LEN];
-	return posix_asctime_r(timeptr, buf);
-}
-
-/**
- * Converts broken-down time to a string in format
- * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
- *
- * @param timeptr Broken-down time structure.
- * @param buf Buffer to store string to, must be at least ASCTIME_BUF_LEN
- *     bytes long.
- * @return Value of buf.
- */
-char *posix_asctime_r(const struct posix_tm *restrict timeptr,
-    char *restrict buf)
-{
-	assert(timeptr != NULL);
-	assert(buf != NULL);
-
-	static const char *wday[] = {
-		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-	};
-	static const char *mon[] = {
-		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-	};
-
-	snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n",
-	    wday[timeptr->tm_wday],
-	    mon[timeptr->tm_mon],
-	    timeptr->tm_mday, timeptr->tm_hour,
-	    timeptr->tm_min, timeptr->tm_sec,
-	    1900 + timeptr->tm_year);
-
-	return buf;
-}
-
-/**
- * Equivalent to asctime(localtime(clock)).
- * 
- * @param timer Time to convert.
- * @return Pointer to a statically allocated string holding the date.
- */
-char *posix_ctime(const time_t *timer)
-{
-	struct posix_tm *loctime = posix_localtime(timer);
-	if (loctime == NULL) {
-		return NULL;
-	}
-	return posix_asctime(loctime);
-}
-
-/**
- * Reentrant variant of ctime().
- * 
- * @param timer Time to convert.
- * @param buf Buffer to store string to. Must be at least ASCTIME_BUF_LEN
- *     bytes long.
- * @return Pointer to buf on success, NULL on falure.
- */
-char *posix_ctime_r(const time_t *timer, char *buf)
-{
-	struct posix_tm loctime;
-	if (posix_localtime_r(timer, &loctime) == NULL) {
-		return NULL;
-	}
-	return posix_asctime_r(&loctime, buf);
-}
-
-/**
- * Convert time and date to a string, based on a specified format and
- * current locale.
- * 
- * @param s Buffer to write string to.
- * @param maxsize Size of the buffer.
- * @param format Format of the output.
- * @param tm Broken-down time to format.
- * @return Number of bytes written.
- */
-size_t posix_strftime(char *restrict s, size_t maxsize,
-    const char *restrict format, const struct posix_tm *restrict tm)
-{
-	assert(s != NULL);
-	assert(format != NULL);
-	assert(tm != NULL);
-
-	// TODO: use locale
-	static const char *wday_abbr[] = {
-		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-	};
-	static const char *wday[] = {
-		"Sunday", "Monday", "Tuesday", "Wednesday",
-		"Thursday", "Friday", "Saturday"
-	};
-	static const char *mon_abbr[] = {
-		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-	};
-	static const char *mon[] = {
-		"January", "February", "March", "April", "May", "June", "July",
-		"August", "September", "October", "November", "December"
-	};
-	
-	if (maxsize < 1) {
-		return 0;
-	}
-	
-	char *ptr = s;
-	size_t consumed;
-	size_t remaining = maxsize;
-	
-	#define append(...) { \
-		/* FIXME: this requires POSIX-correct snprintf */ \
-		/*        otherwise it won't work with non-ascii chars */ \
-		consumed = snprintf(ptr, remaining, __VA_ARGS__); \
-		if (consumed >= remaining) { \
-			return 0; \
-		} \
-		ptr += consumed; \
-		remaining -= consumed; \
-	}
-	
-	#define recurse(fmt) { \
-		consumed = posix_strftime(ptr, remaining, fmt, tm); \
-		if (consumed == 0) { \
-			return 0; \
-		} \
-		ptr += consumed; \
-		remaining -= consumed; \
-	}
-	
-	#define TO_12H(hour) (((hour) > 12) ? ((hour) - 12) : \
-	    (((hour) == 0) ? 12 : (hour)))
-	
-	while (*format != '\0') {
-		if (*format != '%') {
-			append("%c", *format);
-			format++;
-			continue;
-		}
-		
-		format++;
-		if (*format == '0' || *format == '+') {
-			// TODO: padding
-			format++;
-		}
-		while (isdigit(*format)) {
-			// TODO: padding
-			format++;
-		}
-		if (*format == 'O' || *format == 'E') {
-			// TODO: locale's alternative format
-			format++;
-		}
-		
-		switch (*format) {
-		case 'a':
-			append("%s", wday_abbr[tm->tm_wday]); break;
-		case 'A':
-			append("%s", wday[tm->tm_wday]); break;
-		case 'b':
-			append("%s", mon_abbr[tm->tm_mon]); break;
-		case 'B':
-			append("%s", mon[tm->tm_mon]); break;
-		case 'c':
-			// TODO: locale-specific datetime format
-			recurse("%Y-%m-%d %H:%M:%S"); break;
-		case 'C':
-			append("%02d", (1900 + tm->tm_year) / 100); break;
-		case 'd':
-			append("%02d", tm->tm_mday); break;
-		case 'D':
-			recurse("%m/%d/%y"); break;
-		case 'e':
-			append("%2d", tm->tm_mday); break;
-		case 'F':
-			recurse("%+4Y-%m-%d"); break;
-		case 'g':
-			append("%02d", _wbyear(tm) % 100); break;
-		case 'G':
-			append("%d", _wbyear(tm)); break;
-		case 'h':
-			recurse("%b"); break;
-		case 'H':
-			append("%02d", tm->tm_hour); break;
-		case 'I':
-			append("%02d", TO_12H(tm->tm_hour)); break;
-		case 'j':
-			append("%03d", tm->tm_yday); break;
-		case 'k':
-			append("%2d", tm->tm_hour); break;
-		case 'l':
-			append("%2d", TO_12H(tm->tm_hour)); break;
-		case 'm':
-			append("%02d", tm->tm_mon); break;
-		case 'M':
-			append("%02d", tm->tm_min); break;
-		case 'n':
-			append("\n"); break;
-		case 'p':
-			append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break;
-		case 'P':
-			append("%s", tm->tm_hour < 12 ? "am" : "PM"); break;
-		case 'r':
-			recurse("%I:%M:%S %p"); break;
-		case 'R':
-			recurse("%H:%M"); break;
-		case 's':
-			append("%ld", _secs_since_epoch(tm)); break;
-		case 'S':
-			append("%02d", tm->tm_sec); break;
-		case 't':
-			append("\t"); break;
-		case 'T':
-			recurse("%H:%M:%S"); break;
-		case 'u':
-			append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday); break;
-		case 'U':
-			append("%02d", _sun_week_number(tm)); break;
-		case 'V':
-			append("%02d", _iso_week_number(tm)); break;
-		case 'w':
-			append("%d", tm->tm_wday); break;
-		case 'W':
-			append("%02d", _mon_week_number(tm)); break;
-		case 'x':
-			// TODO: locale-specific date format
-			recurse("%Y-%m-%d"); break;
-		case 'X':
-			// TODO: locale-specific time format
-			recurse("%H:%M:%S"); break;
-		case 'y':
-			append("%02d", tm->tm_year % 100); break;
-		case 'Y':
-			append("%d", 1900 + tm->tm_year); break;
-		case 'z':
-			// TODO: timezone
-			break;
-		case 'Z':
-			// TODO: timezone
-			break;
-		case '%':
-			append("%%");
-			break;
-		default:
-			/* Invalid specifier, print verbatim. */
-			while (*format != '%') {
-				format--;
-			}
-			append("%%");
-			break;
-		}
-		format++;
-	}
-	
-	#undef append
-	#undef recurse
-	
-	return maxsize - remaining;
-}
-
-/**
- * Get clock resolution. Only CLOCK_REALTIME is supported.
- *
- * @param clock_id Clock ID.
- * @param res Pointer to the variable where the resolution is to be written.
- * @return 0 on success, -1 with errno set on failure.
- */
-int posix_clock_getres(posix_clockid_t clock_id, struct posix_timespec *res)
-{
-	assert(res != NULL);
-
-	switch (clock_id) {
-		case CLOCK_REALTIME:
-			res->tv_sec = 0;
-			res->tv_nsec = 1000; /* Microsecond resolution. */
-			return 0;
-		default:
-			errno = EINVAL;
-			return -1;
-	}
-}
-
-/**
- * Get time. Only CLOCK_REALTIME is supported.
- * 
- * @param clock_id ID of the clock to query.
- * @param tp Pointer to the variable where the time is to be written.
- * @return 0 on success, -1 with errno on failure.
- */
-int posix_clock_gettime(posix_clockid_t clock_id, struct posix_timespec *tp)
-{
-	assert(tp != NULL);
-
-	switch (clock_id) {
-		case CLOCK_REALTIME:
-			;
-			struct timeval tv;
-			gettimeofday(&tv, NULL);
-			tp->tv_sec = tv.tv_sec;
-			tp->tv_nsec = tv.tv_usec * 1000;
-			return 0;
-		default:
-			errno = EINVAL;
-			return -1;
-	}
-}
-
-/**
- * Set time on a specified clock. As HelenOS doesn't support this yet,
- * this function always fails.
- * 
- * @param clock_id ID of the clock to set.
- * @param tp Time to set.
- * @return 0 on success, -1 with errno on failure.
- */
-int posix_clock_settime(posix_clockid_t clock_id,
-    const struct posix_timespec *tp)
-{
-	assert(tp != NULL);
-
-	switch (clock_id) {
-		case CLOCK_REALTIME:
-			// TODO: setting clock
-			// FIXME: HelenOS doesn't actually support hardware
-			//        clock yet
-			errno = EPERM;
-			return -1;
-		default:
-			errno = EINVAL;
-			return -1;
-	}
-}
-
-/**
- * Sleep on a specified clock.
- * 
- * @param clock_id ID of the clock to sleep on (only CLOCK_REALTIME supported).
- * @param flags Flags (none supported).
- * @param rqtp Sleep time.
- * @param rmtp Remaining time is written here if sleep is interrupted.
- * @return 0 on success, -1 with errno set on failure.
- */
-int posix_clock_nanosleep(posix_clockid_t clock_id, int flags,
-    const struct posix_timespec *rqtp, struct posix_timespec *rmtp)
-{
-	assert(rqtp != NULL);
-	assert(rmtp != NULL);
-
-	switch (clock_id) {
-		case CLOCK_REALTIME:
-			// TODO: interruptible sleep
-			if (rqtp->tv_sec != 0) {
-				sleep(rqtp->tv_sec);
-			}
-			if (rqtp->tv_nsec != 0) {
-				usleep(rqtp->tv_nsec / 1000);
-			}
-			return 0;
-		default:
-			errno = EINVAL;
-			return -1;
-	}
-}
-
-/**
- * Get CPU time used since the process invocation.
- *
- * @return Consumed CPU cycles by this process or -1 if not available.
- */
-posix_clock_t posix_clock(void)
-{
-	posix_clock_t total_cycles = -1;
-	stats_task_t *task_stats = stats_get_task(task_get_id());
-	if (task_stats) {
-		total_cycles = (posix_clock_t) (task_stats->kcycles + task_stats->ucycles);
-		free(task_stats);
-		task_stats = 0;
-	}
-
-	return total_cycles;
-}
-
-/** @}
- */
Index: pace/lib/posix/time.h
===================================================================
--- uspace/lib/posix/time.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,171 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * Copyright (c) 2011 Jiri Zarevucky
- * 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 libposix
- * @{
- */
-/** @file Time measurement support.
- */
-
-#ifndef POSIX_TIME_H_
-#define POSIX_TIME_H_
-
-#include "libc/time.h"
-#include "sys/types.h"
-
-#ifndef NULL
-	#define NULL  ((void *) 0)
-#endif
-
-#ifndef CLOCKS_PER_SEC
-	#define CLOCKS_PER_SEC (1000000L)
-#endif
-
-#ifndef __locale_t_defined
-	#define __locale_t_defined
-	typedef struct __posix_locale *posix_locale_t;
-	#ifndef LIBPOSIX_INTERNAL
-		#define locale_t posix_locale_t
-	#endif
-#endif
-
-#ifndef POSIX_SIGNAL_H_
-	struct posix_sigevent;
-	#ifndef LIBPOSIX_INTERNAL
-		#define sigevent posix_sigevent
-	#endif
-#endif
-
-#undef ASCTIME_BUF_LEN
-#define ASCTIME_BUF_LEN 26
-
-#undef CLOCK_REALTIME
-#define CLOCK_REALTIME ((posix_clockid_t) 0)
-
-struct posix_tm {
-	int tm_sec;         /* Seconds [0,60]. */
-	int tm_min;         /* Minutes [0,59]. */
-	int tm_hour;        /* Hour [0,23]. */
-	int tm_mday;        /* Day of month [1,31]. */
-	int tm_mon;         /* Month of year [0,11]. */
-	int tm_year;        /* Years since 1900. */
-	int tm_wday;        /* Day of week [0,6] (Sunday = 0). */
-	int tm_yday;        /* Day of year [0,365]. */
-	int tm_isdst;       /* Daylight Savings flag. */
-};
-
-struct posix_timespec {
-	time_t tv_sec; /* Seconds. */
-	long tv_nsec; /* Nanoseconds. */
-};
-
-struct posix_itimerspec {
-	struct posix_timespec it_interval; /* Timer period. */
-	struct posix_timespec it_value; /* Timer expiration. */
-};
-
-typedef struct __posix_timer *posix_timer_t;
-
-/* Timezones */
-extern int posix_daylight;
-extern long posix_timezone;
-extern char *posix_tzname[2];
-extern void posix_tzset(void);
-
-/* Elapsed Time */
-extern double posix_difftime(time_t time1, time_t time0);
-
-/* Broken-down Time */
-extern time_t posix_mktime(struct posix_tm *tm);
-extern struct posix_tm *posix_gmtime(const time_t *timer);
-extern struct posix_tm *posix_gmtime_r(const time_t *restrict timer,
-    struct posix_tm *restrict result);
-extern struct posix_tm *posix_localtime(const time_t *timer);
-extern struct posix_tm *posix_localtime_r(const time_t *restrict timer,
-    struct posix_tm *restrict result);
-
-/* Formatting Calendar Time */
-extern char *posix_asctime(const struct posix_tm *timeptr);
-extern char *posix_asctime_r(const struct posix_tm *restrict timeptr,
-    char *restrict buf);
-extern char *posix_ctime(const time_t *timer);
-extern char *posix_ctime_r(const time_t *timer, char *buf);
-extern size_t posix_strftime(char *restrict s, size_t maxsize,
-    const char *restrict format, const struct posix_tm *restrict tm);
-
-/* Clocks */
-extern int posix_clock_getres(posix_clockid_t clock_id,
-    struct posix_timespec *res);
-extern int posix_clock_gettime(posix_clockid_t clock_id,
-    struct posix_timespec *tp);
-extern int posix_clock_settime(posix_clockid_t clock_id,
-    const struct posix_timespec *tp); 
-extern int posix_clock_nanosleep(posix_clockid_t clock_id, int flags,
-    const struct posix_timespec *rqtp, struct posix_timespec *rmtp);
-
-/* CPU Time */
-extern posix_clock_t posix_clock(void);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define tm posix_tm
-	#define timespec posix_timespec
-	#define itimerspec posix_itimerspec
-	#define timer_t posix_timer_t
-
-	#define daylight posix_daylight
-	#define timezone posix_timezone
-	#define tzname posix_tzname
-	#define tzset posix_tzset
-
-	#define difftime posix_difftime
-
-	#define mktime posix_mktime
-	#define gmtime posix_gmtime
-	#define gmtime_r posix_gmtime_r
-	#define localtime posix_localtime
-	#define localtime_r posix_localtime_r
-
-	#define asctime posix_asctime
-	#define asctime_r posix_asctime_r
-	#define ctime posix_ctime
-	#define ctime_r posix_ctime_r
-	#define strftime posix_strftime
-
-	#define clock_getres posix_clock_getres
-	#define clock_gettime posix_clock_gettime
-	#define clock_settime posix_clock_settime
-	#define clock_nanosleep posix_clock_nanosleep
-
-	#define clock posix_clock
-#endif
-
-#endif  // POSIX_TIME_H_
-
-/** @}
- */
Index: pace/lib/posix/unistd.c
===================================================================
--- uspace/lib/posix/unistd.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,424 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Miscellaneous standard definitions.
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "internal/common.h"
-#include "unistd.h"
-
-#include "errno.h"
-#include "string.h"
-#include "fcntl.h"
-
-#include "libc/task.h"
-#include "libc/stats.h"
-#include "libc/malloc.h"
-
-/* Array of environment variable strings (NAME=VALUE). */
-char **posix_environ = NULL;
-char *posix_optarg;
-
-/**
- * Get current user name.
- *
- * @return User name (static) string or NULL if not found.
- */
-char *posix_getlogin(void)
-{
-	/* There is currently no support for user accounts in HelenOS. */
-	return (char *) "user";
-}
-
-/**
- * Get current user name.
- *
- * @param name Pointer to a user supplied buffer.
- * @param namesize Length of the buffer.
- * @return Zero on success, error code otherwise.
- */
-int posix_getlogin_r(char *name, size_t namesize)
-{
-	/* There is currently no support for user accounts in HelenOS. */
-	if (namesize >= 5) {
-		posix_strcpy(name, (char *) "user");
-		return 0;
-	} else {
-		errno = ERANGE;
-		return -1;
-	}
-}
-
-/**
- * Test whether open file descriptor is associated with a terminal.
- *
- * @param fd Open file descriptor to test.
- * @return Boolean result of the test.
- */
-int posix_isatty(int fd)
-{
-	// TODO
-	/* Always returns false, because there is no easy way to find
-	 * out under HelenOS. */
-	return 0;
-}
-
-/**
- * Get the pathname of the current working directory.
- *
- * @param buf Buffer into which the pathname shall be put.
- * @param size Size of the buffer.
- * @return Buffer pointer on success, NULL on failure.
- */
-char *posix_getcwd(char *buf, size_t size)
-{
-	/* Native getcwd() does not set any errno despite the fact that general
-	 * usage pattern of this function depends on it (caller is repeatedly
-	 * guessing the required size of the buffer by checking for ERANGE on
-	 * failure). */
-	if (size == 0) {
-		errno = EINVAL;
-		return NULL;
-	}
-	
-	/* Save the original value to comply with the "no modification on
-	 * success" semantics.
-	 */
-	int orig_errno = errno;
-	errno = EOK;
-	
-	char *ret = getcwd(buf, size);
-	if (ret == NULL) {
-		/* Check errno to avoid shadowing other possible errors. */
-		if (errno == EOK) {
-			errno = ERANGE;
-		}
-	} else {
-		/* Success, restore previous errno value. */
-		errno = orig_errno;
-	}
-	
-	return ret;
-}
-
-/**
- * Change the current working directory.
- *
- * @param path New working directory.
- */
-int posix_chdir(const char *path)
-{
-	return errnify(chdir, path);
-}
-
-/**
- * Determine the page size of the current run of the process.
- *
- * @return Page size of the process.
- */
-int posix_getpagesize(void)
-{
-	return getpagesize();
-}
-
-/**
- * Get the process ID of the calling process.
- *
- * @return Process ID.
- */
-posix_pid_t posix_getpid(void)
-{
-	return task_get_id();
-}
-
-/**
- * Get the real user ID of the calling process.
- *
- * @return User ID.
- */
-posix_uid_t posix_getuid(void)
-{
-	/* There is currently no support for user accounts in HelenOS. */
-	return 0;
-}
-
-/**
- * Get the real group ID of the calling process.
- * 
- * @return Group ID.
- */
-posix_gid_t posix_getgid(void)
-{
-	/* There is currently no support for user accounts in HelenOS. */
-	return 0;
-}
-
-/**
- * Close a file.
- *
- * @param fildes File descriptor of the opened file.
- * @return 0 on success, -1 on error.
- */
-int posix_close(int fildes)
-{
-	return errnify(close, fildes);
-}
-
-/**
- * Read from a file.
- *
- * @param fildes File descriptor of the opened file.
- * @param buf Buffer to which the read bytes shall be stored.
- * @param nbyte Upper limit on the number of read bytes.
- * @return Number of read bytes on success, -1 otherwise.
- */
-ssize_t posix_read(int fildes, void *buf, size_t nbyte)
-{
-	return errnify(read, fildes, buf, nbyte);
-}
-
-/**
- * Write to a file.
- *
- * @param fildes File descriptor of the opened file.
- * @param buf Buffer to write.
- * @param nbyte Size of the buffer.
- * @return Number of written bytes on success, -1 otherwise.
- */
-ssize_t posix_write(int fildes, const void *buf, size_t nbyte)
-{
-	return errnify(write, fildes, buf, nbyte);
-}
-
-/**
- * Requests outstanding data to be written to the underlying storage device.
- *
- * @param fildes File descriptor of the opened file.
- * @return Zero on success, -1 otherwise.
- */
-int posix_fsync(int fildes)
-{
-	return errnify(fsync, fildes);
-}
-
-/**
- * Truncate a file to a specified length.
- *
- * @param fildes File descriptor of the opened file.
- * @param length New length of the file.
- * @return Zero on success, -1 otherwise.
- */
-int posix_ftruncate(int fildes, posix_off_t length)
-{
-	return errnify(ftruncate, fildes, (aoff64_t) length);
-}
-
-/**
- * Remove a directory.
- *
- * @param path Directory pathname.
- * @return Zero on success, -1 otherwise.
- */
-int posix_rmdir(const char *path)
-{
-	return errnify(rmdir, path);
-}
-
-/**
- * Remove a link to a file.
- * 
- * @param path File pathname.
- * @return Zero on success, -1 otherwise.
- */
-int posix_unlink(const char *path)
-{
-	return errnify(unlink, path);
-}
-
-/**
- * Duplicate an open file descriptor.
- *
- * @param fildes File descriptor to be duplicated.
- * @return On success, new file descriptor for the same file, otherwise -1.
- */
-int posix_dup(int fildes)
-{
-	return posix_fcntl(fildes, F_DUPFD, 0);
-}
-
-/**
- * Duplicate an open file descriptor.
- * 
- * @param fildes File descriptor to be duplicated.
- * @param fildes2 File descriptor to be paired with the same file description
- *     as is paired fildes.
- * @return fildes2 on success, -1 otherwise.
- */
-int posix_dup2(int fildes, int fildes2)
-{
-	return errnify(dup2, fildes, fildes2);
-}
-
-/**
- * Determine accessibility of a file.
- *
- * @param path File to check accessibility for.
- * @param amode Either check for existence or intended access mode.
- * @return Zero on success, -1 otherwise.
- */
-int posix_access(const char *path, int amode)
-{
-	if (amode == F_OK || (amode & (X_OK | W_OK | R_OK))) {
-		/* HelenOS doesn't support permissions, permission checks
-		 * are equal to existence check.
-		 *
-		 * Check file existence by attempting to open it.
-		 */
-		int fd = open(path, O_RDONLY);
-		if (fd < 0) {
-			errno = -fd;
-			return -1;
-		}
-		close(fd);
-		return 0;
-	} else {
-		/* Invalid amode argument. */
-		errno = EINVAL;
-		return -1;
-	}
-}
-
-/**
- * Get configurable system variables.
- * 
- * @param name Variable name.
- * @return Variable value.
- */
-long posix_sysconf(int name)
-{
-	long clk_tck = 0;
-	size_t cpu_count = 0;
-	stats_cpu_t *cpu_stats = stats_get_cpus(&cpu_count);
-	if (cpu_stats && cpu_count > 0) {
-		clk_tck = ((long) cpu_stats[0].frequency_mhz) * 1000000L;
-	}
-	if (cpu_stats) {
-		free(cpu_stats);
-		cpu_stats = 0;
-	}
-
-	long phys_pages = 0;
-	long avphys_pages = 0;
-	stats_physmem_t *mem_stats = stats_get_physmem();
-	if (mem_stats) {
-		phys_pages = (long) (mem_stats->total / getpagesize());
-		avphys_pages = (long) (mem_stats->free / getpagesize());
-		free(mem_stats);
-		mem_stats = 0;
-	}
-
-	switch (name) {
-	case _SC_PHYS_PAGES:
-		return phys_pages;
-	case _SC_AVPHYS_PAGES:
-		return avphys_pages;
-	case _SC_PAGESIZE:
-		return getpagesize();
-	case _SC_CLK_TCK:
-		return clk_tck;
-	default:
-		errno = EINVAL;
-		return -1;
-	}
-}
-
-/**
- * 
- * @param path
- * @param name
- * @return
- */
-long posix_pathconf(const char *path, int name)
-{
-	// TODO: low priority, just a compile-time dependency of binutils
-	not_implemented();
-}
-
-/**
- * 
- * @return
- */
-posix_pid_t posix_fork(void)
-{
-	// TODO: low priority, just a compile-time dependency of binutils
-	not_implemented();
-}
-
-/**
- * 
- * @param path
- * @param argv
- * @return
- */
-int posix_execv(const char *path, char *const argv[])
-{
-	// TODO: low priority, just a compile-time dependency of binutils
-	not_implemented();
-}
-
-/**
- * 
- * @param file
- * @param argv
- * @return
- */
-int posix_execvp(const char *file, char *const argv[])
-{
-	// TODO: low priority, just a compile-time dependency of binutils
-	not_implemented();
-}
-
-/**
- * 
- * @param fildes
- * @return
- */
-int posix_pipe(int fildes[2])
-{
-	// TODO: low priority, just a compile-time dependency of binutils
-	not_implemented();
-}
-
-/** @}
- */
Index: pace/lib/posix/unistd.h
===================================================================
--- uspace/lib/posix/unistd.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,192 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Zarevucky
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file Miscellaneous standard definitions.
- */
-
-#ifndef POSIX_UNISTD_H_
-#define POSIX_UNISTD_H_
-
-#include "libc/unistd.h"
-#include "sys/types.h"
-
-/* Process Termination */
-#define _exit exit
-
-extern char *posix_optarg;
-extern int optind, opterr, optopt;
-extern int posix_getopt(int, char * const [], const char *);
-
-/* Environment */
-extern char **posix_environ;
-
-/* Login Information */
-extern char *posix_getlogin(void);
-extern int posix_getlogin_r(char *name, size_t namesize);
-
-/* Identifying Terminals */
-extern int posix_isatty(int fd);
-
-/* Working Directory */
-extern char *posix_getcwd(char *buf, size_t size);
-extern int posix_chdir(const char *path);
-
-/* Query Memory Parameters */
-extern int posix_getpagesize(void);
-
-/* Process Identification */
-extern posix_pid_t posix_getpid(void);
-extern posix_uid_t posix_getuid(void);
-extern posix_gid_t posix_getgid(void);
-
-/* File Manipulation */
-extern int posix_close(int fildes);
-extern ssize_t posix_read(int fildes, void *buf, size_t nbyte);
-extern ssize_t posix_write(int fildes, const void *buf, size_t nbyte);
-extern int posix_fsync(int fildes);
-extern int posix_ftruncate(int fildes, posix_off_t length);
-extern int posix_rmdir(const char *path);
-extern int posix_unlink(const char *path);
-extern int posix_dup(int fildes);
-extern int posix_dup2(int fildes, int fildes2);
-
-/* Standard Streams */
-#undef STDIN_FILENO
-#define STDIN_FILENO (fileno(stdin))
-#undef STDOUT_FILENO
-#define STDOUT_FILENO (fileno(stdout))
-#undef STDERR_FILENO
-#define STDERR_FILENO (fileno(stderr))
-
-/* File Accessibility */
-#undef F_OK
-#undef X_OK
-#undef W_OK
-#undef R_OK
-#define	F_OK 0 /* Test for existence. */
-#define	X_OK 1 /* Test for execute permission. */
-#define	W_OK 2 /* Test for write permission. */
-#define	R_OK 4 /* Test for read permission. */
-extern int posix_access(const char *path, int amode);
-
-/* System Parameters */
-enum {
-	_SC_PHYS_PAGES,
-	_SC_AVPHYS_PAGES,
-	_SC_PAGESIZE,
-	_SC_CLK_TCK
-};
-extern long posix_sysconf(int name);
-
-/* Path Configuration Parameters */
-enum {
-	_PC_2_SYMLINKS,
-	_PC_ALLOC_SIZE_MIN,
-	_PC_ASYNC_IO,
-	_PC_CHOWN_RESTRICTED,
-	_PC_FILESIZEBITS,
-	_PC_LINK_MAX,
-	_PC_MAX_CANON,
-	_PC_MAX_INPUT,
-	_PC_NAME_MAX,
-	_PC_NO_TRUNC,
-	_PC_PATH_MAX,
-	_PC_PIPE_BUF,
-	_PC_PRIO_IO,
-	_PC_REC_INCR_XFER_SIZE,
-	_PC_REC_MIN_XFER_SIZE,
-	_PC_REC_XFER_ALIGN,
-	_PC_SYMLINK_MAX,
-	_PC_SYNC_IO,
-	_PC_VDISABLE
-};
-extern long posix_pathconf(const char *path, int name);
-
-/* Creating a Process */
-extern posix_pid_t posix_fork(void);
-
-/* Executing a File */
-extern int posix_execv(const char *path, char *const argv[]);
-extern int posix_execvp(const char *file, char *const argv[]);
-
-/* Creating a Pipe */
-extern int posix_pipe(int fildes[2]);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define getopt posix_getopt
-	#define optarg posix_optarg
-
-	#define environ posix_environ
-
-	#define getlogin posix_getlogin
-	#define getlogin_r posix_getlogin_r
-
-	#define getcwd posix_getcwd
-	#define chdir posix_chdir
-
-	#define isatty posix_isatty
-
-	#undef getpagesize
-	#define getpagesize posix_getpagesize
-
-	#define getpid posix_getpid
-	#define getuid posix_getuid
-	#define getgid posix_getgid
-
-	#define close posix_close
-	#define read posix_read
-	#define write posix_write
-	#define fsync posix_fsync
-	#define ftruncate posix_ftruncate
-	#define rmdir posix_rmdir
-	#define unlink posix_unlink
-	#define dup posix_dup
-	#define dup2 posix_dup2
-
-	#define access posix_access
-
-	#define sysconf posix_sysconf
-
-	#define pathconf posix_pathconf
-
-	#define fork posix_fork
-
-	#define execv posix_execv
-	#define execvp posix_execvp
-
-	#define pipe posix_pipe
-#endif
-
-#endif /* POSIX_UNISTD_H_ */
-
-/** @}
- */
Index: uspace/lib/softfloat/Makefile
===================================================================
--- uspace/lib/softfloat/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/softfloat/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -29,17 +29,16 @@
 
 USPACE_PREFIX = ../..
-EXTRA_CFLAGS = -Iinclude
 LIBRARY = libsoftfloat
 
 SOURCES = \
-	generic/add.c \
-	generic/common.c \
-	generic/comparison.c \
-	generic/conversion.c \
-	generic/div.c \
-	generic/mul.c \
-	generic/other.c \
-	generic/softfloat.c \
-	generic/sub.c
+	softfloat.c \
+	common.c \
+	add.c \
+	sub.c \
+	div.c \
+	mul.c \
+	comparison.c \
+	conversion.c \
+	other.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/softfloat/add.c
===================================================================
--- uspace/lib/softfloat/add.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/add.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Addition functions.
+ */
+
+#include "sftypes.h"
+#include "add.h"
+#include "comparison.h"
+#include "common.h"
+
+/** Add two single-precision floats with the same sign.
+ *
+ * @param a First input operand.
+ * @param b Second input operand.
+ * @return Result of addition.
+ */
+float32 add_float32(float32 a, float32 b)
+{
+	int expdiff;
+	uint32_t exp1, exp2, frac1, frac2;
+	
+	expdiff = a.parts.exp - b.parts.exp;
+	if (expdiff < 0) {
+		if (is_float32_nan(b)) {
+			/* TODO: fix SigNaN */
+			if (is_float32_signan(b)) {
+			}
+
+			return b;
+		}
+		
+		if (b.parts.exp == FLOAT32_MAX_EXPONENT) { 
+			return b;
+		}
+		
+		frac1 = b.parts.fraction;
+		exp1 = b.parts.exp;
+		frac2 = a.parts.fraction;
+		exp2 = a.parts.exp;
+		expdiff *= -1;
+	} else {
+		if ((is_float32_nan(a)) || (is_float32_nan(b))) {
+			/* TODO: fix SigNaN */
+			if (is_float32_signan(a) || is_float32_signan(b)) {
+			}
+			return (is_float32_nan(a) ? a : b);
+		}
+		
+		if (a.parts.exp == FLOAT32_MAX_EXPONENT) { 
+			return a;
+		}
+		
+		frac1 = a.parts.fraction;
+		exp1 = a.parts.exp;
+		frac2 = b.parts.fraction;
+		exp2 = b.parts.exp;
+	}
+	
+	if (exp1 == 0) {
+		/* both are denormalized */
+		frac1 += frac2;
+		if (frac1 & FLOAT32_HIDDEN_BIT_MASK) {
+			/* result is not denormalized */
+			a.parts.exp = 1;
+		}
+		a.parts.fraction = frac1;
+		return a;
+	}
+	
+	frac1 |= FLOAT32_HIDDEN_BIT_MASK; /* add hidden bit */
+
+	if (exp2 == 0) {
+		/* second operand is denormalized */
+		--expdiff;
+	} else {
+		/* add hidden bit to second operand */
+		frac2 |= FLOAT32_HIDDEN_BIT_MASK; 
+	}
+	
+	/* create some space for rounding */
+	frac1 <<= 6;
+	frac2 <<= 6;
+	
+	if (expdiff < (FLOAT32_FRACTION_SIZE + 2)) {
+		frac2 >>= expdiff;
+		frac1 += frac2;
+	} else {
+		a.parts.exp = exp1;
+		a.parts.fraction = (frac1 >> 6) & (~(FLOAT32_HIDDEN_BIT_MASK));
+		return a;
+	}
+	
+	if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7)) {
+		++exp1;
+		frac1 >>= 1;
+	}
+	
+	/* rounding - if first bit after fraction is set then round up */
+	frac1 += (0x1 << 5);
+	
+	if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7)) { 
+		/* rounding overflow */
+		++exp1;
+		frac1 >>= 1;
+	}
+	
+	if ((exp1 == FLOAT32_MAX_EXPONENT) || (exp2 > exp1)) {
+		/* overflow - set infinity as result */
+		a.parts.exp = FLOAT32_MAX_EXPONENT;
+		a.parts.fraction = 0;
+		return a;
+	}
+	
+	a.parts.exp = exp1;
+	
+	/* Clear hidden bit and shift */
+	a.parts.fraction = ((frac1 >> 6) & (~FLOAT32_HIDDEN_BIT_MASK)); 
+	return a;
+}
+
+/** Add two double-precision floats with the same sign.
+ *
+ * @param a First input operand.
+ * @param b Second input operand.
+ * @return Result of addition.
+ */
+float64 add_float64(float64 a, float64 b)
+{
+	int expdiff;
+	uint32_t exp1, exp2;
+	uint64_t frac1, frac2;
+	
+	expdiff = ((int) a.parts.exp) - b.parts.exp;
+	if (expdiff < 0) {
+		if (is_float64_nan(b)) {
+			/* TODO: fix SigNaN */
+			if (is_float64_signan(b)) {
+			}
+
+			return b;
+		}
+		
+		/* b is infinity and a not */
+		if (b.parts.exp == FLOAT64_MAX_EXPONENT) {
+			return b;
+		}
+		
+		frac1 = b.parts.fraction;
+		exp1 = b.parts.exp;
+		frac2 = a.parts.fraction;
+		exp2 = a.parts.exp;
+		expdiff *= -1;
+	} else {
+		if (is_float64_nan(a)) {
+			/* TODO: fix SigNaN */
+			if (is_float64_signan(a) || is_float64_signan(b)) {
+			}
+			return a;
+		}
+		
+		/* a is infinity and b not */
+		if (a.parts.exp == FLOAT64_MAX_EXPONENT) { 
+			return a;
+		}
+		
+		frac1 = a.parts.fraction;
+		exp1 = a.parts.exp;
+		frac2 = b.parts.fraction;
+		exp2 = b.parts.exp;
+	}
+	
+	if (exp1 == 0) {
+		/* both are denormalized */
+		frac1 += frac2;
+		if (frac1 & FLOAT64_HIDDEN_BIT_MASK) { 
+			/* result is not denormalized */
+			a.parts.exp = 1;
+		}
+		a.parts.fraction = frac1;
+		return a;
+	}
+	
+	/* add hidden bit - frac1 is sure not denormalized */
+	frac1 |= FLOAT64_HIDDEN_BIT_MASK;
+
+	/* second operand ... */
+	if (exp2 == 0) {
+		/* ... is denormalized */
+		--expdiff;	
+	} else {
+		/* is not denormalized */
+		frac2 |= FLOAT64_HIDDEN_BIT_MASK;
+	}
+	
+	/* create some space for rounding */
+	frac1 <<= 6;
+	frac2 <<= 6;
+	
+	if (expdiff < (FLOAT64_FRACTION_SIZE + 2)) {
+		frac2 >>= expdiff;
+		frac1 += frac2;
+	} else {
+		a.parts.exp = exp1;
+		a.parts.fraction = (frac1 >> 6) & (~(FLOAT64_HIDDEN_BIT_MASK));
+		return a;
+	}
+	
+	if (frac1 & (FLOAT64_HIDDEN_BIT_MASK << 7)) {
+		++exp1;
+		frac1 >>= 1;
+	}
+	
+	/* rounding - if first bit after fraction is set then round up */
+	frac1 += (0x1 << 5); 
+	
+	if (frac1 & (FLOAT64_HIDDEN_BIT_MASK << 7)) { 
+		/* rounding overflow */
+		++exp1;
+		frac1 >>= 1;
+	}
+	
+	if ((exp1 == FLOAT64_MAX_EXPONENT) || (exp2 > exp1)) {
+		/* overflow - set infinity as result */
+		a.parts.exp = FLOAT64_MAX_EXPONENT;
+		a.parts.fraction = 0;
+		return a;
+	}
+	
+	a.parts.exp = exp1;
+	/* Clear hidden bit and shift */
+	a.parts.fraction = ((frac1 >> 6) & (~FLOAT64_HIDDEN_BIT_MASK));
+	return a;
+}
+
+/** Add two quadruple-precision floats with the same sign.
+ *
+ * @param a First input operand.
+ * @param b Second input operand.
+ * @return Result of addition.
+ */
+float128 add_float128(float128 a, float128 b)
+{
+	int expdiff;
+	uint32_t exp1, exp2;
+	uint64_t frac1_hi, frac1_lo, frac2_hi, frac2_lo, tmp_hi, tmp_lo;
+
+	expdiff = ((int) a.parts.exp) - b.parts.exp;
+	if (expdiff < 0) {
+		if (is_float128_nan(b)) {
+			/* TODO: fix SigNaN */
+			if (is_float128_signan(b)) {
+			}
+
+			return b;
+		}
+
+		/* b is infinity and a not */
+		if (b.parts.exp == FLOAT128_MAX_EXPONENT) {
+			return b;
+		}
+
+		frac1_hi = b.parts.frac_hi;
+		frac1_lo = b.parts.frac_lo;
+		exp1 = b.parts.exp;
+		frac2_hi = a.parts.frac_hi;
+		frac2_lo = a.parts.frac_lo;
+		exp2 = a.parts.exp;
+		expdiff *= -1;
+	} else {
+		if (is_float128_nan(a)) {
+			/* TODO: fix SigNaN */
+			if (is_float128_signan(a) || is_float128_signan(b)) {
+			}
+			return a;
+		}
+
+		/* a is infinity and b not */
+		if (a.parts.exp == FLOAT128_MAX_EXPONENT) {
+			return a;
+		}
+
+		frac1_hi = a.parts.frac_hi;
+		frac1_lo = a.parts.frac_lo;
+		exp1 = a.parts.exp;
+		frac2_hi = b.parts.frac_hi;
+		frac2_lo = b.parts.frac_lo;
+		exp2 = b.parts.exp;
+	}
+
+	if (exp1 == 0) {
+		/* both are denormalized */
+		add128(frac1_hi, frac1_lo, frac2_hi, frac2_lo, &frac1_hi, &frac1_lo);
+
+		and128(frac1_hi, frac1_lo,
+		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+		    &tmp_hi, &tmp_lo);
+		if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
+			/* result is not denormalized */
+			a.parts.exp = 1;
+		}
+
+		a.parts.frac_hi = frac1_hi;
+		a.parts.frac_lo = frac1_lo;
+		return a;
+	}
+
+	/* add hidden bit - frac1 is sure not denormalized */
+	or128(frac1_hi, frac1_lo,
+	    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+	    &frac1_hi, &frac1_lo);
+
+	/* second operand ... */
+	if (exp2 == 0) {
+		/* ... is denormalized */
+		--expdiff;
+	} else {
+		/* is not denormalized */
+		or128(frac2_hi, frac2_lo,
+		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+		    &frac2_hi, &frac2_lo);
+	}
+
+	/* create some space for rounding */
+	lshift128(frac1_hi, frac1_lo, 6, &frac1_hi, &frac1_lo);
+	lshift128(frac2_hi, frac2_lo, 6, &frac2_hi, &frac2_lo);
+
+	if (expdiff < (FLOAT128_FRACTION_SIZE + 2)) {
+		rshift128(frac2_hi, frac2_lo, expdiff, &frac2_hi, &frac2_lo);
+		add128(frac1_hi, frac1_lo, frac2_hi, frac2_lo, &frac1_hi, &frac1_lo);
+	} else {
+		a.parts.exp = exp1;
+
+		rshift128(frac1_hi, frac1_lo, 6, &frac1_hi, &frac1_lo);
+		not128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+		    &tmp_hi, &tmp_lo);
+		and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+
+		a.parts.frac_hi = tmp_hi;
+		a.parts.frac_lo = tmp_lo;
+		return a;
+	}
+
+	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 7,
+	    &tmp_hi, &tmp_lo);
+	and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+	if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
+		++exp1;
+		rshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
+	}
+
+	/* rounding - if first bit after fraction is set then round up */
+	add128(frac1_hi, frac1_lo, 0x0ll, 0x1ll << 5, &frac1_hi, &frac1_lo);
+
+	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 7,
+	   &tmp_hi, &tmp_lo);
+	and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+	if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
+		/* rounding overflow */
+		++exp1;
+		rshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
+	}
+
+	if ((exp1 == FLOAT128_MAX_EXPONENT ) || (exp2 > exp1)) {
+		/* overflow - set infinity as result */
+		a.parts.exp = FLOAT64_MAX_EXPONENT;
+		a.parts.frac_hi = 0;
+		a.parts.frac_lo = 0;
+		return a;
+	}
+
+	a.parts.exp = exp1;
+	
+	/* Clear hidden bit and shift */
+	rshift128(frac1_hi, frac1_lo, 6, &frac1_hi, &frac1_lo);
+	not128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+	    &tmp_hi, &tmp_lo);
+	and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+
+	a.parts.frac_hi = tmp_hi;
+	a.parts.frac_lo = tmp_lo;
+
+	return a;
+}
+
+/** @}
+ */
Index: uspace/lib/softfloat/add.h
===================================================================
--- uspace/lib/softfloat/add.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/add.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Addition functions.
+ */
+
+#ifndef __ADD_H__
+#define __ADD_H__
+
+extern float32 add_float32(float32, float32);
+extern float64 add_float64(float64, float64);
+extern float96 add_float96(float96, float96);
+extern float128 add_float128(float128, float128);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softfloat/common.c
===================================================================
--- uspace/lib/softfloat/common.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/common.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,690 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Common helper operations.
+ */
+
+#include "sftypes.h"
+#include "common.h"
+
+/* Table for fast leading zeroes counting. */
+char zeroTable[256] = {
+	8, 7, 7, 6, 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, \
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, \
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/**
+ * Take fraction shifted by 10 bits to the left, round it, normalize it
+ * and detect exceptions
+ * 
+ * @param cexp Exponent with bias.
+ * @param cfrac Fraction shifted 10 bits to the left with added hidden bit.
+ * @param sign Resulting sign.
+ * @return Finished double-precision float.
+ */
+float64 finish_float64(int32_t cexp, uint64_t cfrac, char sign)
+{
+	float64 result;
+
+	result.parts.sign = sign;
+
+	/* find first nonzero digit and shift result and detect possibly underflow */
+	while ((cexp > 0) && (cfrac) &&
+	    (!(cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1))))) {
+		cexp--;
+		cfrac <<= 1;
+		/* TODO: fix underflow */
+	}
+	
+	if ((cexp < 0) || (cexp == 0 &&
+	    (!(cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1)))))) {
+		/* FIXME: underflow */
+		result.parts.exp = 0;
+		if ((cexp + FLOAT64_FRACTION_SIZE + 1) < 0) { /* +1 is place for rounding */
+			result.parts.fraction = 0;
+			return result;
+		}
+		
+		while (cexp < 0) {
+			cexp++;
+			cfrac >>= 1;
+		}
+	
+		cfrac += (0x1 << (64 - FLOAT64_FRACTION_SIZE - 3)); 
+		
+		if (!(cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1)))) {
+			result.parts.fraction =
+			    ((cfrac >> (64 - FLOAT64_FRACTION_SIZE - 2)) & (~FLOAT64_HIDDEN_BIT_MASK));
+			return result;
+		}	
+	} else {
+		cfrac += (0x1 << (64 - FLOAT64_FRACTION_SIZE - 3)); 
+	}
+	
+	++cexp;
+
+	if (cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1))) {
+		++cexp;
+		cfrac >>= 1;
+	}
+
+	/* check overflow */
+	if (cexp >= FLOAT64_MAX_EXPONENT) {
+		/* FIXME: overflow, return infinity */
+		result.parts.exp = FLOAT64_MAX_EXPONENT;
+		result.parts.fraction = 0;
+		return result;
+	}
+
+	result.parts.exp = (uint32_t) cexp;
+	
+	result.parts.fraction = 
+	    ((cfrac >> (64 - FLOAT64_FRACTION_SIZE - 2)) & (~FLOAT64_HIDDEN_BIT_MASK));
+	
+	return result;	
+}
+
+/**
+ * Take fraction, round it, normalize it and detect exceptions
+ * 
+ * @param cexp Exponent with bias.
+ * @param cfrac_hi High part of the fraction shifted 14 bits to the left
+ *     with added hidden bit.
+ * @param cfrac_lo Low part of the fraction shifted 14 bits to the left
+ *     with added hidden bit.
+ * @param sign Resulting sign.
+ * @param shift_out Bits right-shifted out from fraction by the caller.
+ * @return Finished quadruple-precision float.
+ */
+float128 finish_float128(int32_t cexp, uint64_t cfrac_hi, uint64_t cfrac_lo, 
+    char sign, uint64_t shift_out)
+{
+	float128 result;
+	uint64_t tmp_hi, tmp_lo;
+
+	result.parts.sign = sign;
+
+	/* find first nonzero digit and shift result and detect possibly underflow */
+	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+	    1, &tmp_hi, &tmp_lo);
+	and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+	while ((cexp > 0) && (lt128(0x0ll, 0x0ll, cfrac_hi, cfrac_lo)) &&
+	    (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo))) {
+		cexp--;
+		lshift128(cfrac_hi, cfrac_lo, 1, &cfrac_hi, &cfrac_lo);
+		/* TODO: fix underflow */
+
+		lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+		    1, &tmp_hi, &tmp_lo);
+		and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+	}
+
+	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+	    1, &tmp_hi, &tmp_lo);
+	and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+	if ((cexp < 0) || (cexp == 0 &&
+	    (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)))) {
+		/* FIXME: underflow */
+		result.parts.exp = 0;
+		if ((cexp + FLOAT128_FRACTION_SIZE + 1) < 0) { /* +1 is place for rounding */
+			result.parts.frac_hi = 0x0ll;
+			result.parts.frac_lo = 0x0ll;
+			return result;
+		}
+
+		while (cexp < 0) {
+			cexp++;
+			rshift128(cfrac_hi, cfrac_lo, 1, &cfrac_hi, &cfrac_lo);
+		}
+
+		if (shift_out & (0x1ull < 64)) {
+			add128(cfrac_hi, cfrac_lo, 0x0ll, 0x1ll, &cfrac_hi, &cfrac_lo);
+		}
+
+		lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+		    1, &tmp_hi, &tmp_lo);
+		and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+		if (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
+			not128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+			    &tmp_hi, &tmp_lo);
+			and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+			result.parts.frac_hi = tmp_hi;
+			result.parts.frac_lo = tmp_lo;
+			return result;
+		}
+	} else {
+		if (shift_out & (0x1ull < 64)) {
+			add128(cfrac_hi, cfrac_lo, 0x0ll, 0x1ll, &cfrac_hi, &cfrac_lo);
+		}
+	}
+
+	++cexp;
+
+	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+	    1, &tmp_hi, &tmp_lo);
+	and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+	if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
+		++cexp;
+		rshift128(cfrac_hi, cfrac_lo, 1, &cfrac_hi, &cfrac_lo);
+	}
+
+	/* check overflow */
+	if (cexp >= FLOAT128_MAX_EXPONENT) {
+		/* FIXME: overflow, return infinity */
+		result.parts.exp = FLOAT128_MAX_EXPONENT;
+		result.parts.frac_hi = 0x0ll;
+		result.parts.frac_lo = 0x0ll;
+		return result;
+	}
+
+	result.parts.exp = (uint32_t) cexp;
+
+	not128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+	    &tmp_hi, &tmp_lo);
+	and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+	result.parts.frac_hi = tmp_hi;
+	result.parts.frac_lo = tmp_lo;
+
+	return result;	
+}
+
+/**
+ * Counts leading zeroes in byte.
+ *
+ * @param i Byte for which to count leading zeroes.
+ * @return Number of detected leading zeroes.
+ */
+int count_zeroes8(uint8_t i)
+{
+	return zeroTable[i];
+}
+
+/** 
+ * Counts leading zeroes in 32bit unsigned integer.
+ *
+ * @param i Integer for which to count leading zeroes.
+ * @return Number of detected leading zeroes.
+ */
+int count_zeroes32(uint32_t i)
+{
+	int j;
+	for (j = 0; j < 32; j += 8) {
+		if (i & (0xFF << (24 - j))) {
+			return (j + count_zeroes8(i >> (24 - j)));
+		}
+	}
+
+	return 32;
+}
+
+/**
+ * Counts leading zeroes in 64bit unsigned integer.
+ *
+ * @param i Integer for which to count leading zeroes.
+ * @return Number of detected leading zeroes.
+ */
+int count_zeroes64(uint64_t i)
+{
+	int j;
+	for (j = 0; j < 64; j += 8) {
+		if (i & (0xFFll << (56 - j))) {
+			return (j + count_zeroes8(i >> (56 - j)));
+		}
+	}
+
+	return 64;
+}
+
+/**
+ * Round and normalize number expressed by exponent and fraction with
+ * first bit (equal to hidden bit) at 30th bit.
+ *
+ * @param exp Exponent part.
+ * @param fraction Fraction with hidden bit shifted to 30th bit.
+ */
+void round_float32(int32_t *exp, uint32_t *fraction)
+{
+	/* rounding - if first bit after fraction is set then round up */
+	(*fraction) += (0x1 << (32 - FLOAT32_FRACTION_SIZE - 3));
+	
+	if ((*fraction) & 
+	    (FLOAT32_HIDDEN_BIT_MASK << (32 - FLOAT32_FRACTION_SIZE - 1))) {
+		/* rounding overflow */
+		++(*exp);
+		(*fraction) >>= 1;
+	}
+	
+	if (((*exp) >= FLOAT32_MAX_EXPONENT) || ((*exp) < 0)) {
+		/* overflow - set infinity as result */
+		(*exp) = FLOAT32_MAX_EXPONENT;
+		(*fraction) = 0;
+	}
+}
+
+/**
+ * Round and normalize number expressed by exponent and fraction with
+ * first bit (equal to hidden bit) at 62nd bit.
+ *
+ * @param exp Exponent part.
+ * @param fraction Fraction with hidden bit shifted to 62nd bit.
+ */
+void round_float64(int32_t *exp, uint64_t *fraction)
+{
+	/* rounding - if first bit after fraction is set then round up */
+	(*fraction) += (0x1 << (64 - FLOAT64_FRACTION_SIZE - 3));
+	
+	if ((*fraction) & 
+	    (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 3))) {
+		/* rounding overflow */
+		++(*exp);
+		(*fraction) >>= 1;
+	}
+	
+	if (((*exp) >= FLOAT64_MAX_EXPONENT) || ((*exp) < 0)) {
+		/* overflow - set infinity as result */
+		(*exp) = FLOAT64_MAX_EXPONENT;
+		(*fraction) = 0;
+	}
+}
+
+/**
+ * Round and normalize number expressed by exponent and fraction with
+ * first bit (equal to hidden bit) at 126th bit.
+ *
+ * @param exp Exponent part.
+ * @param frac_hi High part of fraction part with hidden bit shifted to 126th bit.
+ * @param frac_lo Low part of fraction part with hidden bit shifted to 126th bit.
+ */
+void round_float128(int32_t *exp, uint64_t *frac_hi, uint64_t *frac_lo)
+{
+	uint64_t tmp_hi, tmp_lo;
+
+	/* rounding - if first bit after fraction is set then round up */
+	lshift128(0x0ll, 0x1ll, (128 - FLOAT128_FRACTION_SIZE - 3), &tmp_hi, &tmp_lo);
+	add128(*frac_hi, *frac_lo, tmp_hi, tmp_lo, frac_hi, frac_lo);
+
+	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+	    (128 - FLOAT128_FRACTION_SIZE - 3), &tmp_hi, &tmp_lo);
+	and128(*frac_hi, *frac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+	if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
+		/* rounding overflow */
+		++(*exp);
+		rshift128(*frac_hi, *frac_lo, 1, frac_hi, frac_lo);
+	}
+
+	if (((*exp) >= FLOAT128_MAX_EXPONENT) || ((*exp) < 0)) {
+		/* overflow - set infinity as result */
+		(*exp) = FLOAT128_MAX_EXPONENT;
+		(*frac_hi) = 0;
+		(*frac_lo) = 0;
+	}
+}
+
+/**
+ * Logical shift left on the 128-bit operand.
+ *
+ * @param a_hi High part of the input operand.
+ * @param a_lo Low part of the input operand.
+ * @param shift Number of bits by witch to shift.
+ * @param r_hi Address to store high part of the result.
+ * @param r_lo Address to store low part of the result.
+ */
+void lshift128(
+    uint64_t a_hi, uint64_t a_lo, int shift,
+    uint64_t *r_hi, uint64_t *r_lo)
+{
+	if (shift <= 0) {
+		/* do nothing */
+	} else if (shift >= 128) {
+		a_hi = 0;
+		a_lo = 0;
+	} else if (shift >= 64) {
+		a_hi = a_lo << (shift - 64);
+		a_lo = 0;
+	} else {
+		a_hi <<= shift;
+		a_hi |= a_lo >> (64 - shift);
+		a_lo <<= shift;
+	}
+
+	*r_hi = a_hi;
+	*r_lo = a_lo;
+}
+
+/**
+ * Logical shift right on the 128-bit operand.
+ *
+ * @param a_hi High part of the input operand.
+ * @param a_lo Low part of the input operand.
+ * @param shift Number of bits by witch to shift.
+ * @param r_hi Address to store high part of the result.
+ * @param r_lo Address to store low part of the result.
+ */
+void rshift128(
+    uint64_t a_hi, uint64_t a_lo, int shift,
+    uint64_t *r_hi, uint64_t *r_lo)
+{
+	if (shift <= 0) {
+		/* do nothing */
+	} else 	if (shift >= 128) {
+		a_hi = 0;
+		a_lo = 0;
+	} else if (shift >= 64) {
+		a_lo = a_hi >> (shift - 64);
+		a_hi = 0;
+	} else {
+		a_lo >>= shift;
+		a_lo |= a_hi << (64 - shift);
+		a_hi >>= shift;
+	}
+
+	*r_hi = a_hi;
+	*r_lo = a_lo;
+}
+
+/**
+ * Bitwise AND on 128-bit operands.
+ *
+ * @param a_hi High part of the first input operand.
+ * @param a_lo Low part of the first input operand.
+ * @param b_hi High part of the second input operand.
+ * @param b_lo Low part of the second input operand.
+ * @param r_hi Address to store high part of the result.
+ * @param r_lo Address to store low part of the result.
+ */
+void and128(
+    uint64_t a_hi, uint64_t a_lo,
+    uint64_t b_hi, uint64_t b_lo,
+    uint64_t *r_hi, uint64_t *r_lo)
+{
+	*r_hi = a_hi & b_hi;
+	*r_lo = a_lo & b_lo;
+}
+
+/**
+ * Bitwise inclusive OR on 128-bit operands.
+ *
+ * @param a_hi High part of the first input operand.
+ * @param a_lo Low part of the first input operand.
+ * @param b_hi High part of the second input operand.
+ * @param b_lo Low part of the second input operand.
+ * @param r_hi Address to store high part of the result.
+ * @param r_lo Address to store low part of the result.
+ */
+void or128(
+    uint64_t a_hi, uint64_t a_lo,
+    uint64_t b_hi, uint64_t b_lo,
+    uint64_t *r_hi, uint64_t *r_lo)
+{
+	*r_hi = a_hi | b_hi;
+	*r_lo = a_lo | b_lo;
+}
+
+/**
+ * Bitwise exclusive OR on 128-bit operands.
+ *
+ * @param a_hi High part of the first input operand.
+ * @param a_lo Low part of the first input operand.
+ * @param b_hi High part of the second input operand.
+ * @param b_lo Low part of the second input operand.
+ * @param r_hi Address to store high part of the result.
+ * @param r_lo Address to store low part of the result.
+ */
+void xor128(
+    uint64_t a_hi, uint64_t a_lo,
+    uint64_t b_hi, uint64_t b_lo,
+    uint64_t *r_hi, uint64_t *r_lo)
+{
+	*r_hi = a_hi ^ b_hi;
+	*r_lo = a_lo ^ b_lo;
+}
+
+/**
+ * Bitwise NOT on the 128-bit operand.
+ *
+ * @param a_hi High part of the input operand.
+ * @param a_lo Low part of the input operand.
+ * @param r_hi Address to store high part of the result.
+ * @param r_lo Address to store low part of the result.
+ */
+void not128(
+    uint64_t a_hi, uint64_t a_lo,
+	uint64_t *r_hi, uint64_t *r_lo)
+{
+	*r_hi = ~a_hi;
+	*r_lo = ~a_lo;
+}
+
+/**
+ * Equality comparison of 128-bit operands.
+ *
+ * @param a_hi High part of the first input operand.
+ * @param a_lo Low part of the first input operand.
+ * @param b_hi High part of the second input operand.
+ * @param b_lo Low part of the second input operand.
+ * @return 1 if operands are equal, 0 otherwise.
+ */
+int eq128(uint64_t a_hi, uint64_t a_lo, uint64_t b_hi, uint64_t b_lo)
+{
+	return (a_hi == b_hi) && (a_lo == b_lo);
+}
+
+/**
+ * Lower-or-equal comparison of 128-bit operands.
+ *
+ * @param a_hi High part of the first input operand.
+ * @param a_lo Low part of the first input operand.
+ * @param b_hi High part of the second input operand.
+ * @param b_lo Low part of the second input operand.
+ * @return 1 if a is lower or equal to b, 0 otherwise.
+ */
+int le128(uint64_t a_hi, uint64_t a_lo, uint64_t b_hi, uint64_t b_lo)
+{
+	return (a_hi < b_hi) || ((a_hi == b_hi) && (a_lo <= b_lo));
+}
+
+/**
+ * Lower-than comparison of 128-bit operands.
+ *
+ * @param a_hi High part of the first input operand.
+ * @param a_lo Low part of the first input operand.
+ * @param b_hi High part of the second input operand.
+ * @param b_lo Low part of the second input operand.
+ * @return 1 if a is lower than b, 0 otherwise.
+ */
+int lt128(uint64_t a_hi, uint64_t a_lo, uint64_t b_hi, uint64_t b_lo)
+{
+	return (a_hi < b_hi) || ((a_hi == b_hi) && (a_lo < b_lo));
+}
+
+/**
+ * Addition of two 128-bit unsigned integers.
+ *
+ * @param a_hi High part of the first input operand.
+ * @param a_lo Low part of the first input operand.
+ * @param b_hi High part of the second input operand.
+ * @param b_lo Low part of the second input operand.
+ * @param r_hi Address to store high part of the result.
+ * @param r_lo Address to store low part of the result.
+ */
+void add128(uint64_t a_hi, uint64_t a_lo,
+    uint64_t b_hi, uint64_t b_lo,
+    uint64_t *r_hi, uint64_t *r_lo)
+{
+	uint64_t low = a_lo + b_lo;
+	*r_lo = low;
+	/* detect overflow to add a carry */
+	*r_hi = a_hi + b_hi + (low < a_lo);
+}
+
+/**
+ * Substraction of two 128-bit unsigned integers.
+ *
+ * @param a_hi High part of the first input operand.
+ * @param a_lo Low part of the first input operand.
+ * @param b_hi High part of the second input operand.
+ * @param b_lo Low part of the second input operand.
+ * @param r_hi Address to store high part of the result.
+ * @param r_lo Address to store low part of the result.
+ */
+void sub128(uint64_t a_hi, uint64_t a_lo,
+    uint64_t b_hi, uint64_t b_lo,
+    uint64_t *r_hi, uint64_t *r_lo)
+{
+	*r_lo = a_lo - b_lo;
+	/* detect underflow to substract a carry */
+	*r_hi = a_hi - b_hi - (a_lo < b_lo);
+}
+
+/**
+ * Multiplication of two 64-bit unsigned integers.
+ * 
+ * @param a First input operand.
+ * @param b Second input operand.
+ * @param r_hi Address to store high part of the result.
+ * @param r_lo Address to store low part of the result.
+ */
+void mul64(uint64_t a, uint64_t b, uint64_t *r_hi, uint64_t *r_lo)
+{
+	uint64_t low, high, middle1, middle2;
+	uint32_t alow, blow;
+
+	alow = a & 0xFFFFFFFF;
+	blow = b & 0xFFFFFFFF;
+
+	a >>= 32;
+	b >>= 32;
+
+	low = ((uint64_t) alow) * blow;
+	middle1 = a * blow;
+	middle2 = alow * b;
+	high = a * b;
+
+	middle1 += middle2;
+	high += (((uint64_t) (middle1 < middle2)) << 32) + (middle1 >> 32);
+	middle1 <<= 32;
+	low += middle1;
+	high += (low < middle1);
+	*r_lo = low;
+	*r_hi = high;
+}
+
+/**
+ * Multiplication of two 128-bit unsigned integers.
+ * 
+ * @param a_hi High part of the first input operand.
+ * @param a_lo Low part of the first input operand.
+ * @param b_hi High part of the second input operand.
+ * @param b_lo Low part of the second input operand.
+ * @param r_hihi Address to store first (highest) quarter of the result.
+ * @param r_hilo Address to store second quarter of the result.
+ * @param r_lohi Address to store third quarter of the result.
+ * @param r_lolo Address to store fourth (lowest) quarter of the result.
+ */
+void mul128(uint64_t a_hi, uint64_t a_lo, uint64_t b_hi, uint64_t b_lo,
+    uint64_t *r_hihi, uint64_t *r_hilo, uint64_t *r_lohi, uint64_t *r_lolo)
+{
+	uint64_t hihi, hilo, lohi, lolo;
+	uint64_t tmp1, tmp2;
+
+	mul64(a_lo, b_lo, &lohi, &lolo);
+	mul64(a_lo, b_hi, &hilo, &tmp2);
+	add128(hilo, tmp2, 0x0ll, lohi, &hilo, &lohi);
+	mul64(a_hi, b_hi, &hihi, &tmp1);
+	add128(hihi, tmp1, 0x0ll, hilo, &hihi, &hilo);
+	mul64(a_hi, b_lo, &tmp1, &tmp2);
+	add128(tmp1, tmp2, 0x0ll, lohi, &tmp1, &lohi);
+	add128(hihi, hilo, 0x0ll, tmp1, &hihi, &hilo);
+
+	*r_hihi = hihi;
+	*r_hilo = hilo;
+	*r_lohi = lohi;
+	*r_lolo = lolo;
+}
+
+/**
+ * Estimate the quotient of 128-bit unsigned divident and 64-bit unsigned
+ * divisor.
+ * 
+ * @param a_hi High part of the divident.
+ * @param a_lo Low part of the divident.
+ * @param b Divisor.
+ * @return Quotient approximation.
+ */
+uint64_t div128est(uint64_t a_hi, uint64_t a_lo, uint64_t b)
+{
+	uint64_t b_hi, b_lo;
+	uint64_t rem_hi, rem_lo;
+	uint64_t tmp_hi, tmp_lo;
+	uint64_t result;
+
+	if (b <= a_hi) {
+		return 0xFFFFFFFFFFFFFFFFull;
+	}
+
+	b_hi = b >> 32;
+	result = ((b_hi << 32) <= a_hi) ? (0xFFFFFFFFull << 32) : (a_hi / b_hi) << 32;
+	mul64(b, result, &tmp_hi, &tmp_lo);
+	sub128(a_hi, a_lo, tmp_hi, tmp_lo, &rem_hi, &rem_lo);
+	
+	while ((int64_t) rem_hi < 0) {
+		result -= 0x1ll << 32;
+		b_lo = b << 32;
+		add128(rem_hi, rem_lo, b_hi, b_lo, &rem_hi, &rem_lo);
+	}
+
+	rem_hi = (rem_hi << 32) | (rem_lo >> 32);
+	if ((b_hi << 32) <= rem_hi) {
+		result |= 0xFFFFFFFF;
+	} else {
+		result |= rem_hi / b_hi;
+	}
+
+	return result;
+}
+
+/** @}
+ */
Index: uspace/lib/softfloat/common.h
===================================================================
--- uspace/lib/softfloat/common.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/common.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Common helper operations.
+ */
+
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+#include "sftypes.h"
+
+extern float64 finish_float64(int32_t, uint64_t, char);
+extern float128 finish_float128(int32_t, uint64_t, uint64_t, char, uint64_t);
+
+extern int count_zeroes8(uint8_t);
+extern int count_zeroes32(uint32_t);
+extern int count_zeroes64(uint64_t);
+
+extern void round_float32(int32_t *, uint32_t *);
+extern void round_float64(int32_t *, uint64_t *);
+extern void round_float128(int32_t *, uint64_t *, uint64_t *);
+
+extern void lshift128(uint64_t, uint64_t, int, uint64_t *, uint64_t *);
+extern void rshift128(uint64_t, uint64_t, int, uint64_t *, uint64_t *);
+
+extern void and128(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t *, uint64_t *);
+extern void or128(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t *, uint64_t *);
+extern void xor128(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t *, uint64_t *);
+extern void not128(uint64_t, uint64_t, uint64_t *, uint64_t *);
+
+extern int eq128(uint64_t, uint64_t, uint64_t, uint64_t);
+extern int le128(uint64_t, uint64_t, uint64_t, uint64_t);
+extern int lt128(uint64_t, uint64_t, uint64_t, uint64_t);
+
+extern void add128(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t *, uint64_t *);
+extern void sub128(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t *, uint64_t *);
+
+extern void mul64(uint64_t, uint64_t, uint64_t *, uint64_t *);
+extern void mul128(uint64_t, uint64_t, uint64_t, uint64_t,
+    uint64_t *, uint64_t *, uint64_t *, uint64_t *);
+
+extern uint64_t div128est(uint64_t, uint64_t, uint64_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softfloat/comparison.c
===================================================================
--- uspace/lib/softfloat/comparison.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/comparison.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,442 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Comparison functions.
+ */
+
+#include "sftypes.h"
+#include "comparison.h"
+#include "common.h"
+
+/**
+ * Determines whether the given float represents NaN (either signalling NaN or
+ * quiet NaN).
+ *
+ * @param f Single-precision float.
+ * @return 1 if float is NaN, 0 otherwise.
+ */
+int is_float32_nan(float32 f)
+{
+	/* NaN : exp = 0xff and nonzero fraction */
+	return ((f.parts.exp == 0xFF) && (f.parts.fraction));
+}
+
+/**
+ * Determines whether the given float represents NaN (either signalling NaN or
+ * quiet NaN).
+ *
+ * @param d Double-precision float.
+ * @return 1 if float is NaN, 0 otherwise.
+ */
+int is_float64_nan(float64 d)
+{
+	/* NaN : exp = 0x7ff and nonzero fraction */
+	return ((d.parts.exp == 0x7FF) && (d.parts.fraction));
+}
+
+/**
+ * Determines whether the given float represents NaN (either signalling NaN or
+ * quiet NaN).
+ *
+ * @param ld Quadruple-precision float.
+ * @return 1 if float is NaN, 0 otherwise.
+ */
+int is_float128_nan(float128 ld)
+{
+	/* NaN : exp = 0x7fff and nonzero fraction */
+	return ((ld.parts.exp == 0x7FF) &&
+	    !eq128(ld.parts.frac_hi, ld.parts.frac_lo, 0x0ll, 0x0ll));
+}
+
+/**
+ * Determines whether the given float represents signalling NaN.
+ *
+ * @param f Single-precision float.
+ * @return 1 if float is signalling NaN, 0 otherwise.
+ */
+int is_float32_signan(float32 f)
+{
+	/* SigNaN : exp = 0xff and fraction = 0xxxxx..x (binary),
+	 * where at least one x is nonzero */
+	return ((f.parts.exp == 0xFF) &&
+	    (f.parts.fraction < 0x400000) && (f.parts.fraction));
+}
+
+/**
+ * Determines whether the given float represents signalling NaN.
+ *
+ * @param d Double-precision float.
+ * @return 1 if float is signalling NaN, 0 otherwise.
+ */
+int is_float64_signan(float64 d)
+{
+	/* SigNaN : exp = 0x7ff and fraction = 0xxxxx..x (binary),
+	 * where at least one x is nonzero */
+	return ((d.parts.exp == 0x7FF) &&
+	    (d.parts.fraction) && (d.parts.fraction < 0x8000000000000ll));
+}
+
+/**
+ * Determines whether the given float represents signalling NaN.
+ *
+ * @param ld Quadruple-precision float.
+ * @return 1 if float is signalling NaN, 0 otherwise.
+ */
+int is_float128_signan(float128 ld)
+{
+	/* SigNaN : exp = 0x7fff and fraction = 0xxxxx..x (binary),
+	 * where at least one x is nonzero */
+	return ((ld.parts.exp == 0x7FFF) &&
+	    (ld.parts.frac_hi || ld.parts.frac_lo) &&
+	    lt128(ld.parts.frac_hi, ld.parts.frac_lo, 0x800000000000ll, 0x0ll));
+
+}
+
+/**
+ * Determines whether the given float represents positive or negative infinity.
+ *
+ * @param f Single-precision float.
+ * @return 1 if float is infinite, 0 otherwise.
+ */
+int is_float32_infinity(float32 f)
+{
+	/* NaN : exp = 0x7ff and zero fraction */
+	return ((f.parts.exp == 0xFF) && (f.parts.fraction == 0x0));
+}
+
+/**
+ * Determines whether the given float represents positive or negative infinity.
+ *
+ * @param d Double-precision float.
+ * @return 1 if float is infinite, 0 otherwise.
+ */
+int is_float64_infinity(float64 d)
+{
+	/* NaN : exp = 0x7ff and zero fraction */
+	return ((d.parts.exp == 0x7FF) && (d.parts.fraction == 0x0));
+}
+
+/**
+ * Determines whether the given float represents positive or negative infinity.
+ *
+ * @param ld Quadruple-precision float.
+ * @return 1 if float is infinite, 0 otherwise.
+ */
+int is_float128_infinity(float128 ld)
+{
+	/* NaN : exp = 0x7fff and zero fraction */
+	return ((ld.parts.exp == 0x7FFF) &&
+	    eq128(ld.parts.frac_hi, ld.parts.frac_lo, 0x0ll, 0x0ll));
+}
+
+/**
+ * Determines whether the given float represents positive or negative zero.
+ *
+ * @param f Single-precision float.
+ * @return 1 if float is zero, 0 otherwise.
+ */
+int is_float32_zero(float32 f)
+{
+	return (((f.bin) & 0x7FFFFFFF) == 0);
+}
+
+/**
+ * Determines whether the given float represents positive or negative zero.
+ *
+ * @param d Double-precision float.
+ * @return 1 if float is zero, 0 otherwise.
+ */
+int is_float64_zero(float64 d)
+{
+	return (((d.bin) & 0x7FFFFFFFFFFFFFFFll) == 0);
+}
+
+/**
+ * Determines whether the given float represents positive or negative zero.
+ *
+ * @param ld Quadruple-precision float.
+ * @return 1 if float is zero, 0 otherwise.
+ */
+int is_float128_zero(float128 ld)
+{
+	uint64_t tmp_hi;
+	uint64_t tmp_lo;
+	
+	and128(ld.bin.hi, ld.bin.lo,
+	    0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
+	
+	return eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll);
+}
+
+/**
+ * Determine whether two floats are equal. NaNs are not recognized.
+ *
+ * @a First single-precision operand.
+ * @b Second single-precision operand.
+ * @return 1 if both floats are equal, 0 otherwise.
+ */
+int is_float32_eq(float32 a, float32 b)
+{
+	/* a equals to b or both are zeros (with any sign) */
+	return ((a.bin == b.bin) ||
+	    (((a.bin | b.bin) & 0x7FFFFFFF) == 0));
+}
+
+/**
+ * Determine whether two floats are equal. NaNs are not recognized.
+ *
+ * @a First double-precision operand.
+ * @b Second double-precision operand.
+ * @return 1 if both floats are equal, 0 otherwise.
+ */
+int is_float64_eq(float64 a, float64 b)
+{
+	/* a equals to b or both are zeros (with any sign) */
+	return ((a.bin == b.bin) ||
+	    (((a.bin | b.bin) & 0x7FFFFFFFFFFFFFFFll) == 0));
+}
+
+/**
+ * Determine whether two floats are equal. NaNs are not recognized.
+ *
+ * @a First quadruple-precision operand.
+ * @b Second quadruple-precision operand.
+ * @return 1 if both floats are equal, 0 otherwise.
+ */
+int is_float128_eq(float128 a, float128 b)
+{
+	uint64_t tmp_hi;
+	uint64_t tmp_lo;
+	
+	/* both are zeros (with any sign) */
+	or128(a.bin.hi, a.bin.lo,
+	    b.bin.hi, b.bin.lo, &tmp_hi, &tmp_lo);
+	and128(tmp_hi, tmp_lo,
+	    0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
+	int both_zero = eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll);
+	
+	/* a equals to b */
+	int are_equal = eq128(a.bin.hi, a.bin.lo, b.bin.hi, b.bin.lo);
+	
+	return are_equal || both_zero;
+}
+
+/**
+ * Lower-than comparison between two floats. NaNs are not recognized.
+ *
+ * @a First single-precision operand.
+ * @b Second single-precision operand.
+ * @return 1 if a is lower than b, 0 otherwise.
+ */
+int is_float32_lt(float32 a, float32 b) 
+{
+	if (((a.bin | b.bin) & 0x7FFFFFFF) == 0) {
+		/* +- zeroes */
+		return 0;
+	}
+	
+	if ((a.parts.sign) && (b.parts.sign)) {
+		/* if both are negative, smaller is that with greater binary value */
+		return (a.bin > b.bin);
+	}
+	
+	/*
+	 * lets negate signs - now will be positive numbers always
+	 * bigger than negative (first bit will be set for unsigned
+	 * integer comparison)
+	 */
+	a.parts.sign = !a.parts.sign;
+	b.parts.sign = !b.parts.sign;
+	return (a.bin < b.bin);
+}
+
+/**
+ * Lower-than comparison between two floats. NaNs are not recognized.
+ *
+ * @a First double-precision operand.
+ * @b Second double-precision operand.
+ * @return 1 if a is lower than b, 0 otherwise.
+ */
+int is_float64_lt(float64 a, float64 b)
+{
+	if (((a.bin | b.bin) & 0x7FFFFFFFFFFFFFFFll) == 0) {
+		/* +- zeroes */
+		return 0;
+	}
+	
+	if ((a.parts.sign) && (b.parts.sign)) {
+		/* if both are negative, smaller is that with greater binary value */
+		return (a.bin > b.bin);
+	}
+	
+	/*
+	 * lets negate signs - now will be positive numbers always
+	 * bigger than negative (first bit will be set for unsigned
+	 * integer comparison)
+	 */
+	a.parts.sign = !a.parts.sign;
+	b.parts.sign = !b.parts.sign;
+	return (a.bin < b.bin);
+}
+
+/**
+ * Lower-than comparison between two floats. NaNs are not recognized.
+ *
+ * @a First quadruple-precision operand.
+ * @b Second quadruple-precision operand.
+ * @return 1 if a is lower than b, 0 otherwise.
+ */
+int is_float128_lt(float128 a, float128 b)
+{
+	uint64_t tmp_hi;
+	uint64_t tmp_lo;
+	
+	or128(a.bin.hi, a.bin.lo,
+	    b.bin.hi, b.bin.lo, &tmp_hi, &tmp_lo);
+	and128(tmp_hi, tmp_lo,
+	    0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
+	if (eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll)) {
+		/* +- zeroes */
+		return 0;
+	}
+	
+	if ((a.parts.sign) && (b.parts.sign)) {
+		/* if both are negative, smaller is that with greater binary value */
+		return lt128(b.bin.hi, b.bin.lo, a.bin.hi, a.bin.lo);
+	}
+	
+	/*
+	 * lets negate signs - now will be positive numbers always
+	 * bigger than negative (first bit will be set for unsigned
+	 * integer comparison)
+	 */
+	a.parts.sign = !a.parts.sign;
+	b.parts.sign = !b.parts.sign;
+	return lt128(a.bin.hi, a.bin.lo, b.bin.hi, b.bin.lo);
+}
+
+/**
+ * Greater-than comparison between two floats. NaNs are not recognized.
+ *
+ * @a First single-precision operand.
+ * @b Second single-precision operand.
+ * @return 1 if a is greater than b, 0 otherwise.
+ */
+int is_float32_gt(float32 a, float32 b) 
+{
+	if (((a.bin | b.bin) & 0x7FFFFFFF) == 0) {
+		/* zeroes are equal with any sign */
+		return 0;
+	}
+	
+	if ((a.parts.sign) && (b.parts.sign)) {
+		/* if both are negative, greater is that with smaller binary value */
+		return (a.bin < b.bin);
+	}
+	
+	/*
+	 * lets negate signs - now will be positive numbers always
+	 * bigger than negative (first bit will be set for unsigned
+	 * integer comparison)
+	 */
+	a.parts.sign = !a.parts.sign;
+	b.parts.sign = !b.parts.sign;
+	return (a.bin > b.bin);
+}
+
+/**
+ * Greater-than comparison between two floats. NaNs are not recognized.
+ *
+ * @a First double-precision operand.
+ * @b Second double-precision operand.
+ * @return 1 if a is greater than b, 0 otherwise.
+ */
+int is_float64_gt(float64 a, float64 b)
+{
+	if (((a.bin | b.bin) & 0x7FFFFFFFFFFFFFFFll) == 0) {
+		/* zeroes are equal with any sign */
+		return 0;
+	}
+	
+	if ((a.parts.sign) && (b.parts.sign)) {
+		/* if both are negative, greater is that with smaller binary value */
+		return (a.bin < b.bin);
+	}
+	
+	/*
+	 * lets negate signs - now will be positive numbers always
+	 * bigger than negative (first bit will be set for unsigned
+	 * integer comparison)
+	 */
+	a.parts.sign = !a.parts.sign;
+	b.parts.sign = !b.parts.sign;
+	return (a.bin > b.bin);
+}
+
+/**
+ * Greater-than comparison between two floats. NaNs are not recognized.
+ *
+ * @a First quadruple-precision operand.
+ * @b Second quadruple-precision operand.
+ * @return 1 if a is greater than b, 0 otherwise.
+ */
+int is_float128_gt(float128 a, float128 b)
+{
+	uint64_t tmp_hi;
+	uint64_t tmp_lo;
+	
+	or128(a.bin.hi, a.bin.lo,
+	    b.bin.hi, b.bin.lo, &tmp_hi, &tmp_lo);
+	and128(tmp_hi, tmp_lo,
+	    0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
+	if (eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll)) {
+		/* zeroes are equal with any sign */
+		return 0;
+	}
+	
+	if ((a.parts.sign) && (b.parts.sign)) {
+		/* if both are negative, greater is that with smaller binary value */
+		return lt128(a.bin.hi, a.bin.lo, b.bin.hi, b.bin.lo);
+	}
+	
+	/*
+	 * lets negate signs - now will be positive numbers always
+	 * bigger than negative (first bit will be set for unsigned
+	 * integer comparison)
+	 */
+	a.parts.sign = !a.parts.sign;
+	b.parts.sign = !b.parts.sign;
+	return lt128(b.bin.hi, b.bin.lo, a.bin.hi, a.bin.lo);
+}
+
+/** @}
+ */
Index: uspace/lib/softfloat/comparison.h
===================================================================
--- uspace/lib/softfloat/comparison.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/comparison.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Comparison functions.
+ */
+
+#ifndef __COMPARISON_H__
+#define __COMPARISON_H__
+
+extern int is_float32_nan(float32);
+extern int is_float32_signan(float32);
+
+extern int is_float32_infinity(float32);
+extern int is_float32_zero(float32);
+
+extern int is_float32_eq(float32, float32);
+extern int is_float32_lt(float32, float32);
+extern int is_float32_gt(float32, float32);
+
+extern int is_float64_nan(float64);
+extern int is_float64_signan(float64);
+
+extern int is_float64_infinity(float64);
+extern int is_float64_zero(float64);
+
+extern int is_float64_eq(float64, float64);
+extern int is_float64_lt(float64, float64);
+extern int is_float64_gt(float64, float64);
+
+extern int is_float96_nan(float96);
+extern int is_float96_signan(float96);
+
+extern int is_float96_infinity(float96);
+extern int is_float96_zero(float96);
+
+extern int is_float96_eq(float96, float96);
+extern int is_float96_lt(float96, float96);
+extern int is_float96_gt(float96, float96);
+
+extern int is_float128_nan(float128);
+extern int is_float128_signan(float128);
+
+extern int is_float128_infinity(float128);
+extern int is_float128_zero(float128);
+
+extern int is_float128_eq(float128, float128);
+extern int is_float128_lt(float128, float128);
+extern int is_float128_gt(float128, float128);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softfloat/conversion.c
===================================================================
--- uspace/lib/softfloat/conversion.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/conversion.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1041 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Conversion of precision and conversion between integers and floats.
+ */
+
+#include "sftypes.h"
+#include "conversion.h"
+#include "comparison.h"
+#include "common.h"
+
+float64 float32_to_float64(float32 a)
+{
+	float64 result;
+	uint64_t frac;
+	
+	result.parts.sign = a.parts.sign;
+	result.parts.fraction = a.parts.fraction;
+	result.parts.fraction <<= (FLOAT64_FRACTION_SIZE - FLOAT32_FRACTION_SIZE);
+	
+	if ((is_float32_infinity(a)) || (is_float32_nan(a))) {
+		result.parts.exp = FLOAT64_MAX_EXPONENT;
+		// TODO; check if its correct for SigNaNs
+		return result;
+	}
+	
+	result.parts.exp = a.parts.exp + ((int) FLOAT64_BIAS - FLOAT32_BIAS);
+	if (a.parts.exp == 0) {
+		/* normalize denormalized numbers */
+		
+		if (result.parts.fraction == 0) { /* fix zero */
+			result.parts.exp = 0;
+			return result;
+		}
+			
+		frac = result.parts.fraction;
+		
+		while (!(frac & FLOAT64_HIDDEN_BIT_MASK)) {
+			frac <<= 1;
+			--result.parts.exp;
+		}
+		
+		++result.parts.exp;
+		result.parts.fraction = frac;
+	}
+	
+	return result;
+}
+
+float128 float32_to_float128(float32 a)
+{
+	float128 result;
+	uint64_t frac_hi, frac_lo;
+	uint64_t tmp_hi, tmp_lo;
+	
+	result.parts.sign = a.parts.sign;
+	result.parts.frac_hi = 0;
+	result.parts.frac_lo = a.parts.fraction;
+	lshift128(result.parts.frac_hi, result.parts.frac_lo,
+	    (FLOAT128_FRACTION_SIZE - FLOAT32_FRACTION_SIZE),
+	    &frac_hi, &frac_lo);
+	result.parts.frac_hi = frac_hi;
+	result.parts.frac_lo = frac_lo;
+	
+	if ((is_float32_infinity(a)) || (is_float32_nan(a))) {
+		result.parts.exp = FLOAT128_MAX_EXPONENT;
+		// TODO; check if its correct for SigNaNs
+		return result;
+	}
+	
+	result.parts.exp = a.parts.exp + ((int) FLOAT128_BIAS - FLOAT32_BIAS);
+	if (a.parts.exp == 0) {
+		/* normalize denormalized numbers */
+		
+		if (eq128(result.parts.frac_hi,
+		    result.parts.frac_lo, 0x0ll, 0x0ll)) { /* fix zero */
+			result.parts.exp = 0;
+			return result;
+		}
+		
+		frac_hi = result.parts.frac_hi;
+		frac_lo = result.parts.frac_lo;
+		
+		and128(frac_hi, frac_lo,
+		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+		    &tmp_hi, &tmp_lo);
+		while (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
+			lshift128(frac_hi, frac_lo, 1, &frac_hi, &frac_lo);
+			--result.parts.exp;
+		}
+		
+		++result.parts.exp;
+		result.parts.frac_hi = frac_hi;
+		result.parts.frac_lo = frac_lo;
+	}
+	
+	return result;
+}
+
+float128 float64_to_float128(float64 a)
+{
+	float128 result;
+	uint64_t frac_hi, frac_lo;
+	uint64_t tmp_hi, tmp_lo;
+	
+	result.parts.sign = a.parts.sign;
+	result.parts.frac_hi = 0;
+	result.parts.frac_lo = a.parts.fraction;
+	lshift128(result.parts.frac_hi, result.parts.frac_lo,
+	    (FLOAT128_FRACTION_SIZE - FLOAT64_FRACTION_SIZE),
+	    &frac_hi, &frac_lo);
+	result.parts.frac_hi = frac_hi;
+	result.parts.frac_lo = frac_lo;
+	
+	if ((is_float64_infinity(a)) || (is_float64_nan(a))) {
+		result.parts.exp = FLOAT128_MAX_EXPONENT;
+		// TODO; check if its correct for SigNaNs
+		return result;
+	}
+	
+	result.parts.exp = a.parts.exp + ((int) FLOAT128_BIAS - FLOAT64_BIAS);
+	if (a.parts.exp == 0) {
+		/* normalize denormalized numbers */
+		
+		if (eq128(result.parts.frac_hi,
+		    result.parts.frac_lo, 0x0ll, 0x0ll)) { /* fix zero */
+			result.parts.exp = 0;
+			return result;
+		}
+		
+		frac_hi = result.parts.frac_hi;
+		frac_lo = result.parts.frac_lo;
+		
+		and128(frac_hi, frac_lo,
+		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+		    &tmp_hi, &tmp_lo);
+		while (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
+			lshift128(frac_hi, frac_lo, 1, &frac_hi, &frac_lo);
+			--result.parts.exp;
+		}
+		
+		++result.parts.exp;
+		result.parts.frac_hi = frac_hi;
+		result.parts.frac_lo = frac_lo;
+	}
+	
+	return result;
+}
+
+float32 float64_to_float32(float64 a)
+{
+	float32 result;
+	int32_t exp;
+	uint64_t frac;
+	
+	result.parts.sign = a.parts.sign;
+	
+	if (is_float64_nan(a)) {
+		result.parts.exp = FLOAT32_MAX_EXPONENT;
+		
+		if (is_float64_signan(a)) {
+			/* set first bit of fraction nonzero */
+			result.parts.fraction = FLOAT32_HIDDEN_BIT_MASK >> 1;
+			return result;
+		}
+		
+		/* fraction nonzero but its first bit is zero */
+		result.parts.fraction = 0x1;
+		return result;
+	}
+	
+	if (is_float64_infinity(a)) {
+		result.parts.fraction = 0;
+		result.parts.exp = FLOAT32_MAX_EXPONENT;
+		return result;
+	}
+	
+	exp = (int) a.parts.exp - FLOAT64_BIAS + FLOAT32_BIAS;
+	
+	if (exp >= FLOAT32_MAX_EXPONENT) {
+		/* FIXME: overflow */
+		result.parts.fraction = 0;
+		result.parts.exp = FLOAT32_MAX_EXPONENT;
+		return result;
+	} else if (exp <= 0) {
+		/* underflow or denormalized */
+		
+		result.parts.exp = 0;
+		
+		exp *= -1;	
+		if (exp > FLOAT32_FRACTION_SIZE) {
+			/* FIXME: underflow */
+			result.parts.fraction = 0;
+			return result;
+		}
+		
+		/* denormalized */
+		
+		frac = a.parts.fraction; 
+		frac |= FLOAT64_HIDDEN_BIT_MASK; /* denormalize and set hidden bit */
+		
+		frac >>= (FLOAT64_FRACTION_SIZE - FLOAT32_FRACTION_SIZE + 1);
+		
+		while (exp > 0) {
+			--exp;
+			frac >>= 1;
+		}
+		result.parts.fraction = frac;
+		
+		return result;
+	}
+	
+	result.parts.exp = exp;
+	result.parts.fraction =
+	    a.parts.fraction >> (FLOAT64_FRACTION_SIZE - FLOAT32_FRACTION_SIZE);
+	return result;
+}
+
+float32 float128_to_float32(float128 a)
+{
+	float32 result;
+	int32_t exp;
+	uint64_t frac_hi, frac_lo;
+	
+	result.parts.sign = a.parts.sign;
+	
+	if (is_float128_nan(a)) {
+		result.parts.exp = FLOAT32_MAX_EXPONENT;
+		
+		if (is_float128_signan(a)) {
+			/* set first bit of fraction nonzero */
+			result.parts.fraction = FLOAT32_HIDDEN_BIT_MASK >> 1;
+			return result;
+		}
+		
+		/* fraction nonzero but its first bit is zero */
+		result.parts.fraction = 0x1;
+		return result;
+	}
+	
+	if (is_float128_infinity(a)) {
+		result.parts.fraction = 0;
+		result.parts.exp = FLOAT32_MAX_EXPONENT;
+		return result;
+	}
+	
+	exp = (int) a.parts.exp - FLOAT128_BIAS + FLOAT32_BIAS;
+	
+	if (exp >= FLOAT32_MAX_EXPONENT) {
+		/* FIXME: overflow */
+		result.parts.fraction = 0;
+		result.parts.exp = FLOAT32_MAX_EXPONENT;
+		return result;
+	} else if (exp <= 0) {
+		/* underflow or denormalized */
+		
+		result.parts.exp = 0;
+		
+		exp *= -1;
+		if (exp > FLOAT32_FRACTION_SIZE) {
+			/* FIXME: underflow */
+			result.parts.fraction = 0;
+			return result;
+		}
+		
+		/* denormalized */
+		
+		frac_hi = a.parts.frac_hi;
+		frac_lo = a.parts.frac_lo;
+		
+		/* denormalize and set hidden bit */
+		frac_hi |= FLOAT128_HIDDEN_BIT_MASK_HI;
+		
+		rshift128(frac_hi, frac_lo,
+		    (FLOAT128_FRACTION_SIZE - FLOAT32_FRACTION_SIZE + 1),
+		    &frac_hi, &frac_lo);
+		
+		while (exp > 0) {
+			--exp;
+			rshift128(frac_hi, frac_lo, 1, &frac_hi, &frac_lo);
+		}
+		result.parts.fraction = frac_lo;
+		
+		return result;
+	}
+	
+	result.parts.exp = exp;
+	frac_hi = a.parts.frac_hi;
+	frac_lo = a.parts.frac_lo;
+	rshift128(frac_hi, frac_lo,
+	    (FLOAT128_FRACTION_SIZE - FLOAT32_FRACTION_SIZE + 1),
+	    &frac_hi, &frac_lo);
+	result.parts.fraction = frac_lo;
+	return result;
+}
+
+float64 float128_to_float64(float128 a)
+{
+	float64 result;
+	int32_t exp;
+	uint64_t frac_hi, frac_lo;
+	
+	result.parts.sign = a.parts.sign;
+	
+	if (is_float128_nan(a)) {
+		result.parts.exp = FLOAT64_MAX_EXPONENT;
+		
+		if (is_float128_signan(a)) {
+			/* set first bit of fraction nonzero */
+			result.parts.fraction = FLOAT64_HIDDEN_BIT_MASK >> 1;
+			return result;
+		}
+		
+		/* fraction nonzero but its first bit is zero */
+		result.parts.fraction = 0x1;
+		return result;
+	}
+	
+	if (is_float128_infinity(a)) {
+		result.parts.fraction = 0;
+		result.parts.exp = FLOAT64_MAX_EXPONENT;
+		return result;
+	}
+	
+	exp = (int) a.parts.exp - FLOAT128_BIAS + FLOAT64_BIAS;
+	
+	if (exp >= FLOAT64_MAX_EXPONENT) {
+		/* FIXME: overflow */
+		result.parts.fraction = 0;
+		result.parts.exp = FLOAT64_MAX_EXPONENT;
+		return result;
+	} else if (exp <= 0) {
+		/* underflow or denormalized */
+		
+		result.parts.exp = 0;
+		
+		exp *= -1;
+		if (exp > FLOAT64_FRACTION_SIZE) {
+			/* FIXME: underflow */
+			result.parts.fraction = 0;
+			return result;
+		}
+		
+		/* denormalized */
+		
+		frac_hi = a.parts.frac_hi;
+		frac_lo = a.parts.frac_lo;
+		
+		/* denormalize and set hidden bit */
+		frac_hi |= FLOAT128_HIDDEN_BIT_MASK_HI;
+		
+		rshift128(frac_hi, frac_lo,
+		    (FLOAT128_FRACTION_SIZE - FLOAT64_FRACTION_SIZE + 1),
+		    &frac_hi, &frac_lo);
+		
+		while (exp > 0) {
+			--exp;
+			rshift128(frac_hi, frac_lo, 1, &frac_hi, &frac_lo);
+		}
+		result.parts.fraction = frac_lo;
+		
+		return result;
+	}
+	
+	result.parts.exp = exp;
+	frac_hi = a.parts.frac_hi;
+	frac_lo = a.parts.frac_lo;
+	rshift128(frac_hi, frac_lo,
+	    (FLOAT128_FRACTION_SIZE - FLOAT64_FRACTION_SIZE + 1),
+	    &frac_hi, &frac_lo);
+	result.parts.fraction = frac_lo;
+	return result;
+}
+
+/** Helper procedure for converting float32 to uint32.
+ *
+ * @param a Floating point number in normalized form
+ *     (NaNs or Inf are not checked).
+ * @return Converted unsigned integer.
+ */
+static uint32_t _float32_to_uint32_helper(float32 a)
+{
+	uint32_t frac;
+	
+	if (a.parts.exp < FLOAT32_BIAS) {
+		/* TODO: rounding */
+		return 0;
+	}
+	
+	frac = a.parts.fraction;
+	
+	frac |= FLOAT32_HIDDEN_BIT_MASK;
+	/* shift fraction to left so hidden bit will be the most significant bit */
+	frac <<= 32 - FLOAT32_FRACTION_SIZE - 1; 
+	
+	frac >>= 32 - (a.parts.exp - FLOAT32_BIAS) - 1;
+	if ((a.parts.sign == 1) && (frac != 0)) {
+		frac = ~frac;
+		++frac;
+	}
+	
+	return frac;
+}
+
+/*
+ * FIXME: Im not sure what to return if overflow/underflow happens
+ *  - now its the biggest or the smallest int
+ */
+uint32_t float32_to_uint32(float32 a)
+{
+	if (is_float32_nan(a))
+		return UINT32_MAX;
+	
+	if (is_float32_infinity(a) || (a.parts.exp >= (32 + FLOAT32_BIAS))) {
+		if (a.parts.sign)
+			return UINT32_MIN;
+		
+		return UINT32_MAX;
+	}
+	
+	return _float32_to_uint32_helper(a);
+}
+
+/*
+ * FIXME: Im not sure what to return if overflow/underflow happens
+ *  - now its the biggest or the smallest int
+ */
+int32_t float32_to_int32(float32 a)
+{
+	if (is_float32_nan(a))
+		return INT32_MAX;
+	
+	if (is_float32_infinity(a) || (a.parts.exp >= (32 + FLOAT32_BIAS))) {
+		if (a.parts.sign)
+			return INT32_MIN;
+		
+		return INT32_MAX;
+	}
+	
+	return _float32_to_uint32_helper(a);
+}
+
+/** Helper procedure for converting float32 to uint64.
+ *
+ * @param a Floating point number in normalized form
+ *     (NaNs or Inf are not checked).
+ * @return Converted unsigned integer.
+ */
+static uint64_t _float32_to_uint64_helper(float32 a)
+{
+	uint64_t frac;
+	
+	if (a.parts.exp < FLOAT32_BIAS) {
+		// TODO: rounding
+		return 0;
+	}
+	
+	frac = a.parts.fraction;
+	
+	frac |= FLOAT32_HIDDEN_BIT_MASK;
+	/* shift fraction to left so hidden bit will be the most significant bit */
+	frac <<= 64 - FLOAT32_FRACTION_SIZE - 1;
+	
+	frac >>= 64 - (a.parts.exp - FLOAT32_BIAS) - 1;
+	if ((a.parts.sign == 1) && (frac != 0)) {
+		frac = ~frac;
+		++frac;
+	}
+	
+	return frac;
+}
+
+/*
+ * FIXME: Im not sure what to return if overflow/underflow happens
+ *  - now its the biggest or the smallest int
+ */
+uint64_t float32_to_uint64(float32 a)
+{
+	if (is_float32_nan(a))
+		return UINT64_MAX;
+	
+	if (is_float32_infinity(a) || (a.parts.exp >= (64 + FLOAT32_BIAS))) {
+		if (a.parts.sign)
+			return UINT64_MIN;
+		
+		return UINT64_MAX;
+	}
+	
+	return _float32_to_uint64_helper(a);
+}
+
+/*
+ * FIXME: Im not sure what to return if overflow/underflow happens
+ *  - now its the biggest or the smallest int
+ */
+int64_t float32_to_int64(float32 a)
+{
+	if (is_float32_nan(a))
+		return INT64_MAX;
+	
+	if (is_float32_infinity(a) || (a.parts.exp >= (64 + FLOAT32_BIAS))) {
+		if (a.parts.sign)
+			return INT64_MIN;
+		
+		return INT64_MAX;
+	}
+	
+	return _float32_to_uint64_helper(a);
+}
+
+/** Helper procedure for converting float64 to uint64.
+ *
+ * @param a Floating point number in normalized form
+ *     (NaNs or Inf are not checked).
+ * @return Converted unsigned integer.
+ */
+static uint64_t _float64_to_uint64_helper(float64 a)
+{
+	uint64_t frac;
+	
+	if (a.parts.exp < FLOAT64_BIAS) {
+		// TODO: rounding
+		return 0;
+	}
+	
+	frac = a.parts.fraction;
+	
+	frac |= FLOAT64_HIDDEN_BIT_MASK;
+	/* shift fraction to left so hidden bit will be the most significant bit */
+	frac <<= 64 - FLOAT64_FRACTION_SIZE - 1;
+	
+	frac >>= 64 - (a.parts.exp - FLOAT64_BIAS) - 1;
+	if ((a.parts.sign == 1) && (frac != 0)) {
+		frac = ~frac;
+		++frac;
+	}
+	
+	return frac;
+}
+
+/*
+ * FIXME: Im not sure what to return if overflow/underflow happens
+ *  - now its the biggest or the smallest int
+ */
+uint32_t float64_to_uint32(float64 a)
+{
+	if (is_float64_nan(a))
+		return UINT32_MAX;
+	
+	if (is_float64_infinity(a) || (a.parts.exp >= (32 + FLOAT64_BIAS))) {
+		if (a.parts.sign)
+			return UINT32_MIN;
+		
+		return UINT32_MAX;
+	}
+	
+	return (uint32_t) _float64_to_uint64_helper(a);
+}
+
+/*
+ * FIXME: Im not sure what to return if overflow/underflow happens
+ *  - now its the biggest or the smallest int
+ */
+int32_t float64_to_int32(float64 a)
+{
+	if (is_float64_nan(a))
+		return INT32_MAX;
+	
+	if (is_float64_infinity(a) || (a.parts.exp >= (32 + FLOAT64_BIAS))) {
+		if (a.parts.sign)
+			return INT32_MIN;
+		
+		return INT32_MAX;
+	}
+	
+	return (int32_t) _float64_to_uint64_helper(a);
+}
+
+/*
+ * FIXME: Im not sure what to return if overflow/underflow happens 
+ *  - now its the biggest or the smallest int
+ */
+uint64_t float64_to_uint64(float64 a)
+{
+	if (is_float64_nan(a))
+		return UINT64_MAX;
+	
+	if (is_float64_infinity(a) || (a.parts.exp >= (64 + FLOAT64_BIAS))) {
+		if (a.parts.sign)
+			return UINT64_MIN;
+		
+		return UINT64_MAX;
+	}
+	
+	return _float64_to_uint64_helper(a);
+}
+
+/*
+ * FIXME: Im not sure what to return if overflow/underflow happens 
+ *  - now its the biggest or the smallest int
+ */
+int64_t float64_to_int64(float64 a)
+{
+	if (is_float64_nan(a))
+		return INT64_MAX;
+	
+	if (is_float64_infinity(a) || (a.parts.exp >= (64 + FLOAT64_BIAS))) {
+		if (a.parts.sign)
+			return INT64_MIN;
+		
+		return INT64_MAX;
+	}
+	
+	return _float64_to_uint64_helper(a);
+}
+
+/** Helper procedure for converting float128 to uint64.
+ *
+ * @param a Floating point number in normalized form
+ *     (NaNs or Inf are not checked).
+ * @return Converted unsigned integer.
+ */
+static uint64_t _float128_to_uint64_helper(float128 a)
+{
+	uint64_t frac_hi, frac_lo;
+	
+	if (a.parts.exp < FLOAT128_BIAS) {
+		// TODO: rounding
+		return 0;
+	}
+	
+	frac_hi = a.parts.frac_hi;
+	frac_lo = a.parts.frac_lo;
+	
+	frac_hi |= FLOAT128_HIDDEN_BIT_MASK_HI;
+	/* shift fraction to left so hidden bit will be the most significant bit */
+	lshift128(frac_hi, frac_lo,
+	    (128 - FLOAT128_FRACTION_SIZE - 1), &frac_hi, &frac_lo);
+	
+	rshift128(frac_hi, frac_lo,
+	    (128 - (a.parts.exp - FLOAT128_BIAS) - 1), &frac_hi, &frac_lo);
+	if ((a.parts.sign == 1) && !eq128(frac_hi, frac_lo, 0x0ll, 0x0ll)) {
+		not128(frac_hi, frac_lo, &frac_hi, &frac_lo);
+		add128(frac_hi, frac_lo, 0x0ll, 0x1ll, &frac_hi, &frac_lo);
+	}
+	
+	return frac_lo;
+}
+
+/*
+ * FIXME: Im not sure what to return if overflow/underflow happens
+ *  - now its the biggest or the smallest int
+ */
+uint32_t float128_to_uint32(float128 a)
+{
+	if (is_float128_nan(a))
+		return UINT32_MAX;
+	
+	if (is_float128_infinity(a) || (a.parts.exp >= (32 + FLOAT128_BIAS))) {
+		if (a.parts.sign)
+			return UINT32_MIN;
+		
+		return UINT32_MAX;
+	}
+	
+	return (uint32_t) _float128_to_uint64_helper(a);
+}
+
+/*
+ * FIXME: Im not sure what to return if overflow/underflow happens
+ *  - now its the biggest or the smallest int
+ */
+int32_t float128_to_int32(float128 a)
+{
+	if (is_float128_nan(a))
+		return INT32_MAX;
+	
+	if (is_float128_infinity(a) || (a.parts.exp >= (32 + FLOAT128_BIAS))) {
+		if (a.parts.sign)
+			return INT32_MIN;
+		
+		return INT32_MAX;
+	}
+	
+	return (int32_t) _float128_to_uint64_helper(a);
+}
+
+/*
+ * FIXME: Im not sure what to return if overflow/underflow happens
+ *  - now its the biggest or the smallest int
+ */
+uint64_t float128_to_uint64(float128 a)
+{
+	if (is_float128_nan(a))
+		return UINT64_MAX;
+	
+	if (is_float128_infinity(a) || (a.parts.exp >= (64 + FLOAT128_BIAS))) {
+		if (a.parts.sign)
+			return UINT64_MIN;
+		
+		return UINT64_MAX;
+	}
+	
+	return _float128_to_uint64_helper(a);
+}
+
+/*
+ * FIXME: Im not sure what to return if overflow/underflow happens
+ *  - now its the biggest or the smallest int
+ */
+int64_t float128_to_int64(float128 a)
+{
+	if (is_float128_nan(a))
+		return INT64_MAX;
+	
+	if (is_float128_infinity(a) || (a.parts.exp >= (64 + FLOAT128_BIAS))) {
+		if (a.parts.sign)
+			return INT64_MIN;
+		
+		return INT64_MAX;
+	}
+	
+	return _float128_to_uint64_helper(a);
+}
+
+float32 uint32_to_float32(uint32_t i)
+{
+	int counter;
+	int32_t exp;
+	float32 result;
+	
+	result.parts.sign = 0;
+	result.parts.fraction = 0;
+	
+	counter = count_zeroes32(i);
+	
+	exp = FLOAT32_BIAS + 32 - counter - 1;
+	
+	if (counter == 32) {
+		result.bin = 0;
+		return result;
+	}
+	
+	if (counter > 0) {
+		i <<= counter - 1;
+	} else {
+		i >>= 1;
+	}
+	
+	round_float32(&exp, &i);
+	
+	result.parts.fraction = i >> (32 - FLOAT32_FRACTION_SIZE - 2);
+	result.parts.exp = exp;
+	
+	return result;
+}
+
+float32 int32_to_float32(int32_t i)
+{
+	float32 result;
+	
+	if (i < 0)
+		result = uint32_to_float32((uint32_t) (-i));
+	else
+		result = uint32_to_float32((uint32_t) i);
+	
+	result.parts.sign = i < 0;
+	
+	return result;
+}
+
+float32 uint64_to_float32(uint64_t i)
+{
+	int counter;
+	int32_t exp;
+	uint32_t j;
+	float32 result;
+	
+	result.parts.sign = 0;
+	result.parts.fraction = 0;
+	
+	counter = count_zeroes64(i);
+	
+	exp = FLOAT32_BIAS + 64 - counter - 1;
+	
+	if (counter == 64) {
+		result.bin = 0;
+		return result;
+	}
+	
+	/* Shift all to the first 31 bits (31st will be hidden 1) */
+	if (counter > 33) {
+		i <<= counter - 1 - 32;
+	} else {
+		i >>= 1 + 32 - counter;
+	}
+	
+	j = (uint32_t) i;
+	round_float32(&exp, &j);
+	
+	result.parts.fraction = j >> (32 - FLOAT32_FRACTION_SIZE - 2);
+	result.parts.exp = exp;
+	return result;
+}
+
+float32 int64_to_float32(int64_t i)
+{
+	float32 result;
+	
+	if (i < 0)
+		result = uint64_to_float32((uint64_t) (-i));
+	else
+		result = uint64_to_float32((uint64_t) i);
+	
+	result.parts.sign = i < 0;
+	
+	return result;
+}
+
+float64 uint32_to_float64(uint32_t i)
+{
+	int counter;
+	int32_t exp;
+	float64 result;
+	uint64_t frac;
+	
+	result.parts.sign = 0;
+	result.parts.fraction = 0;
+	
+	counter = count_zeroes32(i);
+	
+	exp = FLOAT64_BIAS + 32 - counter - 1;
+	
+	if (counter == 32) {
+		result.bin = 0;
+		return result;
+	}
+	
+	frac = i;
+	frac <<= counter + 32 - 1;
+	
+	round_float64(&exp, &frac);
+	
+	result.parts.fraction = frac >> (64 - FLOAT64_FRACTION_SIZE - 2);
+	result.parts.exp = exp;
+	
+	return result;
+}
+
+float64 int32_to_float64(int32_t i)
+{
+	float64 result;
+	
+	if (i < 0)
+		result = uint32_to_float64((uint32_t) (-i));
+	else
+		result = uint32_to_float64((uint32_t) i);
+	
+	result.parts.sign = i < 0;
+	
+	return result;
+}
+
+
+float64 uint64_to_float64(uint64_t i)
+{
+	int counter;
+	int32_t exp;
+	float64 result;
+	
+	result.parts.sign = 0;
+	result.parts.fraction = 0;
+	
+	counter = count_zeroes64(i);
+	
+	exp = FLOAT64_BIAS + 64 - counter - 1;
+	
+	if (counter == 64) {
+		result.bin = 0;
+		return result;
+	}
+	
+	if (counter > 0) {
+		i <<= counter - 1;
+	} else {
+		i >>= 1;
+	}
+	
+	round_float64(&exp, &i);
+	
+	result.parts.fraction = i >> (64 - FLOAT64_FRACTION_SIZE - 2);
+	result.parts.exp = exp;
+	return result;
+}
+
+float64 int64_to_float64(int64_t i)
+{
+	float64 result;
+	
+	if (i < 0)
+		result = uint64_to_float64((uint64_t) (-i));
+	else
+		result = uint64_to_float64((uint64_t) i);
+	
+	result.parts.sign = i < 0;
+	
+	return result;
+}
+
+float128 uint32_to_float128(uint32_t i)
+{
+	int counter;
+	int32_t exp;
+	float128 result;
+	uint64_t frac_hi, frac_lo;
+	
+	result.parts.sign = 0;
+	result.parts.frac_hi = 0;
+	result.parts.frac_lo = 0;
+	
+	counter = count_zeroes32(i);
+	
+	exp = FLOAT128_BIAS + 32 - counter - 1;
+	
+	if (counter == 32) {
+		result.bin.hi = 0;
+		result.bin.lo = 0;
+		return result;
+	}
+	
+	frac_hi = 0;
+	frac_lo = i;
+	lshift128(frac_hi, frac_lo, (counter + 96 - 1), &frac_hi, &frac_lo);
+	
+	round_float128(&exp, &frac_hi, &frac_lo);
+	
+	rshift128(frac_hi, frac_lo,
+	    (128 - FLOAT128_FRACTION_SIZE - 2), &frac_hi, &frac_lo);
+	result.parts.frac_hi = frac_hi;
+	result.parts.frac_lo = frac_lo;
+	result.parts.exp = exp;
+	
+	return result;
+}
+
+float128 int32_to_float128(int32_t i)
+{
+	float128 result;
+	
+	if (i < 0)
+		result = uint32_to_float128((uint32_t) (-i));
+	else
+		result = uint32_to_float128((uint32_t) i);
+	
+	result.parts.sign = i < 0;
+	
+	return result;
+}
+
+
+float128 uint64_to_float128(uint64_t i)
+{
+	int counter;
+	int32_t exp;
+	float128 result;
+	uint64_t frac_hi, frac_lo;
+	
+	result.parts.sign = 0;
+	result.parts.frac_hi = 0;
+	result.parts.frac_lo = 0;
+	
+	counter = count_zeroes64(i);
+	
+	exp = FLOAT128_BIAS + 64 - counter - 1;
+	
+	if (counter == 64) {
+		result.bin.hi = 0;
+		result.bin.lo = 0;
+		return result;
+	}
+	
+	frac_hi = 0;
+	frac_lo = i;
+	lshift128(frac_hi, frac_lo, (counter + 64 - 1), &frac_hi, &frac_lo);
+	
+	round_float128(&exp, &frac_hi, &frac_lo);
+	
+	rshift128(frac_hi, frac_lo,
+	    (128 - FLOAT128_FRACTION_SIZE - 2), &frac_hi, &frac_lo);
+	result.parts.frac_hi = frac_hi;
+	result.parts.frac_lo = frac_lo;
+	result.parts.exp = exp;
+	
+	return result;
+}
+
+float128 int64_to_float128(int64_t i)
+{
+	float128 result;
+	
+	if (i < 0)
+		result = uint64_to_float128((uint64_t) (-i));
+	else
+		result = uint64_to_float128((uint64_t) i);
+	
+	result.parts.sign = i < 0;
+	
+	return result;
+}
+
+/** @}
+ */
Index: uspace/lib/softfloat/conversion.h
===================================================================
--- uspace/lib/softfloat/conversion.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/conversion.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Conversion of precision and conversion between integers and floats.
+ */
+
+#ifndef __CONVERSION_H__
+#define __CONVERSION_H__
+
+extern float64 float32_to_float64(float32);
+extern float96 float32_to_float96(float32);
+extern float128 float32_to_float128(float32);
+extern float96 float64_to_float96(float64);
+extern float128 float64_to_float128(float64);
+extern float128 float96_to_float128(float96);
+
+extern float32 float64_to_float32(float64);
+extern float32 float96_to_float32(float96);
+extern float64 float96_to_float64(float96);
+extern float32 float128_to_float32(float128);
+extern float64 float128_to_float64(float128);
+extern float96 float128_to_float96(float128);
+
+extern uint32_t float32_to_uint32(float32);
+extern int32_t float32_to_int32(float32);
+
+extern uint64_t float32_to_uint64(float32);
+extern int64_t float32_to_int64(float32);
+
+extern uint32_t float64_to_uint32(float64);
+extern int32_t float64_to_int32(float64);
+
+extern uint64_t float64_to_uint64(float64);
+extern int64_t float64_to_int64(float64);
+
+extern uint32_t float96_to_uint32(float96);
+extern int32_t float96_to_int32(float96);
+
+extern uint64_t float96_to_uint64(float96);
+extern int64_t float96_to_int64(float96);
+
+extern uint32_t float128_to_uint32(float128);
+extern int32_t float128_to_int32(float128);
+
+extern uint64_t float128_to_uint64(float128);
+extern int64_t float128_to_int64(float128);
+
+extern float32 uint32_to_float32(uint32_t);
+extern float32 int32_to_float32(int32_t);
+
+extern float32 uint64_to_float32(uint64_t);
+extern float32 int64_to_float32(int64_t);
+
+extern float64 uint32_to_float64(uint32_t);
+extern float64 int32_to_float64(int32_t);
+
+extern float64 uint64_to_float64(uint64_t);
+extern float64 int64_to_float64(int64_t);
+
+extern float96 uint32_to_float96(uint32_t);
+extern float96 int32_to_float96(int32_t);
+
+extern float96 uint64_to_float96(uint64_t);
+extern float96 int64_to_float96(int64_t);
+
+extern float128 uint32_to_float128(uint32_t);
+extern float128 int32_to_float128(int32_t);
+
+extern float128 uint64_to_float128(uint64_t);
+extern float128 int64_to_float128(int64_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softfloat/div.c
===================================================================
--- uspace/lib/softfloat/div.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/div.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Division functions.
+ */
+
+#include "sftypes.h"
+#include "add.h"
+#include "div.h"
+#include "comparison.h"
+#include "mul.h"
+#include "common.h"
+
+/** Divide two single-precision floats.
+ *
+ * @param a Nominator.
+ * @param b Denominator.
+ *
+ * @return Result of division.
+ *
+ */
+float32 div_float32(float32 a, float32 b)
+{
+	float32 result;
+	int32_t aexp, bexp, cexp;
+	uint64_t afrac, bfrac, cfrac;
+	
+	result.parts.sign = a.parts.sign ^ b.parts.sign;
+	
+	if (is_float32_nan(a)) {
+		if (is_float32_signan(a)) {
+			// FIXME: SigNaN
+		}
+		/* NaN */
+		return a;
+	}
+	
+	if (is_float32_nan(b)) {
+		if (is_float32_signan(b)) {
+			// FIXME: SigNaN
+		}
+		/* NaN */
+		return b;
+	}
+	
+	if (is_float32_infinity(a)) {
+		if (is_float32_infinity(b)) {
+			/*FIXME: inf / inf */
+			result.bin = FLOAT32_NAN;
+			return result;
+		}
+		/* inf / num */
+		result.parts.exp = a.parts.exp;
+		result.parts.fraction = a.parts.fraction;
+		return result;
+	}
+	
+	if (is_float32_infinity(b)) {
+		if (is_float32_zero(a)) {
+			/* FIXME 0 / inf */
+			result.parts.exp = 0;
+			result.parts.fraction = 0;
+			return result;
+		}
+		/* FIXME: num / inf*/
+		result.parts.exp = 0;
+		result.parts.fraction = 0;
+		return result;
+	}
+	
+	if (is_float32_zero(b)) {
+		if (is_float32_zero(a)) {
+			/*FIXME: 0 / 0*/
+			result.bin = FLOAT32_NAN;
+			return result;
+		}
+		/* FIXME: division by zero */
+		result.parts.exp = 0;
+		result.parts.fraction = 0;
+		return result;
+	}
+	
+	afrac = a.parts.fraction;
+	aexp = a.parts.exp;
+	bfrac = b.parts.fraction;
+	bexp = b.parts.exp;
+	
+	/* denormalized numbers */
+	if (aexp == 0) {
+		if (afrac == 0) {
+			result.parts.exp = 0;
+			result.parts.fraction = 0;
+			return result;
+		}
+		
+		/* normalize it*/
+		afrac <<= 1;
+		/* afrac is nonzero => it must stop */
+		while (!(afrac & FLOAT32_HIDDEN_BIT_MASK)) {
+			afrac <<= 1;
+			aexp--;
+		}
+	}
+	
+	if (bexp == 0) {
+		bfrac <<= 1;
+		/* bfrac is nonzero => it must stop */
+		while (!(bfrac & FLOAT32_HIDDEN_BIT_MASK)) {
+			bfrac <<= 1;
+			bexp--;
+		}
+	}
+	
+	afrac = (afrac | FLOAT32_HIDDEN_BIT_MASK) << (32 - FLOAT32_FRACTION_SIZE - 1);
+	bfrac = (bfrac | FLOAT32_HIDDEN_BIT_MASK) << (32 - FLOAT32_FRACTION_SIZE);
+	
+	if (bfrac <= (afrac << 1)) {
+		afrac >>= 1;
+		aexp++;
+	}
+	
+	cexp = aexp - bexp + FLOAT32_BIAS - 2;
+	
+	cfrac = (afrac << 32) / bfrac;
+	if ((cfrac & 0x3F) == 0) { 
+		cfrac |= (bfrac * cfrac != afrac << 32);
+	}
+	
+	/* pack and round */
+	
+	/* find first nonzero digit and shift result and detect possibly underflow */
+	while ((cexp > 0) && (cfrac) && (!(cfrac & (FLOAT32_HIDDEN_BIT_MASK << 7)))) {
+		cexp--;
+		cfrac <<= 1;
+		/* TODO: fix underflow */
+	}
+	
+	cfrac += (0x1 << 6); /* FIXME: 7 is not sure*/
+	
+	if (cfrac & (FLOAT32_HIDDEN_BIT_MASK << 7)) {
+		++cexp;
+		cfrac >>= 1;
+	}
+	
+	/* check overflow */
+	if (cexp >= FLOAT32_MAX_EXPONENT) {
+		/* FIXME: overflow, return infinity */
+		result.parts.exp = FLOAT32_MAX_EXPONENT;
+		result.parts.fraction = 0;
+		return result;
+	}
+	
+	if (cexp < 0) {
+		/* FIXME: underflow */
+		result.parts.exp = 0;
+		if ((cexp + FLOAT32_FRACTION_SIZE) < 0) {
+			result.parts.fraction = 0;
+			return result;
+		}
+		cfrac >>= 1;
+		while (cexp < 0) {
+			cexp++;
+			cfrac >>= 1;
+		}
+	} else {
+		result.parts.exp = (uint32_t) cexp;
+	}
+	
+	result.parts.fraction = ((cfrac >> 6) & (~FLOAT32_HIDDEN_BIT_MASK)); 
+	
+	return result;
+}
+
+/** Divide two double-precision floats.
+ *
+ * @param a Nominator.
+ * @param b Denominator.
+ *
+ * @return Result of division.
+ *
+ */
+float64 div_float64(float64 a, float64 b) 
+{
+	float64 result;
+	int64_t aexp, bexp, cexp;
+	uint64_t afrac, bfrac, cfrac; 
+	uint64_t remlo, remhi;
+	uint64_t tmplo, tmphi;
+	
+	result.parts.sign = a.parts.sign ^ b.parts.sign;
+	
+	if (is_float64_nan(a)) {
+		if (is_float64_signan(b)) {
+			// FIXME: SigNaN
+			return b;
+		}
+		
+		if (is_float64_signan(a)) {
+			// FIXME: SigNaN
+		}
+		/* NaN */
+		return a;
+	}
+	
+	if (is_float64_nan(b)) {
+		if (is_float64_signan(b)) {
+			// FIXME: SigNaN
+		}
+		/* NaN */
+		return b;
+	}
+	
+	if (is_float64_infinity(a)) {
+		if (is_float64_infinity(b) || is_float64_zero(b)) {
+			// FIXME: inf / inf
+			result.bin = FLOAT64_NAN;
+			return result;
+		}
+		/* inf / num */
+		result.parts.exp = a.parts.exp;
+		result.parts.fraction = a.parts.fraction;
+		return result;
+	}
+	
+	if (is_float64_infinity(b)) {
+		if (is_float64_zero(a)) {
+			/* FIXME 0 / inf */
+			result.parts.exp = 0;
+			result.parts.fraction = 0;
+			return result;
+		}
+		/* FIXME: num / inf*/
+		result.parts.exp = 0;
+		result.parts.fraction = 0;
+		return result;
+	}
+	
+	if (is_float64_zero(b)) {
+		if (is_float64_zero(a)) {
+			/*FIXME: 0 / 0*/
+			result.bin = FLOAT64_NAN;
+			return result;
+		}
+		/* FIXME: division by zero */
+		result.parts.exp = 0;
+		result.parts.fraction = 0;
+		return result;
+	}
+	
+	afrac = a.parts.fraction;
+	aexp = a.parts.exp;
+	bfrac = b.parts.fraction;
+	bexp = b.parts.exp;
+	
+	/* denormalized numbers */
+	if (aexp == 0) {
+		if (afrac == 0) {
+			result.parts.exp = 0;
+			result.parts.fraction = 0;
+			return result;
+		}
+		
+		/* normalize it*/
+		aexp++;
+		/* afrac is nonzero => it must stop */	
+		while (!(afrac & FLOAT64_HIDDEN_BIT_MASK)) {
+			afrac <<= 1;
+			aexp--;
+		}
+	}
+	
+	if (bexp == 0) {
+		bexp++;
+		/* bfrac is nonzero => it must stop */	
+		while (!(bfrac & FLOAT64_HIDDEN_BIT_MASK)) {
+			bfrac <<= 1;
+			bexp--;
+		}
+	}
+	
+	afrac = (afrac | FLOAT64_HIDDEN_BIT_MASK) << (64 - FLOAT64_FRACTION_SIZE - 2);
+	bfrac = (bfrac | FLOAT64_HIDDEN_BIT_MASK) << (64 - FLOAT64_FRACTION_SIZE - 1);
+	
+	if (bfrac <= (afrac << 1)) {
+		afrac >>= 1;
+		aexp++;
+	}
+	
+	cexp = aexp - bexp + FLOAT64_BIAS - 2; 
+	
+	cfrac = div128est(afrac, 0x0ll, bfrac);
+	
+	if ((cfrac & 0x1FF) <= 2) {
+		mul64(bfrac, cfrac, &tmphi, &tmplo);
+		sub128(afrac, 0x0ll, tmphi, tmplo, &remhi, &remlo);
+		
+		while ((int64_t) remhi < 0) {
+			cfrac--;
+			add128(remhi, remlo, 0x0ll, bfrac, &remhi, &remlo);
+		}
+		cfrac |= (remlo != 0);
+	}
+	
+	/* round and shift */
+	result = finish_float64(cexp, cfrac, result.parts.sign);
+	return result;
+}
+
+/** Divide two quadruple-precision floats.
+ *
+ * @param a Nominator.
+ * @param b Denominator.
+ *
+ * @return Result of division.
+ *
+ */
+float128 div_float128(float128 a, float128 b)
+{
+	float128 result;
+	int64_t aexp, bexp, cexp;
+	uint64_t afrac_hi, afrac_lo, bfrac_hi, bfrac_lo, cfrac_hi, cfrac_lo;
+	uint64_t shift_out;
+	uint64_t rem_hihi, rem_hilo, rem_lohi, rem_lolo;
+	uint64_t tmp_hihi, tmp_hilo, tmp_lohi, tmp_lolo;
+	
+	result.parts.sign = a.parts.sign ^ b.parts.sign;
+	
+	if (is_float128_nan(a)) {
+		if (is_float128_signan(b)) {
+			// FIXME: SigNaN
+			return b;
+		}
+		
+		if (is_float128_signan(a)) {
+			// FIXME: SigNaN
+		}
+		/* NaN */
+		return a;
+	}
+	
+	if (is_float128_nan(b)) {
+		if (is_float128_signan(b)) {
+			// FIXME: SigNaN
+		}
+		/* NaN */
+		return b;
+	}
+	
+	if (is_float128_infinity(a)) {
+		if (is_float128_infinity(b) || is_float128_zero(b)) {
+			// FIXME: inf / inf
+			result.bin.hi = FLOAT128_NAN_HI;
+			result.bin.lo = FLOAT128_NAN_LO;
+			return result;
+		}
+		/* inf / num */
+		result.parts.exp = a.parts.exp;
+		result.parts.frac_hi = a.parts.frac_hi;
+		result.parts.frac_lo = a.parts.frac_lo;
+		return result;
+	}
+	
+	if (is_float128_infinity(b)) {
+		if (is_float128_zero(a)) {
+			// FIXME 0 / inf
+			result.parts.exp = 0;
+			result.parts.frac_hi = 0;
+			result.parts.frac_lo = 0;
+			return result;
+		}
+		// FIXME: num / inf
+		result.parts.exp = 0;
+		result.parts.frac_hi = 0;
+		result.parts.frac_lo = 0;
+		return result;
+	}
+	
+	if (is_float128_zero(b)) {
+		if (is_float128_zero(a)) {
+			// FIXME: 0 / 0
+			result.bin.hi = FLOAT128_NAN_HI;
+			result.bin.lo = FLOAT128_NAN_LO;
+			return result;
+		}
+		// FIXME: division by zero
+		result.parts.exp = 0;
+		result.parts.frac_hi = 0;
+		result.parts.frac_lo = 0;
+		return result;
+	}
+	
+	afrac_hi = a.parts.frac_hi;
+	afrac_lo = a.parts.frac_lo;
+	aexp = a.parts.exp;
+	bfrac_hi = b.parts.frac_hi;
+	bfrac_lo = b.parts.frac_lo;
+	bexp = b.parts.exp;
+	
+	/* denormalized numbers */
+	if (aexp == 0) {
+		if (eq128(afrac_hi, afrac_lo, 0x0ll, 0x0ll)) {
+			result.parts.exp = 0;
+			result.parts.frac_hi = 0;
+			result.parts.frac_lo = 0;
+			return result;
+		}
+		
+		/* normalize it*/
+		aexp++;
+		/* afrac is nonzero => it must stop */
+		and128(afrac_hi, afrac_lo,
+		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+		    &tmp_hihi, &tmp_lolo);
+		while (!lt128(0x0ll, 0x0ll, tmp_hihi, tmp_lolo)) {
+			lshift128(afrac_hi, afrac_lo, 1, &afrac_hi, &afrac_lo);
+			aexp--;
+		}
+	}
+	
+	if (bexp == 0) {
+		bexp++;
+		/* bfrac is nonzero => it must stop */
+		and128(bfrac_hi, bfrac_lo,
+		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+		    &tmp_hihi, &tmp_lolo);
+		while (!lt128(0x0ll, 0x0ll, tmp_hihi, tmp_lolo)) {
+			lshift128(bfrac_hi, bfrac_lo, 1, &bfrac_hi, &bfrac_lo);
+			bexp--;
+		}
+	}
+	
+	or128(afrac_hi, afrac_lo,
+	    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+	    &afrac_hi, &afrac_lo);
+	lshift128(afrac_hi, afrac_lo,
+	    (128 - FLOAT128_FRACTION_SIZE - 1), &afrac_hi, &afrac_lo);
+	or128(bfrac_hi, bfrac_lo,
+	    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+	    &bfrac_hi, &bfrac_lo);
+	lshift128(bfrac_hi, bfrac_lo,
+	    (128 - FLOAT128_FRACTION_SIZE - 1), &bfrac_hi, &bfrac_lo);
+	
+	if (le128(bfrac_hi, bfrac_lo, afrac_hi, afrac_lo)) {
+		rshift128(afrac_hi, afrac_lo, 1, &afrac_hi, &afrac_lo);
+		aexp++;
+	}
+	
+	cexp = aexp - bexp + FLOAT128_BIAS - 2;
+	
+	cfrac_hi = div128est(afrac_hi, afrac_lo, bfrac_hi);
+	
+	mul128(bfrac_hi, bfrac_lo, 0x0ll, cfrac_hi,
+	    &tmp_lolo /* dummy */, &tmp_hihi, &tmp_hilo, &tmp_lohi);
+	
+	/* sub192(afrac_hi, afrac_lo, 0,
+	 *     tmp_hihi, tmp_hilo, tmp_lohi
+	 *     &rem_hihi, &rem_hilo, &rem_lohi); */
+	sub128(afrac_hi, afrac_lo, tmp_hihi, tmp_hilo, &rem_hihi, &rem_hilo);
+	if (tmp_lohi > 0) {
+		sub128(rem_hihi, rem_hilo, 0x0ll, 0x1ll, &rem_hihi, &rem_hilo);
+	}
+	rem_lohi = -tmp_lohi;
+	
+	while ((int64_t) rem_hihi < 0) {
+		--cfrac_hi;
+		/* add192(rem_hihi, rem_hilo, rem_lohi,
+		 *     0, bfrac_hi, bfrac_lo,
+		 *     &rem_hihi, &rem_hilo, &rem_lohi); */
+		add128(rem_hilo, rem_lohi, bfrac_hi, bfrac_lo, &rem_hilo, &rem_lohi);
+		if (lt128(rem_hilo, rem_lohi, bfrac_hi, bfrac_lo)) {
+			++rem_hihi;
+		}
+	}
+	
+	cfrac_lo = div128est(rem_hilo, rem_lohi, bfrac_lo);
+	
+	if ((cfrac_lo & 0x3FFF) <= 4) {
+		mul128(bfrac_hi, bfrac_lo, 0x0ll, cfrac_lo,
+		    &tmp_hihi /* dummy */, &tmp_hilo, &tmp_lohi, &tmp_lolo);
+		
+		/* sub192(rem_hilo, rem_lohi, 0,
+		 *     tmp_hilo, tmp_lohi, tmp_lolo,
+		 *     &rem_hilo, &rem_lohi, &rem_lolo); */
+		sub128(rem_hilo, rem_lohi, tmp_hilo, tmp_lohi, &rem_hilo, &rem_lohi);
+		if (tmp_lolo > 0) {
+			sub128(rem_hilo, rem_lohi, 0x0ll, 0x1ll, &rem_hilo, &rem_lohi);
+		}
+		rem_lolo = -tmp_lolo;
+		
+		while ((int64_t) rem_hilo < 0) {
+			--cfrac_lo;
+			/* add192(rem_hilo, rem_lohi, rem_lolo,
+			 *     0, bfrac_hi, bfrac_lo,
+			 *     &rem_hilo, &rem_lohi, &rem_lolo); */
+			add128(rem_lohi, rem_lolo, bfrac_hi, bfrac_lo, &rem_lohi, &rem_lolo);
+			if (lt128(rem_lohi, rem_lolo, bfrac_hi, bfrac_lo)) {
+				++rem_hilo;
+			}
+		}
+		
+		cfrac_lo |= ((rem_hilo | rem_lohi | rem_lolo) != 0 );
+	}
+	
+	shift_out = cfrac_lo << (64 - (128 - FLOAT128_FRACTION_SIZE - 1));
+	rshift128(cfrac_hi, cfrac_lo, (128 - FLOAT128_FRACTION_SIZE - 1),
+	    &cfrac_hi, &cfrac_lo);
+	
+	result = finish_float128(cexp, cfrac_hi, cfrac_lo, result.parts.sign, shift_out);
+	return result;
+}
+
+/** @}
+ */
Index: uspace/lib/softfloat/div.h
===================================================================
--- uspace/lib/softfloat/div.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/div.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Division functions.
+ */
+
+#ifndef __DIV_H__
+#define __DIV_H__
+
+extern float32 div_float32(float32, float32);
+extern float64 div_float64(float64, float64);
+extern float96 div_float96(float96, float96);
+extern float128 div_float128(float128, float128);
+
+#endif
+
+/** @}
+ */
Index: pace/lib/softfloat/generic/add.c
===================================================================
--- uspace/lib/softfloat/generic/add.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,416 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Addition functions.
- */
-
-#include <sftypes.h>
-#include <add.h>
-#include <comparison.h>
-#include <common.h>
-
-/** Add two single-precision floats with the same sign.
- *
- * @param a First input operand.
- * @param b Second input operand.
- * @return Result of addition.
- */
-float32 add_float32(float32 a, float32 b)
-{
-	int expdiff;
-	uint32_t exp1, exp2, frac1, frac2;
-	
-	expdiff = a.parts.exp - b.parts.exp;
-	if (expdiff < 0) {
-		if (is_float32_nan(b)) {
-			/* TODO: fix SigNaN */
-			if (is_float32_signan(b)) {
-			}
-
-			return b;
-		}
-		
-		if (b.parts.exp == FLOAT32_MAX_EXPONENT) { 
-			return b;
-		}
-		
-		frac1 = b.parts.fraction;
-		exp1 = b.parts.exp;
-		frac2 = a.parts.fraction;
-		exp2 = a.parts.exp;
-		expdiff *= -1;
-	} else {
-		if ((is_float32_nan(a)) || (is_float32_nan(b))) {
-			/* TODO: fix SigNaN */
-			if (is_float32_signan(a) || is_float32_signan(b)) {
-			}
-			return (is_float32_nan(a) ? a : b);
-		}
-		
-		if (a.parts.exp == FLOAT32_MAX_EXPONENT) { 
-			return a;
-		}
-		
-		frac1 = a.parts.fraction;
-		exp1 = a.parts.exp;
-		frac2 = b.parts.fraction;
-		exp2 = b.parts.exp;
-	}
-	
-	if (exp1 == 0) {
-		/* both are denormalized */
-		frac1 += frac2;
-		if (frac1 & FLOAT32_HIDDEN_BIT_MASK ) {
-			/* result is not denormalized */
-			a.parts.exp = 1;
-		}
-		a.parts.fraction = frac1;
-		return a;
-	}
-	
-	frac1 |= FLOAT32_HIDDEN_BIT_MASK; /* add hidden bit */
-
-	if (exp2 == 0) {
-		/* second operand is denormalized */
-		--expdiff;
-	} else {
-		/* add hidden bit to second operand */
-		frac2 |= FLOAT32_HIDDEN_BIT_MASK; 
-	}
-	
-	/* create some space for rounding */
-	frac1 <<= 6;
-	frac2 <<= 6;
-	
-	if (expdiff < (FLOAT32_FRACTION_SIZE + 2) ) {
-		frac2 >>= expdiff;
-		frac1 += frac2;
-	} else {
-		a.parts.exp = exp1;
-		a.parts.fraction = (frac1 >> 6) & (~(FLOAT32_HIDDEN_BIT_MASK));
-		return a;
-	}
-	
-	if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7) ) {
-		++exp1;
-		frac1 >>= 1;
-	}
-	
-	/* rounding - if first bit after fraction is set then round up */
-	frac1 += (0x1 << 5);
-	
-	if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7)) { 
-		/* rounding overflow */
-		++exp1;
-		frac1 >>= 1;
-	}
-	
-	if ((exp1 == FLOAT32_MAX_EXPONENT ) || (exp2 > exp1)) {
-		/* overflow - set infinity as result */
-		a.parts.exp = FLOAT32_MAX_EXPONENT;
-		a.parts.fraction = 0;
-		return a;
-	}
-	
-	a.parts.exp = exp1;
-	
-	/* Clear hidden bit and shift */
-	a.parts.fraction = ((frac1 >> 6) & (~FLOAT32_HIDDEN_BIT_MASK)); 
-	return a;
-}
-
-/** Add two double-precision floats with the same sign.
- *
- * @param a First input operand.
- * @param b Second input operand.
- * @return Result of addition.
- */
-float64 add_float64(float64 a, float64 b)
-{
-	int expdiff;
-	uint32_t exp1, exp2;
-	uint64_t frac1, frac2;
-	
-	expdiff = ((int) a.parts.exp) - b.parts.exp;
-	if (expdiff < 0) {
-		if (is_float64_nan(b)) {
-			/* TODO: fix SigNaN */
-			if (is_float64_signan(b)) {
-			}
-
-			return b;
-		}
-		
-		/* b is infinity and a not */
-		if (b.parts.exp == FLOAT64_MAX_EXPONENT) {
-			return b;
-		}
-		
-		frac1 = b.parts.fraction;
-		exp1 = b.parts.exp;
-		frac2 = a.parts.fraction;
-		exp2 = a.parts.exp;
-		expdiff *= -1;
-	} else {
-		if (is_float64_nan(a)) {
-			/* TODO: fix SigNaN */
-			if (is_float64_signan(a) || is_float64_signan(b)) {
-			}
-			return a;
-		}
-		
-		/* a is infinity and b not */
-		if (a.parts.exp == FLOAT64_MAX_EXPONENT) { 
-			return a;
-		}
-		
-		frac1 = a.parts.fraction;
-		exp1 = a.parts.exp;
-		frac2 = b.parts.fraction;
-		exp2 = b.parts.exp;
-	}
-	
-	if (exp1 == 0) {
-		/* both are denormalized */
-		frac1 += frac2;
-		if (frac1 & FLOAT64_HIDDEN_BIT_MASK) { 
-			/* result is not denormalized */
-			a.parts.exp = 1;
-		}
-		a.parts.fraction = frac1;
-		return a;
-	}
-	
-	/* add hidden bit - frac1 is sure not denormalized */
-	frac1 |= FLOAT64_HIDDEN_BIT_MASK;
-
-	/* second operand ... */
-	if (exp2 == 0) {
-		/* ... is denormalized */
-		--expdiff;	
-	} else {
-		/* is not denormalized */
-		frac2 |= FLOAT64_HIDDEN_BIT_MASK;
-	}
-	
-	/* create some space for rounding */
-	frac1 <<= 6;
-	frac2 <<= 6;
-	
-	if (expdiff < (FLOAT64_FRACTION_SIZE + 2)) {
-		frac2 >>= expdiff;
-		frac1 += frac2;
-	} else {
-		a.parts.exp = exp1;
-		a.parts.fraction = (frac1 >> 6) & (~(FLOAT64_HIDDEN_BIT_MASK));
-		return a;
-	}
-	
-	if (frac1 & (FLOAT64_HIDDEN_BIT_MASK << 7)) {
-		++exp1;
-		frac1 >>= 1;
-	}
-	
-	/* rounding - if first bit after fraction is set then round up */
-	frac1 += (0x1 << 5); 
-	
-	if (frac1 & (FLOAT64_HIDDEN_BIT_MASK << 7)) { 
-		/* rounding overflow */
-		++exp1;
-		frac1 >>= 1;
-	}
-	
-	if ((exp1 == FLOAT64_MAX_EXPONENT ) || (exp2 > exp1)) {
-		/* overflow - set infinity as result */
-		a.parts.exp = FLOAT64_MAX_EXPONENT;
-		a.parts.fraction = 0;
-		return a;
-	}
-	
-	a.parts.exp = exp1;
-	/* Clear hidden bit and shift */
-	a.parts.fraction = ((frac1 >> 6 ) & (~FLOAT64_HIDDEN_BIT_MASK));
-	return a;
-}
-
-/** Add two quadruple-precision floats with the same sign.
- *
- * @param a First input operand.
- * @param b Second input operand.
- * @return Result of addition.
- */
-float128 add_float128(float128 a, float128 b)
-{
-	int expdiff;
-	uint32_t exp1, exp2;
-	uint64_t frac1_hi, frac1_lo, frac2_hi, frac2_lo, tmp_hi, tmp_lo;
-
-	expdiff = ((int) a.parts.exp) - b.parts.exp;
-	if (expdiff < 0) {
-		if (is_float128_nan(b)) {
-			/* TODO: fix SigNaN */
-			if (is_float128_signan(b)) {
-			}
-
-			return b;
-		}
-
-		/* b is infinity and a not */
-		if (b.parts.exp == FLOAT128_MAX_EXPONENT) {
-			return b;
-		}
-
-		frac1_hi = b.parts.frac_hi;
-		frac1_lo = b.parts.frac_lo;
-		exp1 = b.parts.exp;
-		frac2_hi = a.parts.frac_hi;
-		frac2_lo = a.parts.frac_lo;
-		exp2 = a.parts.exp;
-		expdiff *= -1;
-	} else {
-		if (is_float128_nan(a)) {
-			/* TODO: fix SigNaN */
-			if (is_float128_signan(a) || is_float128_signan(b)) {
-			}
-			return a;
-		}
-
-		/* a is infinity and b not */
-		if (a.parts.exp == FLOAT128_MAX_EXPONENT) {
-			return a;
-		}
-
-		frac1_hi = a.parts.frac_hi;
-		frac1_lo = a.parts.frac_lo;
-		exp1 = a.parts.exp;
-		frac2_hi = b.parts.frac_hi;
-		frac2_lo = b.parts.frac_lo;
-		exp2 = b.parts.exp;
-	}
-
-	if (exp1 == 0) {
-		/* both are denormalized */
-		add128(frac1_hi, frac1_lo, frac2_hi, frac2_lo, &frac1_hi, &frac1_lo);
-
-		and128(frac1_hi, frac1_lo,
-		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-		    &tmp_hi, &tmp_lo);
-		if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
-			/* result is not denormalized */
-			a.parts.exp = 1;
-		}
-
-		a.parts.frac_hi = frac1_hi;
-		a.parts.frac_lo = frac1_lo;
-		return a;
-	}
-
-	/* add hidden bit - frac1 is sure not denormalized */
-	or128(frac1_hi, frac1_lo,
-	    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-	    &frac1_hi, &frac1_lo);
-
-	/* second operand ... */
-	if (exp2 == 0) {
-		/* ... is denormalized */
-		--expdiff;
-	} else {
-		/* is not denormalized */
-		or128(frac2_hi, frac2_lo,
-		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-		    &frac2_hi, &frac2_lo);
-	}
-
-	/* create some space for rounding */
-	lshift128(frac1_hi, frac1_lo, 6, &frac1_hi, &frac1_lo);
-	lshift128(frac2_hi, frac2_lo, 6, &frac2_hi, &frac2_lo);
-
-	if (expdiff < (FLOAT128_FRACTION_SIZE + 2)) {
-		rshift128(frac2_hi, frac2_lo, expdiff, &frac2_hi, &frac2_lo);
-		add128(frac1_hi, frac1_lo, frac2_hi, frac2_lo, &frac1_hi, &frac1_lo);
-	} else {
-		a.parts.exp = exp1;
-
-		rshift128(frac1_hi, frac1_lo, 6, &frac1_hi, &frac1_lo);
-		not128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-		    &tmp_hi, &tmp_lo);
-		and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-
-		a.parts.frac_hi = tmp_hi;
-		a.parts.frac_lo = tmp_lo;
-		return a;
-	}
-
-	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 7,
-	    &tmp_hi, &tmp_lo);
-	and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-	if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
-		++exp1;
-		rshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
-	}
-
-	/* rounding - if first bit after fraction is set then round up */
-	add128(frac1_hi, frac1_lo, 0x0ll, 0x1ll << 5, &frac1_hi, &frac1_lo);
-
-	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 7,
-	   &tmp_hi, &tmp_lo);
-	and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-	if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
-		/* rounding overflow */
-		++exp1;
-		rshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
-	}
-
-	if ((exp1 == FLOAT128_MAX_EXPONENT ) || (exp2 > exp1)) {
-		/* overflow - set infinity as result */
-		a.parts.exp = FLOAT64_MAX_EXPONENT;
-		a.parts.frac_hi = 0;
-		a.parts.frac_lo = 0;
-		return a;
-	}
-
-	a.parts.exp = exp1;
-	
-	/* Clear hidden bit and shift */
-	rshift128(frac1_hi, frac1_lo, 6, &frac1_hi, &frac1_lo);
-	not128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-	    &tmp_hi, &tmp_lo);
-	and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-
-	a.parts.frac_hi = tmp_hi;
-	a.parts.frac_lo = tmp_lo;
-
-	return a;
-}
-
-/** @}
- */
Index: pace/lib/softfloat/generic/common.c
===================================================================
--- uspace/lib/softfloat/generic/common.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,690 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Common helper operations.
- */
-
-#include <sftypes.h>
-#include <common.h>
-
-/* Table for fast leading zeroes counting. */
-char zeroTable[256] = {
-	8, 7, 7, 6, 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, \
-	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, \
-	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
-	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/** 
- * Take fraction shifted by 10 bits to the left, round it, normalize it
- * and detect exceptions
- * 
- * @param cexp Exponent with bias.
- * @param cfrac Fraction shifted 10 bits to the left with added hidden bit.
- * @param sign Resulting sign.
- * @return Finished double-precision float.
- */
-float64 finish_float64(int32_t cexp, uint64_t cfrac, char sign)
-{
-	float64 result;
-
-	result.parts.sign = sign;
-
-	/* find first nonzero digit and shift result and detect possibly underflow */
-	while ((cexp > 0) && (cfrac) &&
-	    (!(cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1))))) {
-		cexp--; 
-		cfrac <<= 1;
-		/* TODO: fix underflow */
-	}
-	
-	if ((cexp < 0) || (cexp == 0 &&
-	    (!(cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1)))))) {
-		/* FIXME: underflow */
-		result.parts.exp = 0;
-		if ((cexp + FLOAT64_FRACTION_SIZE + 1) < 0) { /* +1 is place for rounding */
-			result.parts.fraction = 0;
-			return result;
-		}
-		
-		while (cexp < 0) {
-			cexp++;
-			cfrac >>= 1;
-		}
-	
-		cfrac += (0x1 << (64 - FLOAT64_FRACTION_SIZE - 3)); 
-		
-		if (!(cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1)))) {
-			result.parts.fraction =
-			    ((cfrac >> (64 - FLOAT64_FRACTION_SIZE - 2)) & (~FLOAT64_HIDDEN_BIT_MASK));
-			return result;
-		}	
-	} else {
-		cfrac += (0x1 << (64 - FLOAT64_FRACTION_SIZE - 3)); 
-	}
-	
-	++cexp;
-
-	if (cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1))) {
-		++cexp;
-		cfrac >>= 1;
-	}	
-
-	/* check overflow */
-	if (cexp >= FLOAT64_MAX_EXPONENT) {
-		/* FIXME: overflow, return infinity */
-		result.parts.exp = FLOAT64_MAX_EXPONENT;
-		result.parts.fraction = 0;
-		return result;
-	}
-
-	result.parts.exp = (uint32_t) cexp;
-	
-	result.parts.fraction = 
-	    ((cfrac >> (64 - FLOAT64_FRACTION_SIZE - 2)) & (~FLOAT64_HIDDEN_BIT_MASK));
-	
-	return result;	
-}
-
-/**
- * Take fraction, round it, normalize it and detect exceptions
- * 
- * @param cexp Exponent with bias.
- * @param cfrac_hi High part of the fraction shifted 14 bits to the left
- *     with added hidden bit.
- * @param cfrac_lo Low part of the fraction shifted 14 bits to the left
- *     with added hidden bit.
- * @param sign Resulting sign.
- * @param shift_out Bits right-shifted out from fraction by the caller.
- * @return Finished quadruple-precision float.
- */
-float128 finish_float128(int32_t cexp, uint64_t cfrac_hi, uint64_t cfrac_lo, 
-    char sign, uint64_t shift_out)
-{
-	float128 result;
-	uint64_t tmp_hi, tmp_lo;
-
-	result.parts.sign = sign;
-
-	/* find first nonzero digit and shift result and detect possibly underflow */
-	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-	    1, &tmp_hi, &tmp_lo);
-	and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-	while ((cexp > 0) && (lt128(0x0ll, 0x0ll, cfrac_hi, cfrac_lo)) &&
-	    (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo))) {
-		cexp--;
-		lshift128(cfrac_hi, cfrac_lo, 1, &cfrac_hi, &cfrac_lo);
-		/* TODO: fix underflow */
-
-		lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-		    1, &tmp_hi, &tmp_lo);
-		and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-	}
-
-	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-	    1, &tmp_hi, &tmp_lo);
-	and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-	if ((cexp < 0) || (cexp == 0 &&
-	    (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)))) {
-		/* FIXME: underflow */
-		result.parts.exp = 0;
-		if ((cexp + FLOAT128_FRACTION_SIZE + 1) < 0) { /* +1 is place for rounding */
-			result.parts.frac_hi = 0x0ll;
-			result.parts.frac_lo = 0x0ll;
-			return result;
-		}
-
-		while (cexp < 0) {
-			cexp++;
-			rshift128(cfrac_hi, cfrac_lo, 1, &cfrac_hi, &cfrac_lo);
-		}
-
-		if (shift_out & (0x1ull < 64)) {
-			add128(cfrac_hi, cfrac_lo, 0x0ll, 0x1ll, &cfrac_hi, &cfrac_lo);
-		}
-
-		lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-		    1, &tmp_hi, &tmp_lo);
-		and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-		if (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
-			not128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-			    &tmp_hi, &tmp_lo);
-			and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-			result.parts.frac_hi = tmp_hi;
-			result.parts.frac_lo = tmp_lo;
-			return result;
-		}
-	} else {
-		if (shift_out & (0x1ull < 64)) {
-			add128(cfrac_hi, cfrac_lo, 0x0ll, 0x1ll, &cfrac_hi, &cfrac_lo);
-		}
-	}
-
-	++cexp;
-
-	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-	    1, &tmp_hi, &tmp_lo);
-	and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-	if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
-		++cexp;
-		rshift128(cfrac_hi, cfrac_lo, 1, &cfrac_hi, &cfrac_lo);
-	}
-
-	/* check overflow */
-	if (cexp >= FLOAT128_MAX_EXPONENT) {
-		/* FIXME: overflow, return infinity */
-		result.parts.exp = FLOAT128_MAX_EXPONENT;
-		result.parts.frac_hi = 0x0ll;
-		result.parts.frac_lo = 0x0ll;
-		return result;
-	}
-
-	result.parts.exp = (uint32_t) cexp;
-
-	not128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-	    &tmp_hi, &tmp_lo);
-	and128(cfrac_hi, cfrac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-	result.parts.frac_hi = tmp_hi;
-	result.parts.frac_lo = tmp_lo;
-
-	return result;	
-}
-
-/**
- * Counts leading zeroes in byte.
- *
- * @param i Byte for which to count leading zeroes.
- * @return Number of detected leading zeroes.
- */
-int count_zeroes8(uint8_t i)
-{
-	return zeroTable[i];
-}
-
-/** 
- * Counts leading zeroes in 32bit unsigned integer.
- *
- * @param i Integer for which to count leading zeroes.
- * @return Number of detected leading zeroes.
- */
-int count_zeroes32(uint32_t i)
-{
-	int j;
-	for (j = 0; j < 32; j += 8) {
-		if (i & (0xFF << (24 - j))) {
-			return (j + count_zeroes8(i >> (24 - j)));
-		}
-	}
-
-	return 32;
-}
-
-/**
- * Counts leading zeroes in 64bit unsigned integer.
- *
- * @param i Integer for which to count leading zeroes.
- * @return Number of detected leading zeroes.
- */
-int count_zeroes64(uint64_t i)
-{
-	int j;
-	for (j = 0; j < 64; j += 8) {
-		if (i & (0xFFll << (56 - j))) {
-			return (j + count_zeroes8(i >> (56 - j)));
-		}
-	}
-
-	return 64;
-}
-
-/**
- * Round and normalize number expressed by exponent and fraction with
- * first bit (equal to hidden bit) at 30th bit.
- *
- * @param exp Exponent part.
- * @param fraction Fraction with hidden bit shifted to 30th bit.
- */
-void round_float32(int32_t *exp, uint32_t *fraction)
-{
-	/* rounding - if first bit after fraction is set then round up */
-	(*fraction) += (0x1 << (32 - FLOAT32_FRACTION_SIZE - 3));
-	
-	if ((*fraction) & 
-	    (FLOAT32_HIDDEN_BIT_MASK << (32 - FLOAT32_FRACTION_SIZE - 1))) {
-		/* rounding overflow */
-		++(*exp);
-		(*fraction) >>= 1;
-	}
-	
-	if (((*exp) >= FLOAT32_MAX_EXPONENT) || ((*exp) < 0)) {
-		/* overflow - set infinity as result */
-		(*exp) = FLOAT32_MAX_EXPONENT;
-		(*fraction) = 0;
-	}
-}
-
-/**
- * Round and normalize number expressed by exponent and fraction with
- * first bit (equal to hidden bit) at 62nd bit.
- *
- * @param exp Exponent part.
- * @param fraction Fraction with hidden bit shifted to 62nd bit.
- */
-void round_float64(int32_t *exp, uint64_t *fraction)
-{
-	/* rounding - if first bit after fraction is set then round up */
-	(*fraction) += (0x1 << (64 - FLOAT64_FRACTION_SIZE - 3));
-	
-	if ((*fraction) & 
-	    (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 3))) {
-		/* rounding overflow */
-		++(*exp);
-		(*fraction) >>= 1;
-	}
-	
-	if (((*exp) >= FLOAT64_MAX_EXPONENT) || ((*exp) < 0)) {
-		/* overflow - set infinity as result */
-		(*exp) = FLOAT64_MAX_EXPONENT;
-		(*fraction) = 0;
-	}
-}
-
-/**
- * Round and normalize number expressed by exponent and fraction with
- * first bit (equal to hidden bit) at 126th bit.
- *
- * @param exp Exponent part.
- * @param frac_hi High part of fraction part with hidden bit shifted to 126th bit.
- * @param frac_lo Low part of fraction part with hidden bit shifted to 126th bit.
- */
-void round_float128(int32_t *exp, uint64_t *frac_hi, uint64_t *frac_lo)
-{
-	uint64_t tmp_hi, tmp_lo;
-
-	/* rounding - if first bit after fraction is set then round up */
-	lshift128(0x0ll, 0x1ll, (128 - FLOAT128_FRACTION_SIZE - 3), &tmp_hi, &tmp_lo);
-	add128(*frac_hi, *frac_lo, tmp_hi, tmp_lo, frac_hi, frac_lo);
-
-	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-	    (128 - FLOAT128_FRACTION_SIZE - 3), &tmp_hi, &tmp_lo);
-	and128(*frac_hi, *frac_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-	if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
-		/* rounding overflow */
-		++(*exp);
-		rshift128(*frac_hi, *frac_lo, 1, frac_hi, frac_lo);
-	}
-
-	if (((*exp) >= FLOAT128_MAX_EXPONENT) || ((*exp) < 0)) {
-		/* overflow - set infinity as result */
-		(*exp) = FLOAT128_MAX_EXPONENT;
-		(*frac_hi) = 0;
-		(*frac_lo) = 0;
-	}
-}
-
-/**
- * Logical shift left on the 128-bit operand.
- *
- * @param a_hi High part of the input operand.
- * @param a_lo Low part of the input operand.
- * @param shift Number of bits by witch to shift.
- * @param r_hi Address to store high part of the result.
- * @param r_lo Address to store low part of the result.
- */
-void lshift128(
-    uint64_t a_hi, uint64_t a_lo, int shift,
-    uint64_t *r_hi, uint64_t *r_lo)
-{
-	if (shift <= 0) {
-		/* do nothing */
-	} else if (shift >= 128) {
-		a_hi = 0;
-		a_lo = 0;
-	} else if (shift >= 64) {
-		a_hi = a_lo << (shift - 64);
-		a_lo = 0;
-	} else {
-		a_hi <<= shift;
-		a_hi |= a_lo >> (64 - shift);
-		a_lo <<= shift;
-	}
-
-	*r_hi = a_hi;
-	*r_lo = a_lo;
-}
-
-/**
- * Logical shift right on the 128-bit operand.
- *
- * @param a_hi High part of the input operand.
- * @param a_lo Low part of the input operand.
- * @param shift Number of bits by witch to shift.
- * @param r_hi Address to store high part of the result.
- * @param r_lo Address to store low part of the result.
- */
-void rshift128(
-    uint64_t a_hi, uint64_t a_lo, int shift,
-    uint64_t *r_hi, uint64_t *r_lo)
-{
-	if (shift <= 0) {
-		/* do nothing */
-	} else 	if (shift >= 128) {
-		a_hi = 0;
-		a_lo = 0;
-	} else if (shift >= 64) {
-		a_lo = a_hi >> (shift - 64);
-		a_hi = 0;
-	} else {
-		a_lo >>= shift;
-		a_lo |= a_hi << (64 - shift);
-		a_hi >>= shift;
-	}
-
-	*r_hi = a_hi;
-	*r_lo = a_lo;
-}
-
-/**
- * Bitwise AND on 128-bit operands.
- *
- * @param a_hi High part of the first input operand.
- * @param a_lo Low part of the first input operand.
- * @param b_hi High part of the second input operand.
- * @param b_lo Low part of the second input operand.
- * @param r_hi Address to store high part of the result.
- * @param r_lo Address to store low part of the result.
- */
-void and128(
-    uint64_t a_hi, uint64_t a_lo,
-    uint64_t b_hi, uint64_t b_lo,
-    uint64_t *r_hi, uint64_t *r_lo)
-{
-	*r_hi = a_hi & b_hi;
-	*r_lo = a_lo & b_lo;
-}
-
-/**
- * Bitwise inclusive OR on 128-bit operands.
- *
- * @param a_hi High part of the first input operand.
- * @param a_lo Low part of the first input operand.
- * @param b_hi High part of the second input operand.
- * @param b_lo Low part of the second input operand.
- * @param r_hi Address to store high part of the result.
- * @param r_lo Address to store low part of the result.
- */
-void or128(
-    uint64_t a_hi, uint64_t a_lo,
-    uint64_t b_hi, uint64_t b_lo,
-    uint64_t *r_hi, uint64_t *r_lo)
-{
-	*r_hi = a_hi | b_hi;
-	*r_lo = a_lo | b_lo;
-}
-
-/**
- * Bitwise exclusive OR on 128-bit operands.
- *
- * @param a_hi High part of the first input operand.
- * @param a_lo Low part of the first input operand.
- * @param b_hi High part of the second input operand.
- * @param b_lo Low part of the second input operand.
- * @param r_hi Address to store high part of the result.
- * @param r_lo Address to store low part of the result.
- */
-void xor128(
-    uint64_t a_hi, uint64_t a_lo,
-    uint64_t b_hi, uint64_t b_lo,
-    uint64_t *r_hi, uint64_t *r_lo)
-{
-	*r_hi = a_hi ^ b_hi;
-	*r_lo = a_lo ^ b_lo;
-}
-
-/**
- * Bitwise NOT on the 128-bit operand.
- *
- * @param a_hi High part of the input operand.
- * @param a_lo Low part of the input operand.
- * @param r_hi Address to store high part of the result.
- * @param r_lo Address to store low part of the result.
- */
-void not128(
-    uint64_t a_hi, uint64_t a_lo,
-	uint64_t *r_hi, uint64_t *r_lo)
-{
-	*r_hi = ~a_hi;
-	*r_lo = ~a_lo;
-}
-
-/**
- * Equality comparison of 128-bit operands.
- *
- * @param a_hi High part of the first input operand.
- * @param a_lo Low part of the first input operand.
- * @param b_hi High part of the second input operand.
- * @param b_lo Low part of the second input operand.
- * @return 1 if operands are equal, 0 otherwise.
- */
-int eq128(uint64_t a_hi, uint64_t a_lo, uint64_t b_hi, uint64_t b_lo)
-{
-	return (a_hi == b_hi) && (a_lo == b_lo);
-}
-
-/**
- * Lower-or-equal comparison of 128-bit operands.
- *
- * @param a_hi High part of the first input operand.
- * @param a_lo Low part of the first input operand.
- * @param b_hi High part of the second input operand.
- * @param b_lo Low part of the second input operand.
- * @return 1 if a is lower or equal to b, 0 otherwise.
- */
-int le128(uint64_t a_hi, uint64_t a_lo, uint64_t b_hi, uint64_t b_lo)
-{
-	return (a_hi < b_hi) || ((a_hi == b_hi) && (a_lo <= b_lo));
-}
-
-/**
- * Lower-than comparison of 128-bit operands.
- *
- * @param a_hi High part of the first input operand.
- * @param a_lo Low part of the first input operand.
- * @param b_hi High part of the second input operand.
- * @param b_lo Low part of the second input operand.
- * @return 1 if a is lower than b, 0 otherwise.
- */
-int lt128(uint64_t a_hi, uint64_t a_lo, uint64_t b_hi, uint64_t b_lo)
-{
-	return (a_hi < b_hi) || ((a_hi == b_hi) && (a_lo < b_lo));
-}
-
-/**
- * Addition of two 128-bit unsigned integers.
- *
- * @param a_hi High part of the first input operand.
- * @param a_lo Low part of the first input operand.
- * @param b_hi High part of the second input operand.
- * @param b_lo Low part of the second input operand.
- * @param r_hi Address to store high part of the result.
- * @param r_lo Address to store low part of the result.
- */
-void add128(uint64_t a_hi, uint64_t a_lo,
-    uint64_t b_hi, uint64_t b_lo,
-    uint64_t *r_hi, uint64_t *r_lo)
-{
-	uint64_t low = a_lo + b_lo;
-	*r_lo = low;
-	/* detect overflow to add a carry */
-	*r_hi = a_hi + b_hi + (low < a_lo);
-}
-
-/**
- * Substraction of two 128-bit unsigned integers.
- *
- * @param a_hi High part of the first input operand.
- * @param a_lo Low part of the first input operand.
- * @param b_hi High part of the second input operand.
- * @param b_lo Low part of the second input operand.
- * @param r_hi Address to store high part of the result.
- * @param r_lo Address to store low part of the result.
- */
-void sub128(uint64_t a_hi, uint64_t a_lo,
-    uint64_t b_hi, uint64_t b_lo,
-    uint64_t *r_hi, uint64_t *r_lo)
-{
-	*r_lo = a_lo - b_lo;
-	/* detect underflow to substract a carry */
-	*r_hi = a_hi - b_hi - (a_lo < b_lo);
-}
-
-/**
- * Multiplication of two 64-bit unsigned integers.
- * 
- * @param a First input operand.
- * @param b Second input operand.
- * @param r_hi Address to store high part of the result.
- * @param r_lo Address to store low part of the result.
- */
-void mul64(uint64_t a, uint64_t b, uint64_t *r_hi, uint64_t *r_lo)
-{
-	uint64_t low, high, middle1, middle2;
-	uint32_t alow, blow;
-
-	alow = a & 0xFFFFFFFF;
-	blow = b & 0xFFFFFFFF;
-
-	a >>= 32;
-	b >>= 32;
-
-	low = ((uint64_t) alow) * blow;
-	middle1 = a * blow;
-	middle2 = alow * b;
-	high = a * b;
-
-	middle1 += middle2;
-	high += (((uint64_t) (middle1 < middle2)) << 32) + (middle1 >> 32);
-	middle1 <<= 32;
-	low += middle1;
-	high += (low < middle1);
-	*r_lo = low;
-	*r_hi = high;
-}
-
-/**
- * Multiplication of two 128-bit unsigned integers.
- * 
- * @param a_hi High part of the first input operand.
- * @param a_lo Low part of the first input operand.
- * @param b_hi High part of the second input operand.
- * @param b_lo Low part of the second input operand.
- * @param r_hihi Address to store first (highest) quarter of the result.
- * @param r_hilo Address to store second quarter of the result.
- * @param r_lohi Address to store third quarter of the result.
- * @param r_lolo Address to store fourth (lowest) quarter of the result.
- */
-void mul128(uint64_t a_hi, uint64_t a_lo, uint64_t b_hi, uint64_t b_lo,
-    uint64_t *r_hihi, uint64_t *r_hilo, uint64_t *r_lohi, uint64_t *r_lolo)
-{
-	uint64_t hihi, hilo, lohi, lolo;
-	uint64_t tmp1, tmp2;
-
-	mul64(a_lo, b_lo, &lohi, &lolo);
-	mul64(a_lo, b_hi, &hilo, &tmp2);
-	add128(hilo, tmp2, 0x0ll, lohi, &hilo, &lohi);
-	mul64(a_hi, b_hi, &hihi, &tmp1);
-	add128(hihi, tmp1, 0x0ll, hilo, &hihi, &hilo);
-	mul64(a_hi, b_lo, &tmp1, &tmp2);
-	add128(tmp1, tmp2, 0x0ll, lohi, &tmp1, &lohi);
-	add128(hihi, hilo, 0x0ll, tmp1, &hihi, &hilo);
-
-	*r_hihi = hihi;
-	*r_hilo = hilo;
-	*r_lohi = lohi;
-	*r_lolo = lolo;
-}
-
-/**
- * Estimate the quotient of 128-bit unsigned divident and 64-bit unsigned
- * divisor.
- * 
- * @param a_hi High part of the divident.
- * @param a_lo Low part of the divident.
- * @param b Divisor.
- * @return Quotient approximation.
- */
-uint64_t div128est(uint64_t a_hi, uint64_t a_lo, uint64_t b)
-{
-	uint64_t b_hi, b_lo;
-	uint64_t rem_hi, rem_lo;
-	uint64_t tmp_hi, tmp_lo;
-	uint64_t result;
-
-	if (b <= a_hi) {
-		return 0xFFFFFFFFFFFFFFFFull;
-	}
-
-	b_hi = b >> 32;
-	result = ((b_hi << 32) <= a_hi) ? (0xFFFFFFFFull << 32) : (a_hi / b_hi) << 32;
-	mul64(b, result, &tmp_hi, &tmp_lo);
-	sub128(a_hi, a_lo, tmp_hi, tmp_lo, &rem_hi, &rem_lo);
-	
-	while ((int64_t) rem_hi < 0) {
-		result -= 0x1ll << 32;
-		b_lo = b << 32;
-		add128(rem_hi, rem_lo, b_hi, b_lo, &rem_hi, &rem_lo);
-	}
-
-	rem_hi = (rem_hi << 32) | (rem_lo >> 32);
-	if ((b_hi << 32) <= rem_hi) {
-		result |= 0xFFFFFFFF;
-	} else {
-		result |= rem_hi / b_hi;
-	}
-
-	return result;
-}
-
-/** @}
- */
Index: pace/lib/softfloat/generic/comparison.c
===================================================================
--- uspace/lib/softfloat/generic/comparison.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,442 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Comparison functions.
- */
-
-#include <sftypes.h>
-#include <comparison.h>
-#include <common.h>
-
-/**
- * Determines whether the given float represents NaN (either signalling NaN or
- * quiet NaN).
- *
- * @param f Single-precision float.
- * @return 1 if float is NaN, 0 otherwise.
- */
-int is_float32_nan(float32 f)
-{
-	/* NaN : exp = 0xff and nonzero fraction */
-	return ((f.parts.exp == 0xFF) && (f.parts.fraction));
-}
-
-/**
- * Determines whether the given float represents NaN (either signalling NaN or
- * quiet NaN).
- *
- * @param d Double-precision float.
- * @return 1 if float is NaN, 0 otherwise.
- */
-int is_float64_nan(float64 d)
-{
-	/* NaN : exp = 0x7ff and nonzero fraction */
-	return ((d.parts.exp == 0x7FF) && (d.parts.fraction));
-}
-
-/**
- * Determines whether the given float represents NaN (either signalling NaN or
- * quiet NaN).
- *
- * @param ld Quadruple-precision float.
- * @return 1 if float is NaN, 0 otherwise.
- */
-int is_float128_nan(float128 ld)
-{
-	/* NaN : exp = 0x7fff and nonzero fraction */
-	return ((ld.parts.exp == 0x7FF) &&
-	    !eq128(ld.parts.frac_hi, ld.parts.frac_lo, 0x0ll, 0x0ll));
-}
-
-/**
- * Determines whether the given float represents signalling NaN.
- *
- * @param f Single-precision float.
- * @return 1 if float is signalling NaN, 0 otherwise.
- */
-int is_float32_signan(float32 f)
-{
-	/* SigNaN : exp = 0xff and fraction = 0xxxxx..x (binary),
-	 * where at least one x is nonzero */
-	return ((f.parts.exp == 0xFF) &&
-	    (f.parts.fraction < 0x400000) && (f.parts.fraction));
-}
-
-/**
- * Determines whether the given float represents signalling NaN.
- *
- * @param d Double-precision float.
- * @return 1 if float is signalling NaN, 0 otherwise.
- */
-int is_float64_signan(float64 d)
-{
-	/* SigNaN : exp = 0x7ff and fraction = 0xxxxx..x (binary),
-	 * where at least one x is nonzero */
-	return ((d.parts.exp == 0x7FF) &&
-	    (d.parts.fraction) && (d.parts.fraction < 0x8000000000000ll));
-}
-
-/**
- * Determines whether the given float represents signalling NaN.
- *
- * @param ld Quadruple-precision float.
- * @return 1 if float is signalling NaN, 0 otherwise.
- */
-int is_float128_signan(float128 ld)
-{
-	/* SigNaN : exp = 0x7fff and fraction = 0xxxxx..x (binary),
-	 * where at least one x is nonzero */
-	return ((ld.parts.exp == 0x7FFF) &&
-	    (ld.parts.frac_hi || ld.parts.frac_lo) &&
-	    lt128(ld.parts.frac_hi, ld.parts.frac_lo, 0x800000000000ll, 0x0ll));
-
-}
-
-/**
- * Determines whether the given float represents positive or negative infinity.
- *
- * @param f Single-precision float.
- * @return 1 if float is infinite, 0 otherwise.
- */
-int is_float32_infinity(float32 f)
-{
-	/* NaN : exp = 0x7ff and zero fraction */
-	return ((f.parts.exp == 0xFF) && (f.parts.fraction == 0x0));
-}
-
-/**
- * Determines whether the given float represents positive or negative infinity.
- *
- * @param d Double-precision float.
- * @return 1 if float is infinite, 0 otherwise.
- */
-int is_float64_infinity(float64 d)
-{
-	/* NaN : exp = 0x7ff and zero fraction */
-	return ((d.parts.exp == 0x7FF) && (d.parts.fraction == 0x0));
-}
-
-/**
- * Determines whether the given float represents positive or negative infinity.
- *
- * @param ld Quadruple-precision float.
- * @return 1 if float is infinite, 0 otherwise.
- */
-int is_float128_infinity(float128 ld)
-{
-	/* NaN : exp = 0x7fff and zero fraction */
-	return ((ld.parts.exp == 0x7FFF) &&
-	    eq128(ld.parts.frac_hi, ld.parts.frac_lo, 0x0ll, 0x0ll));
-}
-
-/**
- * Determines whether the given float represents positive or negative zero.
- *
- * @param f Single-precision float.
- * @return 1 if float is zero, 0 otherwise.
- */
-int is_float32_zero(float32 f)
-{
-	return (((f.bin) & 0x7FFFFFFF) == 0);
-}
-
-/**
- * Determines whether the given float represents positive or negative zero.
- *
- * @param d Double-precision float.
- * @return 1 if float is zero, 0 otherwise.
- */
-int is_float64_zero(float64 d)
-{
-	return (((d.bin) & 0x7FFFFFFFFFFFFFFFll) == 0);
-}
-
-/**
- * Determines whether the given float represents positive or negative zero.
- *
- * @param ld Quadruple-precision float.
- * @return 1 if float is zero, 0 otherwise.
- */
-int is_float128_zero(float128 ld)
-{
-	uint64_t tmp_hi;
-	uint64_t tmp_lo;
-	
-	and128(ld.bin.hi, ld.bin.lo,
-	    0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
-	
-	return eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll);
-}
-
-/**
- * Determine whether two floats are equal. NaNs are not recognized.
- *
- * @a First single-precision operand.
- * @b Second single-precision operand.
- * @return 1 if both floats are equal, 0 otherwise.
- */
-int is_float32_eq(float32 a, float32 b)
-{
-	/* a equals to b or both are zeros (with any sign) */
-	return ((a.bin == b.bin) ||
-	    (((a.bin | b.bin) & 0x7FFFFFFF) == 0));
-}
-
-/**
- * Determine whether two floats are equal. NaNs are not recognized.
- *
- * @a First double-precision operand.
- * @b Second double-precision operand.
- * @return 1 if both floats are equal, 0 otherwise.
- */
-int is_float64_eq(float64 a, float64 b)
-{
-	/* a equals to b or both are zeros (with any sign) */
-	return ((a.bin == b.bin) ||
-	    (((a.bin | b.bin) & 0x7FFFFFFFFFFFFFFFll) == 0));
-}
-
-/**
- * Determine whether two floats are equal. NaNs are not recognized.
- *
- * @a First quadruple-precision operand.
- * @b Second quadruple-precision operand.
- * @return 1 if both floats are equal, 0 otherwise.
- */
-int is_float128_eq(float128 a, float128 b)
-{
-	uint64_t tmp_hi;
-	uint64_t tmp_lo;
-	
-	/* both are zeros (with any sign) */
-	or128(a.bin.hi, a.bin.lo,
-	    b.bin.hi, b.bin.lo, &tmp_hi, &tmp_lo);
-	and128(tmp_hi, tmp_lo,
-	    0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
-	int both_zero = eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll);
-	
-	/* a equals to b */
-	int are_equal = eq128(a.bin.hi, a.bin.lo, b.bin.hi, b.bin.lo);
-	
-	return are_equal || both_zero;
-}
-
-/**
- * Lower-than comparison between two floats. NaNs are not recognized.
- *
- * @a First single-precision operand.
- * @b Second single-precision operand.
- * @return 1 if a is lower than b, 0 otherwise.
- */
-int is_float32_lt(float32 a, float32 b) 
-{
-	if (((a.bin | b.bin) & 0x7FFFFFFF) == 0) {
-		/* +- zeroes */
-		return 0;
-	}
-	
-	if ((a.parts.sign) && (b.parts.sign)) {
-		/* if both are negative, smaller is that with greater binary value */
-		return (a.bin > b.bin);
-	}
-	
-	/*
-	 * lets negate signs - now will be positive numbers always
-	 * bigger than negative (first bit will be set for unsigned
-	 * integer comparison)
-	 */
-	a.parts.sign = !a.parts.sign;
-	b.parts.sign = !b.parts.sign;
-	return (a.bin < b.bin);
-}
-
-/**
- * Lower-than comparison between two floats. NaNs are not recognized.
- *
- * @a First double-precision operand.
- * @b Second double-precision operand.
- * @return 1 if a is lower than b, 0 otherwise.
- */
-int is_float64_lt(float64 a, float64 b)
-{
-	if (((a.bin | b.bin) & 0x7FFFFFFFFFFFFFFFll) == 0) {
-		/* +- zeroes */
-		return 0;
-	}
-	
-	if ((a.parts.sign) && (b.parts.sign)) {
-		/* if both are negative, smaller is that with greater binary value */
-		return (a.bin > b.bin);
-	}
-	
-	/*
-	 * lets negate signs - now will be positive numbers always
-	 * bigger than negative (first bit will be set for unsigned
-	 * integer comparison)
-	 */
-	a.parts.sign = !a.parts.sign;
-	b.parts.sign = !b.parts.sign;
-	return (a.bin < b.bin);
-}
-
-/**
- * Lower-than comparison between two floats. NaNs are not recognized.
- *
- * @a First quadruple-precision operand.
- * @b Second quadruple-precision operand.
- * @return 1 if a is lower than b, 0 otherwise.
- */
-int is_float128_lt(float128 a, float128 b)
-{
-	uint64_t tmp_hi;
-	uint64_t tmp_lo;
-	
-	or128(a.bin.hi, a.bin.lo,
-	    b.bin.hi, b.bin.lo, &tmp_hi, &tmp_lo);
-	and128(tmp_hi, tmp_lo,
-	    0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
-	if (eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll)) {
-		/* +- zeroes */
-		return 0;
-	}
-	
-	if ((a.parts.sign) && (b.parts.sign)) {
-		/* if both are negative, smaller is that with greater binary value */
-		return lt128(b.bin.hi, b.bin.lo, a.bin.hi, a.bin.lo);
-	}
-	
-	/*
-	 * lets negate signs - now will be positive numbers always
-	 * bigger than negative (first bit will be set for unsigned
-	 * integer comparison)
-	 */
-	a.parts.sign = !a.parts.sign;
-	b.parts.sign = !b.parts.sign;
-	return lt128(a.bin.hi, a.bin.lo, b.bin.hi, b.bin.lo);
-}
-
-/**
- * Greater-than comparison between two floats. NaNs are not recognized.
- *
- * @a First single-precision operand.
- * @b Second single-precision operand.
- * @return 1 if a is greater than b, 0 otherwise.
- */
-int is_float32_gt(float32 a, float32 b) 
-{
-	if (((a.bin | b.bin) & 0x7FFFFFFF) == 0) {
-		/* zeroes are equal with any sign */
-		return 0;
-	}
-	
-	if ((a.parts.sign) && (b.parts.sign)) {
-		/* if both are negative, greater is that with smaller binary value */
-		return (a.bin < b.bin);
-	}
-	
-	/*
-	 * lets negate signs - now will be positive numbers always
-	 * bigger than negative (first bit will be set for unsigned
-	 * integer comparison)
-	 */
-	a.parts.sign = !a.parts.sign;
-	b.parts.sign = !b.parts.sign;
-	return (a.bin > b.bin);
-}
-
-/**
- * Greater-than comparison between two floats. NaNs are not recognized.
- *
- * @a First double-precision operand.
- * @b Second double-precision operand.
- * @return 1 if a is greater than b, 0 otherwise.
- */
-int is_float64_gt(float64 a, float64 b)
-{
-	if (((a.bin | b.bin) & 0x7FFFFFFFFFFFFFFFll) == 0) {
-		/* zeroes are equal with any sign */
-		return 0;
-	}
-	
-	if ((a.parts.sign) && (b.parts.sign)) {
-		/* if both are negative, greater is that with smaller binary value */
-		return (a.bin < b.bin);
-	}
-	
-	/*
-	 * lets negate signs - now will be positive numbers always
-	 * bigger than negative (first bit will be set for unsigned
-	 * integer comparison)
-	 */
-	a.parts.sign = !a.parts.sign;
-	b.parts.sign = !b.parts.sign;
-	return (a.bin > b.bin);
-}
-
-/**
- * Greater-than comparison between two floats. NaNs are not recognized.
- *
- * @a First quadruple-precision operand.
- * @b Second quadruple-precision operand.
- * @return 1 if a is greater than b, 0 otherwise.
- */
-int is_float128_gt(float128 a, float128 b)
-{
-	uint64_t tmp_hi;
-	uint64_t tmp_lo;
-	
-	or128(a.bin.hi, a.bin.lo,
-	    b.bin.hi, b.bin.lo, &tmp_hi, &tmp_lo);
-	and128(tmp_hi, tmp_lo,
-	    0x7FFFFFFFFFFFFFFFll, 0xFFFFFFFFFFFFFFFFll, &tmp_hi, &tmp_lo);
-	if (eq128(tmp_hi, tmp_lo, 0x0ll, 0x0ll)) {
-		/* zeroes are equal with any sign */
-		return 0;
-	}
-	
-	if ((a.parts.sign) && (b.parts.sign)) {
-		/* if both are negative, greater is that with smaller binary value */
-		return lt128(a.bin.hi, a.bin.lo, b.bin.hi, b.bin.lo);
-	}
-	
-	/*
-	 * lets negate signs - now will be positive numbers always
-	 * bigger than negative (first bit will be set for unsigned
-	 * integer comparison)
-	 */
-	a.parts.sign = !a.parts.sign;
-	b.parts.sign = !b.parts.sign;
-	return lt128(b.bin.hi, b.bin.lo, a.bin.hi, a.bin.lo);
-}
-
-/** @}
- */
Index: pace/lib/softfloat/generic/conversion.c
===================================================================
--- uspace/lib/softfloat/generic/conversion.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,1041 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Conversion of precision and conversion between integers and floats.
- */
-
-#include <sftypes.h>
-#include <conversion.h>
-#include <comparison.h>
-#include <common.h>
-
-float64 float32_to_float64(float32 a)
-{
-	float64 result;
-	uint64_t frac;
-	
-	result.parts.sign = a.parts.sign;
-	result.parts.fraction = a.parts.fraction;
-	result.parts.fraction <<= (FLOAT64_FRACTION_SIZE - FLOAT32_FRACTION_SIZE);
-	
-	if ((is_float32_infinity(a)) || (is_float32_nan(a))) {
-		result.parts.exp = FLOAT64_MAX_EXPONENT;
-		// TODO; check if its correct for SigNaNs
-		return result;
-	}
-	
-	result.parts.exp = a.parts.exp + ((int) FLOAT64_BIAS - FLOAT32_BIAS);
-	if (a.parts.exp == 0) {
-		/* normalize denormalized numbers */
-		
-		if (result.parts.fraction == 0) { /* fix zero */
-			result.parts.exp = 0;
-			return result;
-		}
-			
-		frac = result.parts.fraction;
-		
-		while (!(frac & FLOAT64_HIDDEN_BIT_MASK)) {
-			frac <<= 1;
-			--result.parts.exp;
-		}
-		
-		++result.parts.exp;
-		result.parts.fraction = frac;
-	}
-	
-	return result;
-}
-
-float128 float32_to_float128(float32 a)
-{
-	float128 result;
-	uint64_t frac_hi, frac_lo;
-	uint64_t tmp_hi, tmp_lo;
-	
-	result.parts.sign = a.parts.sign;
-	result.parts.frac_hi = 0;
-	result.parts.frac_lo = a.parts.fraction;
-	lshift128(result.parts.frac_hi, result.parts.frac_lo,
-	    (FLOAT128_FRACTION_SIZE - FLOAT32_FRACTION_SIZE),
-	    &frac_hi, &frac_lo);
-	result.parts.frac_hi = frac_hi;
-	result.parts.frac_lo = frac_lo;
-	
-	if ((is_float32_infinity(a)) || (is_float32_nan(a))) {
-		result.parts.exp = FLOAT128_MAX_EXPONENT;
-		// TODO; check if its correct for SigNaNs
-		return result;
-	}
-	
-	result.parts.exp = a.parts.exp + ((int) FLOAT128_BIAS - FLOAT32_BIAS);
-	if (a.parts.exp == 0) {
-		/* normalize denormalized numbers */
-		
-		if (eq128(result.parts.frac_hi,
-		    result.parts.frac_lo, 0x0ll, 0x0ll)) { /* fix zero */
-			result.parts.exp = 0;
-			return result;
-		}
-		
-		frac_hi = result.parts.frac_hi;
-		frac_lo = result.parts.frac_lo;
-		
-		and128(frac_hi, frac_lo,
-		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-		    &tmp_hi, &tmp_lo);
-		while (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
-			lshift128(frac_hi, frac_lo, 1, &frac_hi, &frac_lo);
-			--result.parts.exp;
-		}
-		
-		++result.parts.exp;
-		result.parts.frac_hi = frac_hi;
-		result.parts.frac_lo = frac_lo;
-	}
-	
-	return result;
-}
-
-float128 float64_to_float128(float64 a)
-{
-	float128 result;
-	uint64_t frac_hi, frac_lo;
-	uint64_t tmp_hi, tmp_lo;
-	
-	result.parts.sign = a.parts.sign;
-	result.parts.frac_hi = 0;
-	result.parts.frac_lo = a.parts.fraction;
-	lshift128(result.parts.frac_hi, result.parts.frac_lo,
-	    (FLOAT128_FRACTION_SIZE - FLOAT64_FRACTION_SIZE),
-	    &frac_hi, &frac_lo);
-	result.parts.frac_hi = frac_hi;
-	result.parts.frac_lo = frac_lo;
-	
-	if ((is_float64_infinity(a)) || (is_float64_nan(a))) {
-		result.parts.exp = FLOAT128_MAX_EXPONENT;
-		// TODO; check if its correct for SigNaNs
-		return result;
-	}
-	
-	result.parts.exp = a.parts.exp + ((int) FLOAT128_BIAS - FLOAT64_BIAS);
-	if (a.parts.exp == 0) {
-		/* normalize denormalized numbers */
-		
-		if (eq128(result.parts.frac_hi,
-		    result.parts.frac_lo, 0x0ll, 0x0ll)) { /* fix zero */
-			result.parts.exp = 0;
-			return result;
-		}
-		
-		frac_hi = result.parts.frac_hi;
-		frac_lo = result.parts.frac_lo;
-		
-		and128(frac_hi, frac_lo,
-		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-		    &tmp_hi, &tmp_lo);
-		while (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
-			lshift128(frac_hi, frac_lo, 1, &frac_hi, &frac_lo);
-			--result.parts.exp;
-		}
-		
-		++result.parts.exp;
-		result.parts.frac_hi = frac_hi;
-		result.parts.frac_lo = frac_lo;
-	}
-	
-	return result;
-}
-
-float32 float64_to_float32(float64 a)
-{
-	float32 result;
-	int32_t exp;
-	uint64_t frac;
-	
-	result.parts.sign = a.parts.sign;
-	
-	if (is_float64_nan(a)) {
-		result.parts.exp = FLOAT32_MAX_EXPONENT;
-		
-		if (is_float64_signan(a)) {
-			/* set first bit of fraction nonzero */
-			result.parts.fraction = FLOAT32_HIDDEN_BIT_MASK >> 1;
-			return result;
-		}
-		
-		/* fraction nonzero but its first bit is zero */
-		result.parts.fraction = 0x1;
-		return result;
-	}
-	
-	if (is_float64_infinity(a)) {
-		result.parts.fraction = 0;
-		result.parts.exp = FLOAT32_MAX_EXPONENT;
-		return result;
-	}
-	
-	exp = (int) a.parts.exp - FLOAT64_BIAS + FLOAT32_BIAS;
-	
-	if (exp >= FLOAT32_MAX_EXPONENT) {
-		/* FIXME: overflow */
-		result.parts.fraction = 0;
-		result.parts.exp = FLOAT32_MAX_EXPONENT;
-		return result;
-	} else if (exp <= 0) {
-		/* underflow or denormalized */
-		
-		result.parts.exp = 0;
-		
-		exp *= -1;	
-		if (exp > FLOAT32_FRACTION_SIZE) {
-			/* FIXME: underflow */
-			result.parts.fraction = 0;
-			return result;
-		}
-		
-		/* denormalized */
-		
-		frac = a.parts.fraction; 
-		frac |= FLOAT64_HIDDEN_BIT_MASK; /* denormalize and set hidden bit */
-		
-		frac >>= (FLOAT64_FRACTION_SIZE - FLOAT32_FRACTION_SIZE + 1);
-		
-		while (exp > 0) {
-			--exp;
-			frac >>= 1;
-		}
-		result.parts.fraction = frac;
-		
-		return result;
-	}
-	
-	result.parts.exp = exp;
-	result.parts.fraction =
-	    a.parts.fraction >> (FLOAT64_FRACTION_SIZE - FLOAT32_FRACTION_SIZE);
-	return result;
-}
-
-float32 float128_to_float32(float128 a)
-{
-	float32 result;
-	int32_t exp;
-	uint64_t frac_hi, frac_lo;
-	
-	result.parts.sign = a.parts.sign;
-	
-	if (is_float128_nan(a)) {
-		result.parts.exp = FLOAT32_MAX_EXPONENT;
-		
-		if (is_float128_signan(a)) {
-			/* set first bit of fraction nonzero */
-			result.parts.fraction = FLOAT32_HIDDEN_BIT_MASK >> 1;
-			return result;
-		}
-		
-		/* fraction nonzero but its first bit is zero */
-		result.parts.fraction = 0x1;
-		return result;
-	}
-	
-	if (is_float128_infinity(a)) {
-		result.parts.fraction = 0;
-		result.parts.exp = FLOAT32_MAX_EXPONENT;
-		return result;
-	}
-	
-	exp = (int) a.parts.exp - FLOAT128_BIAS + FLOAT32_BIAS;
-	
-	if (exp >= FLOAT32_MAX_EXPONENT) {
-		/* FIXME: overflow */
-		result.parts.fraction = 0;
-		result.parts.exp = FLOAT32_MAX_EXPONENT;
-		return result;
-	} else if (exp <= 0) {
-		/* underflow or denormalized */
-		
-		result.parts.exp = 0;
-		
-		exp *= -1;
-		if (exp > FLOAT32_FRACTION_SIZE) {
-			/* FIXME: underflow */
-			result.parts.fraction = 0;
-			return result;
-		}
-		
-		/* denormalized */
-		
-		frac_hi = a.parts.frac_hi;
-		frac_lo = a.parts.frac_lo;
-		
-		/* denormalize and set hidden bit */
-		frac_hi |= FLOAT128_HIDDEN_BIT_MASK_HI;
-		
-		rshift128(frac_hi, frac_lo,
-		    (FLOAT128_FRACTION_SIZE - FLOAT32_FRACTION_SIZE + 1),
-		    &frac_hi, &frac_lo);
-		
-		while (exp > 0) {
-			--exp;
-			rshift128(frac_hi, frac_lo, 1, &frac_hi, &frac_lo);
-		}
-		result.parts.fraction = frac_lo;
-		
-		return result;
-	}
-	
-	result.parts.exp = exp;
-	frac_hi = a.parts.frac_hi;
-	frac_lo = a.parts.frac_lo;
-	rshift128(frac_hi, frac_lo,
-	    (FLOAT128_FRACTION_SIZE - FLOAT32_FRACTION_SIZE + 1),
-	    &frac_hi, &frac_lo);
-	result.parts.fraction = frac_lo;
-	return result;
-}
-
-float64 float128_to_float64(float128 a)
-{
-	float64 result;
-	int32_t exp;
-	uint64_t frac_hi, frac_lo;
-	
-	result.parts.sign = a.parts.sign;
-	
-	if (is_float128_nan(a)) {
-		result.parts.exp = FLOAT64_MAX_EXPONENT;
-		
-		if (is_float128_signan(a)) {
-			/* set first bit of fraction nonzero */
-			result.parts.fraction = FLOAT64_HIDDEN_BIT_MASK >> 1;
-			return result;
-		}
-		
-		/* fraction nonzero but its first bit is zero */
-		result.parts.fraction = 0x1;
-		return result;
-	}
-	
-	if (is_float128_infinity(a)) {
-		result.parts.fraction = 0;
-		result.parts.exp = FLOAT64_MAX_EXPONENT;
-		return result;
-	}
-	
-	exp = (int) a.parts.exp - FLOAT128_BIAS + FLOAT64_BIAS;
-	
-	if (exp >= FLOAT64_MAX_EXPONENT) {
-		/* FIXME: overflow */
-		result.parts.fraction = 0;
-		result.parts.exp = FLOAT64_MAX_EXPONENT;
-		return result;
-	} else if (exp <= 0) {
-		/* underflow or denormalized */
-		
-		result.parts.exp = 0;
-		
-		exp *= -1;
-		if (exp > FLOAT64_FRACTION_SIZE) {
-			/* FIXME: underflow */
-			result.parts.fraction = 0;
-			return result;
-		}
-		
-		/* denormalized */
-		
-		frac_hi = a.parts.frac_hi;
-		frac_lo = a.parts.frac_lo;
-		
-		/* denormalize and set hidden bit */
-		frac_hi |= FLOAT128_HIDDEN_BIT_MASK_HI;
-		
-		rshift128(frac_hi, frac_lo,
-		    (FLOAT128_FRACTION_SIZE - FLOAT64_FRACTION_SIZE + 1),
-		    &frac_hi, &frac_lo);
-		
-		while (exp > 0) {
-			--exp;
-			rshift128(frac_hi, frac_lo, 1, &frac_hi, &frac_lo);
-		}
-		result.parts.fraction = frac_lo;
-		
-		return result;
-	}
-	
-	result.parts.exp = exp;
-	frac_hi = a.parts.frac_hi;
-	frac_lo = a.parts.frac_lo;
-	rshift128(frac_hi, frac_lo,
-	    (FLOAT128_FRACTION_SIZE - FLOAT64_FRACTION_SIZE + 1),
-	    &frac_hi, &frac_lo);
-	result.parts.fraction = frac_lo;
-	return result;
-}
-
-/** Helper procedure for converting float32 to uint32.
- *
- * @param a Floating point number in normalized form
- *     (NaNs or Inf are not checked).
- * @return Converted unsigned integer.
- */
-static uint32_t _float32_to_uint32_helper(float32 a)
-{
-	uint32_t frac;
-	
-	if (a.parts.exp < FLOAT32_BIAS) {
-		/* TODO: rounding */
-		return 0;
-	}
-	
-	frac = a.parts.fraction;
-	
-	frac |= FLOAT32_HIDDEN_BIT_MASK;
-	/* shift fraction to left so hidden bit will be the most significant bit */
-	frac <<= 32 - FLOAT32_FRACTION_SIZE - 1; 
-	
-	frac >>= 32 - (a.parts.exp - FLOAT32_BIAS) - 1;
-	if ((a.parts.sign == 1) && (frac != 0)) {
-		frac = ~frac;
-		++frac;
-	}
-	
-	return frac;
-}
-
-/*
- * FIXME: Im not sure what to return if overflow/underflow happens
- *  - now its the biggest or the smallest int
- */
-uint32_t float32_to_uint32(float32 a)
-{
-	if (is_float32_nan(a))
-		return UINT32_MAX;
-	
-	if (is_float32_infinity(a) || (a.parts.exp >= (32 + FLOAT32_BIAS))) {
-		if (a.parts.sign)
-			return UINT32_MIN;
-		
-		return UINT32_MAX;
-	}
-	
-	return _float32_to_uint32_helper(a);
-}
-
-/*
- * FIXME: Im not sure what to return if overflow/underflow happens
- *  - now its the biggest or the smallest int
- */
-int32_t float32_to_int32(float32 a)
-{
-	if (is_float32_nan(a))
-		return INT32_MAX;
-	
-	if (is_float32_infinity(a) || (a.parts.exp >= (32 + FLOAT32_BIAS))) {
-		if (a.parts.sign)
-			return INT32_MIN;
-		
-		return INT32_MAX;
-	}
-	
-	return _float32_to_uint32_helper(a);
-}
-
-/** Helper procedure for converting float32 to uint64.
- *
- * @param a Floating point number in normalized form
- *     (NaNs or Inf are not checked).
- * @return Converted unsigned integer.
- */
-static uint64_t _float32_to_uint64_helper(float32 a)
-{
-	uint64_t frac;
-	
-	if (a.parts.exp < FLOAT32_BIAS) {
-		// TODO: rounding
-		return 0;
-	}
-	
-	frac = a.parts.fraction;
-	
-	frac |= FLOAT32_HIDDEN_BIT_MASK;
-	/* shift fraction to left so hidden bit will be the most significant bit */
-	frac <<= 64 - FLOAT32_FRACTION_SIZE - 1;
-	
-	frac >>= 64 - (a.parts.exp - FLOAT32_BIAS) - 1;
-	if ((a.parts.sign == 1) && (frac != 0)) {
-		frac = ~frac;
-		++frac;
-	}
-	
-	return frac;
-}
-
-/*
- * FIXME: Im not sure what to return if overflow/underflow happens
- *  - now its the biggest or the smallest int
- */
-uint64_t float32_to_uint64(float32 a)
-{
-	if (is_float32_nan(a))
-		return UINT64_MAX;
-	
-	if (is_float32_infinity(a) || (a.parts.exp >= (64 + FLOAT32_BIAS))) {
-		if (a.parts.sign)
-			return UINT64_MIN;
-		
-		return UINT64_MAX;
-	}
-	
-	return _float32_to_uint64_helper(a);
-}
-
-/*
- * FIXME: Im not sure what to return if overflow/underflow happens
- *  - now its the biggest or the smallest int
- */
-int64_t float32_to_int64(float32 a)
-{
-	if (is_float32_nan(a))
-		return INT64_MAX;
-	
-	if (is_float32_infinity(a) || (a.parts.exp >= (64 + FLOAT32_BIAS))) {
-		if (a.parts.sign)
-			return INT64_MIN;
-		
-		return INT64_MAX;
-	}
-	
-	return _float32_to_uint64_helper(a);
-}
-
-/** Helper procedure for converting float64 to uint64.
- *
- * @param a Floating point number in normalized form
- *     (NaNs or Inf are not checked).
- * @return Converted unsigned integer.
- */
-static uint64_t _float64_to_uint64_helper(float64 a)
-{
-	uint64_t frac;
-	
-	if (a.parts.exp < FLOAT64_BIAS) {
-		// TODO: rounding
-		return 0;
-	}
-	
-	frac = a.parts.fraction;
-	
-	frac |= FLOAT64_HIDDEN_BIT_MASK;
-	/* shift fraction to left so hidden bit will be the most significant bit */
-	frac <<= 64 - FLOAT64_FRACTION_SIZE - 1;
-	
-	frac >>= 64 - (a.parts.exp - FLOAT64_BIAS) - 1;
-	if ((a.parts.sign == 1) && (frac != 0)) {
-		frac = ~frac;
-		++frac;
-	}
-	
-	return frac;
-}
-
-/*
- * FIXME: Im not sure what to return if overflow/underflow happens
- *  - now its the biggest or the smallest int
- */
-uint32_t float64_to_uint32(float64 a)
-{
-	if (is_float64_nan(a))
-		return UINT32_MAX;
-	
-	if (is_float64_infinity(a) || (a.parts.exp >= (32 + FLOAT64_BIAS))) {
-		if (a.parts.sign)
-			return UINT32_MIN;
-		
-		return UINT32_MAX;
-	}
-	
-	return (uint32_t) _float64_to_uint64_helper(a);
-}
-
-/*
- * FIXME: Im not sure what to return if overflow/underflow happens
- *  - now its the biggest or the smallest int
- */
-int32_t float64_to_int32(float64 a)
-{
-	if (is_float64_nan(a))
-		return INT32_MAX;
-	
-	if (is_float64_infinity(a) || (a.parts.exp >= (32 + FLOAT64_BIAS))) {
-		if (a.parts.sign)
-			return INT32_MIN;
-		
-		return INT32_MAX;
-	}
-	
-	return (int32_t) _float64_to_uint64_helper(a);
-}
-
-/*
- * FIXME: Im not sure what to return if overflow/underflow happens 
- *  - now its the biggest or the smallest int
- */
-uint64_t float64_to_uint64(float64 a)
-{
-	if (is_float64_nan(a))
-		return UINT64_MAX;
-	
-	if (is_float64_infinity(a) || (a.parts.exp >= (64 + FLOAT64_BIAS))) {
-		if (a.parts.sign)
-			return UINT64_MIN;
-		
-		return UINT64_MAX;
-	}
-	
-	return _float64_to_uint64_helper(a);
-}
-
-/*
- * FIXME: Im not sure what to return if overflow/underflow happens 
- *  - now its the biggest or the smallest int
- */
-int64_t float64_to_int64(float64 a)
-{
-	if (is_float64_nan(a))
-		return INT64_MAX;
-	
-	if (is_float64_infinity(a) || (a.parts.exp >= (64 + FLOAT64_BIAS))) {
-		if (a.parts.sign)
-			return INT64_MIN;
-		
-		return INT64_MAX;
-	}
-	
-	return _float64_to_uint64_helper(a);
-}
-
-/** Helper procedure for converting float128 to uint64.
- *
- * @param a Floating point number in normalized form
- *     (NaNs or Inf are not checked).
- * @return Converted unsigned integer.
- */
-static uint64_t _float128_to_uint64_helper(float128 a)
-{
-	uint64_t frac_hi, frac_lo;
-	
-	if (a.parts.exp < FLOAT128_BIAS) {
-		// TODO: rounding
-		return 0;
-	}
-	
-	frac_hi = a.parts.frac_hi;
-	frac_lo = a.parts.frac_lo;
-	
-	frac_hi |= FLOAT128_HIDDEN_BIT_MASK_HI;
-	/* shift fraction to left so hidden bit will be the most significant bit */
-	lshift128(frac_hi, frac_lo,
-	    (128 - FLOAT128_FRACTION_SIZE - 1), &frac_hi, &frac_lo);
-	
-	rshift128(frac_hi, frac_lo,
-	    (128 - (a.parts.exp - FLOAT128_BIAS) - 1), &frac_hi, &frac_lo);
-	if ((a.parts.sign == 1) && !eq128(frac_hi, frac_lo, 0x0ll, 0x0ll)) {
-		not128(frac_hi, frac_lo, &frac_hi, &frac_lo);
-		add128(frac_hi, frac_lo, 0x0ll, 0x1ll, &frac_hi, &frac_lo);
-	}
-	
-	return frac_lo;
-}
-
-/*
- * FIXME: Im not sure what to return if overflow/underflow happens
- *  - now its the biggest or the smallest int
- */
-uint32_t float128_to_uint32(float128 a)
-{
-	if (is_float128_nan(a))
-		return UINT32_MAX;
-	
-	if (is_float128_infinity(a) || (a.parts.exp >= (32 + FLOAT128_BIAS))) {
-		if (a.parts.sign)
-			return UINT32_MIN;
-		
-		return UINT32_MAX;
-	}
-	
-	return (uint32_t) _float128_to_uint64_helper(a);
-}
-
-/*
- * FIXME: Im not sure what to return if overflow/underflow happens
- *  - now its the biggest or the smallest int
- */
-int32_t float128_to_int32(float128 a)
-{
-	if (is_float128_nan(a))
-		return INT32_MAX;
-	
-	if (is_float128_infinity(a) || (a.parts.exp >= (32 + FLOAT128_BIAS))) {
-		if (a.parts.sign)
-			return INT32_MIN;
-		
-		return INT32_MAX;
-	}
-	
-	return (int32_t) _float128_to_uint64_helper(a);
-}
-
-/*
- * FIXME: Im not sure what to return if overflow/underflow happens
- *  - now its the biggest or the smallest int
- */
-uint64_t float128_to_uint64(float128 a)
-{
-	if (is_float128_nan(a))
-		return UINT64_MAX;
-	
-	if (is_float128_infinity(a) || (a.parts.exp >= (64 + FLOAT128_BIAS))) {
-		if (a.parts.sign)
-			return UINT64_MIN;
-		
-		return UINT64_MAX;
-	}
-	
-	return _float128_to_uint64_helper(a);
-}
-
-/*
- * FIXME: Im not sure what to return if overflow/underflow happens
- *  - now its the biggest or the smallest int
- */
-int64_t float128_to_int64(float128 a)
-{
-	if (is_float128_nan(a))
-		return INT64_MAX;
-	
-	if (is_float128_infinity(a) || (a.parts.exp >= (64 + FLOAT128_BIAS))) {
-		if (a.parts.sign)
-			return INT64_MIN;
-		
-		return INT64_MAX;
-	}
-	
-	return _float128_to_uint64_helper(a);
-}
-
-float32 uint32_to_float32(uint32_t i)
-{
-	int counter;
-	int32_t exp;
-	float32 result;
-	
-	result.parts.sign = 0;
-	result.parts.fraction = 0;
-	
-	counter = count_zeroes32(i);
-	
-	exp = FLOAT32_BIAS + 32 - counter - 1;
-	
-	if (counter == 32) {
-		result.bin = 0;
-		return result;
-	}
-	
-	if (counter > 0) {
-		i <<= counter - 1;
-	} else {
-		i >>= 1;
-	}
-	
-	round_float32(&exp, &i);
-	
-	result.parts.fraction = i >> (32 - FLOAT32_FRACTION_SIZE - 2);
-	result.parts.exp = exp;
-	
-	return result;
-}
-
-float32 int32_to_float32(int32_t i)
-{
-	float32 result;
-	
-	if (i < 0)
-		result = uint32_to_float32((uint32_t) (-i));
-	else
-		result = uint32_to_float32((uint32_t) i);
-	
-	result.parts.sign = i < 0;
-	
-	return result;
-}
-
-float32 uint64_to_float32(uint64_t i)
-{
-	int counter;
-	int32_t exp;
-	uint32_t j;
-	float32 result;
-	
-	result.parts.sign = 0;
-	result.parts.fraction = 0;
-	
-	counter = count_zeroes64(i);
-	
-	exp = FLOAT32_BIAS + 64 - counter - 1;
-	
-	if (counter == 64) {
-		result.bin = 0;
-		return result;
-	}
-	
-	/* Shift all to the first 31 bits (31st will be hidden 1) */
-	if (counter > 33) {
-		i <<= counter - 1 - 32;
-	} else {
-		i >>= 1 + 32 - counter;
-	}
-	
-	j = (uint32_t) i;
-	round_float32(&exp, &j);
-	
-	result.parts.fraction = j >> (32 - FLOAT32_FRACTION_SIZE - 2);
-	result.parts.exp = exp;
-	return result;
-}
-
-float32 int64_to_float32(int64_t i)
-{
-	float32 result;
-	
-	if (i < 0)
-		result = uint64_to_float32((uint64_t) (-i));
-	else
-		result = uint64_to_float32((uint64_t) i);
-	
-	result.parts.sign = i < 0;
-	
-	return result;
-}
-
-float64 uint32_to_float64(uint32_t i)
-{
-	int counter;
-	int32_t exp;
-	float64 result;
-	uint64_t frac;
-	
-	result.parts.sign = 0;
-	result.parts.fraction = 0;
-	
-	counter = count_zeroes32(i);
-	
-	exp = FLOAT64_BIAS + 32 - counter - 1;
-	
-	if (counter == 32) {
-		result.bin = 0;
-		return result;
-	}
-	
-	frac = i;
-	frac <<= counter + 32 - 1;
-	
-	round_float64(&exp, &frac);
-	
-	result.parts.fraction = frac >> (64 - FLOAT64_FRACTION_SIZE - 2);
-	result.parts.exp = exp;
-	
-	return result;
-}
-
-float64 int32_to_float64(int32_t i)
-{
-	float64 result;
-	
-	if (i < 0)
-		result = uint32_to_float64((uint32_t) (-i));
-	else
-		result = uint32_to_float64((uint32_t) i);
-	
-	result.parts.sign = i < 0;
-	
-	return result;
-}
-
-
-float64 uint64_to_float64(uint64_t i)
-{
-	int counter;
-	int32_t exp;
-	float64 result;
-	
-	result.parts.sign = 0;
-	result.parts.fraction = 0;
-	
-	counter = count_zeroes64(i);
-	
-	exp = FLOAT64_BIAS + 64 - counter - 1;
-	
-	if (counter == 64) {
-		result.bin = 0;
-		return result;
-	}
-	
-	if (counter > 0) {
-		i <<= counter - 1;
-	} else {
-		i >>= 1;
-	}
-	
-	round_float64(&exp, &i);
-	
-	result.parts.fraction = i >> (64 - FLOAT64_FRACTION_SIZE - 2);
-	result.parts.exp = exp;
-	return result;
-}
-
-float64 int64_to_float64(int64_t i)
-{
-	float64 result;
-	
-	if (i < 0)
-		result = uint64_to_float64((uint64_t) (-i));
-	else
-		result = uint64_to_float64((uint64_t) i);
-	
-	result.parts.sign = i < 0;
-	
-	return result;
-}
-
-float128 uint32_to_float128(uint32_t i)
-{
-	int counter;
-	int32_t exp;
-	float128 result;
-	uint64_t frac_hi, frac_lo;
-	
-	result.parts.sign = 0;
-	result.parts.frac_hi = 0;
-	result.parts.frac_lo = 0;
-	
-	counter = count_zeroes32(i);
-	
-	exp = FLOAT128_BIAS + 32 - counter - 1;
-	
-	if (counter == 32) {
-		result.bin.hi = 0;
-		result.bin.lo = 0;
-		return result;
-	}
-	
-	frac_hi = 0;
-	frac_lo = i;
-	lshift128(frac_hi, frac_lo, (counter + 96 - 1), &frac_hi, &frac_lo);
-	
-	round_float128(&exp, &frac_hi, &frac_lo);
-	
-	rshift128(frac_hi, frac_lo,
-	    (128 - FLOAT128_FRACTION_SIZE - 2), &frac_hi, &frac_lo);
-	result.parts.frac_hi = frac_hi;
-	result.parts.frac_lo = frac_lo;
-	result.parts.exp = exp;
-	
-	return result;
-}
-
-float128 int32_to_float128(int32_t i)
-{
-	float128 result;
-	
-	if (i < 0)
-		result = uint32_to_float128((uint32_t) (-i));
-	else
-		result = uint32_to_float128((uint32_t) i);
-	
-	result.parts.sign = i < 0;
-	
-	return result;
-}
-
-
-float128 uint64_to_float128(uint64_t i)
-{
-	int counter;
-	int32_t exp;
-	float128 result;
-	uint64_t frac_hi, frac_lo;
-	
-	result.parts.sign = 0;
-	result.parts.frac_hi = 0;
-	result.parts.frac_lo = 0;
-	
-	counter = count_zeroes64(i);
-	
-	exp = FLOAT128_BIAS + 64 - counter - 1;
-	
-	if (counter == 64) {
-		result.bin.hi = 0;
-		result.bin.lo = 0;
-		return result;
-	}
-	
-	frac_hi = 0;
-	frac_lo = i;
-	lshift128(frac_hi, frac_lo, (counter + 64 - 1), &frac_hi, &frac_lo);
-	
-	round_float128(&exp, &frac_hi, &frac_lo);
-	
-	rshift128(frac_hi, frac_lo,
-	    (128 - FLOAT128_FRACTION_SIZE - 2), &frac_hi, &frac_lo);
-	result.parts.frac_hi = frac_hi;
-	result.parts.frac_lo = frac_lo;
-	result.parts.exp = exp;
-	
-	return result;
-}
-
-float128 int64_to_float128(int64_t i)
-{
-	float128 result;
-	
-	if (i < 0)
-		result = uint64_to_float128((uint64_t) (-i));
-	else
-		result = uint64_to_float128((uint64_t) i);
-	
-	result.parts.sign = i < 0;
-	
-	return result;
-}
-
-/** @}
- */
Index: pace/lib/softfloat/generic/div.c
===================================================================
--- uspace/lib/softfloat/generic/div.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,542 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Division functions.
- */
-
-#include <sftypes.h>
-#include <add.h>
-#include <div.h>
-#include <comparison.h>
-#include <mul.h>
-#include <common.h>
-
-/** Divide two single-precision floats.
- *
- * @param a Nominator.
- * @param b Denominator.
- *
- * @return Result of division.
- *
- */
-float32 div_float32(float32 a, float32 b)
-{
-	float32 result;
-	int32_t aexp, bexp, cexp;
-	uint64_t afrac, bfrac, cfrac;
-	
-	result.parts.sign = a.parts.sign ^ b.parts.sign;
-	
-	if (is_float32_nan(a)) {
-		if (is_float32_signan(a)) {
-			// FIXME: SigNaN
-		}
-		/* NaN */
-		return a;
-	}
-	
-	if (is_float32_nan(b)) {
-		if (is_float32_signan(b)) {
-			// FIXME: SigNaN
-		}
-		/* NaN */
-		return b;
-	}
-	
-	if (is_float32_infinity(a)) {
-		if (is_float32_infinity(b)) {
-			/*FIXME: inf / inf */
-			result.bin = FLOAT32_NAN;
-			return result;
-		}
-		/* inf / num */
-		result.parts.exp = a.parts.exp;
-		result.parts.fraction = a.parts.fraction;
-		return result;
-	}
-	
-	if (is_float32_infinity(b)) {
-		if (is_float32_zero(a)) {
-			/* FIXME 0 / inf */
-			result.parts.exp = 0;
-			result.parts.fraction = 0;
-			return result;
-		}
-		/* FIXME: num / inf*/
-		result.parts.exp = 0;
-		result.parts.fraction = 0;
-		return result;
-	}
-	
-	if (is_float32_zero(b)) {
-		if (is_float32_zero(a)) {
-			/*FIXME: 0 / 0*/
-			result.bin = FLOAT32_NAN;
-			return result;
-		}
-		/* FIXME: division by zero */
-		result.parts.exp = 0;
-		result.parts.fraction = 0;
-		return result;
-	}
-	
-	afrac = a.parts.fraction;
-	aexp = a.parts.exp;
-	bfrac = b.parts.fraction;
-	bexp = b.parts.exp;
-	
-	/* denormalized numbers */
-	if (aexp == 0) {
-		if (afrac == 0) {
-			result.parts.exp = 0;
-			result.parts.fraction = 0;
-			return result;
-		}
-		
-		/* normalize it*/
-		afrac <<= 1;
-		/* afrac is nonzero => it must stop */
-		while (!(afrac & FLOAT32_HIDDEN_BIT_MASK)) {
-			afrac <<= 1;
-			aexp--;
-		}
-	}
-	
-	if (bexp == 0) {
-		bfrac <<= 1;
-		/* bfrac is nonzero => it must stop */
-		while (!(bfrac & FLOAT32_HIDDEN_BIT_MASK)) {
-			bfrac <<= 1;
-			bexp--;
-		}
-	}
-	
-	afrac = (afrac | FLOAT32_HIDDEN_BIT_MASK) << (32 - FLOAT32_FRACTION_SIZE - 1);
-	bfrac = (bfrac | FLOAT32_HIDDEN_BIT_MASK) << (32 - FLOAT32_FRACTION_SIZE);
-	
-	if (bfrac <= (afrac << 1)) {
-		afrac >>= 1;
-		aexp++;
-	}
-	
-	cexp = aexp - bexp + FLOAT32_BIAS - 2;
-	
-	cfrac = (afrac << 32) / bfrac;
-	if ((cfrac & 0x3F) == 0) { 
-		cfrac |= (bfrac * cfrac != afrac << 32);
-	}
-	
-	/* pack and round */
-	
-	/* find first nonzero digit and shift result and detect possibly underflow */
-	while ((cexp > 0) && (cfrac) && (!(cfrac & (FLOAT32_HIDDEN_BIT_MASK << 7)))) {
-		cexp--;
-		cfrac <<= 1;
-		/* TODO: fix underflow */
-	}
-	
-	cfrac += (0x1 << 6); /* FIXME: 7 is not sure*/
-	
-	if (cfrac & (FLOAT32_HIDDEN_BIT_MASK << 7)) {
-		++cexp;
-		cfrac >>= 1;
-	}
-	
-	/* check overflow */
-	if (cexp >= FLOAT32_MAX_EXPONENT) {
-		/* FIXME: overflow, return infinity */
-		result.parts.exp = FLOAT32_MAX_EXPONENT;
-		result.parts.fraction = 0;
-		return result;
-	}
-	
-	if (cexp < 0) {
-		/* FIXME: underflow */
-		result.parts.exp = 0;
-		if ((cexp + FLOAT32_FRACTION_SIZE) < 0) {
-			result.parts.fraction = 0;
-			return result;
-		}
-		cfrac >>= 1;
-		while (cexp < 0) {
-			cexp++;
-			cfrac >>= 1;
-		}
-	} else {
-		result.parts.exp = (uint32_t) cexp;
-	}
-	
-	result.parts.fraction = ((cfrac >> 6) & (~FLOAT32_HIDDEN_BIT_MASK)); 
-	
-	return result;
-}
-
-/** Divide two double-precision floats.
- *
- * @param a Nominator.
- * @param b Denominator.
- *
- * @return Result of division.
- *
- */
-float64 div_float64(float64 a, float64 b) 
-{
-	float64 result;
-	int64_t aexp, bexp, cexp;
-	uint64_t afrac, bfrac, cfrac; 
-	uint64_t remlo, remhi;
-	uint64_t tmplo, tmphi;
-	
-	result.parts.sign = a.parts.sign ^ b.parts.sign;
-	
-	if (is_float64_nan(a)) {
-		if (is_float64_signan(b)) {
-			// FIXME: SigNaN
-			return b;
-		}
-		
-		if (is_float64_signan(a)) {
-			// FIXME: SigNaN
-		}
-		/* NaN */
-		return a;
-	}
-	
-	if (is_float64_nan(b)) {
-		if (is_float64_signan(b)) {
-			// FIXME: SigNaN
-		}
-		/* NaN */
-		return b;
-	}
-	
-	if (is_float64_infinity(a)) {
-		if (is_float64_infinity(b) || is_float64_zero(b)) {
-			// FIXME: inf / inf
-			result.bin = FLOAT64_NAN;
-			return result;
-		}
-		/* inf / num */
-		result.parts.exp = a.parts.exp;
-		result.parts.fraction = a.parts.fraction;
-		return result;
-	}
-	
-	if (is_float64_infinity(b)) {
-		if (is_float64_zero(a)) {
-			/* FIXME 0 / inf */
-			result.parts.exp = 0;
-			result.parts.fraction = 0;
-			return result;
-		}
-		/* FIXME: num / inf*/
-		result.parts.exp = 0;
-		result.parts.fraction = 0;
-		return result;
-	}
-	
-	if (is_float64_zero(b)) {
-		if (is_float64_zero(a)) {
-			/*FIXME: 0 / 0*/
-			result.bin = FLOAT64_NAN;
-			return result;
-		}
-		/* FIXME: division by zero */
-		result.parts.exp = 0;
-		result.parts.fraction = 0;
-		return result;
-	}
-	
-	afrac = a.parts.fraction;
-	aexp = a.parts.exp;
-	bfrac = b.parts.fraction;
-	bexp = b.parts.exp;
-	
-	/* denormalized numbers */
-	if (aexp == 0) {
-		if (afrac == 0) {
-			result.parts.exp = 0;
-			result.parts.fraction = 0;
-			return result;
-		}
-		
-		/* normalize it*/
-		aexp++;
-		/* afrac is nonzero => it must stop */	
-		while (!(afrac & FLOAT64_HIDDEN_BIT_MASK)) {
-			afrac <<= 1;
-			aexp--;
-		}
-	}
-	
-	if (bexp == 0) {
-		bexp++;
-		/* bfrac is nonzero => it must stop */	
-		while (!(bfrac & FLOAT64_HIDDEN_BIT_MASK)) {
-			bfrac <<= 1;
-			bexp--;
-		}
-	}
-	
-	afrac = (afrac | FLOAT64_HIDDEN_BIT_MASK) << (64 - FLOAT64_FRACTION_SIZE - 2);
-	bfrac = (bfrac | FLOAT64_HIDDEN_BIT_MASK) << (64 - FLOAT64_FRACTION_SIZE - 1);
-	
-	if (bfrac <= (afrac << 1)) {
-		afrac >>= 1;
-		aexp++;
-	}
-	
-	cexp = aexp - bexp + FLOAT64_BIAS - 2; 
-	
-	cfrac = div128est(afrac, 0x0ll, bfrac);
-	
-	if ((cfrac & 0x1FF) <= 2) {
-		mul64(bfrac, cfrac, &tmphi, &tmplo);
-		sub128(afrac, 0x0ll, tmphi, tmplo, &remhi, &remlo);
-		
-		while ((int64_t) remhi < 0) {
-			cfrac--;
-			add128(remhi, remlo, 0x0ll, bfrac, &remhi, &remlo);
-		}
-		cfrac |= (remlo != 0);
-	}
-	
-	/* round and shift */
-	result = finish_float64(cexp, cfrac, result.parts.sign);
-	return result;
-}
-
-/** Divide two quadruple-precision floats.
- *
- * @param a Nominator.
- * @param b Denominator.
- *
- * @return Result of division.
- *
- */
-float128 div_float128(float128 a, float128 b)
-{
-	float128 result;
-	int64_t aexp, bexp, cexp;
-	uint64_t afrac_hi, afrac_lo, bfrac_hi, bfrac_lo, cfrac_hi, cfrac_lo;
-	uint64_t shift_out;
-	uint64_t rem_hihi, rem_hilo, rem_lohi, rem_lolo;
-	uint64_t tmp_hihi, tmp_hilo, tmp_lohi, tmp_lolo;
-	
-	result.parts.sign = a.parts.sign ^ b.parts.sign;
-	
-	if (is_float128_nan(a)) {
-		if (is_float128_signan(b)) {
-			// FIXME: SigNaN
-			return b;
-		}
-		
-		if (is_float128_signan(a)) {
-			// FIXME: SigNaN
-		}
-		/* NaN */
-		return a;
-	}
-	
-	if (is_float128_nan(b)) {
-		if (is_float128_signan(b)) {
-			// FIXME: SigNaN
-		}
-		/* NaN */
-		return b;
-	}
-	
-	if (is_float128_infinity(a)) {
-		if (is_float128_infinity(b) || is_float128_zero(b)) {
-			// FIXME: inf / inf
-			result.bin.hi = FLOAT128_NAN_HI;
-			result.bin.lo = FLOAT128_NAN_LO;
-			return result;
-		}
-		/* inf / num */
-		result.parts.exp = a.parts.exp;
-		result.parts.frac_hi = a.parts.frac_hi;
-		result.parts.frac_lo = a.parts.frac_lo;
-		return result;
-	}
-	
-	if (is_float128_infinity(b)) {
-		if (is_float128_zero(a)) {
-			// FIXME 0 / inf
-			result.parts.exp = 0;
-			result.parts.frac_hi = 0;
-			result.parts.frac_lo = 0;
-			return result;
-		}
-		// FIXME: num / inf
-		result.parts.exp = 0;
-		result.parts.frac_hi = 0;
-		result.parts.frac_lo = 0;
-		return result;
-	}
-	
-	if (is_float128_zero(b)) {
-		if (is_float128_zero(a)) {
-			// FIXME: 0 / 0
-			result.bin.hi = FLOAT128_NAN_HI;
-			result.bin.lo = FLOAT128_NAN_LO;
-			return result;
-		}
-		// FIXME: division by zero
-		result.parts.exp = 0;
-		result.parts.frac_hi = 0;
-		result.parts.frac_lo = 0;
-		return result;
-	}
-	
-	afrac_hi = a.parts.frac_hi;
-	afrac_lo = a.parts.frac_lo;
-	aexp = a.parts.exp;
-	bfrac_hi = b.parts.frac_hi;
-	bfrac_lo = b.parts.frac_lo;
-	bexp = b.parts.exp;
-	
-	/* denormalized numbers */
-	if (aexp == 0) {
-		if (eq128(afrac_hi, afrac_lo, 0x0ll, 0x0ll)) {
-			result.parts.exp = 0;
-			result.parts.frac_hi = 0;
-			result.parts.frac_lo = 0;
-			return result;
-		}
-		
-		/* normalize it*/
-		aexp++;
-		/* afrac is nonzero => it must stop */
-		and128(afrac_hi, afrac_lo,
-		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-		    &tmp_hihi, &tmp_lolo);
-		while (!lt128(0x0ll, 0x0ll, tmp_hihi, tmp_lolo)) {
-			lshift128(afrac_hi, afrac_lo, 1, &afrac_hi, &afrac_lo);
-			aexp--;
-		}
-	}
-	
-	if (bexp == 0) {
-		bexp++;
-		/* bfrac is nonzero => it must stop */
-		and128(bfrac_hi, bfrac_lo,
-		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-		    &tmp_hihi, &tmp_lolo);
-		while (!lt128(0x0ll, 0x0ll, tmp_hihi, tmp_lolo)) {
-			lshift128(bfrac_hi, bfrac_lo, 1, &bfrac_hi, &bfrac_lo);
-			bexp--;
-		}
-	}
-	
-	or128(afrac_hi, afrac_lo,
-	    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-	    &afrac_hi, &afrac_lo);
-	lshift128(afrac_hi, afrac_lo,
-	    (128 - FLOAT128_FRACTION_SIZE - 1), &afrac_hi, &afrac_lo);
-	or128(bfrac_hi, bfrac_lo,
-	    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-	    &bfrac_hi, &bfrac_lo);
-	lshift128(bfrac_hi, bfrac_lo,
-	    (128 - FLOAT128_FRACTION_SIZE - 1), &bfrac_hi, &bfrac_lo);
-	
-	if (le128(bfrac_hi, bfrac_lo, afrac_hi, afrac_lo)) {
-		rshift128(afrac_hi, afrac_lo, 1, &afrac_hi, &afrac_lo);
-		aexp++;
-	}
-	
-	cexp = aexp - bexp + FLOAT128_BIAS - 2;
-	
-	cfrac_hi = div128est(afrac_hi, afrac_lo, bfrac_hi);
-	
-	mul128(bfrac_hi, bfrac_lo, 0x0ll, cfrac_hi,
-	    &tmp_lolo /* dummy */, &tmp_hihi, &tmp_hilo, &tmp_lohi);
-	
-	/* sub192(afrac_hi, afrac_lo, 0,
-	 *     tmp_hihi, tmp_hilo, tmp_lohi
-	 *     &rem_hihi, &rem_hilo, &rem_lohi); */
-	sub128(afrac_hi, afrac_lo, tmp_hihi, tmp_hilo, &rem_hihi, &rem_hilo);
-	if (tmp_lohi > 0) {
-		sub128(rem_hihi, rem_hilo, 0x0ll, 0x1ll, &rem_hihi, &rem_hilo);
-	}
-	rem_lohi = -tmp_lohi;
-	
-	while ((int64_t) rem_hihi < 0) {
-		--cfrac_hi;
-		/* add192(rem_hihi, rem_hilo, rem_lohi,
-		 *     0, bfrac_hi, bfrac_lo,
-		 *     &rem_hihi, &rem_hilo, &rem_lohi); */
-		add128(rem_hilo, rem_lohi, bfrac_hi, bfrac_lo, &rem_hilo, &rem_lohi);
-		if (lt128(rem_hilo, rem_lohi, bfrac_hi, bfrac_lo)) {
-			++rem_hihi;
-		}
-	}
-	
-	cfrac_lo = div128est(rem_hilo, rem_lohi, bfrac_lo);
-	
-	if ((cfrac_lo & 0x3FFF) <= 4) {
-		mul128(bfrac_hi, bfrac_lo, 0x0ll, cfrac_lo,
-		    &tmp_hihi /* dummy */, &tmp_hilo, &tmp_lohi, &tmp_lolo);
-		
-		/* sub192(rem_hilo, rem_lohi, 0,
-		 *     tmp_hilo, tmp_lohi, tmp_lolo,
-		 *     &rem_hilo, &rem_lohi, &rem_lolo); */
-		sub128(rem_hilo, rem_lohi, tmp_hilo, tmp_lohi, &rem_hilo, &rem_lohi);
-		if (tmp_lolo > 0) {
-			sub128(rem_hilo, rem_lohi, 0x0ll, 0x1ll, &rem_hilo, &rem_lohi);
-		}
-		rem_lolo = -tmp_lolo;
-		
-		while ((int64_t) rem_hilo < 0) {
-			--cfrac_lo;
-			/* add192(rem_hilo, rem_lohi, rem_lolo,
-			 *     0, bfrac_hi, bfrac_lo,
-			 *     &rem_hilo, &rem_lohi, &rem_lolo); */
-			add128(rem_lohi, rem_lolo, bfrac_hi, bfrac_lo, &rem_lohi, &rem_lolo);
-			if (lt128(rem_lohi, rem_lolo, bfrac_hi, bfrac_lo)) {
-				++rem_hilo;
-			}
-		}
-		
-		cfrac_lo |= ((rem_hilo | rem_lohi | rem_lolo) != 0 );
-	}
-	
-	shift_out = cfrac_lo << (64 - (128 - FLOAT128_FRACTION_SIZE - 1));
-	rshift128(cfrac_hi, cfrac_lo, (128 - FLOAT128_FRACTION_SIZE - 1),
-	    &cfrac_hi, &cfrac_lo);
-	
-	result = finish_float128(cexp, cfrac_hi, cfrac_lo, result.parts.sign, shift_out);
-	return result;
-}
-
-/** @}
- */
Index: pace/lib/softfloat/generic/mul.c
===================================================================
--- uspace/lib/softfloat/generic/mul.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,383 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Multiplication functions.
- */
-
-#include <sftypes.h>
-#include <mul.h>
-#include <comparison.h>
-#include <common.h>
-
-/** Multiply two single-precision floats.
- *
- * @param a First input operand.
- * @param b Second input operand.
- *
- * @return Result of multiplication.
- *
- */
-float32 mul_float32(float32 a, float32 b)
-{
-	float32 result;
-	uint64_t frac1, frac2;
-	int32_t exp;
-	
-	result.parts.sign = a.parts.sign ^ b.parts.sign;
-	
-	if (is_float32_nan(a) || is_float32_nan(b)) {
-		/* TODO: fix SigNaNs */
-		if (is_float32_signan(a)) {
-			result.parts.fraction = a.parts.fraction;
-			result.parts.exp = a.parts.exp;
-			return result;
-		}
-		if (is_float32_signan(b)) { /* TODO: fix SigNaN */
-			result.parts.fraction = b.parts.fraction;
-			result.parts.exp = b.parts.exp;
-			return result;
-		}
-		/* set NaN as result */
-		result.bin = FLOAT32_NAN;
-		return result;
-	}
-	
-	if (is_float32_infinity(a)) {
-		if (is_float32_zero(b)) {
-			/* FIXME: zero * infinity */
-			result.bin = FLOAT32_NAN;
-			return result;
-		}
-		result.parts.fraction = a.parts.fraction;
-		result.parts.exp = a.parts.exp;
-		return result;
-	}
-	
-	if (is_float32_infinity(b)) {
-		if (is_float32_zero(a)) {
-			/* FIXME: zero * infinity */
-			result.bin = FLOAT32_NAN;
-			return result;
-		}
-		result.parts.fraction = b.parts.fraction;
-		result.parts.exp = b.parts.exp;
-		return result;
-	}
-	
-	/* exp is signed so we can easy detect underflow */
-	exp = a.parts.exp + b.parts.exp;
-	exp -= FLOAT32_BIAS;
-	
-	if (exp >= FLOAT32_MAX_EXPONENT) {
-		/* FIXME: overflow */
-		/* set infinity as result */
-		result.bin = FLOAT32_INF;
-		result.parts.sign = a.parts.sign ^ b.parts.sign;
-		return result;
-	}
-	
-	if (exp < 0) { 
-		/* FIXME: underflow */
-		/* return signed zero */
-		result.parts.fraction = 0x0;
-		result.parts.exp = 0x0;
-		return result;
-	}
-	
-	frac1 = a.parts.fraction;
-	if (a.parts.exp > 0) {
-		frac1 |= FLOAT32_HIDDEN_BIT_MASK;
-	} else {
-		++exp;
-	}
-	
-	frac2 = b.parts.fraction;
-	
-	if (b.parts.exp > 0) {
-		frac2 |= FLOAT32_HIDDEN_BIT_MASK;
-	} else {
-		++exp;
-	}
-	
-	frac1 <<= 1; /* one bit space for rounding */
-	
-	frac1 = frac1 * frac2;
-	
-	/* round and return */
-	while ((exp < FLOAT32_MAX_EXPONENT) &&
-	    (frac1 >= (1 << (FLOAT32_FRACTION_SIZE + 2)))) {
-		/* 23 bits of fraction + one more for hidden bit (all shifted 1 bit left) */
-		++exp;
-		frac1 >>= 1;
-	}
-	
-	/* rounding */
-	/* ++frac1; FIXME: not works - without it is ok */
-	frac1 >>= 1; /* shift off rounding space */
-	
-	if ((exp < FLOAT32_MAX_EXPONENT) &&
-	    (frac1 >= (1 << (FLOAT32_FRACTION_SIZE + 1)))) {
-		++exp;
-		frac1 >>= 1;
-	}
-	
-	if (exp >= FLOAT32_MAX_EXPONENT) {
-		/* TODO: fix overflow */
-		/* return infinity*/
-		result.parts.exp = FLOAT32_MAX_EXPONENT;
-		result.parts.fraction = 0x0;
-		return result;
-	}
-	
-	exp -= FLOAT32_FRACTION_SIZE;
-	
-	if (exp <= FLOAT32_FRACTION_SIZE) {
-		/* denormalized number */
-		frac1 >>= 1; /* denormalize */
-		while ((frac1 > 0) && (exp < 0)) {
-			frac1 >>= 1;
-			++exp;
-		}
-		if (frac1 == 0) {
-			/* FIXME : underflow */
-			result.parts.exp = 0;
-			result.parts.fraction = 0;
-			return result;
-		}
-	}
-	result.parts.exp = exp; 
-	result.parts.fraction = frac1 & ((1 << FLOAT32_FRACTION_SIZE) - 1);
-	
-	return result;
-}
-
-/** Multiply two double-precision floats.
- *
- * @param a First input operand.
- * @param b Second input operand.
- *
- * @return Result of multiplication.
- *
- */
-float64 mul_float64(float64 a, float64 b)
-{
-	float64 result;
-	uint64_t frac1, frac2;
-	int32_t exp;
-	
-	result.parts.sign = a.parts.sign ^ b.parts.sign;
-	
-	if (is_float64_nan(a) || is_float64_nan(b)) {
-		/* TODO: fix SigNaNs */
-		if (is_float64_signan(a)) {
-			result.parts.fraction = a.parts.fraction;
-			result.parts.exp = a.parts.exp;
-			return result;
-		}
-		if (is_float64_signan(b)) { /* TODO: fix SigNaN */
-			result.parts.fraction = b.parts.fraction;
-			result.parts.exp = b.parts.exp;
-			return result;
-		}
-		/* set NaN as result */
-		result.bin = FLOAT64_NAN;
-		return result;
-	}
-	
-	if (is_float64_infinity(a)) {
-		if (is_float64_zero(b)) {
-			/* FIXME: zero * infinity */
-			result.bin = FLOAT64_NAN;
-			return result;
-		}
-		result.parts.fraction = a.parts.fraction;
-		result.parts.exp = a.parts.exp;
-		return result;
-	}
-	
-	if (is_float64_infinity(b)) {
-		if (is_float64_zero(a)) {
-			/* FIXME: zero * infinity */
-			result.bin = FLOAT64_NAN;
-			return result;
-		}
-		result.parts.fraction = b.parts.fraction;
-		result.parts.exp = b.parts.exp;
-		return result;
-	}
-	
-	/* exp is signed so we can easy detect underflow */
-	exp = a.parts.exp + b.parts.exp - FLOAT64_BIAS;
-	
-	frac1 = a.parts.fraction;
-	
-	if (a.parts.exp > 0) {
-		frac1 |= FLOAT64_HIDDEN_BIT_MASK;
-	} else {
-		++exp;
-	}
-	
-	frac2 = b.parts.fraction;
-	
-	if (b.parts.exp > 0) {
-		frac2 |= FLOAT64_HIDDEN_BIT_MASK;
-	} else {
-		++exp;
-	}
-	
-	frac1 <<= (64 - FLOAT64_FRACTION_SIZE - 1);
-	frac2 <<= (64 - FLOAT64_FRACTION_SIZE - 2);
-	
-	mul64(frac1, frac2, &frac1, &frac2);
-	
-	frac1 |= (frac2 != 0);
-	if (frac1 & (0x1ll << 62)) {
-		frac1 <<= 1;
-		exp--;
-	}
-	
-	result = finish_float64(exp, frac1, result.parts.sign);
-	return result;
-}
-
-/** Multiply two quadruple-precision floats.
- *
- * @param a First input operand.
- * @param b Second input operand.
- *
- * @return Result of multiplication.
- *
- */
-float128 mul_float128(float128 a, float128 b)
-{
-	float128 result;
-	uint64_t frac1_hi, frac1_lo, frac2_hi, frac2_lo, tmp_hi, tmp_lo;
-	int32_t exp;
-	
-	result.parts.sign = a.parts.sign ^ b.parts.sign;
-	
-	if (is_float128_nan(a) || is_float128_nan(b)) {
-		/* TODO: fix SigNaNs */
-		if (is_float128_signan(a)) {
-			result.parts.frac_hi = a.parts.frac_hi;
-			result.parts.frac_lo = a.parts.frac_lo;
-			result.parts.exp = a.parts.exp;
-			return result;
-		}
-		if (is_float128_signan(b)) { /* TODO: fix SigNaN */
-			result.parts.frac_hi = b.parts.frac_hi;
-			result.parts.frac_lo = b.parts.frac_lo;
-			result.parts.exp = b.parts.exp;
-			return result;
-		}
-		/* set NaN as result */
-		result.bin.hi = FLOAT128_NAN_HI;
-		result.bin.lo = FLOAT128_NAN_LO;
-		return result;
-	}
-	
-	if (is_float128_infinity(a)) {
-		if (is_float128_zero(b)) {
-			/* FIXME: zero * infinity */
-			result.bin.hi = FLOAT128_NAN_HI;
-			result.bin.lo = FLOAT128_NAN_LO;
-			return result;
-		}
-		result.parts.frac_hi = a.parts.frac_hi;
-		result.parts.frac_lo = a.parts.frac_lo;
-		result.parts.exp = a.parts.exp;
-		return result;
-	}
-	
-	if (is_float128_infinity(b)) {
-		if (is_float128_zero(a)) {
-			/* FIXME: zero * infinity */
-			result.bin.hi = FLOAT128_NAN_HI;
-			result.bin.lo = FLOAT128_NAN_LO;
-			return result;
-		}
-		result.parts.frac_hi = b.parts.frac_hi;
-		result.parts.frac_lo = b.parts.frac_lo;
-		result.parts.exp = b.parts.exp;
-		return result;
-	}
-	
-	/* exp is signed so we can easy detect underflow */
-	exp = a.parts.exp + b.parts.exp - FLOAT128_BIAS - 1;
-	
-	frac1_hi = a.parts.frac_hi;
-	frac1_lo = a.parts.frac_lo;
-	
-	if (a.parts.exp > 0) {
-		or128(frac1_hi, frac1_lo,
-		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-		    &frac1_hi, &frac1_lo);
-	} else {
-		++exp;
-	}
-	
-	frac2_hi = b.parts.frac_hi;
-	frac2_lo = b.parts.frac_lo;
-	
-	if (b.parts.exp > 0) {
-		or128(frac2_hi, frac2_lo,
-		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-		    &frac2_hi, &frac2_lo);
-	} else {
-		++exp;
-	}
-	
-	lshift128(frac2_hi, frac2_lo,
-	    128 - FLOAT128_FRACTION_SIZE, &frac2_hi, &frac2_lo);
-	
-	tmp_hi = frac1_hi;
-	tmp_lo = frac1_lo;
-	mul128(frac1_hi, frac1_lo, frac2_hi, frac2_lo,
-	    &frac1_hi, &frac1_lo, &frac2_hi, &frac2_lo);
-	add128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &frac1_hi, &frac1_lo);
-	frac2_hi |= (frac2_lo != 0x0ll);
-	
-	if ((FLOAT128_HIDDEN_BIT_MASK_HI << 1) <= frac1_hi) {
-		frac2_hi >>= 1;
-		if (frac1_lo & 0x1ll) {
-			frac2_hi |= (0x1ull < 64);
-		}
-		rshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
-		++exp;
-	}
-	
-	result = finish_float128(exp, frac1_hi, frac1_lo, result.parts.sign, frac2_hi);
-	return result;
-}
-
-/** @}
- */
Index: pace/lib/softfloat/generic/other.c
===================================================================
--- uspace/lib/softfloat/generic/other.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,37 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * 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 softfloat
- * @{
- */
-/** @file Other functions (power, complex).
- */
-
-
-/** @}
- */
Index: pace/lib/softfloat/generic/softfloat.c
===================================================================
--- uspace/lib/softfloat/generic/softfloat.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,1270 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat generic
- * @ingroup sfl
- * @brief Architecture independent parts of FPU software emulation library.
- * @{
- */
-/** @file Softfloat API.
- */
-
-#include <softfloat.h>
-#include <sftypes.h>
-
-#include <add.h>
-#include <sub.h>
-#include <mul.h>
-#include <div.h>
-
-#include <conversion.h>
-#include <comparison.h>
-#include <other.h>
-
-/* Arithmetic functions */
-
-float __addsf3(float a, float b)
-{
-	float_t fa;
-	float_t fb;
-	float_t res;
-	
-	fa.val = a;
-	fb.val = b;
-	
-	if (fa.data.parts.sign != fb.data.parts.sign) {
-		if (fa.data.parts.sign) {
-			fa.data.parts.sign = 0;
-			res.data = sub_float(fb.data, fa.data);
-			
-			return res.val;
-		}
-		
-		fb.data.parts.sign = 0;
-		res.data = sub_float(fa.data, fb.data);
-		
-		return res.val;
-	}
-	
-	res.data = add_float(fa.data, fb.data);
-	return res.val;
-}
-
-double __adddf3(double a, double b)
-{
-	double_t da;
-	double_t db;
-	double_t res;
-	
-	da.val = a;
-	db.val = b;
-	
-	if (da.data.parts.sign != db.data.parts.sign) {
-		if (da.data.parts.sign) {
-			da.data.parts.sign = 0;
-			res.data = sub_double(db.data, da.data);
-			
-			return res.val;
-		}
-		
-		db.data.parts.sign = 0;
-		res.data = sub_double(da.data, db.data);
-		
-		return res.val;
-	}
-	
-	res.data = add_double(da.data, db.data);
-	return res.val;
-}
-
-long double __addtf3(long double a, long double b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	long_double_t res;
-	
-	ta.val = a;
-	tb.val = b;
-	
-	if (ta.data.parts.sign != tb.data.parts.sign) {
-		if (ta.data.parts.sign) {
-			ta.data.parts.sign = 0;
-			res.data = sub_long_double(tb.data, ta.data);
-			
-			return res.val;
-		}
-		
-		tb.data.parts.sign = 0;
-		res.data = sub_long_double(ta.data, tb.data);
-		
-		return res.val;
-	}
-	
-	res.data = add_long_double(ta.data, tb.data);
-	return res.val;
-}
-
-float __subsf3(float a, float b)
-{
-	float_t fa;
-	float_t fb;
-	float_t res;
-	
-	fa.val = a;
-	fb.val = b;
-	
-	if (fa.data.parts.sign != fb.data.parts.sign) {
-		fb.data.parts.sign = !fb.data.parts.sign;
-		res.data = add_float(fa.data, fb.data);
-		
-		return res.val;
-	}
-	
-	res.data = sub_float(fa.data, fb.data);
-	return res.val;
-}
-
-double __subdf3(double a, double b)
-{
-	double_t da;
-	double_t db;
-	double_t res;
-	
-	da.val = a;
-	db.val = b;
-	
-	if (da.data.parts.sign != db.data.parts.sign) {
-		db.data.parts.sign = !db.data.parts.sign;
-		res.data = add_double(da.data, db.data);
-		
-		return res.val;
-	}
-	
-	res.data = sub_double(da.data, db.data);
-	return res.val;
-}
-
-long double __subtf3(long double a, long double b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	long_double_t res;
-	
-	ta.val = a;
-	tb.val = b;
-	
-	if (ta.data.parts.sign != tb.data.parts.sign) {
-		tb.data.parts.sign = !tb.data.parts.sign;
-		res.data = add_long_double(ta.data, tb.data);
-		
-		return res.val;
-	}
-	
-	res.data = sub_long_double(ta.data, tb.data);
-	return res.val;
-}
-
-float __mulsf3(float a, float b)
-{
-	float_t fa;
-	float_t fb;
-	float_t res;
-	
-	fa.val = a;
-	fb.val = b;
-	
-	res.data = mul_float(fa.data, fb.data);
-	return res.val;
-}
-
-double __muldf3(double a, double b)
-{
-	double_t da;
-	double_t db;
-	double_t res;
-	
-	da.val = a;
-	db.val = b;
-	
-	res.data = mul_double(da.data, db.data);
-	return res.val;
-}
-
-long double __multf3(long double a, long double b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	long_double_t res;
-	
-	ta.val = a;
-	tb.val = b;
-	
-	res.data = mul_long_double(ta.data, tb.data);
-	return res.val;
-}
-
-float __divsf3(float a, float b)
-{
-	float_t fa;
-	float_t fb;
-	float_t res;
-	
-	fa.val = a;
-	fb.val = b;
-	
-	res.data = div_float(fa.data, fb.data);
-	return res.val;
-}
-
-double __divdf3(double a, double b)
-{
-	double_t da;
-	double_t db;
-	double_t res;
-	
-	da.val = a;
-	db.val = b;
-	
-	res.data = div_double(da.data, db.data);
-	return res.val;
-}
-
-long double __divtf3(long double a, long double b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	long_double_t res;
-	
-	ta.val = a;
-	tb.val = b;
-	
-	res.data = div_long_double(ta.data, tb.data);
-	return res.val;
-}
-
-float __negsf2(float a)
-{
-	float_t fa;
-	
-	fa.val = a;
-	fa.data.parts.sign = !fa.data.parts.sign;
-	
-	return fa.val;
-}
-
-double __negdf2(double a)
-{
-	double_t da;
-	
-	da.val = a;
-	da.data.parts.sign = !da.data.parts.sign;
-	
-	return da.val;
-}
-
-long double __negtf2(long double a)
-{
-	long_double_t ta;
-	
-	ta.val = a;
-	ta.data.parts.sign = !ta.data.parts.sign;
-	
-	return ta.val;
-}
-
-/* Conversion functions */
-
-double __extendsfdf2(float a)
-{
-	float_t fa;
-	double_t res;
-	
-	fa.val = a;
-	res.data = float_to_double(fa.data);
-	
-	return res.val;
-}
-
-long double __extendsftf2(float a)
-{
-	float_t fa;
-	long_double_t res;
-	
-	fa.val = a;
-	res.data = float_to_long_double(fa.data);
-	
-	return res.val;
-}
-
-long double __extenddftf2(double a)
-{
-	double_t da;
-	long_double_t res;
-	
-	da.val = a;
-	res.data = double_to_long_double(da.data);
-	
-	return res.val;
-}
-
-float __truncdfsf2(double a)
-{
-	double_t da;
-	float_t res;
-	
-	da.val = a;
-	res.data = double_to_float(da.data);
-	
-	return res.val;
-}
-
-float __trunctfsf2(long double a)
-{
-	long_double_t ta;
-	float_t res;
-	
-	ta.val = a;
-	res.data = long_double_to_float(ta.data);
-	
-	return res.val;
-}
-
-double __trunctfdf2(long double a)
-{
-	long_double_t ta;
-	double_t res;
-	
-	ta.val = a;
-	res.data = long_double_to_double(ta.data);
-	
-	return res.val;
-}
-
-int __fixsfsi(float a)
-{
-	float_t fa;
-	
-	fa.val = a;
-	return float_to_int(fa.data);
-}
-
-int __fixdfsi(double a)
-{
-	double_t da;
-	
-	da.val = a;
-	return double_to_int(da.data);
-}
-
-int __fixtfsi(long double a)
-{
-	long_double_t ta;
-	
-	ta.val = a;
-	return long_double_to_int(ta.data);
-}
- 
-long __fixsfdi(float a)
-{
-	float_t fa;
-	
-	fa.val = a;
-	return float_to_long(fa.data);
-}
-
-long __fixdfdi(double a)
-{
-	double_t da;
-	
-	da.val = a;
-	return double_to_long(da.data);
-}
-
-long __fixtfdi(long double a)
-{
-	long_double_t ta;
-	
-	ta.val = a;
-	return long_double_to_long(ta.data);
-}
- 
-long long __fixsfti(float a)
-{
-	float_t fa;
-	
-	fa.val = a;
-	return float_to_llong(fa.data);
-}
-
-long long __fixdfti(double a)
-{
-	double_t da;
-	
-	da.val = a;
-	return double_to_llong(da.data);
-}
-
-long long __fixtfti(long double a)
-{
-	long_double_t ta;
-	
-	ta.val = a;
-	return long_double_to_llong(ta.data);
-}
-
-unsigned int __fixunssfsi(float a)
-{
-	float_t fa;
-	
-	fa.val = a;
-	return float_to_uint(fa.data);
-}
-
-unsigned int __fixunsdfsi(double a)
-{
-	double_t da;
-	
-	da.val = a;
-	return double_to_uint(da.data);
-}
-
-unsigned int __fixunstfsi(long double a)
-{
-	long_double_t ta;
-	
-	ta.val = a;
-	return long_double_to_uint(ta.data);
-}
- 
-unsigned long __fixunssfdi(float a)
-{
-	float_t fa;
-	
-	fa.val = a;
-	return float_to_ulong(fa.data);
-}
-
-unsigned long __fixunsdfdi(double a)
-{
-	double_t da;
-	
-	da.val = a;
-	return double_to_ulong(da.data);
-}
-
-unsigned long __fixunstfdi(long double a)
-{
-	long_double_t ta;
-	
-	ta.val = a;
-	return long_double_to_ulong(ta.data);
-}
- 
-unsigned long long __fixunssfti(float a)
-{
-	float_t fa;
-	
-	fa.val = a;
-	return float_to_ullong(fa.data);
-}
-
-unsigned long long __fixunsdfti(double a)
-{
-	double_t da;
-	
-	da.val = a;
-	return double_to_ullong(da.data);
-}
-
-unsigned long long __fixunstfti(long double a)
-{
-	long_double_t ta;
-	
-	ta.val = a;
-	return long_double_to_ullong(ta.data);
-}
- 
-float __floatsisf(int i)
-{
-	float_t res;
-	
-	res.data = int_to_float(i);
-	return res.val;
-}
-
-double __floatsidf(int i)
-{
-	double_t res;
-	
-	res.data = int_to_double(i);
-	return res.val;
-}
-
-long double __floatsitf(int i)
-{
-	long_double_t res;
-	
-	res.data = int_to_long_double(i);
-	return res.val;
-}
- 
-float __floatdisf(long i)
-{
-	float_t res;
-	
-	res.data = long_to_float(i);
-	return res.val;
-}
-
-double __floatdidf(long i)
-{
-	double_t res;
-	
-	res.data = long_to_double(i);
-	return res.val;
-}
-
-long double __floatditf(long i)
-{
-	long_double_t res;
-	
-	res.data = long_to_long_double(i);
-	return res.val;
-}
-
-float __floattisf(long long i)
-{
-	float_t res;
-	
-	res.data = llong_to_float(i);
-	return res.val;
-}
-
-double __floattidf(long long i)
-{
-	double_t res;
-	
-	res.data = llong_to_double(i);
-	return res.val;
-}
-
-long double __floattitf(long long i)
-{
-	long_double_t res;
-	
-	res.data = llong_to_long_double(i);
-	return res.val;
-}
-
-float __floatunsisf(unsigned int i)
-{
-	float_t res;
-	
-	res.data = uint_to_float(i);
-	return res.val;
-}
-
-double __floatunsidf(unsigned int i)
-{
-	double_t res;
-	
-	res.data = uint_to_double(i);
-	return res.val;
-}
-
-long double __floatunsitf(unsigned int i)
-{
-	long_double_t res;
-	
-	res.data = uint_to_long_double(i);
-	return res.val;
-}
- 
-float __floatundisf(unsigned long i)
-{
-	float_t res;
-	
-	res.data = ulong_to_float(i);
-	return res.val;
-}
-
-double __floatundidf(unsigned long i)
-{
-	double_t res;
-	
-	res.data = ulong_to_double(i);
-	return res.val;
-}
-
-long double __floatunditf(unsigned long i)
-{
-	long_double_t res;
-	
-	res.data = ulong_to_long_double(i);
-	return res.val;
-}
- 
-float __floatuntisf(unsigned long long i)
-{
-	float_t res;
-	
-	res.data = ullong_to_float(i);
-	return res.val;
-}
-
-double __floatuntidf(unsigned long long i)
-{
-	double_t res;
-	
-	res.data = ullong_to_double(i);
-	return res.val;
-}
-
-long double __floatuntitf(unsigned long long i)
-{
-	long_double_t res;
-	
-	res.data = ullong_to_long_double(i);
-	return res.val;
-}
-
-/* Comparison functions */
-
-int __cmpsf2(float a, float b) 
-{
-	float_t fa;
-	float_t fb;
-	
-	fa.val = a;
-	fb.val = b;
-	
-	if ((is_float_nan(fa.data)) || (is_float_nan(fb.data))) {
-		/* no special constant for unordered - maybe signaled? */
-		return 1;
-	}
-	
-	if (is_float_eq(fa.data, fb.data))
-		return 0;
-	
-	if (is_float_lt(fa.data, fb.data))
-		return -1;
-	
-	return 1;
-}
-
-int __cmpdf2(double a, double b)
-{
-	double_t da;
-	double_t db;
-	
-	da.val = a;
-	db.val = b;
-	
-	if ((is_double_nan(da.data)) || (is_double_nan(db.data))) {
-		/* no special constant for unordered - maybe signaled? */
-		return 1;
-	}
-	
-	if (is_double_eq(da.data, db.data))
-		return 0;
-	
-	if (is_double_lt(da.data, db.data))
-		return -1;
-	
-	return 1;
-}
-
-int __cmptf2(long double a, long double b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = a;
-	tb.val = b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data))) {
-		/* no special constant for unordered - maybe signaled? */
-		return 1;
-	}
-	
-	if (is_long_double_eq(ta.data, tb.data))
-		return 0;
-	
-	if (is_long_double_lt(ta.data, tb.data))
-		return -1;
-	
-	return 1;
-}
-
-int __unordsf2(float a, float b)
-{
-	float_t fa;
-	float_t fb;
-	
-	fa.val = a;
-	fb.val = b;
-	
-	return ((is_float_nan(fa.data)) || (is_float_nan(fb.data)));
-}
-
-int __unorddf2(double a, double b)
-{
-	double_t da;
-	double_t db;
-	
-	da.val = a;
-	db.val = b;
-	
-	return ((is_double_nan(da.data)) || (is_double_nan(db.data)));
-}
-
-int __unordtf2(long double a, long double b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = a;
-	tb.val = b;
-	
-	return ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)));
-}
-
-int __eqsf2(float a, float b)
-{
-	float_t fa;
-	float_t fb;
-	
-	fa.val = a;
-	fb.val = b;
-	
-	if ((is_float_nan(fa.data)) || (is_float_nan(fb.data))) {
-		// TODO: sigNaNs
-		return 1;
-	}
-	
-	return is_float_eq(fa.data, fb.data) - 1;
-}
-
-int __eqdf2(double a, double b)
-{
-	double_t da;
-	double_t db;
-	
-	da.val = a;
-	db.val = b;
-	
-	if ((is_double_nan(da.data)) || (is_double_nan(db.data))) {
-		// TODO: sigNaNs
-		return 1;
-	}
-	
-	return is_double_eq(da.data, db.data) - 1;
-}
-
-int __eqtf2(long double a, long double b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = a;
-	tb.val = b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data))) {
-		// TODO: sigNaNs
-		return 1;
-	}
-	
-	return is_long_double_eq(ta.data, tb.data) - 1;
-}
-
-int __nesf2(float a, float b)
-{
-	/* strange behavior, but it was in gcc documentation */
-	return __eqsf2(a, b);
-}
-
-int __nedf2(double a, double b)
-{
-	/* strange behavior, but it was in gcc documentation */
-	return __eqdf2(a, b);
-}
-
-int __netf2(long double a, long double b)
-{
-	/* strange behavior, but it was in gcc documentation */
-	return __eqtf2(a, b);
-}
-
-int __gesf2(float a, float b)
-{
-	float_t fa;
-	float_t fb;
-	
-	fa.val = a;
-	fb.val = b;
-	
-	if ((is_float_nan(fa.data)) || (is_float_nan(fb.data))) {
-		// TODO: sigNaNs
-		return -1;
-	}
-	
-	if (is_float_eq(fa.data, fb.data))
-		return 0;
-	
-	if (is_float_gt(fa.data, fb.data))
-		return 1;
-	
-	return -1;
-}
-
-int __gedf2(double a, double b)
-{
-	double_t da;
-	double_t db;
-	
-	da.val = a;
-	db.val = b;
-	
-	if ((is_double_nan(da.data)) || (is_double_nan(db.data))) {
-		// TODO: sigNaNs
-		return -1;
-	}
-	
-	if (is_double_eq(da.data, db.data))
-		return 0;
-	
-	if (is_double_gt(da.data, db.data))
-		return 1;
-	
-	return -1;
-}
-
-int __getf2(long double a, long double b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = a;
-	tb.val = b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data))) {
-		// TODO: sigNaNs
-		return -1;
-	}
-	
-	if (is_long_double_eq(ta.data, tb.data))
-		return 0;
-	
-	if (is_long_double_gt(ta.data, tb.data))
-		return 1;
-	
-	return -1;
-}
-
-int __ltsf2(float a, float b)
-{
-	float_t fa;
-	float_t fb;
-	
-	fa.val = a;
-	fb.val = b;
-	
-	if ((is_float_nan(fa.data)) || (is_float_nan(fb.data))) {
-		// TODO: sigNaNs
-		return 1;
-	}
-	
-	if (is_float_lt(fa.data, fb.data))
-		return -1;
-	
-	return 0;
-}
-
-int __ltdf2(double a, double b)
-{
-	double_t da;
-	double_t db;
-	
-	da.val = a;
-	db.val = b;
-	
-	if ((is_double_nan(da.data)) || (is_double_nan(db.data))) {
-		// TODO: sigNaNs
-		return 1;
-	}
-	
-	if (is_double_lt(da.data, db.data))
-		return -1;
-	
-	return 0;
-}
-
-int __lttf2(long double a, long double b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = a;
-	tb.val = b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data))) {
-		// TODO: sigNaNs
-		return 1;
-	}
-	
-	if (is_long_double_lt(ta.data, tb.data))
-		return -1;
-	
-	return 0;
-}
-
-int __lesf2(float a, float b)
-{
-	float_t fa;
-	float_t fb;
-	
-	fa.val = a;
-	fb.val = b;
-	
-	if ((is_float_nan(fa.data)) || (is_float_nan(fb.data))) {
-		// TODO: sigNaNs
-		return 1;
-	}
-	
-	if (is_float_eq(fa.data, fb.data))
-		return 0;
-	
-	if (is_float_lt(fa.data, fb.data))
-		return -1;
-	
-	return 1;
-}
-
-int __ledf2(double a, double b)
-{
-	double_t da;
-	double_t db;
-	
-	da.val = a;
-	db.val = b;
-	
-	if ((is_double_nan(da.data)) || (is_double_nan(db.data))) {
-		// TODO: sigNaNs
-		return 1;
-	}
-	
-	if (is_double_eq(da.data, db.data))
-		return 0;
-	
-	if (is_double_lt(da.data, db.data))
-		return -1;
-	
-	return 1;
-}
-
-int __letf2(long double a, long double b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = a;
-	tb.val = b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data))) {
-		// TODO: sigNaNs
-		return 1;
-	}
-	
-	if (is_long_double_eq(ta.data, tb.data))
-		return 0;
-	
-	if (is_long_double_lt(ta.data, tb.data))
-		return -1;
-	
-	return 1;
-}
-
-int __gtsf2(float a, float b)
-{
-	float_t fa;
-	float_t fb;
-	
-	fa.val = a;
-	fb.val = b;
-	
-	if ((is_float_nan(fa.data)) || (is_float_nan(fb.data))) {
-		// TODO: sigNaNs
-		return -1;
-	}
-	
-	if (is_float_gt(fa.data, fb.data))
-		return 1;
-	
-	return 0;
-}
-
-int __gtdf2(double a, double b)
-{
-	double_t da;
-	double_t db;
-	
-	da.val = a;
-	db.val = b;
-	
-	if ((is_double_nan(da.data)) || (is_double_nan(db.data))) {
-		// TODO: sigNaNs
-		return -1;
-	}
-	
-	if (is_double_gt(da.data, db.data))
-		return 1;
-	
-	return 0;
-}
-
-int __gttf2(long double a, long double b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = a;
-	tb.val = b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data))) {
-		// TODO: sigNaNs
-		return -1;
-	}
-	
-	if (is_long_double_gt(ta.data, tb.data))
-		return 1;
-	
-	return 0;
-}
-
-/* SPARC quadruple-precision wrappers */
-
-void _Qp_add(long double *c, long double *a, long double *b)
-{
-	*c = __addtf3(*a, *b);
-}
-
-void _Qp_sub(long double *c, long double *a, long double *b)
-{
-	*c = __subtf3(*a, *b);
-}
-
-void _Qp_mul(long double *c, long double *a, long double *b)
-{
-	*c = __multf3(*a, *b);
-}
-
-void _Qp_div(long double *c, long double *a, long double *b)
-{
-	*c = __divtf3(*a, *b);
-}
-
-void _Qp_neg(long double *c, long double *a)
-{
-	*c = __negtf2(*a);
-}
-
-void _Qp_stoq(long double *c, float a)
-{
-	*c = __extendsftf2(a);
-}
-
-void _Qp_dtoq(long double *c, double a)
-{
-	*c = __extenddftf2(a);
-}
-
-float _Qp_qtos(long double *a)
-{
-	return __trunctfsf2(*a);
-}
-
-double _Qp_qtod(long double *a)
-{
-	return __trunctfdf2(*a);
-}
-
-int _Qp_qtoi(long double *a)
-{
-	return __fixtfsi(*a);
-}
-
-unsigned int _Qp_qtoui(long double *a)
-{
-	return __fixunstfsi(*a);
-}
-
-long _Qp_qtox(long double *a)
-{
-	return __fixtfdi(*a);
-}
-
-unsigned long _Qp_qtoux(long double *a)
-{
-	return __fixunstfdi(*a);
-}
-
-void _Qp_itoq(long double *c, int a)
-{
-	*c = __floatsitf(a);
-}
-
-void _Qp_uitoq(long double *c, unsigned int a)
-{
-	*c = __floatunsitf(a);
-}
-
-void _Qp_xtoq(long double *c, long a)
-{
-	*c = __floatditf(a);
-}
-
-void _Qp_uxtoq(long double *c, unsigned long a)
-{
-	*c = __floatunditf(a);
-}
-
-int _Qp_cmp(long double *a, long double *b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = *a;
-	tb.val = *b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
-		return 3;
-	
-	if (is_long_double_eq(ta.data, tb.data))
-		return 0;
-	
-	if (is_long_double_lt(ta.data, tb.data))
-		return 1;
-	
-	return 2;
-}
-
-int _Qp_cmpe(long double *a, long double *b)
-{
-	/* strange, but is defined this way in SPARC Compliance Definition */
-	return _Qp_cmp(a, b);
-}
-
-int _Qp_feq(long double *a, long double *b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = *a;
-	tb.val = *b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
-		return 0;
-	
-	return is_long_double_eq(ta.data, tb.data);
-}
-
-int _Qp_fge(long double *a, long double *b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = *a;
-	tb.val = *b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
-		return 0;
-	
-	return is_long_double_eq(ta.data, tb.data) ||
-	    is_long_double_gt(ta.data, tb.data);
-}
-
-int _Qp_fgt(long double *a, long double *b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = *a;
-	tb.val = *b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
-		return 0;
-	
-	return is_long_double_gt(ta.data, tb.data);
-}
-
-int _Qp_fle(long double*a, long double *b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = *a;
-	tb.val = *b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
-		return 0;
-	
-	return is_long_double_eq(ta.data, tb.data) ||
-	    is_long_double_lt(ta.data, tb.data);
-}
-
-int _Qp_flt(long double *a, long double *b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = *a;
-	tb.val = *b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
-		return 0;
-	
-	return is_long_double_lt(ta.data, tb.data);
-}
-
-int _Qp_fne(long double *a, long double *b)
-{
-	long_double_t ta;
-	long_double_t tb;
-	
-	ta.val = *a;
-	tb.val = *b;
-	
-	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
-		return 0;
-	
-	return !is_long_double_eq(ta.data, tb.data);
-}
-
-/** @}
- */
Index: pace/lib/softfloat/generic/sub.c
===================================================================
--- uspace/lib/softfloat/generic/sub.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,441 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Substraction functions.
- */
-
-#include <sftypes.h>
-#include <sub.h>
-#include <comparison.h>
-#include <common.h>
-
-/** Subtract two single-precision floats with the same sign.
- *
- * @param a First input operand.
- * @param b Second input operand.
- *
- * @return Result of substraction.
- *
- */
-float32 sub_float32(float32 a, float32 b)
-{
-	int expdiff;
-	uint32_t exp1, exp2, frac1, frac2;
-	float32 result;
-	
-	result.bin = 0;
-	
-	expdiff = a.parts.exp - b.parts.exp;
-	if ((expdiff < 0 ) || ((expdiff == 0) &&
-	    (a.parts.fraction < b.parts.fraction))) {
-		if (is_float32_nan(b)) {
-			if (is_float32_signan(b)) {
-				// TODO: fix SigNaN
-			}
-			
-			return b;
-		}
-		
-		if (b.parts.exp == FLOAT32_MAX_EXPONENT) {
-			/* num -(+-inf) = -+inf */
-			b.parts.sign = !b.parts.sign;
-			return b;
-		}
-		
-		result.parts.sign = !a.parts.sign;
-		
-		frac1 = b.parts.fraction;
-		exp1 = b.parts.exp;
-		frac2 = a.parts.fraction;
-		exp2 = a.parts.exp;
-		expdiff *= -1;
-	} else {
-		if (is_float32_nan(a)) {
-			if ((is_float32_signan(a)) || (is_float32_signan(b))) {
-				// TODO: fix SigNaN
-			}
-			
-			return a;
-		}
-		
-		if (a.parts.exp == FLOAT32_MAX_EXPONENT) {
-			if (b.parts.exp == FLOAT32_MAX_EXPONENT) {
-				/* inf - inf => nan */
-				// TODO: fix exception
-				result.bin = FLOAT32_NAN;
-				return result;
-			}
-			
-			return a;
-		}
-		
-		result.parts.sign = a.parts.sign;
-		
-		frac1 = a.parts.fraction;
-		exp1 = a.parts.exp;
-		frac2 = b.parts.fraction;
-		exp2 = b.parts.exp;
-	}
-	
-	if (exp1 == 0) {
-		/* both are denormalized */
-		result.parts.fraction = frac1 - frac2;
-		if (result.parts.fraction > frac1) {
-			// TODO: underflow exception
-			return result;
-		}
-		
-		result.parts.exp = 0;
-		return result;
-	}
-	
-	/* add hidden bit */
-	frac1 |= FLOAT32_HIDDEN_BIT_MASK;
-	
-	if (exp2 == 0) {
-		/* denormalized */
-		--expdiff;
-	} else {
-		/* normalized */
-		frac2 |= FLOAT32_HIDDEN_BIT_MASK;
-	}
-	
-	/* create some space for rounding */
-	frac1 <<= 6;
-	frac2 <<= 6;
-	
-	if (expdiff > FLOAT32_FRACTION_SIZE + 1)
-		goto done;
-	
-	frac1 = frac1 - (frac2 >> expdiff);
-	
-done:
-	/* TODO: find first nonzero digit and shift result and detect possibly underflow */
-	while ((exp1 > 0) && (!(frac1 & (FLOAT32_HIDDEN_BIT_MASK << 6 )))) {
-		--exp1;
-		frac1 <<= 1;
-		/* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
-	}
-	
-	/* rounding - if first bit after fraction is set then round up */
-	frac1 += 0x20;
-	
-	if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7)) {
-		++exp1;
-		frac1 >>= 1;
-	}
-	
-	/* Clear hidden bit and shift */
-	result.parts.fraction = ((frac1 >> 6) & (~FLOAT32_HIDDEN_BIT_MASK));
-	result.parts.exp = exp1;
-	
-	return result;
-}
-
-/** Subtract two double-precision floats with the same sign.
- *
- * @param a First input operand.
- * @param b Second input operand.
- *
- * @return Result of substraction.
- *
- */
-float64 sub_float64(float64 a, float64 b)
-{
-	int expdiff;
-	uint32_t exp1, exp2;
-	uint64_t frac1, frac2;
-	float64 result;
-	
-	result.bin = 0;
-	
-	expdiff = a.parts.exp - b.parts.exp;
-	if ((expdiff < 0 ) ||
-	    ((expdiff == 0) && (a.parts.fraction < b.parts.fraction))) {
-		if (is_float64_nan(b)) {
-			if (is_float64_signan(b)) {
-				// TODO: fix SigNaN
-			}
-			
-			return b;
-		}
-		
-		if (b.parts.exp == FLOAT64_MAX_EXPONENT) {
-			/* num -(+-inf) = -+inf */
-			b.parts.sign = !b.parts.sign;
-			return b;
-		}
-		
-		result.parts.sign = !a.parts.sign;
-		
-		frac1 = b.parts.fraction;
-		exp1 = b.parts.exp;
-		frac2 = a.parts.fraction;
-		exp2 = a.parts.exp;
-		expdiff *= -1;
-	} else {
-		if (is_float64_nan(a)) {
-			if (is_float64_signan(a) || is_float64_signan(b)) {
-				// TODO: fix SigNaN
-			}
-			
-			return a;
-		}
-		
-		if (a.parts.exp == FLOAT64_MAX_EXPONENT) {
-			if (b.parts.exp == FLOAT64_MAX_EXPONENT) {
-				/* inf - inf => nan */
-				// TODO: fix exception
-				result.bin = FLOAT64_NAN;
-				return result;
-			}
-			
-			return a;
-		}
-		
-		result.parts.sign = a.parts.sign;
-		
-		frac1 = a.parts.fraction;
-		exp1 = a.parts.exp;
-		frac2 = b.parts.fraction;
-		exp2 = b.parts.exp;
-	}
-	
-	if (exp1 == 0) {
-		/* both are denormalized */
-		result.parts.fraction = frac1 - frac2;
-		if (result.parts.fraction > frac1) {
-			// TODO: underflow exception
-			return result;
-		}
-		
-		result.parts.exp = 0;
-		return result;
-	}
-	
-	/* add hidden bit */
-	frac1 |= FLOAT64_HIDDEN_BIT_MASK;
-	
-	if (exp2 == 0) {
-		/* denormalized */
-		--expdiff;
-	} else {
-		/* normalized */
-		frac2 |= FLOAT64_HIDDEN_BIT_MASK;
-	}
-	
-	/* create some space for rounding */
-	frac1 <<= 6;
-	frac2 <<= 6;
-	
-	if (expdiff > FLOAT64_FRACTION_SIZE + 1)
-		goto done;
-	
-	frac1 = frac1 - (frac2 >> expdiff);
-	
-done:
-	/* TODO: find first nonzero digit and shift result and detect possibly underflow */
-	while ((exp1 > 0) && (!(frac1 & (FLOAT64_HIDDEN_BIT_MASK << 6 )))) {
-		--exp1;
-		frac1 <<= 1;
-		/* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
-	}
-	
-	/* rounding - if first bit after fraction is set then round up */
-	frac1 += 0x20;
-	
-	if (frac1 & (FLOAT64_HIDDEN_BIT_MASK << 7)) {
-		++exp1;
-		frac1 >>= 1;
-	}
-	
-	/* Clear hidden bit and shift */
-	result.parts.fraction = ((frac1 >> 6) & (~FLOAT64_HIDDEN_BIT_MASK));
-	result.parts.exp = exp1;
-	
-	return result;
-}
-
-/** Subtract two quadruple-precision floats with the same sign.
- *
- * @param a First input operand.
- * @param b Second input operand.
- *
- * @return Result of substraction.
- *
- */
-float128 sub_float128(float128 a, float128 b)
-{
-	int expdiff;
-	uint32_t exp1, exp2;
-	uint64_t frac1_hi, frac1_lo, frac2_hi, frac2_lo, tmp_hi, tmp_lo;
-	float128 result;
-	
-	result.bin.hi = 0;
-	result.bin.lo = 0;
-	
-	expdiff = a.parts.exp - b.parts.exp;
-	if ((expdiff < 0 ) || ((expdiff == 0) &&
-	    lt128(a.parts.frac_hi, a.parts.frac_lo, b.parts.frac_hi, b.parts.frac_lo))) {
-		if (is_float128_nan(b)) {
-			if (is_float128_signan(b)) {
-				// TODO: fix SigNaN
-			}
-			
-			return b;
-		}
-		
-		if (b.parts.exp == FLOAT128_MAX_EXPONENT) {
-			/* num -(+-inf) = -+inf */
-			b.parts.sign = !b.parts.sign;
-			return b;
-		}
-		
-		result.parts.sign = !a.parts.sign;
-		
-		frac1_hi = b.parts.frac_hi;
-		frac1_lo = b.parts.frac_lo;
-		exp1 = b.parts.exp;
-		frac2_hi = a.parts.frac_hi;
-		frac2_lo = a.parts.frac_lo;
-		exp2 = a.parts.exp;
-		expdiff *= -1;
-	} else {
-		if (is_float128_nan(a)) {
-			if (is_float128_signan(a) || is_float128_signan(b)) {
-				// TODO: fix SigNaN
-			}
-			
-			return a;
-		}
-		
-		if (a.parts.exp == FLOAT128_MAX_EXPONENT) {
-			if (b.parts.exp == FLOAT128_MAX_EXPONENT) {
-				/* inf - inf => nan */
-				// TODO: fix exception
-				result.bin.hi = FLOAT128_NAN_HI;
-				result.bin.lo = FLOAT128_NAN_LO;
-				return result;
-			}
-			return a;
-		}
-		
-		result.parts.sign = a.parts.sign;
-		
-		frac1_hi = a.parts.frac_hi;
-		frac1_lo = a.parts.frac_lo;
-		exp1 = a.parts.exp;
-		frac2_hi = b.parts.frac_hi;
-		frac2_lo = b.parts.frac_lo;
-		exp2 = b.parts.exp;
-	}
-	
-	if (exp1 == 0) {
-		/* both are denormalized */
-		sub128(frac1_hi, frac1_lo, frac2_hi, frac2_lo, &tmp_hi, &tmp_lo);
-		result.parts.frac_hi = tmp_hi;
-		result.parts.frac_lo = tmp_lo;
-		if (lt128(frac1_hi, frac1_lo, result.parts.frac_hi, result.parts.frac_lo)) {
-			// TODO: underflow exception
-			return result;
-		}
-		
-		result.parts.exp = 0;
-		return result;
-	}
-	
-	/* add hidden bit */
-	or128(frac1_hi, frac1_lo,
-	    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-	    &frac1_hi, &frac1_lo);
-	
-	if (exp2 == 0) {
-		/* denormalized */
-		--expdiff;
-	} else {
-		/* normalized */
-		or128(frac2_hi, frac2_lo,
-		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-		    &frac2_hi, &frac2_lo);
-	}
-	
-	/* create some space for rounding */
-	lshift128(frac1_hi, frac1_lo, 6, &frac1_hi, &frac1_lo);
-	lshift128(frac2_hi, frac2_lo, 6, &frac2_hi, &frac2_lo);
-	
-	if (expdiff > FLOAT128_FRACTION_SIZE + 1)
-		goto done;
-	
-	rshift128(frac2_hi, frac2_lo, expdiff, &tmp_hi, &tmp_lo);
-	sub128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &frac1_hi, &frac1_lo);
-	
-done:
-	/* TODO: find first nonzero digit and shift result and detect possibly underflow */
-	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 6,
-	    &tmp_hi, &tmp_lo);
-	and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-	while ((exp1 > 0) && (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo))) {
-		--exp1;
-		lshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
-		/* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
-		
-		lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 6,
-		    &tmp_hi, &tmp_lo);
-		and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-	}
-	
-	/* rounding - if first bit after fraction is set then round up */
-	add128(frac1_hi, frac1_lo, 0x0ll, 0x20ll, &frac1_hi, &frac1_lo);
-	
-	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 7,
-	   &tmp_hi, &tmp_lo);
-	and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-	if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
-		++exp1;
-		rshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
-	}
-	
-	/* Clear hidden bit and shift */
-	rshift128(frac1_hi, frac1_lo, 6, &frac1_hi, &frac1_lo);
-	not128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
-	    &tmp_hi, &tmp_lo);
-	and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
-	result.parts.frac_hi = tmp_hi;
-	result.parts.frac_lo = tmp_lo;
-	
-	result.parts.exp = exp1;
-	
-	return result;
-}
-
-/** @}
- */
Index: pace/lib/softfloat/include/add.h
===================================================================
--- uspace/lib/softfloat/include/add.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Addition functions.
- */
-
-#ifndef __ADD_H__
-#define __ADD_H__
-
-extern float32 add_float32(float32, float32);
-extern float64 add_float64(float64, float64);
-extern float96 add_float96(float96, float96);
-extern float128 add_float128(float128, float128);
-
-#endif
-
-/** @}
- */
Index: pace/lib/softfloat/include/common.h
===================================================================
--- uspace/lib/softfloat/include/common.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,76 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Common helper operations.
- */
-
-#ifndef __COMMON_H__
-#define __COMMON_H__
-
-#include <sftypes.h>
-
-extern float64 finish_float64(int32_t, uint64_t, char);
-extern float128 finish_float128(int32_t, uint64_t, uint64_t, char, uint64_t);
-
-extern int count_zeroes8(uint8_t);
-extern int count_zeroes32(uint32_t);
-extern int count_zeroes64(uint64_t);
-
-extern void round_float32(int32_t *, uint32_t *);
-extern void round_float64(int32_t *, uint64_t *);
-extern void round_float128(int32_t *, uint64_t *, uint64_t *);
-
-extern void lshift128(uint64_t, uint64_t, int, uint64_t *, uint64_t *);
-extern void rshift128(uint64_t, uint64_t, int, uint64_t *, uint64_t *);
-
-extern void and128(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t *, uint64_t *);
-extern void or128(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t *, uint64_t *);
-extern void xor128(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t *, uint64_t *);
-extern void not128(uint64_t, uint64_t, uint64_t *, uint64_t *);
-
-extern int eq128(uint64_t, uint64_t, uint64_t, uint64_t);
-extern int le128(uint64_t, uint64_t, uint64_t, uint64_t);
-extern int lt128(uint64_t, uint64_t, uint64_t, uint64_t);
-
-extern void add128(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t *, uint64_t *);
-extern void sub128(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t *, uint64_t *);
-
-extern void mul64(uint64_t, uint64_t, uint64_t *, uint64_t *);
-extern void mul128(uint64_t, uint64_t, uint64_t, uint64_t,
-    uint64_t *, uint64_t *, uint64_t *, uint64_t *);
-
-extern uint64_t div128est(uint64_t, uint64_t, uint64_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/softfloat/include/comparison.h
===================================================================
--- uspace/lib/softfloat/include/comparison.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,82 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Comparison functions.
- */
-
-#ifndef __COMPARISON_H__
-#define __COMPARISON_H__
-
-extern int is_float32_nan(float32);
-extern int is_float32_signan(float32);
-
-extern int is_float32_infinity(float32);
-extern int is_float32_zero(float32);
-
-extern int is_float32_eq(float32, float32);
-extern int is_float32_lt(float32, float32);
-extern int is_float32_gt(float32, float32);
-
-extern int is_float64_nan(float64);
-extern int is_float64_signan(float64);
-
-extern int is_float64_infinity(float64);
-extern int is_float64_zero(float64);
-
-extern int is_float64_eq(float64, float64);
-extern int is_float64_lt(float64, float64);
-extern int is_float64_gt(float64, float64);
-
-extern int is_float96_nan(float96);
-extern int is_float96_signan(float96);
-
-extern int is_float96_infinity(float96);
-extern int is_float96_zero(float96);
-
-extern int is_float96_eq(float96, float96);
-extern int is_float96_lt(float96, float96);
-extern int is_float96_gt(float96, float96);
-
-extern int is_float128_nan(float128);
-extern int is_float128_signan(float128);
-
-extern int is_float128_infinity(float128);
-extern int is_float128_zero(float128);
-
-extern int is_float128_eq(float128, float128);
-extern int is_float128_lt(float128, float128);
-extern int is_float128_gt(float128, float128);
-
-#endif
-
-/** @}
- */
Index: pace/lib/softfloat/include/conversion.h
===================================================================
--- uspace/lib/softfloat/include/conversion.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,104 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Conversion of precision and conversion between integers and floats.
- */
-
-#ifndef __CONVERSION_H__
-#define __CONVERSION_H__
-
-extern float64 float32_to_float64(float32);
-extern float96 float32_to_float96(float32);
-extern float128 float32_to_float128(float32);
-extern float96 float64_to_float96(float64);
-extern float128 float64_to_float128(float64);
-extern float128 float96_to_float128(float96);
-
-extern float32 float64_to_float32(float64);
-extern float32 float96_to_float32(float96);
-extern float64 float96_to_float64(float96);
-extern float32 float128_to_float32(float128);
-extern float64 float128_to_float64(float128);
-extern float96 float128_to_float96(float128);
-
-extern uint32_t float32_to_uint32(float32);
-extern int32_t float32_to_int32(float32);
-
-extern uint64_t float32_to_uint64(float32);
-extern int64_t float32_to_int64(float32);
-
-extern uint32_t float64_to_uint32(float64);
-extern int32_t float64_to_int32(float64);
-
-extern uint64_t float64_to_uint64(float64);
-extern int64_t float64_to_int64(float64);
-
-extern uint32_t float96_to_uint32(float96);
-extern int32_t float96_to_int32(float96);
-
-extern uint64_t float96_to_uint64(float96);
-extern int64_t float96_to_int64(float96);
-
-extern uint32_t float128_to_uint32(float128);
-extern int32_t float128_to_int32(float128);
-
-extern uint64_t float128_to_uint64(float128);
-extern int64_t float128_to_int64(float128);
-
-extern float32 uint32_to_float32(uint32_t);
-extern float32 int32_to_float32(int32_t);
-
-extern float32 uint64_to_float32(uint64_t);
-extern float32 int64_to_float32(int64_t);
-
-extern float64 uint32_to_float64(uint32_t);
-extern float64 int32_to_float64(int32_t);
-
-extern float64 uint64_to_float64(uint64_t);
-extern float64 int64_to_float64(int64_t);
-
-extern float96 uint32_to_float96(uint32_t);
-extern float96 int32_to_float96(int32_t);
-
-extern float96 uint64_to_float96(uint64_t);
-extern float96 int64_to_float96(int64_t);
-
-extern float128 uint32_to_float128(uint32_t);
-extern float128 int32_to_float128(int32_t);
-
-extern float128 uint64_to_float128(uint64_t);
-extern float128 int64_to_float128(int64_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/softfloat/include/div.h
===================================================================
--- uspace/lib/softfloat/include/div.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Division functions.
- */
-
-#ifndef __DIV_H__
-#define __DIV_H__
-
-extern float32 div_float32(float32, float32);
-extern float64 div_float64(float64, float64);
-extern float96 div_float96(float96, float96);
-extern float128 div_float128(float128, float128);
-
-#endif
-
-/** @}
- */
Index: pace/lib/softfloat/include/mul.h
===================================================================
--- uspace/lib/softfloat/include/mul.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Multiplication functions.
- */
-
-#ifndef __MUL_H__
-#define __MUL_H__
-
-extern float32 mul_float32(float32, float32);
-extern float64 mul_float64(float64, float64);
-extern float96 mul_float96(float96, float96);
-extern float128 mul_float128(float128, float128);
-
-#endif
-
-/** @}
- */
Index: pace/lib/softfloat/include/other.h
===================================================================
--- uspace/lib/softfloat/include/other.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,41 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * 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 softfloat
- * @{
- */
-/** @file Other functions (power, complex).
- */
-
-#ifndef __OTHER_H__
-#define __OTHER_H__
-
-#endif
-
-/** @}
- */
Index: pace/lib/softfloat/include/sftypes.h
===================================================================
--- uspace/lib/softfloat/include/sftypes.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,608 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Floating point types and constants.
- */
-
-#ifndef __SFTYPES_H__
-#define __SFTYPES_H__
-
-#include <byteorder.h>
-#include <stdint.h>
-
-/*
- * For recognizing NaNs or infinity use specialized comparison
- * functions, comparing with these constants is not sufficient.
- */
-
-#define FLOAT32_NAN     UINT32_C(0x7FC00001)
-#define FLOAT32_SIGNAN  UINT32_C(0x7F800001)
-#define FLOAT32_INF     UINT32_C(0x7F800000)
-
-#define FLOAT64_NAN     UINT64_C(0x7FF8000000000001)
-#define FLOAT64_SIGNAN  UINT64_C(0x7FF0000000000001)
-#define FLOAT64_INF     UINT64_C(0x7FF0000000000000)
-
-#define FLOAT96_NAN_HI     UINT64_C(0x7FFF80000000)
-#define FLOAT96_NAN_LO     UINT32_C(0x00010000)
-#define FLOAT96_SIGNAN_HI  UINT64_C(0x7FFF00000000)
-#define FLOAT96_SIGNAN_LO  UINT32_C(0x00010000)
-
-#define FLOAT128_NAN_HI     UINT64_C(0x7FFF800000000000)
-#define FLOAT128_NAN_LO     UINT64_C(0x0000000000000001)
-#define FLOAT128_SIGNAN_HI  UINT64_C(0x7FFF000000000000)
-#define FLOAT128_SIGNAN_LO  UINT64_C(0x0000000000000001)
-#define FLOAT128_INF_HI     UINT64_C(0x7FFF000000000000)
-#define FLOAT128_INF_LO     UINT64_C(0x0000000000000000)
-
-#define FLOAT32_FRACTION_SIZE   23
-#define FLOAT64_FRACTION_SIZE   52
-#define FLOAT96_FRACTION_SIZE   64
-#define FLOAT128_FRACTION_SIZE  112
-#define FLOAT128_FRAC_HI_SIZE   48
-#define FLOAT128_FRAC_LO_SIZE   64
-
-#define FLOAT32_HIDDEN_BIT_MASK      UINT32_C(0x800000)
-#define FLOAT64_HIDDEN_BIT_MASK      UINT64_C(0x10000000000000)
-#define FLOAT128_HIDDEN_BIT_MASK_HI  UINT64_C(0x1000000000000)
-#define FLOAT128_HIDDEN_BIT_MASK_LO  UINT64_C(0x0000000000000000)
-
-#define FLOAT32_MAX_EXPONENT   0xFF
-#define FLOAT64_MAX_EXPONENT   0x7FF
-#define FLOAT96_MAX_EXPONENT   0x7FFF
-#define FLOAT128_MAX_EXPONENT  0x7FFF
-
-#define FLOAT32_BIAS   0x7F
-#define FLOAT64_BIAS   0x3FF
-#define FLOAT96_BIAS   0x3FFF
-#define FLOAT128_BIAS  0x3FFF
-
-#if defined(__BE__)
-
-typedef union {
-	uint32_t bin;
-	
-	struct {
-		uint32_t sign : 1;
-		uint32_t exp : 8;
-		uint32_t fraction : 23;
-	} parts __attribute__((packed));
-} float32;
-
-typedef union {
-	uint64_t bin;
-	
-	struct {
-		uint64_t sign : 1;
-		uint64_t exp : 11;
-		uint64_t fraction : 52;
-	} parts __attribute__((packed));
-} float64;
-
-typedef union {
-	struct {
-		uint64_t hi;
-		uint32_t lo;
-	} bin __attribute__((packed));
-	
-	struct {
-		uint64_t padding : 16;
-		uint64_t sign : 1;
-		uint64_t exp : 15;
-		uint64_t fraction : 64;
-	} parts __attribute__((packed));
-} float96;
-
-typedef union {
-	struct {
-		uint64_t hi;
-		uint64_t lo;
-	} bin __attribute__((packed));
-	
-	struct {
-		uint64_t sign : 1;
-		uint64_t exp : 15;
-		uint64_t frac_hi : 48;
-		uint64_t frac_lo : 64;
-	} parts __attribute__((packed));
-} float128;
-
-#elif defined(__LE__)
-
-typedef union {
-	uint32_t bin;
-	
-	struct {
-		uint32_t fraction : 23;
-		uint32_t exp : 8;
-		uint32_t sign : 1;
-	} parts __attribute__((packed));
-} float32;
-
-typedef union {
-	uint64_t bin;
-	
-	struct {
-		uint64_t fraction : 52;
-		uint64_t exp : 11;
-		uint64_t sign : 1;
-	} parts __attribute__((packed));
-} float64;
-
-typedef union {
-	struct {
-		uint32_t lo;
-		uint64_t hi;
-	} bin __attribute__((packed));
-	
-	struct {
-		uint64_t fraction : 64;
-		uint64_t exp : 15;
-		uint64_t sign : 1;
-		uint64_t padding : 16;
-	} parts __attribute__((packed));
-} float96;
-
-typedef union {
-	struct {
-		uint64_t lo;
-		uint64_t hi;
-	} bin __attribute__((packed));
-	
-	struct {
-		uint64_t frac_lo : 64;
-		uint64_t frac_hi : 48;
-		uint64_t exp : 15;
-		uint64_t sign : 1;
-	} parts __attribute__((packed));
-} float128;
-
-#else
-	#error Unknown endianess
-#endif
-
-typedef union {
-	float val;
-	
-#if defined(FLOAT_SIZE_32)
-	float32 data;
-#elif defined(FLOAT_SIZE_64)
-	float64 data;
-#elif defined(FLOAT_SIZE_96)
-	float96 data;
-#elif defined(FLOAT_SIZE_128)
-	float128 data;
-#else
-	#error Unsupported float size
-#endif
-} float_t;
-
-typedef union {
-	double val;
-	
-#if defined(DOUBLE_SIZE_32)
-	float32 data;
-#elif defined(DOUBLE_SIZE_64)
-	float64 data;
-#elif defined(DOUBLE_SIZE_96)
-	float96 data;
-#elif defined(DOUBLE_SIZE_128)
-	float128 data;
-#else
-	#error Unsupported double size
-#endif
-} double_t;
-
-typedef union {
-	long double val;
-	
-#if defined(LONG_DOUBLE_SIZE_32)
-	float32 data;
-#elif defined(LONG_DOUBLE_SIZE_64)
-	float64 data;
-#elif defined(LONG_DOUBLE_SIZE_96)
-	float96 data;
-#elif defined(LONG_DOUBLE_SIZE_128)
-	float128 data;
-#else
-	#error Unsupported long double size
-#endif
-} long_double_t;
-
-
-#if defined(INT_SIZE_8)
-
-#define _to_int   _to_int8
-#define from_int  int8
-
-#elif defined(INT_SIZE_16)
-
-#define _to_int   _to_int16
-#define from_int  int16
-
-#elif defined(INT_SIZE_32)
-
-#define _to_int   _to_int32
-#define from_int  int32
-
-#elif defined(INT_SIZE_64)
-
-#define _to_int   _to_int64
-#define from_int  int64
-
-#endif
-
-
-#if defined(UINT_SIZE_8)
-
-#define _to_uint   _to_uint8
-#define from_uint  uint8
-
-#elif defined(UINT_SIZE_16)
-
-#define _to_uint   _to_uint16
-#define from_uint  uint16
-
-#elif defined(UINT_SIZE_32)
-
-#define _to_uint   _to_uint32
-#define from_uint  uint32
-
-#elif defined(UINT_SIZE_64)
-
-#define _to_uint   _to_uint64
-#define from_uint  uint64
-
-#endif
-
-
-#if defined(LONG_SIZE_8)
-
-#define _to_long   _to_int8
-#define from_long  int8
-
-#elif defined(LONG_SIZE_16)
-
-#define _to_long   _to_int16
-#define from_long  int16
-
-#elif defined(LONG_SIZE_32)
-
-#define _to_long   _to_int32
-#define from_long  int32
-
-#elif defined(LONG_SIZE_64)
-
-#define _to_long   _to_int64
-#define from_long  int64
-
-#endif
-
-
-#if defined(ULONG_SIZE_8)
-
-#define _to_ulong   _to_uint8
-#define from_ulong  uint8
-
-#elif defined(ULONG_SIZE_16)
-
-#define _to_ulong   _to_uint16
-#define from_ulong  uint16
-
-#elif defined(ULONG_SIZE_32)
-
-#define _to_ulong   _to_uint32
-#define from_ulong  uint32
-
-#elif defined(ULONG_SIZE_64)
-
-#define _to_ulong   _to_uint64
-#define from_ulong  uint64
-
-#endif
-
-
-#if defined(LLONG_SIZE_8)
-
-#define _to_llong   _to_int8
-#define from_llong  int8
-
-#elif defined(LLONG_SIZE_16)
-
-#define _to_llong   _to_int16
-#define from_llong  int16
-
-#elif defined(LLONG_SIZE_32)
-
-#define _to_llong   _to_int32
-#define from_llong  int32
-
-#elif defined(LLONG_SIZE_64)
-
-#define _to_llong   _to_int64
-#define from_llong  int64
-
-#endif
-
-
-#if defined(ULLONG_SIZE_8)
-
-#define _to_ullong   _to_uint8
-#define from_ullong  uint8
-
-#elif defined(ULLONG_SIZE_16)
-
-#define _to_ullong   _to_uint16
-#define from_ullong  uint16
-
-#elif defined(ULLONG_SIZE_32)
-
-#define _to_ullong   _to_uint32
-#define from_ullong  uint32
-
-#elif defined(ULLONG_SIZE_64)
-
-#define _to_ullong   _to_uint64
-#define from_ullong  uint64
-
-#endif
-
-
-#if defined(FLOAT_SIZE_32)
-
-#define add_float     add_float32
-#define sub_float     sub_float32
-#define mul_float     mul_float32
-#define div_float     div_float32
-#define _to_float     _to_float32
-#define from_float    float32
-#define is_float_nan  is_float32_nan
-#define is_float_eq   is_float32_eq
-#define is_float_lt   is_float32_lt
-#define is_float_gt   is_float32_gt
-
-#elif defined(FLOAT_SIZE_64)
-
-#define add_float     add_float64
-#define sub_float     sub_float64
-#define mul_float     mul_float64
-#define div_float     div_float64
-#define _to_float     _to_float64
-#define from_float    float64
-#define is_float_nan  is_float64_nan
-#define is_float_eq   is_float64_eq
-#define is_float_lt   is_float64_lt
-#define is_float_gt   is_float64_gt
-
-#elif defined(FLOAT_SIZE_96)
-
-#define add_float     add_float96
-#define sub_float     sub_float96
-#define mul_float     mul_float96
-#define div_float     div_float96
-#define _to_float     _to_float96
-#define from_float    float96
-#define is_float_nan  is_float96_nan
-#define is_float_eq   is_float96_eq
-#define is_float_lt   is_float96_lt
-#define is_float_gt   is_float96_gt
-
-#elif defined(FLOAT_SIZE_128)
-
-#define add_float     add_float128
-#define sub_float     sub_float128
-#define mul_float     mul_float128
-#define div_float     div_float128
-#define _to_float     _to_float128
-#define from_float    float128
-#define is_float_nan  is_float128_nan
-#define is_float_eq   is_float128_eq
-#define is_float_lt   is_float128_lt
-#define is_float_gt   is_float128_gt
-
-#endif
-
-
-#if defined(DOUBLE_SIZE_32)
-
-#define add_double     add_float32
-#define sub_double     sub_float32
-#define mul_double     mul_float32
-#define div_double     div_float32
-#define _to_double     _to_float32
-#define from_double    float32
-#define is_double_nan  is_float32_nan
-#define is_double_eq   is_float32_eq
-#define is_double_lt   is_float32_lt
-#define is_double_gt   is_float32_gt
-
-#elif defined(DOUBLE_SIZE_64)
-
-#define add_double     add_float64
-#define sub_double     sub_float64
-#define mul_double     mul_float64
-#define div_double     div_float64
-#define _to_double     _to_float64
-#define from_double    float64
-#define is_double_nan  is_float64_nan
-#define is_double_eq   is_float64_eq
-#define is_double_lt   is_float64_lt
-#define is_double_gt   is_float64_gt
-
-#elif defined(DOUBLE_SIZE_96)
-
-#define add_double     add_float96
-#define sub_double     sub_float96
-#define mul_double     mul_float96
-#define div_double     div_float96
-#define _to_double     _to_float96
-#define from_double    float96
-#define is_double_nan  is_float96_nan
-#define is_double_eq   is_float96_eq
-#define is_double_lt   is_float96_lt
-#define is_double_gt   is_float96_gt
-
-#elif defined(DOUBLE_SIZE_128)
-
-#define add_double     add_float128
-#define sub_double     sub_float128
-#define mul_double     mul_float128
-#define div_double     div_float128
-#define _to_double     _to_float128
-#define from_double    float128
-#define is_double_nan  is_float128_nan
-#define is_double_eq   is_float128_eq
-#define is_double_lt   is_float128_lt
-#define is_double_gt   is_float128_gt
-
-#endif
-
-
-#if defined(LONG_DOUBLE_SIZE_32)
-
-#define add_long_double     add_float32
-#define sub_long_double     sub_float32
-#define mul_long_double     mul_float32
-#define div_long_double     div_float32
-#define _to_long_double     _to_float32
-#define from_long_double    float32
-#define is_long_double_nan  is_float32_nan
-#define is_long_double_eq   is_float32_eq
-#define is_long_double_lt   is_float32_lt
-#define is_long_double_gt   is_float32_gt
-
-#elif defined(LONG_DOUBLE_SIZE_64)
-
-#define add_long_double     add_float64
-#define sub_long_double     sub_float64
-#define mul_long_double     mul_float64
-#define div_long_double     div_float64
-#define _to_long_double     _to_float64
-#define from_long_double    float64
-#define is_long_double_nan  is_float64_nan
-#define is_long_double_eq   is_float64_eq
-#define is_long_double_lt   is_float64_lt
-#define is_long_double_gt   is_float64_gt
-
-#elif defined(LONG_DOUBLE_SIZE_96)
-
-#define add_long_double     add_float96
-#define sub_long_double     sub_float96
-#define mul_long_double     mul_float96
-#define div_long_double     div_float96
-#define _to_long_double     _to_float96
-#define from_long_double    float96
-#define is_long_double_nan  is_float96_nan
-#define is_long_double_eq   is_float96_eq
-#define is_long_double_lt   is_float96_lt
-#define is_long_double_gt   is_float96_gt
-
-#elif defined(LONG_DOUBLE_SIZE_128)
-
-#define add_long_double     add_float128
-#define sub_long_double     sub_float128
-#define mul_long_double     mul_float128
-#define div_long_double     div_float128
-#define _to_long_double     _to_float128
-#define from_long_double    float128
-#define is_long_double_nan  is_float128_nan
-#define is_long_double_eq   is_float128_eq
-#define is_long_double_lt   is_float128_lt
-#define is_long_double_gt   is_float128_gt
-
-#endif
-
-
-#define CONCAT(a, b)       CONCAT_ARGS(a, b)
-#define CONCAT_ARGS(a, b)  a ## b
-
-#define float32_to_float32(arg)    (arg)
-#define float64_to_float64(arg)    (arg)
-#define float96_to_float96(arg)    (arg)
-#define float128_to_float128(arg)  (arg)
-
-#define float_to_double       CONCAT(from_float, _to_double)
-#define float_to_long_double  CONCAT(from_float, _to_long_double)
-#define float_to_int          CONCAT(from_float, _to_int)
-#define float_to_uint         CONCAT(from_float, _to_uint)
-#define float_to_long         CONCAT(from_float, _to_long)
-#define float_to_ulong        CONCAT(from_float, _to_ulong)
-#define float_to_llong        CONCAT(from_float, _to_llong)
-#define float_to_ullong       CONCAT(from_float, _to_ullong)
-
-#define double_to_float        CONCAT(from_double, _to_float)
-#define double_to_long_double  CONCAT(from_double, _to_long_double)
-#define double_to_int          CONCAT(from_double, _to_int)
-#define double_to_uint         CONCAT(from_double, _to_uint)
-#define double_to_long         CONCAT(from_double, _to_long)
-#define double_to_ulong        CONCAT(from_double, _to_ulong)
-#define double_to_llong        CONCAT(from_double, _to_llong)
-#define double_to_ullong       CONCAT(from_double, _to_ullong)
-
-#define long_double_to_float   CONCAT(from_long_double, _to_float)
-#define long_double_to_double  CONCAT(from_long_double, _to_double)
-#define long_double_to_int     CONCAT(from_long_double, _to_int)
-#define long_double_to_uint    CONCAT(from_long_double, _to_uint)
-#define long_double_to_long    CONCAT(from_long_double, _to_long)
-#define long_double_to_ulong   CONCAT(from_long_double, _to_ulong)
-#define long_double_to_llong   CONCAT(from_long_double, _to_llong)
-#define long_double_to_ullong  CONCAT(from_long_double, _to_ullong)
-
-#define int_to_float        CONCAT(from_int, _to_float)
-#define int_to_double       CONCAT(from_int, _to_double)
-#define int_to_long_double  CONCAT(from_int, _to_long_double)
-
-#define uint_to_float        CONCAT(from_uint, _to_float)
-#define uint_to_double       CONCAT(from_uint, _to_double)
-#define uint_to_long_double  CONCAT(from_uint, _to_long_double)
-
-#define long_to_float        CONCAT(from_long, _to_float)
-#define long_to_double       CONCAT(from_long, _to_double)
-#define long_to_long_double  CONCAT(from_long, _to_long_double)
-
-#define ulong_to_float        CONCAT(from_ulong, _to_float)
-#define ulong_to_double       CONCAT(from_ulong, _to_double)
-#define ulong_to_long_double  CONCAT(from_ulong, _to_long_double)
-
-#define llong_to_float        CONCAT(from_llong, _to_float)
-#define llong_to_double       CONCAT(from_llong, _to_double)
-#define llong_to_long_double  CONCAT(from_llong, _to_long_double)
-
-#define ullong_to_float        CONCAT(from_ullong, _to_float)
-#define ullong_to_double       CONCAT(from_ullong, _to_double)
-#define ullong_to_long_double  CONCAT(from_ullong, _to_long_double)
-
-
-#endif
-
-/** @}
- */
Index: pace/lib/softfloat/include/softfloat.h
===================================================================
--- uspace/lib/softfloat/include/softfloat.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,212 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Softfloat API.
- */
-
-#ifndef __SOFTFLOAT_H__
-#define __SOFTFLOAT_H__
-
-extern float __addsf3(float, float);
-extern double __adddf3(double, double);
-extern long double __addtf3(long double, long double);
-extern long double __addxf3(long double, long double);
-
-extern float __subsf3(float, float);
-extern double __subdf3(double, double);
-extern long double __subtf3(long double, long double);
-extern long double __subxf3(long double, long double);
-
-extern float __mulsf3(float, float);
-extern double __muldf3(double, double);
-extern long double __multf3(long double, long double);
-extern long double __mulxf3(long double, long double);
-
-extern float __divsf3(float, float);
-extern double __divdf3(double, double);
-extern long double __divtf3(long double, long double);
-extern long double __divxf3(long double, long double);
-
-extern float __negsf2(float);
-extern double __negdf2(double);
-extern long double __negtf2(long double);
-extern long double __negxf2(long double);
-
-extern double __extendsfdf2(float);
-extern long double __extendsftf2(float);
-extern long double __extendsfxf2(float);
-extern long double __extenddftf2(double);
-extern long double __extenddfxf2(double);
-
-extern double __truncxfdf2(long double);
-extern double __trunctfdf2(long double);
-extern float __truncxfsf2(long double);
-extern float __trunctfsf2(long double);
-extern float __truncdfsf2(double);
-
-extern int __fixsfsi(float);
-extern int __fixdfsi(double);
-extern int __fixtfsi(long double);
-extern int __fixxfsi(long double);
-
-extern long __fixsfdi(float);
-extern long __fixdfdi(double);
-extern long __fixtfdi(long double);
-extern long __fixxfdi(long double);
-
-extern long long __fixsfti(float);
-extern long long __fixdfti(double);
-extern long long __fixtfti(long double);
-extern long long __fixxfti(long double);
-
-extern unsigned int __fixunssfsi(float);
-extern unsigned int __fixunsdfsi(double);
-extern unsigned int __fixunstfsi(long double);
-extern unsigned int __fixunsxfsi(long double);
-
-extern unsigned long __fixunssfdi(float);
-extern unsigned long __fixunsdfdi(double);
-extern unsigned long __fixunstfdi(long double);
-extern unsigned long __fixunsxfdi(long double);
-
-extern unsigned long long __fixunssfti(float);
-extern unsigned long long __fixunsdfti(double);
-extern unsigned long long __fixunstfti(long double);
-extern unsigned long long __fixunsxfti(long double);
-
-extern float __floatsisf(int);
-extern double __floatsidf(int);
-extern long double __floatsitf(int);
-extern long double __floatsixf(int);
-
-extern float __floatdisf(long);
-extern double __floatdidf(long);
-extern long double __floatditf(long);
-extern long double __floatdixf(long);
-
-extern float __floattisf(long long);
-extern double __floattidf(long long);
-extern long double __floattitf(long long);
-extern long double __floattixf(long long);
-
-extern float __floatunsisf(unsigned int);
-extern double __floatunsidf(unsigned int);
-extern long double __floatunsitf(unsigned int);
-extern long double __floatunsixf(unsigned int);
-
-extern float __floatundisf(unsigned long);
-extern double __floatundidf(unsigned long);
-extern long double __floatunditf(unsigned long);
-extern long double __floatundixf(unsigned long);
-
-extern float __floatuntisf(unsigned long long);
-extern double __floatuntidf(unsigned long long);
-extern long double __floatuntitf(unsigned long long);
-extern long double __floatuntixf(unsigned long long);
-
-extern int __cmpsf2(float, float);
-extern int __cmpdf2(double, double);
-extern int __cmptf2(long double, long double);
-
-extern int __unordsf2(float, float);
-extern int __unorddf2(double, double);
-extern int __unordtf2(long double, long double);
-
-extern int __eqsf2(float, float);
-extern int __eqdf2(double, double);
-extern int __eqtf2(long double, long double);
-
-extern int __nesf2(float, float);
-extern int __nedf2(double, double);
-extern int __netf2(long double, long double);
-
-extern int __gesf2(float, float);
-extern int __gedf2(double, double);
-extern int __getf2(long double, long double);
-
-extern int __ltsf2(float, float);
-extern int __ltdf2(double, double);
-extern int __lttf2(long double, long double);
-
-extern int __lesf2(float, float);
-extern int __ledf2(double, double);
-extern int __letf2(long double, long double);
-
-extern int __gtsf2(float, float);
-extern int __gtdf2(double, double);
-extern int __gttf2(long double, long double);
-
-/* Not implemented yet */
-extern float __powisf2(float, int);
-extern double __powidf2 (double, int);
-extern long double __powitf2(long double, int);
-extern long double __powixf2(long double, int);
-
-/* SPARC quadruple-precision wrappers */
-
-extern void _Qp_add(long double *, long double *, long double *);
-extern void _Qp_sub(long double *, long double *, long double *);
-extern void _Qp_mul(long double *, long double *, long double *);
-extern void _Qp_div(long double *, long double *, long double *);
-extern void _Qp_neg(long double *, long double *);
-
-extern void _Qp_stoq(long double *, float);
-extern void _Qp_dtoq(long double *, double);
-extern float _Qp_qtos(long double *);
-extern double _Qp_qtod(long double *);
-
-extern int _Qp_qtoi(long double *);
-extern unsigned int _Qp_qtoui(long double *);
-extern long _Qp_qtox(long double *);
-extern unsigned long _Qp_qtoux(long double *);
-
-extern void _Qp_itoq(long double *, int);
-extern void _Qp_uitoq(long double *, unsigned int);
-extern void _Qp_xtoq(long double *, long);
-extern void _Qp_uxtoq(long double *, unsigned long);
-
-extern int _Qp_cmp(long double *, long double *);
-extern int _Qp_cmpe(long double *, long double *);
-extern int _Qp_feq(long double *, long double *);
-extern int _Qp_fge(long double *, long double *);
-extern int _Qp_fgt(long double *, long double *);
-extern int _Qp_fle(long double*, long double *);
-extern int _Qp_flt(long double *, long double *);
-extern int _Qp_fne(long double *, long double *);
-
-/* Not implemented yet */
-extern void _Qp_sqrt(long double *, long double *);
-
-#endif
-
-/** @}
- */
Index: pace/lib/softfloat/include/sub.h
===================================================================
--- uspace/lib/softfloat/include/sub.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2005 Josef Cejka
- * Copyright (c) 2011 Petr Koupy
- * 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 softfloat
- * @{
- */
-/** @file Substraction functions.
- */
-
-#ifndef __SUB_H__
-#define __SUB_H__
-
-extern float32 sub_float32(float32, float32);
-extern float64 sub_float64(float64, float64);
-extern float96 sub_float96(float96, float96);
-extern float128 sub_float128(float128, float128);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/softfloat/mul.c
===================================================================
--- uspace/lib/softfloat/mul.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/mul.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Multiplication functions.
+ */
+
+#include "sftypes.h"
+#include "mul.h"
+#include "comparison.h"
+#include "common.h"
+
+/** Multiply two single-precision floats.
+ *
+ * @param a First input operand.
+ * @param b Second input operand.
+ *
+ * @return Result of multiplication.
+ *
+ */
+float32 mul_float32(float32 a, float32 b)
+{
+	float32 result;
+	uint64_t frac1, frac2;
+	int32_t exp;
+	
+	result.parts.sign = a.parts.sign ^ b.parts.sign;
+	
+	if (is_float32_nan(a) || is_float32_nan(b)) {
+		/* TODO: fix SigNaNs */
+		if (is_float32_signan(a)) {
+			result.parts.fraction = a.parts.fraction;
+			result.parts.exp = a.parts.exp;
+			return result;
+		}
+		if (is_float32_signan(b)) { /* TODO: fix SigNaN */
+			result.parts.fraction = b.parts.fraction;
+			result.parts.exp = b.parts.exp;
+			return result;
+		}
+		/* set NaN as result */
+		result.bin = FLOAT32_NAN;
+		return result;
+	}
+	
+	if (is_float32_infinity(a)) {
+		if (is_float32_zero(b)) {
+			/* FIXME: zero * infinity */
+			result.bin = FLOAT32_NAN;
+			return result;
+		}
+		result.parts.fraction = a.parts.fraction;
+		result.parts.exp = a.parts.exp;
+		return result;
+	}
+	
+	if (is_float32_infinity(b)) {
+		if (is_float32_zero(a)) {
+			/* FIXME: zero * infinity */
+			result.bin = FLOAT32_NAN;
+			return result;
+		}
+		result.parts.fraction = b.parts.fraction;
+		result.parts.exp = b.parts.exp;
+		return result;
+	}
+	
+	/* exp is signed so we can easy detect underflow */
+	exp = a.parts.exp + b.parts.exp;
+	exp -= FLOAT32_BIAS;
+	
+	if (exp >= FLOAT32_MAX_EXPONENT) {
+		/* FIXME: overflow */
+		/* set infinity as result */
+		result.bin = FLOAT32_INF;
+		result.parts.sign = a.parts.sign ^ b.parts.sign;
+		return result;
+	}
+	
+	if (exp < 0) { 
+		/* FIXME: underflow */
+		/* return signed zero */
+		result.parts.fraction = 0x0;
+		result.parts.exp = 0x0;
+		return result;
+	}
+	
+	frac1 = a.parts.fraction;
+	if (a.parts.exp > 0) {
+		frac1 |= FLOAT32_HIDDEN_BIT_MASK;
+	} else {
+		++exp;
+	}
+	
+	frac2 = b.parts.fraction;
+	
+	if (b.parts.exp > 0) {
+		frac2 |= FLOAT32_HIDDEN_BIT_MASK;
+	} else {
+		++exp;
+	}
+	
+	frac1 <<= 1; /* one bit space for rounding */
+	
+	frac1 = frac1 * frac2;
+	
+	/* round and return */
+	while ((exp < FLOAT32_MAX_EXPONENT) &&
+	    (frac1 >= (1 << (FLOAT32_FRACTION_SIZE + 2)))) {
+		/* 23 bits of fraction + one more for hidden bit (all shifted 1 bit left) */
+		++exp;
+		frac1 >>= 1;
+	}
+	
+	/* rounding */
+	/* ++frac1; FIXME: not works - without it is ok */
+	frac1 >>= 1; /* shift off rounding space */
+	
+	if ((exp < FLOAT32_MAX_EXPONENT) &&
+	    (frac1 >= (1 << (FLOAT32_FRACTION_SIZE + 1)))) {
+		++exp;
+		frac1 >>= 1;
+	}
+	
+	if (exp >= FLOAT32_MAX_EXPONENT) {
+		/* TODO: fix overflow */
+		/* return infinity*/
+		result.parts.exp = FLOAT32_MAX_EXPONENT;
+		result.parts.fraction = 0x0;
+		return result;
+	}
+	
+	exp -= FLOAT32_FRACTION_SIZE;
+	
+	if (exp <= FLOAT32_FRACTION_SIZE) {
+		/* denormalized number */
+		frac1 >>= 1; /* denormalize */
+		while ((frac1 > 0) && (exp < 0)) {
+			frac1 >>= 1;
+			++exp;
+		}
+		if (frac1 == 0) {
+			/* FIXME : underflow */
+			result.parts.exp = 0;
+			result.parts.fraction = 0;
+			return result;
+		}
+	}
+	result.parts.exp = exp; 
+	result.parts.fraction = frac1 & ((1 << FLOAT32_FRACTION_SIZE) - 1);
+	
+	return result;
+}
+
+/** Multiply two double-precision floats.
+ *
+ * @param a First input operand.
+ * @param b Second input operand.
+ *
+ * @return Result of multiplication.
+ *
+ */
+float64 mul_float64(float64 a, float64 b)
+{
+	float64 result;
+	uint64_t frac1, frac2;
+	int32_t exp;
+	
+	result.parts.sign = a.parts.sign ^ b.parts.sign;
+	
+	if (is_float64_nan(a) || is_float64_nan(b)) {
+		/* TODO: fix SigNaNs */
+		if (is_float64_signan(a)) {
+			result.parts.fraction = a.parts.fraction;
+			result.parts.exp = a.parts.exp;
+			return result;
+		}
+		if (is_float64_signan(b)) { /* TODO: fix SigNaN */
+			result.parts.fraction = b.parts.fraction;
+			result.parts.exp = b.parts.exp;
+			return result;
+		}
+		/* set NaN as result */
+		result.bin = FLOAT64_NAN;
+		return result;
+	}
+	
+	if (is_float64_infinity(a)) {
+		if (is_float64_zero(b)) {
+			/* FIXME: zero * infinity */
+			result.bin = FLOAT64_NAN;
+			return result;
+		}
+		result.parts.fraction = a.parts.fraction;
+		result.parts.exp = a.parts.exp;
+		return result;
+	}
+	
+	if (is_float64_infinity(b)) {
+		if (is_float64_zero(a)) {
+			/* FIXME: zero * infinity */
+			result.bin = FLOAT64_NAN;
+			return result;
+		}
+		result.parts.fraction = b.parts.fraction;
+		result.parts.exp = b.parts.exp;
+		return result;
+	}
+	
+	/* exp is signed so we can easy detect underflow */
+	exp = a.parts.exp + b.parts.exp - FLOAT64_BIAS;
+	
+	frac1 = a.parts.fraction;
+	
+	if (a.parts.exp > 0) {
+		frac1 |= FLOAT64_HIDDEN_BIT_MASK;
+	} else {
+		++exp;
+	}
+	
+	frac2 = b.parts.fraction;
+	
+	if (b.parts.exp > 0) {
+		frac2 |= FLOAT64_HIDDEN_BIT_MASK;
+	} else {
+		++exp;
+	}
+	
+	frac1 <<= (64 - FLOAT64_FRACTION_SIZE - 1);
+	frac2 <<= (64 - FLOAT64_FRACTION_SIZE - 2);
+	
+	mul64(frac1, frac2, &frac1, &frac2);
+	
+	frac1 |= (frac2 != 0);
+	if (frac1 & (0x1ll << 62)) {
+		frac1 <<= 1;
+		exp--;
+	}
+	
+	result = finish_float64(exp, frac1, result.parts.sign);
+	return result;
+}
+
+/** Multiply two quadruple-precision floats.
+ *
+ * @param a First input operand.
+ * @param b Second input operand.
+ *
+ * @return Result of multiplication.
+ *
+ */
+float128 mul_float128(float128 a, float128 b)
+{
+	float128 result;
+	uint64_t frac1_hi, frac1_lo, frac2_hi, frac2_lo, tmp_hi, tmp_lo;
+	int32_t exp;
+	
+	result.parts.sign = a.parts.sign ^ b.parts.sign;
+	
+	if (is_float128_nan(a) || is_float128_nan(b)) {
+		/* TODO: fix SigNaNs */
+		if (is_float128_signan(a)) {
+			result.parts.frac_hi = a.parts.frac_hi;
+			result.parts.frac_lo = a.parts.frac_lo;
+			result.parts.exp = a.parts.exp;
+			return result;
+		}
+		if (is_float128_signan(b)) { /* TODO: fix SigNaN */
+			result.parts.frac_hi = b.parts.frac_hi;
+			result.parts.frac_lo = b.parts.frac_lo;
+			result.parts.exp = b.parts.exp;
+			return result;
+		}
+		/* set NaN as result */
+		result.bin.hi = FLOAT128_NAN_HI;
+		result.bin.lo = FLOAT128_NAN_LO;
+		return result;
+	}
+	
+	if (is_float128_infinity(a)) {
+		if (is_float128_zero(b)) {
+			/* FIXME: zero * infinity */
+			result.bin.hi = FLOAT128_NAN_HI;
+			result.bin.lo = FLOAT128_NAN_LO;
+			return result;
+		}
+		result.parts.frac_hi = a.parts.frac_hi;
+		result.parts.frac_lo = a.parts.frac_lo;
+		result.parts.exp = a.parts.exp;
+		return result;
+	}
+	
+	if (is_float128_infinity(b)) {
+		if (is_float128_zero(a)) {
+			/* FIXME: zero * infinity */
+			result.bin.hi = FLOAT128_NAN_HI;
+			result.bin.lo = FLOAT128_NAN_LO;
+			return result;
+		}
+		result.parts.frac_hi = b.parts.frac_hi;
+		result.parts.frac_lo = b.parts.frac_lo;
+		result.parts.exp = b.parts.exp;
+		return result;
+	}
+	
+	/* exp is signed so we can easy detect underflow */
+	exp = a.parts.exp + b.parts.exp - FLOAT128_BIAS - 1;
+	
+	frac1_hi = a.parts.frac_hi;
+	frac1_lo = a.parts.frac_lo;
+	
+	if (a.parts.exp > 0) {
+		or128(frac1_hi, frac1_lo,
+		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+		    &frac1_hi, &frac1_lo);
+	} else {
+		++exp;
+	}
+	
+	frac2_hi = b.parts.frac_hi;
+	frac2_lo = b.parts.frac_lo;
+	
+	if (b.parts.exp > 0) {
+		or128(frac2_hi, frac2_lo,
+		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+		    &frac2_hi, &frac2_lo);
+	} else {
+		++exp;
+	}
+	
+	lshift128(frac2_hi, frac2_lo,
+	    128 - FLOAT128_FRACTION_SIZE, &frac2_hi, &frac2_lo);
+	
+	tmp_hi = frac1_hi;
+	tmp_lo = frac1_lo;
+	mul128(frac1_hi, frac1_lo, frac2_hi, frac2_lo,
+	    &frac1_hi, &frac1_lo, &frac2_hi, &frac2_lo);
+	add128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &frac1_hi, &frac1_lo);
+	frac2_hi |= (frac2_lo != 0x0ll);
+	
+	if ((FLOAT128_HIDDEN_BIT_MASK_HI << 1) <= frac1_hi) {
+		frac2_hi >>= 1;
+		if (frac1_lo & 0x1ll) {
+			frac2_hi |= (0x1ull < 64);
+		}
+		rshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
+		++exp;
+	}
+	
+	result = finish_float128(exp, frac1_hi, frac1_lo, result.parts.sign, frac2_hi);
+	return result;
+}
+
+/** @}
+ */
Index: uspace/lib/softfloat/mul.h
===================================================================
--- uspace/lib/softfloat/mul.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/mul.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Multiplication functions.
+ */
+
+#ifndef __MUL_H__
+#define __MUL_H__
+
+extern float32 mul_float32(float32, float32);
+extern float64 mul_float64(float64, float64);
+extern float96 mul_float96(float96, float96);
+extern float128 mul_float128(float128, float128);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softfloat/other.c
===================================================================
--- uspace/lib/softfloat/other.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/other.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * 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 softfloat
+ * @{
+ */
+/** @file Other functions (power, complex).
+ */
+
+
+/** @}
+ */
Index: uspace/lib/softfloat/other.h
===================================================================
--- uspace/lib/softfloat/other.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/other.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * 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 softfloat
+ * @{
+ */
+/** @file Other functions (power, complex).
+ */
+
+#ifndef __OTHER_H__
+#define __OTHER_H__
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softfloat/sftypes.h
===================================================================
--- uspace/lib/softfloat/sftypes.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/sftypes.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Floating point types and constants.
+ */
+
+#ifndef __SFTYPES_H__
+#define __SFTYPES_H__
+
+#include <byteorder.h>
+#include <stdint.h>
+
+/*
+ * For recognizing NaNs or infinity use specialized comparison
+ * functions, comparing with these constants is not sufficient.
+ */
+
+#define FLOAT32_NAN     UINT32_C(0x7FC00001)
+#define FLOAT32_SIGNAN  UINT32_C(0x7F800001)
+#define FLOAT32_INF     UINT32_C(0x7F800000)
+
+#define FLOAT64_NAN     UINT64_C(0x7FF8000000000001)
+#define FLOAT64_SIGNAN  UINT64_C(0x7FF0000000000001)
+#define FLOAT64_INF     UINT64_C(0x7FF0000000000000)
+
+#define FLOAT96_NAN_HI     UINT64_C(0x7FFF80000000)
+#define FLOAT96_NAN_LO     UINT32_C(0x00010000)
+#define FLOAT96_SIGNAN_HI  UINT64_C(0x7FFF00000000)
+#define FLOAT96_SIGNAN_LO  UINT32_C(0x00010000)
+
+#define FLOAT128_NAN_HI     UINT64_C(0x7FFF800000000000)
+#define FLOAT128_NAN_LO     UINT64_C(0x0000000000000001)
+#define FLOAT128_SIGNAN_HI  UINT64_C(0x7FFF000000000000)
+#define FLOAT128_SIGNAN_LO  UINT64_C(0x0000000000000001)
+#define FLOAT128_INF_HI     UINT64_C(0x7FFF000000000000)
+#define FLOAT128_INF_LO     UINT64_C(0x0000000000000000)
+
+#define FLOAT32_FRACTION_SIZE   23
+#define FLOAT64_FRACTION_SIZE   52
+#define FLOAT96_FRACTION_SIZE   64
+#define FLOAT128_FRACTION_SIZE  112
+#define FLOAT128_FRAC_HI_SIZE   48
+#define FLOAT128_FRAC_LO_SIZE   64
+
+#define FLOAT32_HIDDEN_BIT_MASK      UINT32_C(0x800000)
+#define FLOAT64_HIDDEN_BIT_MASK      UINT64_C(0x10000000000000)
+#define FLOAT128_HIDDEN_BIT_MASK_HI  UINT64_C(0x1000000000000)
+#define FLOAT128_HIDDEN_BIT_MASK_LO  UINT64_C(0x0000000000000000)
+
+#define FLOAT32_MAX_EXPONENT   0xFF
+#define FLOAT64_MAX_EXPONENT   0x7FF
+#define FLOAT96_MAX_EXPONENT   0x7FFF
+#define FLOAT128_MAX_EXPONENT  0x7FFF
+
+#define FLOAT32_BIAS   0x7F
+#define FLOAT64_BIAS   0x3FF
+#define FLOAT96_BIAS   0x3FFF
+#define FLOAT128_BIAS  0x3FFF
+
+#if defined(__BE__)
+
+typedef union {
+	uint32_t bin;
+	
+	struct {
+		uint32_t sign : 1;
+		uint32_t exp : 8;
+		uint32_t fraction : 23;
+	} parts __attribute__((packed));
+} float32;
+
+typedef union {
+	uint64_t bin;
+	
+	struct {
+		uint64_t sign : 1;
+		uint64_t exp : 11;
+		uint64_t fraction : 52;
+	} parts __attribute__((packed));
+} float64;
+
+typedef union {
+	struct {
+		uint64_t hi;
+		uint32_t lo;
+	} bin __attribute__((packed));
+	
+	struct {
+		uint64_t padding : 16;
+		uint64_t sign : 1;
+		uint64_t exp : 15;
+		uint64_t fraction : 64;
+	} parts __attribute__((packed));
+} float96;
+
+typedef union {
+	struct {
+		uint64_t hi;
+		uint64_t lo;
+	} bin __attribute__((packed));
+	
+	struct {
+		uint64_t sign : 1;
+		uint64_t exp : 15;
+		uint64_t frac_hi : 48;
+		uint64_t frac_lo : 64;
+	} parts __attribute__((packed));
+} float128;
+
+#elif defined(__LE__)
+
+typedef union {
+	uint32_t bin;
+	
+	struct {
+		uint32_t fraction : 23;
+		uint32_t exp : 8;
+		uint32_t sign : 1;
+	} parts __attribute__((packed));
+} float32;
+
+typedef union {
+	uint64_t bin;
+	
+	struct {
+		uint64_t fraction : 52;
+		uint64_t exp : 11;
+		uint64_t sign : 1;
+	} parts __attribute__((packed));
+} float64;
+
+typedef union {
+	struct {
+		uint32_t lo;
+		uint64_t hi;
+	} bin __attribute__((packed));
+	
+	struct {
+		uint64_t fraction : 64;
+		uint64_t exp : 15;
+		uint64_t sign : 1;
+		uint64_t padding : 16;
+	} parts __attribute__((packed));
+} float96;
+
+typedef union {
+	struct {
+		uint64_t lo;
+		uint64_t hi;
+	} bin __attribute__((packed));
+	
+	struct {
+		uint64_t frac_lo : 64;
+		uint64_t frac_hi : 48;
+		uint64_t exp : 15;
+		uint64_t sign : 1;
+	} parts __attribute__((packed));
+} float128;
+
+#else
+	#error Unknown endianess
+#endif
+
+typedef union {
+	float val;
+	
+#if defined(FLOAT_SIZE_32)
+	float32 data;
+#elif defined(FLOAT_SIZE_64)
+	float64 data;
+#elif defined(FLOAT_SIZE_96)
+	float96 data;
+#elif defined(FLOAT_SIZE_128)
+	float128 data;
+#else
+	#error Unsupported float size
+#endif
+} float_t;
+
+typedef union {
+	double val;
+	
+#if defined(DOUBLE_SIZE_32)
+	float32 data;
+#elif defined(DOUBLE_SIZE_64)
+	float64 data;
+#elif defined(DOUBLE_SIZE_96)
+	float96 data;
+#elif defined(DOUBLE_SIZE_128)
+	float128 data;
+#else
+	#error Unsupported double size
+#endif
+} double_t;
+
+typedef union {
+	long double val;
+	
+#if defined(LONG_DOUBLE_SIZE_32)
+	float32 data;
+#elif defined(LONG_DOUBLE_SIZE_64)
+	float64 data;
+#elif defined(LONG_DOUBLE_SIZE_96)
+	float96 data;
+#elif defined(LONG_DOUBLE_SIZE_128)
+	float128 data;
+#else
+	#error Unsupported long double size
+#endif
+} long_double_t;
+
+
+#if defined(INT_SIZE_8)
+
+#define _to_int   _to_int8
+#define from_int  int8
+
+#elif defined(INT_SIZE_16)
+
+#define _to_int   _to_int16
+#define from_int  int16
+
+#elif defined(INT_SIZE_32)
+
+#define _to_int   _to_int32
+#define from_int  int32
+
+#elif defined(INT_SIZE_64)
+
+#define _to_int   _to_int64
+#define from_int  int64
+
+#endif
+
+
+#if defined(UINT_SIZE_8)
+
+#define _to_uint   _to_uint8
+#define from_uint  uint8
+
+#elif defined(UINT_SIZE_16)
+
+#define _to_uint   _to_uint16
+#define from_uint  uint16
+
+#elif defined(UINT_SIZE_32)
+
+#define _to_uint   _to_uint32
+#define from_uint  uint32
+
+#elif defined(UINT_SIZE_64)
+
+#define _to_uint   _to_uint64
+#define from_uint  uint64
+
+#endif
+
+
+#if defined(LONG_SIZE_8)
+
+#define _to_long   _to_int8
+#define from_long  int8
+
+#elif defined(LONG_SIZE_16)
+
+#define _to_long   _to_int16
+#define from_long  int16
+
+#elif defined(LONG_SIZE_32)
+
+#define _to_long   _to_int32
+#define from_long  int32
+
+#elif defined(LONG_SIZE_64)
+
+#define _to_long   _to_int64
+#define from_long  int64
+
+#endif
+
+
+#if defined(ULONG_SIZE_8)
+
+#define _to_ulong   _to_uint8
+#define from_ulong  uint8
+
+#elif defined(ULONG_SIZE_16)
+
+#define _to_ulong   _to_uint16
+#define from_ulong  uint16
+
+#elif defined(ULONG_SIZE_32)
+
+#define _to_ulong   _to_uint32
+#define from_ulong  uint32
+
+#elif defined(ULONG_SIZE_64)
+
+#define _to_ulong   _to_uint64
+#define from_ulong  uint64
+
+#endif
+
+
+#if defined(LLONG_SIZE_8)
+
+#define _to_llong   _to_int8
+#define from_llong  int8
+
+#elif defined(LLONG_SIZE_16)
+
+#define _to_llong   _to_int16
+#define from_llong  int16
+
+#elif defined(LLONG_SIZE_32)
+
+#define _to_llong   _to_int32
+#define from_llong  int32
+
+#elif defined(LLONG_SIZE_64)
+
+#define _to_llong   _to_int64
+#define from_llong  int64
+
+#endif
+
+
+#if defined(ULLONG_SIZE_8)
+
+#define _to_ullong   _to_uint8
+#define from_ullong  uint8
+
+#elif defined(ULLONG_SIZE_16)
+
+#define _to_ullong   _to_uint16
+#define from_ullong  uint16
+
+#elif defined(ULLONG_SIZE_32)
+
+#define _to_ullong   _to_uint32
+#define from_ullong  uint32
+
+#elif defined(ULLONG_SIZE_64)
+
+#define _to_ullong   _to_uint64
+#define from_ullong  uint64
+
+#endif
+
+
+#if defined(FLOAT_SIZE_32)
+
+#define add_float     add_float32
+#define sub_float     sub_float32
+#define mul_float     mul_float32
+#define div_float     div_float32
+#define _to_float     _to_float32
+#define from_float    float32
+#define is_float_nan  is_float32_nan
+#define is_float_eq   is_float32_eq
+#define is_float_lt   is_float32_lt
+#define is_float_gt   is_float32_gt
+
+#elif defined(FLOAT_SIZE_64)
+
+#define add_float     add_float64
+#define sub_float     sub_float64
+#define mul_float     mul_float64
+#define div_float     div_float64
+#define _to_float     _to_float64
+#define from_float    float64
+#define is_float_nan  is_float64_nan
+#define is_float_eq   is_float64_eq
+#define is_float_lt   is_float64_lt
+#define is_float_gt   is_float64_gt
+
+#elif defined(FLOAT_SIZE_96)
+
+#define add_float     add_float96
+#define sub_float     sub_float96
+#define mul_float     mul_float96
+#define div_float     div_float96
+#define _to_float     _to_float96
+#define from_float    float96
+#define is_float_nan  is_float96_nan
+#define is_float_eq   is_float96_eq
+#define is_float_lt   is_float96_lt
+#define is_float_gt   is_float96_gt
+
+#elif defined(FLOAT_SIZE_128)
+
+#define add_float     add_float128
+#define sub_float     sub_float128
+#define mul_float     mul_float128
+#define div_float     div_float128
+#define _to_float     _to_float128
+#define from_float    float128
+#define is_float_nan  is_float128_nan
+#define is_float_eq   is_float128_eq
+#define is_float_lt   is_float128_lt
+#define is_float_gt   is_float128_gt
+
+#endif
+
+
+#if defined(DOUBLE_SIZE_32)
+
+#define add_double     add_float32
+#define sub_double     sub_float32
+#define mul_double     mul_float32
+#define div_double     div_float32
+#define _to_double     _to_float32
+#define from_double    float32
+#define is_double_nan  is_float32_nan
+#define is_double_eq   is_float32_eq
+#define is_double_lt   is_float32_lt
+#define is_double_gt   is_float32_gt
+
+#elif defined(DOUBLE_SIZE_64)
+
+#define add_double     add_float64
+#define sub_double     sub_float64
+#define mul_double     mul_float64
+#define div_double     div_float64
+#define _to_double     _to_float64
+#define from_double    float64
+#define is_double_nan  is_float64_nan
+#define is_double_eq   is_float64_eq
+#define is_double_lt   is_float64_lt
+#define is_double_gt   is_float64_gt
+
+#elif defined(DOUBLE_SIZE_96)
+
+#define add_double     add_float96
+#define sub_double     sub_float96
+#define mul_double     mul_float96
+#define div_double     div_float96
+#define _to_double     _to_float96
+#define from_double    float96
+#define is_double_nan  is_float96_nan
+#define is_double_eq   is_float96_eq
+#define is_double_lt   is_float96_lt
+#define is_double_gt   is_float96_gt
+
+#elif defined(DOUBLE_SIZE_128)
+
+#define add_double     add_float128
+#define sub_double     sub_float128
+#define mul_double     mul_float128
+#define div_double     div_float128
+#define _to_double     _to_float128
+#define from_double    float128
+#define is_double_nan  is_float128_nan
+#define is_double_eq   is_float128_eq
+#define is_double_lt   is_float128_lt
+#define is_double_gt   is_float128_gt
+
+#endif
+
+
+#if defined(LONG_DOUBLE_SIZE_32)
+
+#define add_long_double     add_float32
+#define sub_long_double     sub_float32
+#define mul_long_double     mul_float32
+#define div_long_double     div_float32
+#define _to_long_double     _to_float32
+#define from_long_double    float32
+#define is_long_double_nan  is_float32_nan
+#define is_long_double_eq   is_float32_eq
+#define is_long_double_lt   is_float32_lt
+#define is_long_double_gt   is_float32_gt
+
+#elif defined(LONG_DOUBLE_SIZE_64)
+
+#define add_long_double     add_float64
+#define sub_long_double     sub_float64
+#define mul_long_double     mul_float64
+#define div_long_double     div_float64
+#define _to_long_double     _to_float64
+#define from_long_double    float64
+#define is_long_double_nan  is_float64_nan
+#define is_long_double_eq   is_float64_eq
+#define is_long_double_lt   is_float64_lt
+#define is_long_double_gt   is_float64_gt
+
+#elif defined(LONG_DOUBLE_SIZE_96)
+
+#define add_long_double     add_float96
+#define sub_long_double     sub_float96
+#define mul_long_double     mul_float96
+#define div_long_double     div_float96
+#define _to_long_double     _to_float96
+#define from_long_double    float96
+#define is_long_double_nan  is_float96_nan
+#define is_long_double_eq   is_float96_eq
+#define is_long_double_lt   is_float96_lt
+#define is_long_double_gt   is_float96_gt
+
+#elif defined(LONG_DOUBLE_SIZE_128)
+
+#define add_long_double     add_float128
+#define sub_long_double     sub_float128
+#define mul_long_double     mul_float128
+#define div_long_double     div_float128
+#define _to_long_double     _to_float128
+#define from_long_double    float128
+#define is_long_double_nan  is_float128_nan
+#define is_long_double_eq   is_float128_eq
+#define is_long_double_lt   is_float128_lt
+#define is_long_double_gt   is_float128_gt
+
+#endif
+
+
+#define CONCAT(a, b)       CONCAT_ARGS(a, b)
+#define CONCAT_ARGS(a, b)  a ## b
+
+#define float32_to_float32(arg)    (arg)
+#define float64_to_float64(arg)    (arg)
+#define float96_to_float96(arg)    (arg)
+#define float128_to_float128(arg)  (arg)
+
+#define float_to_double       CONCAT(from_float, _to_double)
+#define float_to_long_double  CONCAT(from_float, _to_long_double)
+#define float_to_int          CONCAT(from_float, _to_int)
+#define float_to_uint         CONCAT(from_float, _to_uint)
+#define float_to_long         CONCAT(from_float, _to_long)
+#define float_to_ulong        CONCAT(from_float, _to_ulong)
+#define float_to_llong        CONCAT(from_float, _to_llong)
+#define float_to_ullong       CONCAT(from_float, _to_ullong)
+
+#define double_to_float        CONCAT(from_double, _to_float)
+#define double_to_long_double  CONCAT(from_double, _to_long_double)
+#define double_to_int          CONCAT(from_double, _to_int)
+#define double_to_uint         CONCAT(from_double, _to_uint)
+#define double_to_long         CONCAT(from_double, _to_long)
+#define double_to_ulong        CONCAT(from_double, _to_ulong)
+#define double_to_llong        CONCAT(from_double, _to_llong)
+#define double_to_ullong       CONCAT(from_double, _to_ullong)
+
+#define long_double_to_float   CONCAT(from_long_double, _to_float)
+#define long_double_to_double  CONCAT(from_long_double, _to_double)
+#define long_double_to_int     CONCAT(from_long_double, _to_int)
+#define long_double_to_uint    CONCAT(from_long_double, _to_uint)
+#define long_double_to_long    CONCAT(from_long_double, _to_long)
+#define long_double_to_ulong   CONCAT(from_long_double, _to_ulong)
+#define long_double_to_llong   CONCAT(from_long_double, _to_llong)
+#define long_double_to_ullong  CONCAT(from_long_double, _to_ullong)
+
+#define int_to_float        CONCAT(from_int, _to_float)
+#define int_to_double       CONCAT(from_int, _to_double)
+#define int_to_long_double  CONCAT(from_int, _to_long_double)
+
+#define uint_to_float        CONCAT(from_uint, _to_float)
+#define uint_to_double       CONCAT(from_uint, _to_double)
+#define uint_to_long_double  CONCAT(from_uint, _to_long_double)
+
+#define long_to_float        CONCAT(from_long, _to_float)
+#define long_to_double       CONCAT(from_long, _to_double)
+#define long_to_long_double  CONCAT(from_long, _to_long_double)
+
+#define ulong_to_float        CONCAT(from_ulong, _to_float)
+#define ulong_to_double       CONCAT(from_ulong, _to_double)
+#define ulong_to_long_double  CONCAT(from_ulong, _to_long_double)
+
+#define llong_to_float        CONCAT(from_llong, _to_float)
+#define llong_to_double       CONCAT(from_llong, _to_double)
+#define llong_to_long_double  CONCAT(from_llong, _to_long_double)
+
+#define ullong_to_float        CONCAT(from_ullong, _to_float)
+#define ullong_to_double       CONCAT(from_ullong, _to_double)
+#define ullong_to_long_double  CONCAT(from_ullong, _to_long_double)
+
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softfloat/softfloat.c
===================================================================
--- uspace/lib/softfloat/softfloat.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/softfloat.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1353 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat generic
+ * @ingroup sfl
+ * @brief Architecture independent parts of FPU software emulation library.
+ * @{
+ */
+/** @file Softfloat API.
+ */
+
+#include "softfloat.h"
+#include "sftypes.h"
+#include "add.h"
+#include "sub.h"
+#include "mul.h"
+#include "div.h"
+#include "conversion.h"
+#include "comparison.h"
+#include "other.h"
+
+/* Arithmetic functions */
+
+float __addsf3(float a, float b)
+{
+	float_t fa;
+	float_t fb;
+	float_t res;
+	
+	fa.val = a;
+	fb.val = b;
+	
+	if (fa.data.parts.sign != fb.data.parts.sign) {
+		if (fa.data.parts.sign) {
+			fa.data.parts.sign = 0;
+			res.data = sub_float(fb.data, fa.data);
+			
+			return res.val;
+		}
+		
+		fb.data.parts.sign = 0;
+		res.data = sub_float(fa.data, fb.data);
+		
+		return res.val;
+	}
+	
+	res.data = add_float(fa.data, fb.data);
+	return res.val;
+}
+
+double __adddf3(double a, double b)
+{
+	double_t da;
+	double_t db;
+	double_t res;
+	
+	da.val = a;
+	db.val = b;
+	
+	if (da.data.parts.sign != db.data.parts.sign) {
+		if (da.data.parts.sign) {
+			da.data.parts.sign = 0;
+			res.data = sub_double(db.data, da.data);
+			
+			return res.val;
+		}
+		
+		db.data.parts.sign = 0;
+		res.data = sub_double(da.data, db.data);
+		
+		return res.val;
+	}
+	
+	res.data = add_double(da.data, db.data);
+	return res.val;
+}
+
+long double __addtf3(long double a, long double b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	long_double_t res;
+	
+	ta.val = a;
+	tb.val = b;
+	
+	if (ta.data.parts.sign != tb.data.parts.sign) {
+		if (ta.data.parts.sign) {
+			ta.data.parts.sign = 0;
+			res.data = sub_long_double(tb.data, ta.data);
+			
+			return res.val;
+		}
+		
+		tb.data.parts.sign = 0;
+		res.data = sub_long_double(ta.data, tb.data);
+		
+		return res.val;
+	}
+	
+	res.data = add_long_double(ta.data, tb.data);
+	return res.val;
+}
+
+float __subsf3(float a, float b)
+{
+	float_t fa;
+	float_t fb;
+	float_t res;
+	
+	fa.val = a;
+	fb.val = b;
+	
+	if (fa.data.parts.sign != fb.data.parts.sign) {
+		fb.data.parts.sign = !fb.data.parts.sign;
+		res.data = add_float(fa.data, fb.data);
+		
+		return res.val;
+	}
+	
+	res.data = sub_float(fa.data, fb.data);
+	return res.val;
+}
+
+double __subdf3(double a, double b)
+{
+	double_t da;
+	double_t db;
+	double_t res;
+	
+	da.val = a;
+	db.val = b;
+	
+	if (da.data.parts.sign != db.data.parts.sign) {
+		db.data.parts.sign = !db.data.parts.sign;
+		res.data = add_double(da.data, db.data);
+		
+		return res.val;
+	}
+	
+	res.data = sub_double(da.data, db.data);
+	return res.val;
+}
+
+long double __subtf3(long double a, long double b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	long_double_t res;
+	
+	ta.val = a;
+	tb.val = b;
+	
+	if (ta.data.parts.sign != tb.data.parts.sign) {
+		tb.data.parts.sign = !tb.data.parts.sign;
+		res.data = add_long_double(ta.data, tb.data);
+		
+		return res.val;
+	}
+	
+	res.data = sub_long_double(ta.data, tb.data);
+	return res.val;
+}
+
+float __mulsf3(float a, float b)
+{
+	float_t fa;
+	float_t fb;
+	float_t res;
+	
+	fa.val = a;
+	fb.val = b;
+	
+	res.data = mul_float(fa.data, fb.data);
+	return res.val;
+}
+
+double __muldf3(double a, double b)
+{
+	double_t da;
+	double_t db;
+	double_t res;
+	
+	da.val = a;
+	db.val = b;
+	
+	res.data = mul_double(da.data, db.data);
+	return res.val;
+}
+
+long double __multf3(long double a, long double b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	long_double_t res;
+	
+	ta.val = a;
+	tb.val = b;
+	
+	res.data = mul_long_double(ta.data, tb.data);
+	return res.val;
+}
+
+float __divsf3(float a, float b)
+{
+	float_t fa;
+	float_t fb;
+	float_t res;
+	
+	fa.val = a;
+	fb.val = b;
+	
+	res.data = div_float(fa.data, fb.data);
+	return res.val;
+}
+
+double __divdf3(double a, double b)
+{
+	double_t da;
+	double_t db;
+	double_t res;
+	
+	da.val = a;
+	db.val = b;
+	
+	res.data = div_double(da.data, db.data);
+	return res.val;
+}
+
+long double __divtf3(long double a, long double b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	long_double_t res;
+	
+	ta.val = a;
+	tb.val = b;
+	
+	res.data = div_long_double(ta.data, tb.data);
+	return res.val;
+}
+
+float __negsf2(float a)
+{
+	float_t fa;
+	
+	fa.val = a;
+	fa.data.parts.sign = !fa.data.parts.sign;
+	
+	return fa.val;
+}
+
+double __negdf2(double a)
+{
+	double_t da;
+	
+	da.val = a;
+	da.data.parts.sign = !da.data.parts.sign;
+	
+	return da.val;
+}
+
+long double __negtf2(long double a)
+{
+	long_double_t ta;
+	
+	ta.val = a;
+	ta.data.parts.sign = !ta.data.parts.sign;
+	
+	return ta.val;
+}
+
+/* Conversion functions */
+
+double __extendsfdf2(float a)
+{
+	float_t fa;
+	double_t res;
+	
+	fa.val = a;
+	res.data = float_to_double(fa.data);
+	
+	return res.val;
+}
+
+long double __extendsftf2(float a)
+{
+	float_t fa;
+	long_double_t res;
+	
+	fa.val = a;
+	res.data = float_to_long_double(fa.data);
+	
+	return res.val;
+}
+
+long double __extenddftf2(double a)
+{
+	double_t da;
+	long_double_t res;
+	
+	da.val = a;
+	res.data = double_to_long_double(da.data);
+	
+	return res.val;
+}
+
+float __truncdfsf2(double a)
+{
+	double_t da;
+	float_t res;
+	
+	da.val = a;
+	res.data = double_to_float(da.data);
+	
+	return res.val;
+}
+
+float __trunctfsf2(long double a)
+{
+	long_double_t ta;
+	float_t res;
+	
+	ta.val = a;
+	res.data = long_double_to_float(ta.data);
+	
+	return res.val;
+}
+
+double __trunctfdf2(long double a)
+{
+	long_double_t ta;
+	double_t res;
+	
+	ta.val = a;
+	res.data = long_double_to_double(ta.data);
+	
+	return res.val;
+}
+
+int __fixsfsi(float a)
+{
+	float_t fa;
+	
+	fa.val = a;
+	return float_to_int(fa.data);
+}
+
+int __fixdfsi(double a)
+{
+	double_t da;
+	
+	da.val = a;
+	return double_to_int(da.data);
+}
+
+int __fixtfsi(long double a)
+{
+	long_double_t ta;
+	
+	ta.val = a;
+	return long_double_to_int(ta.data);
+}
+ 
+long __fixsfdi(float a)
+{
+	float_t fa;
+	
+	fa.val = a;
+	return float_to_long(fa.data);
+}
+
+long __fixdfdi(double a)
+{
+	double_t da;
+	
+	da.val = a;
+	return double_to_long(da.data);
+}
+
+long __fixtfdi(long double a)
+{
+	long_double_t ta;
+	
+	ta.val = a;
+	return long_double_to_long(ta.data);
+}
+ 
+long long __fixsfti(float a)
+{
+	float_t fa;
+	
+	fa.val = a;
+	return float_to_llong(fa.data);
+}
+
+long long __fixdfti(double a)
+{
+	double_t da;
+	
+	da.val = a;
+	return double_to_llong(da.data);
+}
+
+long long __fixtfti(long double a)
+{
+	long_double_t ta;
+	
+	ta.val = a;
+	return long_double_to_llong(ta.data);
+}
+
+unsigned int __fixunssfsi(float a)
+{
+	float_t fa;
+	
+	fa.val = a;
+	return float_to_uint(fa.data);
+}
+
+unsigned int __fixunsdfsi(double a)
+{
+	double_t da;
+	
+	da.val = a;
+	return double_to_uint(da.data);
+}
+
+unsigned int __fixunstfsi(long double a)
+{
+	long_double_t ta;
+	
+	ta.val = a;
+	return long_double_to_uint(ta.data);
+}
+ 
+unsigned long __fixunssfdi(float a)
+{
+	float_t fa;
+	
+	fa.val = a;
+	return float_to_ulong(fa.data);
+}
+
+unsigned long __fixunsdfdi(double a)
+{
+	double_t da;
+	
+	da.val = a;
+	return double_to_ulong(da.data);
+}
+
+unsigned long __fixunstfdi(long double a)
+{
+	long_double_t ta;
+	
+	ta.val = a;
+	return long_double_to_ulong(ta.data);
+}
+ 
+unsigned long long __fixunssfti(float a)
+{
+	float_t fa;
+	
+	fa.val = a;
+	return float_to_ullong(fa.data);
+}
+
+unsigned long long __fixunsdfti(double a)
+{
+	double_t da;
+	
+	da.val = a;
+	return double_to_ullong(da.data);
+}
+
+unsigned long long __fixunstfti(long double a)
+{
+	long_double_t ta;
+	
+	ta.val = a;
+	return long_double_to_ullong(ta.data);
+}
+ 
+float __floatsisf(int i)
+{
+	float_t res;
+	
+	res.data = int_to_float(i);
+	return res.val;
+}
+
+double __floatsidf(int i)
+{
+	double_t res;
+	
+	res.data = int_to_double(i);
+	return res.val;
+}
+
+long double __floatsitf(int i)
+{
+	long_double_t res;
+	
+	res.data = int_to_long_double(i);
+	return res.val;
+}
+ 
+float __floatdisf(long i)
+{
+	float_t res;
+	
+	res.data = long_to_float(i);
+	return res.val;
+}
+
+double __floatdidf(long i)
+{
+	double_t res;
+	
+	res.data = long_to_double(i);
+	return res.val;
+}
+
+long double __floatditf(long i)
+{
+	long_double_t res;
+	
+	res.data = long_to_long_double(i);
+	return res.val;
+}
+
+float __floattisf(long long i)
+{
+	float_t res;
+	
+	res.data = llong_to_float(i);
+	return res.val;
+}
+
+double __floattidf(long long i)
+{
+	double_t res;
+	
+	res.data = llong_to_double(i);
+	return res.val;
+}
+
+long double __floattitf(long long i)
+{
+	long_double_t res;
+	
+	res.data = llong_to_long_double(i);
+	return res.val;
+}
+
+float __floatunsisf(unsigned int i)
+{
+	float_t res;
+	
+	res.data = uint_to_float(i);
+	return res.val;
+}
+
+double __floatunsidf(unsigned int i)
+{
+	double_t res;
+	
+	res.data = uint_to_double(i);
+	return res.val;
+}
+
+long double __floatunsitf(unsigned int i)
+{
+	long_double_t res;
+	
+	res.data = uint_to_long_double(i);
+	return res.val;
+}
+ 
+float __floatundisf(unsigned long i)
+{
+	float_t res;
+	
+	res.data = ulong_to_float(i);
+	return res.val;
+}
+
+double __floatundidf(unsigned long i)
+{
+	double_t res;
+	
+	res.data = ulong_to_double(i);
+	return res.val;
+}
+
+long double __floatunditf(unsigned long i)
+{
+	long_double_t res;
+	
+	res.data = ulong_to_long_double(i);
+	return res.val;
+}
+ 
+float __floatuntisf(unsigned long long i)
+{
+	float_t res;
+	
+	res.data = ullong_to_float(i);
+	return res.val;
+}
+
+double __floatuntidf(unsigned long long i)
+{
+	double_t res;
+	
+	res.data = ullong_to_double(i);
+	return res.val;
+}
+
+long double __floatuntitf(unsigned long long i)
+{
+	long_double_t res;
+	
+	res.data = ullong_to_long_double(i);
+	return res.val;
+}
+
+/* Comparison functions */
+
+int __cmpsf2(float a, float b) 
+{
+	float_t fa;
+	float_t fb;
+	
+	fa.val = a;
+	fb.val = b;
+	
+	if ((is_float_nan(fa.data)) || (is_float_nan(fb.data))) {
+		/* no special constant for unordered - maybe signaled? */
+		return 1;
+	}
+	
+	if (is_float_eq(fa.data, fb.data))
+		return 0;
+	
+	if (is_float_lt(fa.data, fb.data))
+		return -1;
+	
+	return 1;
+}
+
+int __cmpdf2(double a, double b)
+{
+	double_t da;
+	double_t db;
+	
+	da.val = a;
+	db.val = b;
+	
+	if ((is_double_nan(da.data)) || (is_double_nan(db.data))) {
+		/* no special constant for unordered - maybe signaled? */
+		return 1;
+	}
+	
+	if (is_double_eq(da.data, db.data))
+		return 0;
+	
+	if (is_double_lt(da.data, db.data))
+		return -1;
+	
+	return 1;
+}
+
+int __cmptf2(long double a, long double b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = a;
+	tb.val = b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data))) {
+		/* no special constant for unordered - maybe signaled? */
+		return 1;
+	}
+	
+	if (is_long_double_eq(ta.data, tb.data))
+		return 0;
+	
+	if (is_long_double_lt(ta.data, tb.data))
+		return -1;
+	
+	return 1;
+}
+
+int __unordsf2(float a, float b)
+{
+	float_t fa;
+	float_t fb;
+	
+	fa.val = a;
+	fb.val = b;
+	
+	return ((is_float_nan(fa.data)) || (is_float_nan(fb.data)));
+}
+
+int __unorddf2(double a, double b)
+{
+	double_t da;
+	double_t db;
+	
+	da.val = a;
+	db.val = b;
+	
+	return ((is_double_nan(da.data)) || (is_double_nan(db.data)));
+}
+
+int __unordtf2(long double a, long double b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = a;
+	tb.val = b;
+	
+	return ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)));
+}
+
+int __eqsf2(float a, float b)
+{
+	float_t fa;
+	float_t fb;
+	
+	fa.val = a;
+	fb.val = b;
+	
+	if ((is_float_nan(fa.data)) || (is_float_nan(fb.data))) {
+		// TODO: sigNaNs
+		return 1;
+	}
+	
+	return is_float_eq(fa.data, fb.data) - 1;
+}
+
+int __eqdf2(double a, double b)
+{
+	double_t da;
+	double_t db;
+	
+	da.val = a;
+	db.val = b;
+	
+	if ((is_double_nan(da.data)) || (is_double_nan(db.data))) {
+		// TODO: sigNaNs
+		return 1;
+	}
+	
+	return is_double_eq(da.data, db.data) - 1;
+}
+
+int __eqtf2(long double a, long double b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = a;
+	tb.val = b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data))) {
+		// TODO: sigNaNs
+		return 1;
+	}
+	
+	return is_long_double_eq(ta.data, tb.data) - 1;
+}
+
+int __nesf2(float a, float b)
+{
+	/* strange behavior, but it was in gcc documentation */
+	return __eqsf2(a, b);
+}
+
+int __nedf2(double a, double b)
+{
+	/* strange behavior, but it was in gcc documentation */
+	return __eqdf2(a, b);
+}
+
+int __netf2(long double a, long double b)
+{
+	/* strange behavior, but it was in gcc documentation */
+	return __eqtf2(a, b);
+}
+
+int __gesf2(float a, float b)
+{
+	float_t fa;
+	float_t fb;
+	
+	fa.val = a;
+	fb.val = b;
+	
+	if ((is_float_nan(fa.data)) || (is_float_nan(fb.data))) {
+		// TODO: sigNaNs
+		return -1;
+	}
+	
+	if (is_float_eq(fa.data, fb.data))
+		return 0;
+	
+	if (is_float_gt(fa.data, fb.data))
+		return 1;
+	
+	return -1;
+}
+
+int __gedf2(double a, double b)
+{
+	double_t da;
+	double_t db;
+	
+	da.val = a;
+	db.val = b;
+	
+	if ((is_double_nan(da.data)) || (is_double_nan(db.data))) {
+		// TODO: sigNaNs
+		return -1;
+	}
+	
+	if (is_double_eq(da.data, db.data))
+		return 0;
+	
+	if (is_double_gt(da.data, db.data))
+		return 1;
+	
+	return -1;
+}
+
+int __getf2(long double a, long double b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = a;
+	tb.val = b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data))) {
+		// TODO: sigNaNs
+		return -1;
+	}
+	
+	if (is_long_double_eq(ta.data, tb.data))
+		return 0;
+	
+	if (is_long_double_gt(ta.data, tb.data))
+		return 1;
+	
+	return -1;
+}
+
+int __ltsf2(float a, float b)
+{
+	float_t fa;
+	float_t fb;
+	
+	fa.val = a;
+	fb.val = b;
+	
+	if ((is_float_nan(fa.data)) || (is_float_nan(fb.data))) {
+		// TODO: sigNaNs
+		return 1;
+	}
+	
+	if (is_float_lt(fa.data, fb.data))
+		return -1;
+	
+	return 0;
+}
+
+int __ltdf2(double a, double b)
+{
+	double_t da;
+	double_t db;
+	
+	da.val = a;
+	db.val = b;
+	
+	if ((is_double_nan(da.data)) || (is_double_nan(db.data))) {
+		// TODO: sigNaNs
+		return 1;
+	}
+	
+	if (is_double_lt(da.data, db.data))
+		return -1;
+	
+	return 0;
+}
+
+int __lttf2(long double a, long double b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = a;
+	tb.val = b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data))) {
+		// TODO: sigNaNs
+		return 1;
+	}
+	
+	if (is_long_double_lt(ta.data, tb.data))
+		return -1;
+	
+	return 0;
+}
+
+int __lesf2(float a, float b)
+{
+	float_t fa;
+	float_t fb;
+	
+	fa.val = a;
+	fb.val = b;
+	
+	if ((is_float_nan(fa.data)) || (is_float_nan(fb.data))) {
+		// TODO: sigNaNs
+		return 1;
+	}
+	
+	if (is_float_eq(fa.data, fb.data))
+		return 0;
+	
+	if (is_float_lt(fa.data, fb.data))
+		return -1;
+	
+	return 1;
+}
+
+int __ledf2(double a, double b)
+{
+	double_t da;
+	double_t db;
+	
+	da.val = a;
+	db.val = b;
+	
+	if ((is_double_nan(da.data)) || (is_double_nan(db.data))) {
+		// TODO: sigNaNs
+		return 1;
+	}
+	
+	if (is_double_eq(da.data, db.data))
+		return 0;
+	
+	if (is_double_lt(da.data, db.data))
+		return -1;
+	
+	return 1;
+}
+
+int __letf2(long double a, long double b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = a;
+	tb.val = b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data))) {
+		// TODO: sigNaNs
+		return 1;
+	}
+	
+	if (is_long_double_eq(ta.data, tb.data))
+		return 0;
+	
+	if (is_long_double_lt(ta.data, tb.data))
+		return -1;
+	
+	return 1;
+}
+
+int __gtsf2(float a, float b)
+{
+	float_t fa;
+	float_t fb;
+	
+	fa.val = a;
+	fb.val = b;
+	
+	if ((is_float_nan(fa.data)) || (is_float_nan(fb.data))) {
+		// TODO: sigNaNs
+		return -1;
+	}
+	
+	if (is_float_gt(fa.data, fb.data))
+		return 1;
+	
+	return 0;
+}
+
+int __gtdf2(double a, double b)
+{
+	double_t da;
+	double_t db;
+	
+	da.val = a;
+	db.val = b;
+	
+	if ((is_double_nan(da.data)) || (is_double_nan(db.data))) {
+		// TODO: sigNaNs
+		return -1;
+	}
+	
+	if (is_double_gt(da.data, db.data))
+		return 1;
+	
+	return 0;
+}
+
+int __gttf2(long double a, long double b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = a;
+	tb.val = b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data))) {
+		// TODO: sigNaNs
+		return -1;
+	}
+	
+	if (is_long_double_gt(ta.data, tb.data))
+		return 1;
+	
+	return 0;
+}
+
+/* SPARC quadruple-precision wrappers */
+
+void _Qp_add(long double *c, long double *a, long double *b)
+{
+	*c = __addtf3(*a, *b);
+}
+
+void _Qp_sub(long double *c, long double *a, long double *b)
+{
+	*c = __subtf3(*a, *b);
+}
+
+void _Qp_mul(long double *c, long double *a, long double *b)
+{
+	*c = __multf3(*a, *b);
+}
+
+void _Qp_div(long double *c, long double *a, long double *b)
+{
+	*c = __divtf3(*a, *b);
+}
+
+void _Qp_neg(long double *c, long double *a)
+{
+	*c = __negtf2(*a);
+}
+
+void _Qp_stoq(long double *c, float a)
+{
+	*c = __extendsftf2(a);
+}
+
+void _Qp_dtoq(long double *c, double a)
+{
+	*c = __extenddftf2(a);
+}
+
+float _Qp_qtos(long double *a)
+{
+	return __trunctfsf2(*a);
+}
+
+double _Qp_qtod(long double *a)
+{
+	return __trunctfdf2(*a);
+}
+
+int _Qp_qtoi(long double *a)
+{
+	return __fixtfsi(*a);
+}
+
+unsigned int _Qp_qtoui(long double *a)
+{
+	return __fixunstfsi(*a);
+}
+
+long _Qp_qtox(long double *a)
+{
+	return __fixtfdi(*a);
+}
+
+unsigned long _Qp_qtoux(long double *a)
+{
+	return __fixunstfdi(*a);
+}
+
+void _Qp_itoq(long double *c, int a)
+{
+	*c = __floatsitf(a);
+}
+
+void _Qp_uitoq(long double *c, unsigned int a)
+{
+	*c = __floatunsitf(a);
+}
+
+void _Qp_xtoq(long double *c, long a)
+{
+	*c = __floatditf(a);
+}
+
+void _Qp_uxtoq(long double *c, unsigned long a)
+{
+	*c = __floatunditf(a);
+}
+
+int _Qp_cmp(long double *a, long double *b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = *a;
+	tb.val = *b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
+		return 3;
+	
+	if (is_long_double_eq(ta.data, tb.data))
+		return 0;
+	
+	if (is_long_double_lt(ta.data, tb.data))
+		return 1;
+	
+	return 2;
+}
+
+int _Qp_cmpe(long double *a, long double *b)
+{
+	/* strange, but is defined this way in SPARC Compliance Definition */
+	return _Qp_cmp(a, b);
+}
+
+int _Qp_feq(long double *a, long double *b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = *a;
+	tb.val = *b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
+		return 0;
+	
+	return is_long_double_eq(ta.data, tb.data);
+}
+
+int _Qp_fge(long double *a, long double *b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = *a;
+	tb.val = *b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
+		return 0;
+	
+	return is_long_double_eq(ta.data, tb.data) ||
+	    is_long_double_gt(ta.data, tb.data);
+}
+
+int _Qp_fgt(long double *a, long double *b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = *a;
+	tb.val = *b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
+		return 0;
+	
+	return is_long_double_gt(ta.data, tb.data);
+}
+
+int _Qp_fle(long double*a, long double *b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = *a;
+	tb.val = *b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
+		return 0;
+	
+	return is_long_double_eq(ta.data, tb.data) ||
+	    is_long_double_lt(ta.data, tb.data);
+}
+
+int _Qp_flt(long double *a, long double *b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = *a;
+	tb.val = *b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
+		return 0;
+	
+	return is_long_double_lt(ta.data, tb.data);
+}
+
+int _Qp_fne(long double *a, long double *b)
+{
+	long_double_t ta;
+	long_double_t tb;
+	
+	ta.val = *a;
+	tb.val = *b;
+	
+	if ((is_long_double_nan(ta.data)) || (is_long_double_nan(tb.data)))
+		return 0;
+	
+	return !is_long_double_eq(ta.data, tb.data);
+}
+
+double __aeabi_i2d(int i)
+{
+	return __floatsidf(i);
+}
+
+double __aeabi_ui2d(unsigned int i)
+{
+	return __floatunsidf(i);
+}
+
+int __aeabi_f2iz(float a)
+{
+	return __fixsfsi(a);
+}
+
+int __aeabi_d2iz(double a)
+{
+	return __fixdfsi(a);
+}
+
+unsigned int __aeabi_d2uiz(double a)
+{
+	return __fixunsdfsi(a);
+}
+
+int __aeabi_dcmpge(double a, double b)
+{
+	return __gedf2(a, b);
+}
+
+int __aeabi_dcmpgt(double a, double b)
+{
+	return __gtdf2(a, b);
+}
+
+int __aeabi_dcmplt(double a, double b)
+{
+	return __ltdf2(a, b);
+}
+
+int __aeabi_dcmpeq(double a, double b)
+{
+	return __eqdf2(a, b);
+}
+
+float __aeabi_fadd(float a, float b)
+{
+	return __addsf3(a, b);
+}
+
+float __aeabi_fsub(float a, float b)
+{
+	return __subsf3(a, b);
+}
+
+float __aeabi_fmul(float a, float b)
+{
+	return __mulsf3(a, b);
+}
+
+float __aeabi_fdiv(float a, float b)
+{
+	return __divsf3(a, b);
+}
+
+double __aeabi_dadd(double a, double b)
+{
+	return __adddf3(a, b);
+}
+
+double __aeabi_dsub(double a, double b)
+{
+	return __subdf3(a, b);
+}
+
+double __aeabi_dmul(double a, double b)
+{
+	return __muldf3(a, b);
+}
+
+double __aeabi_ddiv(double a, double b)
+{
+	return __divdf3(a, b);
+}
+
+/** @}
+ */
Index: uspace/lib/softfloat/softfloat.h
===================================================================
--- uspace/lib/softfloat/softfloat.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/softfloat.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Softfloat API.
+ */
+
+#ifndef __SOFTFLOAT_H__
+#define __SOFTFLOAT_H__
+
+extern float __addsf3(float, float);
+extern double __adddf3(double, double);
+extern long double __addtf3(long double, long double);
+extern long double __addxf3(long double, long double);
+
+extern float __subsf3(float, float);
+extern double __subdf3(double, double);
+extern long double __subtf3(long double, long double);
+extern long double __subxf3(long double, long double);
+
+extern float __mulsf3(float, float);
+extern double __muldf3(double, double);
+extern long double __multf3(long double, long double);
+extern long double __mulxf3(long double, long double);
+
+extern float __divsf3(float, float);
+extern double __divdf3(double, double);
+extern long double __divtf3(long double, long double);
+extern long double __divxf3(long double, long double);
+
+extern float __negsf2(float);
+extern double __negdf2(double);
+extern long double __negtf2(long double);
+extern long double __negxf2(long double);
+
+extern double __extendsfdf2(float);
+extern long double __extendsftf2(float);
+extern long double __extendsfxf2(float);
+extern long double __extenddftf2(double);
+extern long double __extenddfxf2(double);
+
+extern double __truncxfdf2(long double);
+extern double __trunctfdf2(long double);
+extern float __truncxfsf2(long double);
+extern float __trunctfsf2(long double);
+extern float __truncdfsf2(double);
+
+extern int __fixsfsi(float);
+extern int __fixdfsi(double);
+extern int __fixtfsi(long double);
+extern int __fixxfsi(long double);
+
+extern long __fixsfdi(float);
+extern long __fixdfdi(double);
+extern long __fixtfdi(long double);
+extern long __fixxfdi(long double);
+
+extern long long __fixsfti(float);
+extern long long __fixdfti(double);
+extern long long __fixtfti(long double);
+extern long long __fixxfti(long double);
+
+extern unsigned int __fixunssfsi(float);
+extern unsigned int __fixunsdfsi(double);
+extern unsigned int __fixunstfsi(long double);
+extern unsigned int __fixunsxfsi(long double);
+
+extern unsigned long __fixunssfdi(float);
+extern unsigned long __fixunsdfdi(double);
+extern unsigned long __fixunstfdi(long double);
+extern unsigned long __fixunsxfdi(long double);
+
+extern unsigned long long __fixunssfti(float);
+extern unsigned long long __fixunsdfti(double);
+extern unsigned long long __fixunstfti(long double);
+extern unsigned long long __fixunsxfti(long double);
+
+extern float __floatsisf(int);
+extern double __floatsidf(int);
+extern long double __floatsitf(int);
+extern long double __floatsixf(int);
+
+extern float __floatdisf(long);
+extern double __floatdidf(long);
+extern long double __floatditf(long);
+extern long double __floatdixf(long);
+
+extern float __floattisf(long long);
+extern double __floattidf(long long);
+extern long double __floattitf(long long);
+extern long double __floattixf(long long);
+
+extern float __floatunsisf(unsigned int);
+extern double __floatunsidf(unsigned int);
+extern long double __floatunsitf(unsigned int);
+extern long double __floatunsixf(unsigned int);
+
+extern float __floatundisf(unsigned long);
+extern double __floatundidf(unsigned long);
+extern long double __floatunditf(unsigned long);
+extern long double __floatundixf(unsigned long);
+
+extern float __floatuntisf(unsigned long long);
+extern double __floatuntidf(unsigned long long);
+extern long double __floatuntitf(unsigned long long);
+extern long double __floatuntixf(unsigned long long);
+
+extern int __cmpsf2(float, float);
+extern int __cmpdf2(double, double);
+extern int __cmptf2(long double, long double);
+
+extern int __unordsf2(float, float);
+extern int __unorddf2(double, double);
+extern int __unordtf2(long double, long double);
+
+extern int __eqsf2(float, float);
+extern int __eqdf2(double, double);
+extern int __eqtf2(long double, long double);
+
+extern int __nesf2(float, float);
+extern int __nedf2(double, double);
+extern int __netf2(long double, long double);
+
+extern int __gesf2(float, float);
+extern int __gedf2(double, double);
+extern int __getf2(long double, long double);
+
+extern int __ltsf2(float, float);
+extern int __ltdf2(double, double);
+extern int __lttf2(long double, long double);
+
+extern int __lesf2(float, float);
+extern int __ledf2(double, double);
+extern int __letf2(long double, long double);
+
+extern int __gtsf2(float, float);
+extern int __gtdf2(double, double);
+extern int __gttf2(long double, long double);
+
+/* Not implemented yet */
+extern float __powisf2(float, int);
+extern double __powidf2 (double, int);
+extern long double __powitf2(long double, int);
+extern long double __powixf2(long double, int);
+
+/* SPARC quadruple-precision wrappers */
+extern void _Qp_add(long double *, long double *, long double *);
+extern void _Qp_sub(long double *, long double *, long double *);
+extern void _Qp_mul(long double *, long double *, long double *);
+extern void _Qp_div(long double *, long double *, long double *);
+extern void _Qp_neg(long double *, long double *);
+
+extern void _Qp_stoq(long double *, float);
+extern void _Qp_dtoq(long double *, double);
+extern float _Qp_qtos(long double *);
+extern double _Qp_qtod(long double *);
+
+extern int _Qp_qtoi(long double *);
+extern unsigned int _Qp_qtoui(long double *);
+extern long _Qp_qtox(long double *);
+extern unsigned long _Qp_qtoux(long double *);
+
+extern void _Qp_itoq(long double *, int);
+extern void _Qp_uitoq(long double *, unsigned int);
+extern void _Qp_xtoq(long double *, long);
+extern void _Qp_uxtoq(long double *, unsigned long);
+
+extern int _Qp_cmp(long double *, long double *);
+extern int _Qp_cmpe(long double *, long double *);
+extern int _Qp_feq(long double *, long double *);
+extern int _Qp_fge(long double *, long double *);
+extern int _Qp_fgt(long double *, long double *);
+extern int _Qp_fle(long double*, long double *);
+extern int _Qp_flt(long double *, long double *);
+extern int _Qp_fne(long double *, long double *);
+
+/* ARM EABI */
+extern double __aeabi_i2d(int);
+extern double __aeabi_ui2d(unsigned int);
+extern unsigned int __aeabi_d2uiz(double);
+
+extern int __aeabi_f2iz(float);
+extern int __aeabi_d2iz(double);
+
+extern int __aeabi_dcmpge(double, double);
+extern int __aeabi_dcmpgt(double, double);
+extern int __aeabi_dcmplt(double, double);
+extern int __aeabi_dcmpeq(double, double);
+
+extern float __aeabi_fadd(float, float);
+extern float __aeabi_fsub(float, float);
+extern float __aeabi_fmul(float, float);
+extern float __aeabi_fdiv(float, float);
+
+extern double __aeabi_dadd(double, double);
+extern double __aeabi_dsub(double, double);
+extern double __aeabi_dmul(double, double);
+extern double __aeabi_ddiv(double, double);
+
+/* Not implemented yet */
+extern void _Qp_sqrt(long double *, long double *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softfloat/sub.c
===================================================================
--- uspace/lib/softfloat/sub.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/sub.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Substraction functions.
+ */
+
+#include "sftypes.h"
+#include "sub.h"
+#include "comparison.h"
+#include "common.h"
+
+/** Subtract two single-precision floats with the same sign.
+ *
+ * @param a First input operand.
+ * @param b Second input operand.
+ *
+ * @return Result of substraction.
+ *
+ */
+float32 sub_float32(float32 a, float32 b)
+{
+	int expdiff;
+	uint32_t exp1, exp2, frac1, frac2;
+	float32 result;
+	
+	result.bin = 0;
+	
+	expdiff = a.parts.exp - b.parts.exp;
+	if ((expdiff < 0 ) || ((expdiff == 0) &&
+	    (a.parts.fraction < b.parts.fraction))) {
+		if (is_float32_nan(b)) {
+			if (is_float32_signan(b)) {
+				// TODO: fix SigNaN
+			}
+			
+			return b;
+		}
+		
+		if (b.parts.exp == FLOAT32_MAX_EXPONENT) {
+			/* num -(+-inf) = -+inf */
+			b.parts.sign = !b.parts.sign;
+			return b;
+		}
+		
+		result.parts.sign = !a.parts.sign;
+		
+		frac1 = b.parts.fraction;
+		exp1 = b.parts.exp;
+		frac2 = a.parts.fraction;
+		exp2 = a.parts.exp;
+		expdiff *= -1;
+	} else {
+		if (is_float32_nan(a)) {
+			if ((is_float32_signan(a)) || (is_float32_signan(b))) {
+				// TODO: fix SigNaN
+			}
+			
+			return a;
+		}
+		
+		if (a.parts.exp == FLOAT32_MAX_EXPONENT) {
+			if (b.parts.exp == FLOAT32_MAX_EXPONENT) {
+				/* inf - inf => nan */
+				// TODO: fix exception
+				result.bin = FLOAT32_NAN;
+				return result;
+			}
+			
+			return a;
+		}
+		
+		result.parts.sign = a.parts.sign;
+		
+		frac1 = a.parts.fraction;
+		exp1 = a.parts.exp;
+		frac2 = b.parts.fraction;
+		exp2 = b.parts.exp;
+	}
+	
+	if (exp1 == 0) {
+		/* both are denormalized */
+		result.parts.fraction = frac1 - frac2;
+		if (result.parts.fraction > frac1) {
+			// TODO: underflow exception
+			return result;
+		}
+		
+		result.parts.exp = 0;
+		return result;
+	}
+	
+	/* add hidden bit */
+	frac1 |= FLOAT32_HIDDEN_BIT_MASK;
+	
+	if (exp2 == 0) {
+		/* denormalized */
+		--expdiff;
+	} else {
+		/* normalized */
+		frac2 |= FLOAT32_HIDDEN_BIT_MASK;
+	}
+	
+	/* create some space for rounding */
+	frac1 <<= 6;
+	frac2 <<= 6;
+	
+	if (expdiff > FLOAT32_FRACTION_SIZE + 1)
+		goto done;
+	
+	frac1 = frac1 - (frac2 >> expdiff);
+	
+done:
+	/* TODO: find first nonzero digit and shift result and detect possibly underflow */
+	while ((exp1 > 0) && (!(frac1 & (FLOAT32_HIDDEN_BIT_MASK << 6 )))) {
+		--exp1;
+		frac1 <<= 1;
+		/* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
+	}
+	
+	/* rounding - if first bit after fraction is set then round up */
+	frac1 += 0x20;
+	
+	if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7)) {
+		++exp1;
+		frac1 >>= 1;
+	}
+	
+	/* Clear hidden bit and shift */
+	result.parts.fraction = ((frac1 >> 6) & (~FLOAT32_HIDDEN_BIT_MASK));
+	result.parts.exp = exp1;
+	
+	return result;
+}
+
+/** Subtract two double-precision floats with the same sign.
+ *
+ * @param a First input operand.
+ * @param b Second input operand.
+ *
+ * @return Result of substraction.
+ *
+ */
+float64 sub_float64(float64 a, float64 b)
+{
+	int expdiff;
+	uint32_t exp1, exp2;
+	uint64_t frac1, frac2;
+	float64 result;
+	
+	result.bin = 0;
+	
+	expdiff = a.parts.exp - b.parts.exp;
+	if ((expdiff < 0 ) ||
+	    ((expdiff == 0) && (a.parts.fraction < b.parts.fraction))) {
+		if (is_float64_nan(b)) {
+			if (is_float64_signan(b)) {
+				// TODO: fix SigNaN
+			}
+			
+			return b;
+		}
+		
+		if (b.parts.exp == FLOAT64_MAX_EXPONENT) {
+			/* num -(+-inf) = -+inf */
+			b.parts.sign = !b.parts.sign;
+			return b;
+		}
+		
+		result.parts.sign = !a.parts.sign;
+		
+		frac1 = b.parts.fraction;
+		exp1 = b.parts.exp;
+		frac2 = a.parts.fraction;
+		exp2 = a.parts.exp;
+		expdiff *= -1;
+	} else {
+		if (is_float64_nan(a)) {
+			if (is_float64_signan(a) || is_float64_signan(b)) {
+				// TODO: fix SigNaN
+			}
+			
+			return a;
+		}
+		
+		if (a.parts.exp == FLOAT64_MAX_EXPONENT) {
+			if (b.parts.exp == FLOAT64_MAX_EXPONENT) {
+				/* inf - inf => nan */
+				// TODO: fix exception
+				result.bin = FLOAT64_NAN;
+				return result;
+			}
+			
+			return a;
+		}
+		
+		result.parts.sign = a.parts.sign;
+		
+		frac1 = a.parts.fraction;
+		exp1 = a.parts.exp;
+		frac2 = b.parts.fraction;
+		exp2 = b.parts.exp;
+	}
+	
+	if (exp1 == 0) {
+		/* both are denormalized */
+		result.parts.fraction = frac1 - frac2;
+		if (result.parts.fraction > frac1) {
+			// TODO: underflow exception
+			return result;
+		}
+		
+		result.parts.exp = 0;
+		return result;
+	}
+	
+	/* add hidden bit */
+	frac1 |= FLOAT64_HIDDEN_BIT_MASK;
+	
+	if (exp2 == 0) {
+		/* denormalized */
+		--expdiff;
+	} else {
+		/* normalized */
+		frac2 |= FLOAT64_HIDDEN_BIT_MASK;
+	}
+	
+	/* create some space for rounding */
+	frac1 <<= 6;
+	frac2 <<= 6;
+	
+	if (expdiff > FLOAT64_FRACTION_SIZE + 1)
+		goto done;
+	
+	frac1 = frac1 - (frac2 >> expdiff);
+	
+done:
+	/* TODO: find first nonzero digit and shift result and detect possibly underflow */
+	while ((exp1 > 0) && (!(frac1 & (FLOAT64_HIDDEN_BIT_MASK << 6 )))) {
+		--exp1;
+		frac1 <<= 1;
+		/* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
+	}
+	
+	/* rounding - if first bit after fraction is set then round up */
+	frac1 += 0x20;
+	
+	if (frac1 & (FLOAT64_HIDDEN_BIT_MASK << 7)) {
+		++exp1;
+		frac1 >>= 1;
+	}
+	
+	/* Clear hidden bit and shift */
+	result.parts.fraction = ((frac1 >> 6) & (~FLOAT64_HIDDEN_BIT_MASK));
+	result.parts.exp = exp1;
+	
+	return result;
+}
+
+/** Subtract two quadruple-precision floats with the same sign.
+ *
+ * @param a First input operand.
+ * @param b Second input operand.
+ *
+ * @return Result of substraction.
+ *
+ */
+float128 sub_float128(float128 a, float128 b)
+{
+	int expdiff;
+	uint32_t exp1, exp2;
+	uint64_t frac1_hi, frac1_lo, frac2_hi, frac2_lo, tmp_hi, tmp_lo;
+	float128 result;
+	
+	result.bin.hi = 0;
+	result.bin.lo = 0;
+	
+	expdiff = a.parts.exp - b.parts.exp;
+	if ((expdiff < 0 ) || ((expdiff == 0) &&
+	    lt128(a.parts.frac_hi, a.parts.frac_lo, b.parts.frac_hi, b.parts.frac_lo))) {
+		if (is_float128_nan(b)) {
+			if (is_float128_signan(b)) {
+				// TODO: fix SigNaN
+			}
+			
+			return b;
+		}
+		
+		if (b.parts.exp == FLOAT128_MAX_EXPONENT) {
+			/* num -(+-inf) = -+inf */
+			b.parts.sign = !b.parts.sign;
+			return b;
+		}
+		
+		result.parts.sign = !a.parts.sign;
+		
+		frac1_hi = b.parts.frac_hi;
+		frac1_lo = b.parts.frac_lo;
+		exp1 = b.parts.exp;
+		frac2_hi = a.parts.frac_hi;
+		frac2_lo = a.parts.frac_lo;
+		exp2 = a.parts.exp;
+		expdiff *= -1;
+	} else {
+		if (is_float128_nan(a)) {
+			if (is_float128_signan(a) || is_float128_signan(b)) {
+				// TODO: fix SigNaN
+			}
+			
+			return a;
+		}
+		
+		if (a.parts.exp == FLOAT128_MAX_EXPONENT) {
+			if (b.parts.exp == FLOAT128_MAX_EXPONENT) {
+				/* inf - inf => nan */
+				// TODO: fix exception
+				result.bin.hi = FLOAT128_NAN_HI;
+				result.bin.lo = FLOAT128_NAN_LO;
+				return result;
+			}
+			return a;
+		}
+		
+		result.parts.sign = a.parts.sign;
+		
+		frac1_hi = a.parts.frac_hi;
+		frac1_lo = a.parts.frac_lo;
+		exp1 = a.parts.exp;
+		frac2_hi = b.parts.frac_hi;
+		frac2_lo = b.parts.frac_lo;
+		exp2 = b.parts.exp;
+	}
+	
+	if (exp1 == 0) {
+		/* both are denormalized */
+		sub128(frac1_hi, frac1_lo, frac2_hi, frac2_lo, &tmp_hi, &tmp_lo);
+		result.parts.frac_hi = tmp_hi;
+		result.parts.frac_lo = tmp_lo;
+		if (lt128(frac1_hi, frac1_lo, result.parts.frac_hi, result.parts.frac_lo)) {
+			// TODO: underflow exception
+			return result;
+		}
+		
+		result.parts.exp = 0;
+		return result;
+	}
+	
+	/* add hidden bit */
+	or128(frac1_hi, frac1_lo,
+	    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+	    &frac1_hi, &frac1_lo);
+	
+	if (exp2 == 0) {
+		/* denormalized */
+		--expdiff;
+	} else {
+		/* normalized */
+		or128(frac2_hi, frac2_lo,
+		    FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+		    &frac2_hi, &frac2_lo);
+	}
+	
+	/* create some space for rounding */
+	lshift128(frac1_hi, frac1_lo, 6, &frac1_hi, &frac1_lo);
+	lshift128(frac2_hi, frac2_lo, 6, &frac2_hi, &frac2_lo);
+	
+	if (expdiff > FLOAT128_FRACTION_SIZE + 1)
+		goto done;
+	
+	rshift128(frac2_hi, frac2_lo, expdiff, &tmp_hi, &tmp_lo);
+	sub128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &frac1_hi, &frac1_lo);
+	
+done:
+	/* TODO: find first nonzero digit and shift result and detect possibly underflow */
+	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 6,
+	    &tmp_hi, &tmp_lo);
+	and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+	while ((exp1 > 0) && (!lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo))) {
+		--exp1;
+		lshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
+		/* TODO: fix underflow - frac1 == 0 does not necessary means underflow... */
+		
+		lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 6,
+		    &tmp_hi, &tmp_lo);
+		and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+	}
+	
+	/* rounding - if first bit after fraction is set then round up */
+	add128(frac1_hi, frac1_lo, 0x0ll, 0x20ll, &frac1_hi, &frac1_lo);
+	
+	lshift128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO, 7,
+	   &tmp_hi, &tmp_lo);
+	and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+	if (lt128(0x0ll, 0x0ll, tmp_hi, tmp_lo)) {
+		++exp1;
+		rshift128(frac1_hi, frac1_lo, 1, &frac1_hi, &frac1_lo);
+	}
+	
+	/* Clear hidden bit and shift */
+	rshift128(frac1_hi, frac1_lo, 6, &frac1_hi, &frac1_lo);
+	not128(FLOAT128_HIDDEN_BIT_MASK_HI, FLOAT128_HIDDEN_BIT_MASK_LO,
+	    &tmp_hi, &tmp_lo);
+	and128(frac1_hi, frac1_lo, tmp_hi, tmp_lo, &tmp_hi, &tmp_lo);
+	result.parts.frac_hi = tmp_hi;
+	result.parts.frac_lo = tmp_lo;
+	
+	result.parts.exp = exp1;
+	
+	return result;
+}
+
+/** @}
+ */
Index: uspace/lib/softfloat/sub.h
===================================================================
--- uspace/lib/softfloat/sub.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softfloat/sub.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2005 Josef Cejka
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softfloat
+ * @{
+ */
+/** @file Substraction functions.
+ */
+
+#ifndef __SUB_H__
+#define __SUB_H__
+
+extern float32 sub_float32(float32, float32);
+extern float64 sub_float64(float64, float64);
+extern float96 sub_float96(float96, float96);
+extern float128 sub_float128(float128, float128);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softrend/Makefile
===================================================================
--- uspace/lib/softrend/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softrend/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,41 @@
+#
+# Copyright (c) 2011 Petr Koupy
+# 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 = ../..
+LIBRARY = libsoftrend
+SLIBRARY = libsoftrend.so.0.0
+LSONAME = libsoftrend.so0
+
+SOURCES = \
+	compose.c \
+	filter.c \
+	pixconv.c \
+	rectangle.c \
+	transform.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/softrend/compose.c
===================================================================
--- uspace/lib/softrend/compose.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softrend/compose.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 softrend
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include "compose.h"
+
+pixel_t compose_clr(pixel_t fg, pixel_t bg)
+{
+	return 0;
+}
+
+pixel_t compose_src(pixel_t fg, pixel_t bg)
+{
+	return fg;
+}
+
+pixel_t compose_dst(pixel_t fg, pixel_t bg)
+{
+	return bg;
+}
+
+pixel_t compose_over(pixel_t fg, pixel_t bg)
+{
+	double mul;
+	double mul_cmp;
+
+	double res_a;
+	double res_r;
+	double res_g;
+	double res_b;
+
+	if (ALPHA(bg) == 255) {
+		res_a = 1;
+		mul = ((double) ALPHA(fg)) / 255.0;
+		mul_cmp = 1 - mul;
+	} else {
+		double fg_a = ((double) ALPHA(fg)) / 255.0;
+		double bg_a = ((double) ALPHA(bg)) / 255.0;
+
+		res_a = 1 - (1 - fg_a) * (1 - bg_a);
+		mul = fg_a / res_a;
+		mul_cmp = 1 - mul;
+	}
+
+	res_r = mul * ((double) RED(fg)) + mul_cmp * ((double) RED(bg));
+	res_g = mul * ((double) GREEN(fg)) + mul_cmp * ((double) GREEN(bg));
+	res_b = mul * ((double) BLUE(fg)) + mul_cmp * ((double) BLUE(bg));
+
+	return PIXEL((unsigned) (res_a * 255),
+	    (unsigned) res_r, (unsigned) res_g, (unsigned) res_b);
+}
+
+pixel_t compose_in(pixel_t fg, pixel_t bg)
+{
+	// TODO
+	return 0;
+}
+
+pixel_t compose_out(pixel_t fg, pixel_t bg)
+{
+	// TODO
+	return 0;
+}
+
+pixel_t compose_atop(pixel_t fg, pixel_t bg)
+{
+	// TODO
+	return 0;
+}
+
+pixel_t compose_xor(pixel_t fg, pixel_t bg)
+{
+	// TODO
+	return 0;
+}
+
+pixel_t compose_add(pixel_t fg, pixel_t bg)
+{
+	// TODO
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/lib/softrend/compose.h
===================================================================
--- uspace/lib/softrend/compose.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softrend/compose.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 softrend
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef SOFTREND_COMPOSE_H_
+#define SOFTREND_COMPOSE_H_
+
+#include <io/pixel.h>
+
+typedef pixel_t (*compose_t)(pixel_t, pixel_t);
+
+extern pixel_t compose_clr(pixel_t, pixel_t);
+extern pixel_t compose_src(pixel_t, pixel_t);
+extern pixel_t compose_dst(pixel_t, pixel_t);
+
+extern pixel_t compose_over(pixel_t, pixel_t);
+extern pixel_t compose_in(pixel_t, pixel_t);
+extern pixel_t compose_out(pixel_t, pixel_t);
+extern pixel_t compose_atop(pixel_t, pixel_t);
+extern pixel_t compose_xor(pixel_t, pixel_t);
+extern pixel_t compose_add(pixel_t, pixel_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softrend/filter.c
===================================================================
--- uspace/lib/softrend/filter.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softrend/filter.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 softrend
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include "filter.h"
+
+pixel_t filter_nearest(pixelmap_t *pixmap, double x, double y, bool tile)
+{
+	long _x = x > 0 ? (long) (x + 0.5) : (long) (x - 0.5);
+	long _y = y > 0 ? (long) (y + 0.5) : (long) (y - 0.5);
+
+	if (tile) {
+		_x %= pixmap->width;
+		_y %= pixmap->height;
+	} else if (_x < 0 || _x >= (long) pixmap->width || _y < 0 || _y >= (long) pixmap->height) {
+		return 0;
+	}
+
+	return pixelmap_get_pixel(pixmap, (sysarg_t) _x, (sysarg_t) _y);
+}
+
+pixel_t filter_bilinear(pixelmap_t *pixmap, double x, double y, bool tile)
+{
+	// TODO
+	return 0;
+}
+
+pixel_t filter_bicubic(pixelmap_t *pixmap, double x, double y, bool tile)
+{
+	// TODO
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/lib/softrend/filter.h
===================================================================
--- uspace/lib/softrend/filter.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softrend/filter.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 softrend
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef SOFTREND_FILTER_H_
+#define SOFTREND_FILTER_H_
+
+#include <bool.h>
+#include <io/pixelmap.h>
+
+typedef pixel_t (*filter_t)(pixelmap_t *, double, double, bool);
+
+extern pixel_t filter_nearest(pixelmap_t *, double, double, bool);
+extern pixel_t filter_bilinear(pixelmap_t *, double, double, bool);
+extern pixel_t filter_bicubic(pixelmap_t *, double, double, bool);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softrend/pixconv.c
===================================================================
--- uspace/lib/softrend/pixconv.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softrend/pixconv.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softrend
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <byteorder.h>
+#include "pixconv.h"
+
+/** Pixel conversion and mask functions
+ *
+ * These functions write an ARGB pixel value to a memory location
+ * in a predefined format. The naming convention corresponds to
+ * the names of the visuals and the format created by these functions.
+ * The functions use the so called network bit order (i.e. big endian)
+ * with respect to their names.
+ */
+
+void pixel2argb_8888(void *dst, pixel_t pix)
+{
+	*((uint32_t *) dst) = host2uint32_t_be(
+	    (ALPHA(pix) << 24) | (RED(pix) << 16) | (GREEN(pix) << 8) | (BLUE(pix)));
+}
+
+void pixel2abgr_8888(void *dst, pixel_t pix)
+{
+	*((uint32_t *) dst) = host2uint32_t_be(
+	    (ALPHA(pix) << 24) | (BLUE(pix) << 16) | (GREEN(pix) << 8) | (RED(pix)));
+}
+
+void pixel2rgba_8888(void *dst, pixel_t pix)
+{
+	*((uint32_t *) dst) = host2uint32_t_be(
+	    (RED(pix) << 24) | (GREEN(pix) << 16) | (BLUE(pix) << 8) | (ALPHA(pix)));
+}
+
+void pixel2bgra_8888(void *dst, pixel_t pix)
+{
+	*((uint32_t *) dst) = host2uint32_t_be(
+	    (BLUE(pix) << 24) | (GREEN(pix) << 16) | (RED(pix) << 8) | (ALPHA(pix)));
+}
+
+void pixel2rgb_0888(void *dst, pixel_t pix)
+{
+	*((uint32_t *) dst) = host2uint32_t_be(
+	    (RED(pix) << 16) | (GREEN(pix) << 8) | (BLUE(pix)));
+}
+
+void pixel2bgr_0888(void *dst, pixel_t pix)
+{
+	*((uint32_t *) dst) = host2uint32_t_be(
+	    (BLUE(pix) << 16) | (GREEN(pix) << 8) | (RED(pix)));
+}
+
+void pixel2rgb_8880(void *dst, pixel_t pix)
+{
+	*((uint32_t *) dst) = host2uint32_t_be(
+	    (RED(pix) << 24) | (GREEN(pix) << 16) | (BLUE(pix) << 8));
+}
+
+void pixel2bgr_8880(void *dst, pixel_t pix)
+{
+	*((uint32_t *) dst) = host2uint32_t_be(
+	    (BLUE(pix) << 24) | (GREEN(pix) << 16) | (RED(pix) << 8));
+}
+
+void pixel2rgb_888(void *dst, pixel_t pix)
+{
+	((uint8_t *) dst)[0] = RED(pix);
+	((uint8_t *) dst)[1] = GREEN(pix);
+	((uint8_t *) dst)[2] = BLUE(pix);
+}
+
+void pixel2bgr_888(void *dst, pixel_t pix)
+{
+	((uint8_t *) dst)[0] = BLUE(pix);
+	((uint8_t *) dst)[1] = GREEN(pix);
+	((uint8_t *) dst)[2] = RED(pix);
+}
+
+void pixel2rgb_555_be(void *dst, pixel_t pix)
+{
+	*((uint16_t *) dst) = host2uint16_t_be(
+	    (NARROW(RED(pix), 5) << 10) | (NARROW(GREEN(pix), 5) << 5) | (NARROW(BLUE(pix), 5)));
+}
+
+void pixel2rgb_555_le(void *dst, pixel_t pix)
+{
+	*((uint16_t *) dst) = host2uint16_t_le(
+	    (NARROW(RED(pix), 5) << 10) | (NARROW(GREEN(pix), 5) << 5) | (NARROW(BLUE(pix), 5)));
+}
+
+void pixel2rgb_565_be(void *dst, pixel_t pix)
+{
+	*((uint16_t *) dst) = host2uint16_t_be(
+	    (NARROW(RED(pix), 5) << 11) | (NARROW(GREEN(pix), 6) << 5) | (NARROW(BLUE(pix), 5)));
+}
+
+void pixel2rgb_565_le(void *dst, pixel_t pix)
+{
+	*((uint16_t *) dst) = host2uint16_t_le(
+	    (NARROW(RED(pix), 5) << 11) | (NARROW(GREEN(pix), 6) << 5) | (NARROW(BLUE(pix), 5)));
+}
+
+void pixel2bgr_323(void *dst, pixel_t pix)
+{
+	*((uint8_t *) dst) =
+	    ~((NARROW(RED(pix), 3) << 5) | (NARROW(GREEN(pix), 2) << 3) | NARROW(BLUE(pix), 3));
+}
+
+void pixel2gray_8(void *dst, pixel_t pix)
+{
+	uint32_t red = RED(pix) * 5034375;
+	uint32_t green = GREEN(pix) * 9886846;
+	uint32_t blue = BLUE(pix) * 1920103;
+
+	*((uint8_t *) dst) = (red + green + blue) >> 24;
+}
+
+void visual_mask_8888(void *dst, bool mask)
+{
+	pixel2abgr_8888(dst, mask ? 0xffffffff : 0);
+}
+
+void visual_mask_0888(void *dst, bool mask)
+{
+	pixel2bgr_0888(dst, mask ? 0xffffffff : 0);
+}
+
+void visual_mask_8880(void *dst, bool mask)
+{
+	pixel2bgr_8880(dst, mask ? 0xffffffff : 0);
+}
+
+void visual_mask_888(void *dst, bool mask)
+{
+	pixel2bgr_888(dst, mask ? 0xffffffff : 0);
+}
+
+void visual_mask_555(void *dst, bool mask)
+{
+	pixel2rgb_555_be(dst, mask ? 0xffffffff : 0);
+}
+
+void visual_mask_565(void *dst, bool mask)
+{
+	pixel2rgb_565_be(dst, mask ? 0xffffffff : 0);
+}
+
+void visual_mask_323(void *dst, bool mask)
+{
+	pixel2bgr_323(dst, mask ? 0x0 : ~0x0);
+}
+
+void visual_mask_8(void *dst, bool mask)
+{
+	pixel2gray_8(dst, mask ? 0xffffffff : 0);
+}
+
+pixel_t argb_8888_2pixel(void *src)
+{
+	return (uint32_t_be2host(*((uint32_t *) src)));
+}
+
+pixel_t abgr_8888_2pixel(void *src)
+{
+	uint32_t val = uint32_t_be2host(*((uint32_t *) src));
+	return ((val & 0xff000000) | ((val & 0xff0000) >> 16) | (val & 0xff00) | ((val & 0xff) << 16));
+}
+
+pixel_t rgba_8888_2pixel(void *src)
+{
+	uint32_t val = uint32_t_be2host(*((uint32_t *) src));
+	return ((val << 24) | (val >> 8));
+}
+
+pixel_t bgra_8888_2pixel(void *src)
+{
+	uint32_t val = uint32_t_be2host(*((uint32_t *) src));
+	return ((val >> 24) | ((val & 0xff0000) >> 8) | ((val & 0xff00) << 8) | (val << 24));
+}
+
+pixel_t rgb_0888_2pixel(void *src)
+{
+	return (0xff000000 | (uint32_t_be2host(*((uint32_t *) src)) & 0xffffff));
+}
+
+pixel_t bgr_0888_2pixel(void *src)
+{
+	uint32_t val = uint32_t_be2host(*((uint32_t *) src));
+	return (0xff000000 | ((val & 0xff0000) >> 16) | (val & 0xff00) | ((val & 0xff) << 16));
+}
+
+pixel_t rgb_8880_2pixel(void *src)
+{
+	return (0xff000000 | (uint32_t_be2host(*((uint32_t *) src)) >> 8));
+}
+
+pixel_t bgr_8880_2pixel(void *src)
+{
+	uint32_t val = uint32_t_be2host(*((uint32_t *) src));
+	return (0xff000000 | (val >> 24) | ((val & 0xff0000) >> 8) | ((val & 0xff00) << 8));
+}
+
+pixel_t rgb_888_2pixel(void *src)
+{
+	uint8_t red = ((uint8_t *) src)[0];
+	uint8_t green = ((uint8_t *) src)[1];
+	uint8_t blue = ((uint8_t *) src)[2];
+
+	return (0xff000000 | (red << 16) | (green << 8) | (blue));
+}
+
+pixel_t bgr_888_2pixel(void *src)
+{
+	uint8_t blue = ((uint8_t *) src)[0];
+	uint8_t green = ((uint8_t *) src)[1];
+	uint8_t red = ((uint8_t *) src)[2];
+
+	return (0xff000000 | (red << 16) | (green << 8) | (blue));
+}
+
+pixel_t rgb_555_be_2pixel(void *src)
+{
+	uint16_t val = uint16_t_be2host(*((uint16_t *) src));
+	return (0xff000000 | ((val & 0x7c00) << 9) | ((val & 0x3e0) << 6) | ((val & 0x1f) << 3));
+}
+
+pixel_t rgb_555_le_2pixel(void *src)
+{
+	uint16_t val = uint16_t_le2host(*((uint16_t *) src));
+	return (0xff000000 | ((val & 0x7c00) << 9) | ((val & 0x3e0) << 6) | ((val & 0x1f) << 3));
+}
+
+pixel_t rgb_565_be_2pixel(void *src)
+{
+	uint16_t val = uint16_t_be2host(*((uint16_t *) src));
+	return (0xff000000 | ((val & 0xf800) << 8) | ((val & 0x7e0) << 5) | ((val & 0x1f) << 3));
+}
+
+pixel_t rgb_565_le_2pixel(void *src)
+{
+	uint16_t val = uint16_t_le2host(*((uint16_t *) src));
+	return (0xff000000 | ((val & 0xf800) << 8) | ((val & 0x7e0) << 5) | ((val & 0x1f) << 3));
+}
+
+pixel_t bgr_323_2pixel(void *src)
+{
+	uint8_t val = ~(*((uint8_t *) src));
+	return (0xff000000 | ((val & 0xe0) << 16) | ((val & 0x18) << 11) | ((val & 0x7) << 5));
+}
+
+pixel_t gray_8_2pixel(void *src)
+{
+	uint8_t val = *((uint8_t *) src);
+	return (0xff000000 | (val << 16) | (val << 8) | (val));
+}
+
+/** @}
+ */
Index: uspace/lib/softrend/pixconv.h
===================================================================
--- uspace/lib/softrend/pixconv.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softrend/pixconv.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softrend
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef SOFTREND_PIXCONV_H_
+#define SOFTREND_PIXCONV_H_
+
+#include <bool.h>
+#include <io/pixel.h>
+
+/** Function to render a pixel. */
+typedef void (*pixel2visual_t)(void *, pixel_t);
+
+/** Function to render a bit mask. */
+typedef void (*visual_mask_t)(void *, bool);
+
+/** Function to retrieve a pixel. */
+typedef pixel_t (*visual2pixel_t)(void *);
+
+extern void pixel2argb_8888(void *, pixel_t);
+extern void pixel2abgr_8888(void *, pixel_t);
+extern void pixel2rgba_8888(void *, pixel_t);
+extern void pixel2bgra_8888(void *, pixel_t);
+extern void pixel2rgb_0888(void *, pixel_t);
+extern void pixel2bgr_0888(void *, pixel_t);
+extern void pixel2rgb_8880(void *, pixel_t);
+extern void pixel2bgr_8880(void *, pixel_t);
+extern void pixel2rgb_888(void *, pixel_t);
+extern void pixel2bgr_888(void *, pixel_t);
+extern void pixel2rgb_555_be(void *, pixel_t);
+extern void pixel2rgb_555_le(void *, pixel_t);
+extern void pixel2rgb_565_be(void *, pixel_t);
+extern void pixel2rgb_565_le(void *, pixel_t);
+extern void pixel2bgr_323(void *, pixel_t);
+extern void pixel2gray_8(void *, pixel_t);
+
+extern void visual_mask_8888(void *, bool);
+extern void visual_mask_0888(void *, bool);
+extern void visual_mask_8880(void *, bool);
+extern void visual_mask_888(void *, bool);
+extern void visual_mask_555(void *, bool);
+extern void visual_mask_565(void *, bool);
+extern void visual_mask_323(void *, bool);
+extern void visual_mask_8(void *, bool);
+
+extern pixel_t argb_8888_2pixel(void *);
+extern pixel_t abgr_8888_2pixel(void *);
+extern pixel_t rgba_8888_2pixel(void *);
+extern pixel_t bgra_8888_2pixel(void *);
+extern pixel_t rgb_0888_2pixel(void *);
+extern pixel_t bgr_0888_2pixel(void *);
+extern pixel_t rgb_8880_2pixel(void *);
+extern pixel_t bgr_8880_2pixel(void *);
+extern pixel_t rgb_888_2pixel(void *);
+extern pixel_t bgr_888_2pixel(void *);
+extern pixel_t rgb_555_be_2pixel(void *);
+extern pixel_t rgb_555_le_2pixel(void *);
+extern pixel_t rgb_565_be_2pixel(void *);
+extern pixel_t rgb_565_le_2pixel(void *);
+extern pixel_t bgr_323_2pixel(void *);
+extern pixel_t gray_8_2pixel(void *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softrend/rectangle.c
===================================================================
--- uspace/lib/softrend/rectangle.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softrend/rectangle.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 softrend
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include "rectangle.h"
+
+bool rectangle_intersect(
+    sysarg_t x1, sysarg_t y1, sysarg_t w1, sysarg_t h1,
+    sysarg_t x2, sysarg_t y2, sysarg_t w2, sysarg_t h2,
+    sysarg_t *x_out, sysarg_t *y_out, sysarg_t *w_out, sysarg_t *h_out)
+{
+	sysarg_t l, r, t, b;
+
+	l = x1 < x2 ? x2 : x1;
+	t = y1 < y2 ? y2 : y1;
+	r = x1 + w1 < x2 + w2 ? x1 + w1 : x2 + w2;
+	b = y1 + h1 < y2 + h2 ? y1 + h1 : y2 + h2;
+
+	if (l < r && t < b) {
+		(*x_out) = l;
+		(*y_out) = t;
+		(*w_out) = r - l;
+		(*h_out) = b - t;
+		return true;
+	} else {
+		(*x_out) = 0;
+		(*y_out) = 0;
+		(*w_out) = 0;
+		(*h_out) = 0;
+		return false;
+	}
+}
+
+void rectangle_union(
+    sysarg_t x1, sysarg_t y1, sysarg_t w1, sysarg_t h1,
+    sysarg_t x2, sysarg_t y2, sysarg_t w2, sysarg_t h2,
+    sysarg_t *x_out, sysarg_t *y_out, sysarg_t *w_out, sysarg_t *h_out)
+{
+	sysarg_t l, r, t, b;
+
+	l = x1 > x2 ? x2 : x1;
+	t = y1 > y2 ? y2 : y1;
+	r = x1 + w1 > x2 + w2 ? x1 + w1 : x2 + w2;
+	b = y1 + h1 > y2 + h2 ? y1 + h1 : y2 + h2;
+
+	(*x_out) = l;
+	(*y_out) = t;
+	(*w_out) = r - l;
+	(*h_out) = b - t;
+}
+
+/** @}
+ */
Index: uspace/lib/softrend/rectangle.h
===================================================================
--- uspace/lib/softrend/rectangle.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softrend/rectangle.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 softrend
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef SOFTREND_RECTANGLE_H_
+#define SOFTREND_RECTANGLE_H_
+
+#include <sys/types.h>
+#include <bool.h>
+
+extern bool rectangle_intersect(
+    sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *);
+extern void rectangle_union(
+    sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softrend/transform.c
===================================================================
--- uspace/lib/softrend/transform.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softrend/transform.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softrend
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include "transform.h"
+
+void transform_multiply(transform_t *res, const transform_t *left, const transform_t *right)
+{
+	for (int i = 0; i < 3; ++i) {
+		for (int j = 0; j < 3; ++j) {
+			double comb = 0;
+			for (int k = 0; k < 3; ++k) {
+				comb += left->m[i][k] * right->m[k][j];
+			}
+			res->m[i][j] = comb;
+		}
+	}
+}
+
+void transform_invert(transform_t *t)
+{
+	double a = t->m[1][1] * t->m[2][2] - t->m[1][2] * t->m[2][1];
+	double b = t->m[1][2] * t->m[2][0] - t->m[2][2] * t->m[1][0];
+	double c = t->m[1][0] * t->m[2][1] - t->m[1][1] * t->m[2][0];
+	double d = t->m[0][2] * t->m[2][1] - t->m[0][1] * t->m[2][2];
+	double e = t->m[0][0] * t->m[2][2] - t->m[0][2] * t->m[2][0];
+	double f = t->m[2][0] * t->m[0][1] - t->m[0][0] * t->m[2][1];
+	double g = t->m[0][1] * t->m[1][2] - t->m[0][2] * t->m[1][1];
+	double h = t->m[0][2] * t->m[1][0] - t->m[0][0] * t->m[1][2];
+	double k = t->m[0][0] * t->m[1][1] - t->m[0][1] * t->m[1][0];
+
+	double det = t->m[0][0] * a + t->m[0][1] * b + t->m[0][2] * c;
+	det = 1 / det;
+
+	t->m[0][0] = a * det;   t->m[0][1] = d * det;   t->m[0][2] = g * det;
+	t->m[1][0] = b * det;   t->m[1][1] = e * det;   t->m[1][2] = h * det;
+	t->m[2][0] = c * det;   t->m[2][1] = f * det;   t->m[2][2] = k * det;
+}
+
+void transform_identity(transform_t *t)
+{
+	t->m[0][0] = 1;   t->m[0][1] = 0;   t->m[0][2] = 0;
+	t->m[1][0] = 0;   t->m[1][1] = 1;   t->m[1][2] = 0;
+	t->m[2][0] = 0;   t->m[2][1] = 0;   t->m[2][2] = 1;
+}
+
+void transform_translate(transform_t *t, double dx, double dy)
+{
+	transform_t a;
+	a.m[0][0] = 1;   a.m[0][1] = 0;   a.m[0][2] = dx;
+	a.m[1][0] = 0;   a.m[1][1] = 1;   a.m[1][2] = dy;
+	a.m[2][0] = 0;   a.m[2][1] = 0;   a.m[2][2] = 1;
+
+	transform_t r;
+	transform_multiply(&r, &a, t);
+	*t = r;
+}
+
+void transform_scale(transform_t *t, double qx, double qy)
+{
+	transform_t a;
+	a.m[0][0] = qx;  a.m[0][1] = 0;   a.m[0][2] = 0;
+	a.m[1][0] = 0;   a.m[1][1] = qy;  a.m[1][2] = 0;
+	a.m[2][0] = 0;   a.m[2][1] = 0;   a.m[2][2] = 1;
+
+	transform_t r;
+	transform_multiply(&r, &a, t);
+	*t = r;
+}
+
+void transform_rotate(transform_t *t, double rad)
+{
+	double s, c;
+
+	// FIXME: temporary solution until there are trigonometric functions in libc
+
+	while (rad < 0) {
+		rad += (2 * PI);
+	}
+	
+	while (rad > (2 * PI)) {
+		rad -= (2 * PI);
+	}
+
+	if (rad >= 0 && rad < (PI / 4)) {
+		s = 0; c = 1;
+	} else if (rad >= (PI / 4) && rad < (3 * PI / 4)) {
+		s = 1; c = 0;
+	} else if (rad >= (3 * PI / 4) && rad < (5 * PI / 4)) {
+		s = 0; c = -1;
+	} else if (rad >= (5 * PI / 4) && rad < (7 * PI / 4)) {
+		s = -1; c = 0;
+	} else {
+		s = 0; c = 1;
+	}
+
+	transform_t a;
+	a.m[0][0] = c;   a.m[0][1] = -s;  a.m[0][2] = 0;
+	a.m[1][0] = s;   a.m[1][1] = c;   a.m[1][2] = 0;
+	a.m[2][0] = 0;   a.m[2][1] = 0;   a.m[2][2] = 1;
+
+	transform_t r;
+	transform_multiply(&r, &a, t);
+	*t = r;
+}
+
+void transform_apply_linear(const transform_t *t, double *x, double *y)
+{
+	double x_ = *x;
+	double y_ = *y;
+	*x = x_ * t->m[0][0] + y_ * t->m[0][1];
+	*y = x_ * t->m[1][0] + y_ * t->m[1][1];
+}
+
+void transform_apply_affine(const transform_t *t, double *x, double *y)
+{
+	double x_ = *x;
+	double y_ = *y;
+	*x = x_ * t->m[0][0] + y_ * t->m[0][1] + t->m[0][2];
+	*y = x_ * t->m[1][0] + y_ * t->m[1][1] + t->m[1][2];
+}
+
+/** @}
+ */
Index: uspace/lib/softrend/transform.h
===================================================================
--- uspace/lib/softrend/transform.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/lib/softrend/transform.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011 Petr Koupy
+ * 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 softrend
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef SOFTREND_TRANSFORM_H_
+#define SOFTREND_TRANSFORM_H_
+
+#ifndef PI
+#define PI 3.141592653589793
+#endif
+
+typedef struct {
+	double m[3][3];
+} transform_t;
+
+extern void transform_multiply(transform_t *, const transform_t *, const transform_t *);
+extern void transform_invert(transform_t *);
+
+extern void transform_identity(transform_t *);
+extern void transform_translate(transform_t *, double, double);
+extern void transform_scale(transform_t *, double, double);
+extern void transform_rotate(transform_t *, double);
+
+extern void transform_apply_linear(const transform_t *, double *, double *);
+extern void transform_apply_affine(const transform_t *, double *, double *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/usb/include/usb/debug.h
===================================================================
--- uspace/lib/usb/include/usb/debug.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usb/include/usb/debug.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,4 +38,5 @@
 #include <inttypes.h>
 #include <usb/usb.h>
+#include <io/log.h>
 #include <assert.h>
 
@@ -43,52 +44,13 @@
     const uint8_t *, size_t);
 
-/** Logging level. */
-typedef enum {
-	/** Fatal, unrecoverable, error.
-	 * Such error prevents the driver from working at all.
-	 */
-	USB_LOG_LEVEL_FATAL,
+#define USB_LOG_LEVEL_FATAL LVL_FATAL
+#define USB_LOG_LEVEL_ERROR LVL_ERROR
+#define USB_LOG_LEVEL_WARNING LVL_WARN
+#define USB_LOG_LEVEL_INFO LVL_NOTE
+#define USB_LOG_LEVEL_DEBUG LVL_DEBUG
+#define USB_LOG_LEVEL_DEBUG2 LVL_DEBUG2
 
-	/** Serious but recoverable error
-	 * Shall be used for errors fatal for single device but not for
-	 * driver itself.
-	 */
-	USB_LOG_LEVEL_ERROR,
-
-	/** Warning.
-	 * Problems from which the driver is able to recover gracefully.
-	 */
-	USB_LOG_LEVEL_WARNING,
-
-	/** Information message.
-	 * This should be the last level that is printed by default to
-	 * the screen.
-	 * Typical usage is to inform that new device was found and what
-	 * are its capabilities.
-	 * Do not use for repetitive actions (such as device polling).
-	 */
-	USB_LOG_LEVEL_INFO,
-
-	/** Debugging message. */
-	USB_LOG_LEVEL_DEBUG,
-
-	/** More detailed debugging message. */
-	USB_LOG_LEVEL_DEBUG2,
-
-	/** Terminating constant for logging levels. */
-	USB_LOG_LEVEL_MAX
-} usb_log_level_t;
-
-/** Default log level. */
-#ifdef CONFIG_USB_VERBOSE
-	#define USB_LOG_LEVEL_DEFAULT USB_LOG_LEVEL_DEBUG
-#else
-	#define USB_LOG_LEVEL_DEFAULT USB_LOG_LEVEL_INFO
-#endif
-
-void usb_log_enable(usb_log_level_t, const char *);
-
-void usb_log_printf(usb_log_level_t, const char *, ...)
-	PRINTF_ATTRIBUTE(2, 3);
+#define usb_log_printf(level, format, ...) \
+	log_msg(LOG_DEFAULT, level, format, ##__VA_ARGS__)
 
 /** Log fatal error. */
Index: uspace/lib/usb/include/usb/hc.h
===================================================================
--- uspace/lib/usb/include/usb/hc.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usb/include/usb/hc.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -77,6 +77,5 @@
 }
 
-int usb_hc_connection_initialize_from_device(usb_hc_connection_t *,
-    const ddf_dev_t *);
+int usb_hc_connection_initialize_from_device(usb_hc_connection_t *, ddf_dev_t *);
 
 void usb_hc_connection_deinitialize(usb_hc_connection_t *);
Index: uspace/lib/usb/src/ddfiface.c
===================================================================
--- uspace/lib/usb/src/ddfiface.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usb/src/ddfiface.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -68,5 +68,5 @@
 {
 	assert(fun);
-	return usb_get_hc_by_handle(fun->handle, handle);
+	return usb_get_hc_by_handle(ddf_fun_get_handle(fun), handle);
 }
 
@@ -82,5 +82,5 @@
 
 	if (handle != NULL) {
-		*handle = fun->handle;
+		*handle = ddf_fun_get_handle(fun);
 	}
 
@@ -99,5 +99,5 @@
 {
 	assert(fun);
-	return usb_get_address_by_handle(fun->handle, address);
+	return usb_get_address_by_handle(ddf_fun_get_handle(fun), address);
 }
 
@@ -116,7 +116,5 @@
     usb_address_t *address)
 {
-	assert(fun);
-	assert(fun->driver_data);
-	const usb_hub_attached_device_t *device = fun->driver_data;
+	const usb_hub_attached_device_t *device = ddf_fun_data_get(fun);
 	assert(device->fun == fun);
 	if (address)
Index: uspace/lib/usb/src/debug.c
===================================================================
--- uspace/lib/usb/src/debug.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usb/src/debug.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,115 +40,4 @@
 #include <ddf/log.h>
 #include <usb/debug.h>
-
-/** Level of logging messages. */
-static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING;
-
-/** Prefix for logging messages. */
-static const char *log_prefix = "usb";
-
-/** Serialization mutex for logging functions. */
-static FIBRIL_MUTEX_INITIALIZE(log_serializer);
-
-/** File where to store the log. */
-static FILE *log_stream = NULL;
-
-
-/** Enable logging.
- *
- * @param level Maximal enabled level (including this one).
- * @param message_prefix Prefix for each printed message.
- */
-void usb_log_enable(usb_log_level_t level, const char *message_prefix)
-{
-	log_prefix = message_prefix;
-	log_level = level;
-	if (log_stream == NULL) {
-		char *fname;
-		int rc = asprintf(&fname, "/log/%s", message_prefix);
-		if (rc > 0) {
-			log_stream = fopen(fname, "w");
-			if (log_stream != NULL)
-				setvbuf(log_stream, NULL, _IOFBF, BUFSIZ);
-			
-			free(fname);
-		}
-	}
-}
-
-/** Get log level name prefix.
- *
- * @param level Log level.
- * @return String prefix for the message.
- */
-static const char *log_level_name(usb_log_level_t level)
-{
-	switch (level) {
-		case USB_LOG_LEVEL_FATAL:
-			return " FATAL";
-		case USB_LOG_LEVEL_ERROR:
-			return " ERROR";
-		case USB_LOG_LEVEL_WARNING:
-			return " WARN";
-		case USB_LOG_LEVEL_INFO:
-			return " info";
-		default:
-			return "";
-	}
-}
-
-/** Print logging message.
- *
- * @param level Verbosity level of the message.
- * @param format Formatting directive.
- */
-void usb_log_printf(usb_log_level_t level, const char *format, ...)
-{
-	FILE *screen_stream = NULL;
-	switch (level) {
-		case USB_LOG_LEVEL_FATAL:
-		case USB_LOG_LEVEL_ERROR:
-			screen_stream = stderr;
-			break;
-		default:
-			screen_stream = stdout;
-			break;
-	}
-	assert(screen_stream != NULL);
-
-	va_list args;
-
-	/*
-	 * Serialize access to log files.
-	 * Print to screen only messages with higher level than the one
-	 * specified during logging initialization.
-	 * Print also to file, to it print one more (lower) level as well.
-	 */
-	fibril_mutex_lock(&log_serializer);
-
-	const char *level_name = log_level_name(level);
-
-	if ((log_stream != NULL) && (level <= log_level + 1)) {
-		va_start(args, format);
-
-		fprintf(log_stream, "[%s]%s: ", log_prefix, level_name);
-		vfprintf(log_stream, format, args);
-		fflush(log_stream);
-
-		va_end(args);
-	}
-
-	if (level <= log_level) {
-		va_start(args, format);
-
-		fprintf(screen_stream, "[%s]%s: ", log_prefix, level_name);
-		vfprintf(screen_stream, format, args);
-		fflush(screen_stream);
-
-		va_end(args);
-	}
-
-	fibril_mutex_unlock(&log_serializer);
-}
-
 
 #define REMAINDER_STR_FMT " (%zu)..."
Index: uspace/lib/usb/src/hc.c
===================================================================
--- uspace/lib/usb/src/hc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usb/src/hc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -115,14 +115,11 @@
  */
 int usb_hc_connection_initialize_from_device(usb_hc_connection_t *connection,
-    const ddf_dev_t *device)
-{
-	assert(connection);
-
-	if (device == NULL) {
+    ddf_dev_t *device)
+{
+	if (device == NULL)
 		return EBADMEM;
-	}
 
 	devman_handle_t hc_handle;
-	const int rc = usb_get_hc_by_handle(device->handle, &hc_handle);
+	const int rc = usb_get_hc_by_handle(ddf_dev_get_handle(device), &hc_handle);
 	if (rc == EOK) {
 		usb_hc_connection_initialize(connection, hc_handle);
Index: uspace/lib/usbdev/include/usb/dev/usb_device_connection.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/usb_device_connection.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbdev/include/usb/dev/usb_device_connection.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -72,5 +72,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Register endpoint on the device.
  * @param instance device connection structure to use.
@@ -91,5 +91,5 @@
 	    instance->address, ep, type, direction, packet_size, interval);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Unregister endpoint on the device.
  * @param instance device connection structure
@@ -105,5 +105,5 @@
 	    instance->address, ep, dir);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Get data from the device.
  * @param[in] instance device connection structure to use.
@@ -122,5 +122,5 @@
 	    instance->address, ep, setup, data, size, rsize);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Send data to the device.
  * @param instance device connection structure to use.
@@ -138,5 +138,5 @@
 	    instance->address, ep, setup, data, size);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Wrapper for read calls with no setup stage.
  * @param[in] instance device connection structure.
@@ -153,5 +153,5 @@
 	return usb_device_control_read(instance, ep, 0, data, size, real_size);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Wrapper for write calls with no setup stage.
  * @param instance device connection structure.
Index: uspace/lib/usbdev/src/devdrv.c
===================================================================
--- uspace/lib/usbdev/src/devdrv.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbdev/src/devdrv.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -74,5 +74,5 @@
 	return ddf_driver_main(&generic_driver);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Count number of pipes the driver expects.
  *
@@ -87,5 +87,5 @@
 	return count;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback when a new device is supposed to be controlled by this driver.
  *
@@ -105,5 +105,5 @@
 	if (dev == NULL) {
 		usb_log_error("USB device `%s' structure allocation failed.\n",
-		    gen_dev->name);
+		    ddf_dev_get_name(gen_dev));
 		return ENOMEM;
 	}
@@ -114,5 +114,5 @@
 	if (rc != EOK) {
 		usb_log_error("USB device `%s' init failed (%s): %s.\n",
-		    gen_dev->name, err_msg, str_error(rc));
+		    ddf_dev_get_name(gen_dev), err_msg, str_error(rc));
 		return rc;
 	}
@@ -124,5 +124,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback when a device is supposed to be removed from the system.
  *
@@ -139,5 +139,5 @@
 		return ENOTSUP;
 	/* Just tell the driver to stop whatever it is doing */
-	usb_device_t *usb_dev = gen_dev->driver_data;
+	usb_device_t *usb_dev = ddf_dev_data_get(gen_dev);
 	const int ret = driver->ops->device_rem(usb_dev);
 	if (ret != EOK)
@@ -146,5 +146,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Callback when a device was removed from the system.
  *
@@ -160,5 +160,5 @@
 	if (driver->ops->device_gone == NULL)
 		return ENOTSUP;
-	usb_device_t *usb_dev = gen_dev->driver_data;
+	usb_device_t *usb_dev = ddf_dev_data_get(gen_dev);
 	const int ret = driver->ops->device_gone(usb_dev);
 	if (ret == EOK)
@@ -167,5 +167,5 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Destroy existing pipes of a USB device.
  *
@@ -178,5 +178,5 @@
 	dev->pipes_count = 0;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Change interface setting of a device.
  * This function selects new alternate setting of an interface by issuing
@@ -415,5 +415,5 @@
 	usb_address_t address;
 
-	int rc = usb_get_info_by_handle(ddf_dev->handle,
+	int rc = usb_get_info_by_handle(ddf_dev_get_handle(ddf_dev),
 	    &hc_handle, &address, &usb_dev->interface_no);
 	if (rc != EOK) {
Index: uspace/lib/usbdev/src/devpoll.c
===================================================================
--- uspace/lib/usbdev/src/devpoll.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbdev/src/devpoll.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -80,5 +80,5 @@
 		usb_log_debug("Poll%p: started polling of `%s' - " \
 		    "interface %d (%s,%d,%d), %zuB/%zu.\n",
-		    data, data->dev->ddf_dev->name,
+		    data, ddf_dev_get_name(data->dev->ddf_dev),
 		    (int) mapping->interface->interface_number,
 		    usb_str_class(mapping->interface->interface_class),
@@ -159,8 +159,10 @@
 		if (failed) {
 			usb_log_error("Polling of device `%s' terminated: "
-			    "recurring failures.\n", data->dev->ddf_dev->name);
+			    "recurring failures.\n", ddf_dev_get_name(
+			    data->dev->ddf_dev));
 		} else {
 			usb_log_debug("Polling of device `%s' terminated: "
-			    "driver request.\n", data->dev->ddf_dev->name);
+			    "driver request.\n", ddf_dev_get_name(
+			    data->dev->ddf_dev));
 		}
 	}
Index: uspace/lib/usbdev/src/hub.c
===================================================================
--- uspace/lib/usbdev/src/hub.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbdev/src/hub.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -63,5 +63,5 @@
 		return EBADMEM;
 	return usb_hc_bind_address(connection,
-	    attached_device->address, attached_device->fun->handle);
+	    attached_device->address, ddf_fun_get_handle(attached_device->fun));
 }
 
@@ -287,7 +287,4 @@
 	rc = usb_hub_register_device(hc_conn, &new_device);
 	if (rc != EOK) {
-		/* We know nothing about that data. */
-		if (new_dev_data)
-			child_fun->driver_data = NULL;
 		/* The child function is already created. */
 		ddf_fun_destroy(child_fun);
Index: uspace/lib/usbdev/src/pipes.c
===================================================================
--- uspace/lib/usbdev/src/pipes.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbdev/src/pipes.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -54,5 +54,5 @@
 	return usb_hc_connection_open(pipe->wire->hc_connection);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Terminate a long transfer on a pipe.
  * @param pipe Pipe where to end the long transfer.
@@ -67,5 +67,5 @@
 	return usb_hc_connection_close(pipe->wire->hc_connection);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Try to clear endpoint halt of default control pipe.
  *
@@ -85,5 +85,5 @@
 	pipe->auto_reset_halt = true;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Request a control read transfer on an endpoint pipe.
  *
@@ -135,5 +135,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Request a control write transfer on an endpoint pipe.
  *
@@ -182,5 +182,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Request a read (in) transfer on an endpoint pipe.
  *
@@ -227,5 +227,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Request a write (out) transfer on an endpoint pipe.
  *
@@ -259,5 +259,5 @@
 	    pipe->endpoint_no, buffer, size);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize USB endpoint pipe.
  *
@@ -287,5 +287,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize USB endpoint pipe as the default zero control pipe.
  *
@@ -307,5 +307,5 @@
 	return rc;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Register endpoint with the host controller.
  *
@@ -323,5 +323,5 @@
 	   pipe->direction, pipe->max_packet_size, interval);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Revert endpoint registration with the host controller.
  *
Index: uspace/lib/usbdev/src/pipesinit.c
===================================================================
--- uspace/lib/usbdev/src/pipesinit.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbdev/src/pipesinit.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -154,5 +154,5 @@
     usb_endpoint_mapping_t *mapping, size_t mapping_count,
     usb_standard_interface_descriptor_t *interface,
-    usb_standard_endpoint_descriptor_t *endpoint,
+    usb_standard_endpoint_descriptor_t *endpoint_desc,
     usb_device_connection_t *wire)
 {
@@ -163,13 +163,13 @@
 
 	/* Actual endpoint number is in bits 0..3 */
-	const usb_endpoint_t ep_no = endpoint->endpoint_address & 0x0F;
+	const usb_endpoint_t ep_no = endpoint_desc->endpoint_address & 0x0F;
 
 	const usb_endpoint_description_t description = {
 		/* Endpoint direction is set by bit 7 */
-		.direction = (endpoint->endpoint_address & 128)
+		.direction = (endpoint_desc->endpoint_address & 128)
 		    ? USB_DIRECTION_IN : USB_DIRECTION_OUT,
 		/* Transfer type is in bits 0..2 and
 		 * the enum values corresponds 1:1 */
-		.transfer_type = endpoint->attributes & 3,
+		.transfer_type = endpoint_desc->attributes & 3,
 
 		/* Get interface characteristics. */
@@ -194,5 +194,6 @@
 
 	int rc = usb_pipe_initialize(&ep_mapping->pipe, wire,
-	    ep_no, description.transfer_type, endpoint->max_packet_size,
+	    ep_no, description.transfer_type,
+	    uint16_usb2host(endpoint_desc->max_packet_size),
 	    description.direction);
 	if (rc != EOK) {
@@ -201,5 +202,5 @@
 
 	ep_mapping->present = true;
-	ep_mapping->descriptor = endpoint;
+	ep_mapping->descriptor = endpoint_desc;
 	ep_mapping->interface = interface;
 
Index: uspace/lib/usbdev/src/recognise.c
===================================================================
--- uspace/lib/usbdev/src/recognise.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbdev/src/recognise.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,4 +33,7 @@
  * Functions for recognition of attached devices.
  */
+
+/** XXX Fix this */
+#define _DDF_DATA_IMPLANT
 
 #include <sys/types.h>
@@ -352,9 +355,10 @@
 	
 	if (dev_ops != NULL)
-		child->ops = dev_ops;
+		ddf_fun_set_ops(child, dev_ops);
 	else
-		child->ops = &child_ops;
-	
-	child->driver_data = dev_data;
+		ddf_fun_set_ops(child, &child_ops);
+	
+	ddf_fun_data_implant(child, dev_data);
+	
 	/*
 	 * Store the attached device in fun
@@ -373,7 +377,20 @@
 	}
 	
-	rc = usb_device_create_match_ids(ctrl_pipe, &child->match_ids);
+	match_id_list_t match_ids;
+	init_match_ids(&match_ids);
+	rc = usb_device_create_match_ids(ctrl_pipe, &match_ids);
 	if (rc != EOK)
 		goto failure;
+	
+	list_foreach(match_ids.ids, id_link) {
+		match_id_t *match_id = list_get_instance(id_link, match_id_t, link);
+		rc = ddf_fun_add_match_id(child, match_id->id, match_id->score);
+		if (rc != EOK) {
+			clean_match_ids(&match_ids);
+			goto failure;
+		}
+	}
+	
+	clean_match_ids(&match_ids);
 	
 	rc = ddf_fun_bind(child);
@@ -386,8 +403,4 @@
 failure:
 	if (child != NULL) {
-		/* We know nothing about the data if it came from outside. */
-		if (dev_data)
-			child->driver_data = NULL;
-		
 		/* This takes care of match_id deallocation as well. */
 		ddf_fun_destroy(child);
Index: uspace/lib/usbdev/src/request.c
===================================================================
--- uspace/lib/usbdev/src/request.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbdev/src/request.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -114,5 +114,5 @@
   * 	(in native endianness).
   * @param actual_data_size Actual size of transfered data
-  * 	(in native endianness).
+  *        (in native endianness).
   * @return Error code.
   * @retval EBADMEM @p pipe is NULL.
@@ -147,7 +147,7 @@
 		    | (request_type << 5) | recipient,
 		.request = request,
-		.value = value,
-		.index = index,
-		.length = (uint16_t) data_size,
+		.value = uint16_host2usb(value),
+		.index = uint16_host2usb(index),
+		.length = uint16_host2usb(data_size),
 	};
 
@@ -375,5 +375,5 @@
 	usb_standard_device_descriptor_t descriptor_tmp;
 	int rc = usb_request_get_descriptor(pipe,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE, 
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
 	    USB_DESCTYPE_DEVICE, 0, 0,
 	    &descriptor_tmp, sizeof(descriptor_tmp),
@@ -435,5 +435,4 @@
 	/* Everything is okay, copy the descriptor. */
 	memcpy(descriptor, &descriptor_tmp, sizeof(descriptor_tmp));
-
 	return EOK;
 }
@@ -495,9 +494,11 @@
 		return ENOENT;
 	}
-	if (bare_config.total_length < sizeof(bare_config)) {
+
+	const size_t total_length = uint16_usb2host(bare_config.total_length);
+	if (total_length < sizeof(bare_config)) {
 		return ELIMIT;
 	}
 
-	void *buffer = malloc(bare_config.total_length);
+	void *buffer = malloc(total_length);
 	if (buffer == NULL) {
 		return ENOMEM;
@@ -506,5 +507,5 @@
 	size_t transferred = 0;
 	rc = usb_request_get_full_configuration_descriptor(pipe, index,
-	    buffer, bare_config.total_length, &transferred);
+	    buffer, total_length, &transferred);
 	if (rc != EOK) {
 		free(buffer);
@@ -512,5 +513,5 @@
 	}
 
-	if (transferred != bare_config.total_length) {
+	if (transferred != total_length) {
 		free(buffer);
 		return ELIMIT;
@@ -522,5 +523,5 @@
 
 	if (descriptor_size != NULL) {
-		*descriptor_size = bare_config.total_length;
+		*descriptor_size = total_length;
 	}
 
Index: uspace/lib/usbhid/include/usb/hid/hid_report_items.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hid_report_items.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhid/include/usb/hid/hid_report_items.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,5 +38,5 @@
 #include <stdint.h>
 
-/*---------------------------------------------------------------------------*/
+
 /*
  * Item prefix
@@ -56,5 +56,5 @@
 #define USB_HID_ITEM_IS_LONG(data)	(data == 0xFE)
 
-/*---------------------------------------------------------------------------*/
+
 /*
  * Extended usage macros
@@ -70,5 +70,5 @@
 #define USB_HID_EXTENDED_USAGE(usage)		(usage & 0xFFFF)
 
-/*---------------------------------------------------------------------------*/
+
 /*
  * Input/Output/Feature Item flags
@@ -142,5 +142,5 @@
 #define USB_HID_ITEM_FLAG_BUFFERED(flags)	((flags & 0x100) == 0x100)
 
-/*---------------------------------------------------------------------------*/
+
 
 /* MAIN ITEMS */
@@ -185,5 +185,5 @@
 #define USB_HID_REPORT_TAG_END_COLLECTION	0xC
 
-/*---------------------------------------------------------------------------*/
+
 
 /* GLOBAL ITEMS */
@@ -272,5 +272,5 @@
 #define USB_HID_REPORT_TAG_POP			0xB
 
-/*---------------------------------------------------------------------------*/
+
 
 /* LOCAL ITEMS */
@@ -347,5 +347,5 @@
 #define USB_HID_REPORT_TAG_DELIMITER		0xA
 
-/*---------------------------------------------------------------------------*/
+
 
 #endif
Index: uspace/lib/usbhid/include/usb/hid/hidpath.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hidpath.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhid/include/usb/hid/hidpath.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,5 +41,5 @@
 
 
-/*---------------------------------------------------------------------------*/
+
 /*
  * Flags of usage paths comparison modes.
@@ -73,5 +73,5 @@
 #define USB_HID_PATH_COMPARE_ANYWHERE		8
 
-/*----------------------------------------------------------------------------*/
+
 /** 
  * Item of usage path structure. Last item of linked list describes one item
@@ -93,5 +93,5 @@
 
 
-/*---------------------------------------------------------------------------*/
+
 /** 
  * USB HID usage path structure.
@@ -112,5 +112,5 @@
 } usb_hid_report_path_t;
 
-/*---------------------------------------------------------------------------*/
+
 usb_hid_report_path_t *usb_hid_report_path(void);
 
Index: uspace/lib/usbhid/include/usb/hid/hidtypes.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hidtypes.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhid/include/usb/hid/hidtypes.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -39,5 +39,5 @@
 #include <adt/list.h>
 
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -69,5 +69,5 @@
 	(((x) < 0 ) ? ((1 << (size)) + (x)) : (x))
 
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -86,5 +86,5 @@
 } usb_hid_report_type_t;
 
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -111,5 +111,5 @@
 	
 } usb_hid_report_t;
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -135,5 +135,5 @@
 	link_t reports_link;
 } usb_hid_report_description_t;
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -202,5 +202,5 @@
 } usb_hid_report_field_t;
 
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -287,5 +287,5 @@
 	int in_delimiter;
 } usb_hid_report_item_t;
-/*---------------------------------------------------------------------------*/
+
 /**
  * Enum of the keyboard modifiers 
@@ -314,5 +314,5 @@
 	USB_HID_MOD_RGUI
 };
-/*---------------------------------------------------------------------------*/
+
 
 
Index: uspace/lib/usbhid/include/usb/hid/request.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/request.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhid/include/usb/hid/request.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,5 +42,5 @@
 #include <usb/dev/pipes.h>
 
-/*----------------------------------------------------------------------------*/
+
 
 int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no,
@@ -61,5 +61,5 @@
 int usbhid_req_get_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t *duration);
 
-/*----------------------------------------------------------------------------*/
+
 
 #endif /* USB_KBD_HIDREQ_H_ */
Index: uspace/lib/usbhid/src/hiddescriptor.c
===================================================================
--- uspace/lib/usbhid/src/hiddescriptor.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhid/src/hiddescriptor.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,5 +41,5 @@
 #include <assert.h>
 
-/*---------------------------------------------------------------------------*/
+
 /*
  * Constants defining current parsing mode for correct parsing of the set of
@@ -61,5 +61,5 @@
 #define INSIDE_DELIMITER_SET	2
 
-/*---------------------------------------------------------------------------*/
+
 	
 /** The new report item flag. Used to determine when the item is completly
@@ -78,5 +78,5 @@
 #define USB_HID_UNKNOWN_TAG		-99
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Checks if given collection path is already present in report structure and
@@ -124,5 +124,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Initialize the report descriptor parser structure
@@ -147,5 +147,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -314,5 +314,5 @@
 	return EOK;
 }
-/*---------------------------------------------------------------------------*/
+
 /**
  * Finds description of report with given report_id and of given type in
@@ -348,5 +348,5 @@
 	return NULL;
 }
-/*---------------------------------------------------------------------------*/
+
 
 /** Parse HID report descriptor.
@@ -536,5 +536,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -871,5 +871,5 @@
 	return EOK;
 }
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -892,5 +892,5 @@
 	return result;
 }
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -941,5 +941,5 @@
 
 }
-/*---------------------------------------------------------------------------*/
+
 
 /**
@@ -972,5 +972,5 @@
 	}
 }
-/*---------------------------------------------------------------------------*/
+
 
 
@@ -1022,5 +1022,5 @@
 	return;
 }
-/*---------------------------------------------------------------------------*/
+
 
 /**
Index: uspace/lib/usbhid/src/hidparser.c
===================================================================
--- uspace/lib/usbhid/src/hidparser.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhid/src/hidparser.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,5 +41,5 @@
 #include <assert.h>
 
-/*---------------------------------------------------------------------------*/
+
 /*
  * Data translation private functions
@@ -52,5 +52,5 @@
 	int32_t value);
 
-/*---------------------------------------------------------------------------*/
+
 
 static int usb_pow(int a, int b)
@@ -68,5 +68,5 @@
 	}
 }
-/*---------------------------------------------------------------------------*/
+
 
 /** Returns size of report of specified report id and type in items
@@ -117,5 +117,5 @@
 	}
 }
-/*---------------------------------------------------------------------------*/
+
 
 /** Parse and act upon a HID report.
@@ -192,5 +192,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Translate data from the report as specified in report descriptor item
@@ -274,5 +274,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /* OUTPUT API */
 
@@ -431,5 +431,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Translate given data for putting them into the outoput report
@@ -476,5 +476,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Clones given state table
@@ -497,5 +497,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Function for sequence walking through the report. Returns next field in the
@@ -552,5 +552,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Returns next report_id of report of specified type. If zero is given than
@@ -600,5 +600,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Reset all local items in given state table
Index: uspace/lib/usbhid/src/hidpath.c
===================================================================
--- uspace/lib/usbhid/src/hidpath.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhid/src/hidpath.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,5 +41,5 @@
 #include <assert.h>
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Compares two usages if they are same or not or one of the usages is not
@@ -63,5 +63,5 @@
 	((page1 == page2) || (page1 == 0) || (page2 == 0))
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Appends one item (couple of usage_path and usage) into the usage path
@@ -93,5 +93,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Removes last item from the usage path structure
@@ -114,5 +114,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Nulls last item of the usage path structure.
@@ -133,5 +133,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Modifies last item of usage path structure by given usage page or usage
@@ -164,5 +164,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  *
@@ -188,5 +188,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Compares two usage paths structures
@@ -354,5 +354,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Allocates and initializes new usage path structure.
@@ -376,5 +376,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Releases given usage path structure.
@@ -395,5 +395,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Clone content of given usage path to the new one
@@ -441,5 +441,5 @@
 }
 
-/*---------------------------------------------------------------------------*/
+
 /**
  * Sets report id in usage path structure
Index: uspace/lib/usbhid/src/hidreport.c
===================================================================
--- uspace/lib/usbhid/src/hidreport.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhid/src/hidreport.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -50,5 +50,5 @@
 #include <usb/hid/hidreport.h>
 
-static int usb_hid_get_report_descriptor(usb_device_t *dev, 
+static int usb_hid_get_report_descriptor(usb_device_t *dev,
     uint8_t **report_desc, size_t *size)
 {
@@ -69,6 +69,6 @@
 	 * First nested descriptor of the configuration descriptor.
 	 */
-	const uint8_t *d = 
-	    usb_dp_get_nested_descriptor(&parser, &parser_data, 
+	const uint8_t *d =
+	    usb_dp_get_nested_descriptor(&parser, &parser_data,
 	    dev->descriptors.configuration);
 	
@@ -78,5 +78,5 @@
 	int i = 0;
 	while (d != NULL && i < dev->interface_no) {
-		d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
+		d = usb_dp_get_sibling_descriptor(&parser, &parser_data,
 		    dev->descriptors.configuration, d);
 		++i;
@@ -99,5 +99,5 @@
 	 */
 	while (d != NULL && *(d + 1) != USB_DESCTYPE_HID) {
-		d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
+		d = usb_dp_get_sibling_descriptor(&parser, &parser_data,
 		    iface_desc, d);
 	}
@@ -114,8 +114,8 @@
 	}
 	
-	usb_standard_hid_descriptor_t *hid_desc = 
+	usb_standard_hid_descriptor_t *hid_desc =
 	    (usb_standard_hid_descriptor_t *)d;
 	
-	uint16_t length =  hid_desc->report_desc_info.length;
+	uint16_t length = uint16_usb2host(hid_desc->report_desc_info.length);
 	size_t actual_size = 0;
 
@@ -161,5 +161,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 
 int usb_hid_process_report_descriptor(usb_device_t *dev, 
Index: uspace/lib/usbhid/src/hidreq.c
===================================================================
--- uspace/lib/usbhid/src/hidreq.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhid/src/hidreq.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -45,5 +45,5 @@
 #include <usb/hid/request.h>
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Send Set Report request to the HID device.
@@ -97,5 +97,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Send Set Protocol request to the HID device.
@@ -145,5 +145,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Send Set Idle request to the HID device.
@@ -195,5 +195,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Send Get Report request to the HID device.
@@ -251,5 +251,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Send Get Protocol request to the HID device.
@@ -310,5 +310,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 /**
  * Send Get Idle request to the HID device.
@@ -373,5 +373,5 @@
 }
 
-/*----------------------------------------------------------------------------*/
+
 
 /**
Index: uspace/lib/usbhost/include/usb/host/hcd.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/hcd.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhost/include/usb/host/hcd.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -98,8 +98,7 @@
  * @return pointer cast to hcd_t*.
  */
-static inline hcd_t * fun_to_hcd(const ddf_fun_t *fun)
+static inline hcd_t *fun_to_hcd(ddf_fun_t *fun)
 {
-	assert(fun);
-	return fun->driver_data;
+	return ddf_fun_data_get(fun);
 }
 
Index: uspace/lib/usbhost/src/endpoint.c
===================================================================
--- uspace/lib/usbhost/src/endpoint.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhost/src/endpoint.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -72,5 +72,5 @@
 	return instance;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Properly dispose of endpoint_t structure.
  * @param instance endpoint_t structure.
@@ -84,5 +84,5 @@
 	free(instance);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Set device specific data and hooks.
  * @param instance endpoint_t structure.
@@ -101,5 +101,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Clear device specific data and hooks.
  * @param instance endpoint_t structure.
@@ -115,5 +115,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Mark the endpoint as active and block access for further fibrils.
  * @param instance endpoint_t structure.
@@ -128,5 +128,5 @@
 	fibril_mutex_unlock(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Mark the endpoint as inactive and allow access for further fibrils.
  * @param instance endpoint_t structure.
@@ -140,5 +140,5 @@
 	fibril_condvar_signal(&instance->avail);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Get the value of toggle bit.
  * @param instance endpoint_t structure.
@@ -156,5 +156,5 @@
 	return ret;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Set the value of toggle bit.
  * @param instance endpoint_t structure.
Index: uspace/lib/usbhost/src/usb_device_manager.c
===================================================================
--- uspace/lib/usbhost/src/usb_device_manager.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhost/src/usb_device_manager.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -61,5 +61,5 @@
 	return new_address;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize device manager structure.
  *
@@ -82,5 +82,5 @@
 	fibril_mutex_initialize(&instance->guard);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Request USB address.
  * @param instance usb_device_manager
@@ -124,5 +124,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Bind USB address to devman handle.
  *
@@ -156,5 +156,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Release used USB address.
  *
@@ -182,5 +182,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Find USB address associated with the device.
  *
@@ -205,5 +205,5 @@
 	return ENOENT;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Find devman handle and speed assigned to USB address.
  *
Index: uspace/lib/usbhost/src/usb_endpoint_manager.c
===================================================================
--- uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -61,5 +61,5 @@
 	    && (address == ep->address);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Get list that holds endpoints for given address.
  * @param instance usb_endpoint_manager structure, non-null.
@@ -73,5 +73,5 @@
 	return &instance->endpoint_lists[addr % ENDPOINT_LIST_COUNT];
 }
-/*----------------------------------------------------------------------------*/
+
 /** Internal search function, works on locked structure.
  * @param instance usb_endpoint_manager structure, non-null.
@@ -97,5 +97,5 @@
 	return NULL;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Calculate bandwidth that needs to be reserved for communication with EP.
  * Calculation follows USB 1.1 specification.
@@ -145,5 +145,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Initialize to default state.
  * You need to provide valid bw_count function if you plan to use
@@ -168,5 +168,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Check setup packet data for signs of toggle reset.
  *
@@ -227,5 +227,5 @@
 	}
 }
-/*----------------------------------------------------------------------------*/
+
 /** Register endpoint structure.
  * Checks for duplicates.
@@ -262,5 +262,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Unregister endpoint structure.
  * Checks for duplicates.
@@ -286,5 +286,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Find endpoint_t representing the given communication route.
  * @param instance usb_endpoint_manager, non-null.
@@ -301,5 +301,5 @@
 	return ep;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Create and register new endpoint_t structure.
  * @param instance usb_endpoint_manager structure, non-null.
@@ -364,5 +364,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Unregister and destroy endpoint_t structure representing given route.
  * @param instance usb_endpoint_manager structure, non-null.
@@ -395,5 +395,5 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Unregister and destroy all endpoints using given address.
  * @param instance usb_endpoint_manager structure, non-null.
Index: uspace/lib/usbhost/src/usb_transfer_batch.c
===================================================================
--- uspace/lib/usbhost/src/usb_transfer_batch.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/lib/usbhost/src/usb_transfer_batch.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -96,5 +96,5 @@
 	return instance;
 }
-/*----------------------------------------------------------------------------*/
+
 /** Correctly dispose all used data structures.
  *
@@ -116,5 +116,5 @@
 	free(instance);
 }
-/*----------------------------------------------------------------------------*/
+
 /** Prepare data and call the right callback.
  *
Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -51,7 +51,7 @@
 #include <libarch/ddi.h>
 #include <ddi.h>
-#include <ipc/bd.h>
 #include <async.h>
 #include <as.h>
+#include <bd_srv.h>
 #include <fibril_synch.h>
 #include <stdint.h>
@@ -98,26 +98,33 @@
 
 /** Per-disk state. */
-static disk_t disk[MAX_DISKS];
+static disk_t ata_disk[MAX_DISKS];
 
 static void print_syntax(void);
 static int ata_bd_init(void);
 static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *);
-static int ata_bd_read_blocks(int disk_id, uint64_t ba, size_t cnt,
+
+static int ata_bd_open(bd_srvs_t *, bd_srv_t *);
+static int ata_bd_close(bd_srv_t *);
+static int ata_bd_read_blocks(bd_srv_t *, uint64_t ba, size_t cnt, void *buf,
+    size_t);
+static int ata_bd_read_toc(bd_srv_t *, uint8_t session, void *buf, size_t);
+static int ata_bd_write_blocks(bd_srv_t *, uint64_t ba, size_t cnt,
+    const void *buf, size_t);
+static int ata_bd_get_block_size(bd_srv_t *, size_t *);
+static int ata_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
+
+static int ata_rcmd_read(disk_t *disk, uint64_t ba, size_t cnt,
     void *buf);
-static int ata_bd_write_blocks(int disk_id, uint64_t ba, size_t cnt,
-    const void *buf);
-static int ata_rcmd_read(int disk_id, uint64_t ba, size_t cnt,
-    void *buf);
-static int ata_rcmd_write(int disk_id, uint64_t ba, size_t cnt,
+static int ata_rcmd_write(disk_t *disk, uint64_t ba, size_t cnt,
     const void *buf);
 static int disk_init(disk_t *d, int disk_id);
-static int drive_identify(int drive_id, void *buf);
-static int identify_pkt_dev(int dev_idx, void *buf);
-static int ata_cmd_packet(int dev_idx, const void *cpkt, size_t cpkt_size,
+static int drive_identify(disk_t *disk, void *buf);
+static int identify_pkt_dev(disk_t *disk, void *buf);
+static int ata_cmd_packet(disk_t *disk, const void *cpkt, size_t cpkt_size,
     void *obuf, size_t obuf_size);
-static int ata_pcmd_inquiry(int dev_idx, void *obuf, size_t obuf_size);
-static int ata_pcmd_read_12(int dev_idx, uint64_t ba, size_t cnt,
+static int ata_pcmd_inquiry(disk_t *disk, void *obuf, size_t obuf_size);
+static int ata_pcmd_read_12(disk_t *disk, uint64_t ba, size_t cnt,
     void *obuf, size_t obuf_size);
-static int ata_pcmd_read_toc(int dev_idx, uint8_t ses,
+static int ata_pcmd_read_toc(disk_t *disk, uint8_t ses,
     void *obuf, size_t obuf_size);
 static void disk_print_summary(disk_t *d);
@@ -126,4 +133,24 @@
 static int wait_status(unsigned set, unsigned n_reset, uint8_t *pstatus,
     unsigned timeout);
+
+static bd_ops_t ata_bd_ops = {
+	.open = ata_bd_open,
+	.close = ata_bd_close,
+	.read_blocks = ata_bd_read_blocks,
+	.read_toc = ata_bd_read_toc,
+	.write_blocks = ata_bd_write_blocks,
+	.get_block_size = ata_bd_get_block_size,
+	.get_num_blocks = ata_bd_get_num_blocks
+};
+
+static disk_t *bd_srv_disk(bd_srv_t *bd)
+{
+	return (disk_t *)bd->srvs->sarg;
+}
+
+static int disk_dev_idx(disk_t *disk)
+{
+	return (disk->disk_id & 1);
+}
 
 int main(int argc, char **argv)
@@ -161,8 +188,8 @@
 		fflush(stdout);
 
-		rc = disk_init(&disk[i], i);
+		rc = disk_init(&ata_disk[i], i);
 
 		if (rc == EOK) {
-			disk_print_summary(&disk[i]);
+			disk_print_summary(&ata_disk[i]);
 		} else {
 			printf("Not found.\n");
@@ -174,9 +201,9 @@
 	for (i = 0; i < MAX_DISKS; i++) {
 		/* Skip unattached drives. */
-		if (disk[i].present == false)
+		if (ata_disk[i].present == false)
 			continue;
 		
 		snprintf(name, 16, "%s/ata%udisk%d", NAMESPACE, ctl_num, i);
-		rc = loc_service_register(name, &disk[i].service_id);
+		rc = loc_service_register(name, &ata_disk[i].service_id);
 		if (rc != EOK) {
 			printf(NAME ": Unable to register device %s.\n", name);
@@ -217,6 +244,6 @@
 		case am_chs:
 			printf("CHS %u cylinders, %u heads, %u sectors",
-			    disk->geom.cylinders, disk->geom.heads,
-			    disk->geom.sectors);
+			    d->geom.cylinders, d->geom.heads,
+			    d->geom.sectors);
 			break;
 		case am_lba28:
@@ -273,15 +300,7 @@
 static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	void *fs_va = NULL;
-	ipc_callid_t callid;
-	ipc_call_t call;
-	sysarg_t method;
 	service_id_t dsid;
-	size_t comm_size;	/**< Size of the communication area. */
-	unsigned int flags;
-	int retval;
-	uint64_t ba;
-	size_t cnt;
-	int disk_id, i;
+	int i;
+	disk_t *disk;
 
 	/* Get the device service ID. */
@@ -289,80 +308,15 @@
 
 	/* Determine which disk device is the client connecting to. */
-	disk_id = -1;
+	disk = NULL;
 	for (i = 0; i < MAX_DISKS; i++)
-		if (disk[i].service_id == dsid)
-			disk_id = i;
-
-	if (disk_id < 0 || disk[disk_id].present == false) {
+		if (ata_disk[i].service_id == dsid)
+			disk = &ata_disk[i];
+
+	if (disk == NULL || disk->present == false) {
 		async_answer_0(iid, EINVAL);
 		return;
 	}
 
-	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	async_answer_0(iid, EOK);
-
-	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	(void) async_share_out_finalize(callid, &fs_va);
-	if (fs_va == AS_MAP_FAILED) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	while (true) {
-		callid = async_get_call(&call);
-		method = IPC_GET_IMETHOD(call);
-		
-		if (!method) {
-			/* The other side has hung up. */
-			async_answer_0(callid, EOK);
-			return;
-		}
-		
-		switch (method) {
-		case BD_READ_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * disk[disk_id].block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = ata_bd_read_blocks(disk_id, ba, cnt, fs_va);
-			break;
-		case BD_WRITE_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * disk[disk_id].block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = ata_bd_write_blocks(disk_id, ba, cnt, fs_va);
-			break;
-		case BD_GET_BLOCK_SIZE:
-			async_answer_1(callid, EOK, disk[disk_id].block_size);
-			continue;
-		case BD_GET_NUM_BLOCKS:
-			async_answer_2(callid, EOK, LOWER32(disk[disk_id].blocks),
-			    UPPER32(disk[disk_id].blocks));
-			continue;
-		case BD_READ_TOC:
-			cnt = IPC_GET_ARG1(call);
-			if (disk[disk_id].dev_type == ata_pkt_dev)
-				retval = ata_pcmd_read_toc(disk_id, cnt, fs_va,
-				    disk[disk_id].block_size);
-			else
-				retval = EINVAL;
-			break;
-		default:
-			retval = EINVAL;
-			break;
-		}
-		async_answer_0(callid, retval);
-	}
+	bd_conn(iid, icall, &disk->bds);
 }
 
@@ -384,9 +338,14 @@
 	unsigned i;
 
+	d->disk_id = disk_id;
 	d->present = false;
 	fibril_mutex_initialize(&d->lock);
 
+	bd_srvs_init(&d->bds);
+	d->bds.ops = &ata_bd_ops;
+	d->bds.sarg = d;
+
 	/* Try identify command. */
-	rc = drive_identify(disk_id, &idata);
+	rc = drive_identify(d, &idata);
 	if (rc == EOK) {
 		/* Success. It's a register (non-packet) device. */
@@ -408,5 +367,5 @@
 
 		if (bc == PDEV_SIGNATURE_BC) {
-			rc = identify_pkt_dev(disk_id, &idata);
+			rc = identify_pkt_dev(d, &idata);
 			if (rc == EOK) {
 				/* We have a packet device. */
@@ -492,5 +451,5 @@
 	if (d->dev_type == ata_pkt_dev) {
 		/* Send inquiry. */
-		rc = ata_pcmd_inquiry(0, &inq_data, sizeof(inq_data));
+		rc = ata_pcmd_inquiry(d, &inq_data, sizeof(inq_data));
 		if (rc != EOK) {
 			printf("Device inquiry failed.\n");
@@ -514,16 +473,31 @@
 }
 
+static int ata_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
+{
+	return EOK;
+}
+
+static int ata_bd_close(bd_srv_t *bd)
+{
+	return EOK;
+}
+
 /** Read multiple blocks from the device. */
-static int ata_bd_read_blocks(int disk_id, uint64_t ba, size_t cnt,
-    void *buf) {
-
+static int ata_bd_read_blocks(bd_srv_t *bd, uint64_t ba, size_t cnt,
+    void *buf, size_t size)
+{
+	disk_t *disk = bd_srv_disk(bd);
 	int rc;
 
+	if (size < cnt * disk->block_size)
+		return EINVAL;
+
 	while (cnt > 0) {
-		if (disk[disk_id].dev_type == ata_reg_dev)
-			rc = ata_rcmd_read(disk_id, ba, 1, buf);
-		else
-			rc = ata_pcmd_read_12(disk_id, ba, 1, buf,
-			    disk[disk_id].block_size);
+		if (disk->dev_type == ata_reg_dev) {
+			rc = ata_rcmd_read(disk, ba, 1, buf);
+		} else {
+			rc = ata_pcmd_read_12(disk, ba, 1, buf,
+			    disk->block_size);
+		}
 
 		if (rc != EOK)
@@ -532,21 +506,33 @@
 		++ba;
 		--cnt;
-		buf += disk[disk_id].block_size;
-	}
-
-	return EOK;
+		buf += disk->block_size;
+	}
+
+	return EOK;
+}
+
+/** Read TOC from device. */
+static int ata_bd_read_toc(bd_srv_t *bd, uint8_t session, void *buf, size_t size)
+{
+	disk_t *disk = bd_srv_disk(bd);
+
+	return ata_pcmd_read_toc(disk, session, buf, size);
 }
 
 /** Write multiple blocks to the device. */
-static int ata_bd_write_blocks(int disk_id, uint64_t ba, size_t cnt,
-    const void *buf) {
-
+static int ata_bd_write_blocks(bd_srv_t *bd, uint64_t ba, size_t cnt,
+    const void *buf, size_t size)
+{
+	disk_t *disk = bd_srv_disk(bd);
 	int rc;
 
-	if (disk[disk_id].dev_type != ata_reg_dev)
+	if (disk->dev_type != ata_reg_dev)
 		return ENOTSUP;
 
+	if (size < cnt * disk->block_size)
+		return EINVAL;
+
 	while (cnt > 0) {
-		rc = ata_rcmd_write(disk_id, ba, 1, buf);
+		rc = ata_rcmd_write(disk, ba, 1, buf);
 		if (rc != EOK)
 			return rc;
@@ -554,7 +540,25 @@
 		++ba;
 		--cnt;
-		buf += disk[disk_id].block_size;
-	}
-
+		buf += disk->block_size;
+	}
+
+	return EOK;
+}
+
+/** Get device block size. */
+static int ata_bd_get_block_size(bd_srv_t *bd, size_t *rbsize)
+{
+	disk_t *disk = bd_srv_disk(bd);
+
+	*rbsize = disk->block_size;
+	return EOK;
+}
+
+/** Get device number of blocks. */
+static int ata_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
+{
+	disk_t *disk = bd_srv_disk(bd);
+
+	*rnb = disk->blocks;
 	return EOK;
 }
@@ -565,5 +569,5 @@
  * whether an ATA device is present and if so, to determine its parameters.
  *
- * @param disk_id	Device ID, 0 or 1.
+ * @param disk		Disk
  * @param buf		Pointer to a 512-byte buffer.
  *
@@ -571,5 +575,5 @@
  *			not present). EIO if device responds with error.
  */
-static int drive_identify(int disk_id, void *buf)
+static int drive_identify(disk_t *disk, void *buf)
 {
 	uint16_t data;
@@ -578,5 +582,5 @@
 	size_t i;
 
-	drv_head = ((disk_id != 0) ? DHR_DRV : 0);
+	drv_head = ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0);
 
 	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
@@ -624,8 +628,8 @@
  * whether an ATAPI device is present and if so, to determine its parameters.
  *
- * @param dev_idx	Device index, 0 or 1.
+ * @param disk		Disk
  * @param buf		Pointer to a 512-byte buffer.
  */
-static int identify_pkt_dev(int dev_idx, void *buf)
+static int identify_pkt_dev(disk_t *disk, void *buf)
 {
 	uint16_t data;
@@ -634,5 +638,5 @@
 	size_t i;
 
-	drv_head = ((dev_idx != 0) ? DHR_DRV : 0);
+	drv_head = ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0);
 
 	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
@@ -669,5 +673,5 @@
  * Only data-in commands are supported (e.g. inquiry, read).
  *
- * @param dev_idx	Device index (0 or 1)
+ * @param disk		Disk
  * @param obuf		Buffer for storing data read from device
  * @param obuf_size	Size of obuf in bytes
@@ -675,5 +679,5 @@
  * @return EOK on success, EIO on error.
  */
-static int ata_cmd_packet(int dev_idx, const void *cpkt, size_t cpkt_size,
+static int ata_cmd_packet(disk_t *disk, const void *cpkt, size_t cpkt_size,
     void *obuf, size_t obuf_size)
 {
@@ -681,17 +685,15 @@
 	uint8_t status;
 	uint8_t drv_head;
-	disk_t *d;
 	size_t data_size;
 	uint16_t val;
 
-	d = &disk[dev_idx];
-	fibril_mutex_lock(&d->lock);
+	fibril_mutex_lock(&disk->lock);
 
 	/* New value for Drive/Head register */
 	drv_head =
-	    ((dev_idx != 0) ? DHR_DRV : 0);
+	    ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0);
 
 	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) {
-		fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
 		return EIO;
 	}
@@ -700,5 +702,5 @@
 
 	if (wait_status(0, ~(SR_BSY|SR_DRQ), NULL, TIMEOUT_BSY) != EOK) {
-		fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
 		return EIO;
 	}
@@ -711,5 +713,5 @@
 
 	if (wait_status(SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
-		fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
 		return EIO;
 	}
@@ -720,10 +722,10 @@
 
 	if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
-		fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
 		return EIO;
 	}
 
 	if ((status & SR_DRQ) == 0) {
-		fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
 		return EIO;
 	}
@@ -736,5 +738,5 @@
 	if (data_size > obuf_size) {
 		/* Output buffer is too small to store data. */
-		fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
 		return EIO;
 	}
@@ -747,9 +749,9 @@
 
 	if (status & SR_ERR) {
-		fibril_mutex_unlock(&d->lock);
-		return EIO;
-	}
-
-	fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
+		return EIO;
+	}
+
+	fibril_mutex_unlock(&disk->lock);
 
 	return EOK;
@@ -758,5 +760,5 @@
 /** Issue ATAPI Inquiry.
  *
- * @param dev_idx	Device index (0 or 1)
+ * @param disk		Disk
  * @param obuf		Buffer for storing inquiry data read from device
  * @param obuf_size	Size of obuf in bytes
@@ -764,5 +766,5 @@
  * @return EOK on success, EIO on error.
  */
-static int ata_pcmd_inquiry(int dev_idx, void *obuf, size_t obuf_size)
+static int ata_pcmd_inquiry(disk_t *disk, void *obuf, size_t obuf_size)
 {
 	ata_pcmd_inquiry_t cp;
@@ -774,5 +776,5 @@
 	cp.alloc_len = min(obuf_size, 0xff); /* Allocation length */
 
-	rc = ata_cmd_packet(0, &cp, sizeof(cp), obuf, obuf_size);
+	rc = ata_cmd_packet(disk, &cp, sizeof(cp), obuf, obuf_size);
 	if (rc != EOK)
 		return rc;
@@ -786,5 +788,5 @@
  * function will fail.
  *
- * @param dev_idx	Device index (0 or 1)
+ * @param disk		Disk
  * @param ba		Starting block address
  * @param cnt		Number of blocks to read
@@ -794,5 +796,5 @@
  * @return EOK on success, EIO on error.
  */
-static int ata_pcmd_read_12(int dev_idx, uint64_t ba, size_t cnt,
+static int ata_pcmd_read_12(disk_t *disk, uint64_t ba, size_t cnt,
     void *obuf, size_t obuf_size)
 {
@@ -809,5 +811,5 @@
 	cp.nblocks = host2uint32_t_be(cnt);
 
-	rc = ata_cmd_packet(0, &cp, sizeof(cp), obuf, obuf_size);
+	rc = ata_cmd_packet(disk, &cp, sizeof(cp), obuf, obuf_size);
 	if (rc != EOK)
 		return rc;
@@ -826,5 +828,5 @@
  * function will fail.
  *
- * @param dev_idx	Device index (0 or 1)
+ * @param disk		Disk
  * @param session	Starting session
  * @param obuf		Buffer for storing inquiry data read from device
@@ -833,5 +835,5 @@
  * @return EOK on success, EIO on error.
  */
-static int ata_pcmd_read_toc(int dev_idx, uint8_t session, void *obuf,
+static int ata_pcmd_read_toc(disk_t *disk, uint8_t session, void *obuf,
     size_t obuf_size)
 {
@@ -857,5 +859,5 @@
 /** Read a physical from the device.
  *
- * @param disk_id	Device index (0 or 1)
+ * @param disk		Disk
  * @param ba		Address the first block.
  * @param cnt		Number of blocks to transfer.
@@ -864,5 +866,5 @@
  * @return EOK on success, EIO on error.
  */
-static int ata_rcmd_read(int disk_id, uint64_t ba, size_t blk_cnt,
+static int ata_rcmd_read(disk_t *disk, uint64_t ba, size_t blk_cnt,
     void *buf)
 {
@@ -871,28 +873,25 @@
 	uint8_t status;
 	uint8_t drv_head;
-	disk_t *d;
 	block_coord_t bc;
 
-	d = &disk[disk_id];
-	
 	/* Silence warning. */
 	memset(&bc, 0, sizeof(bc));
 
 	/* Compute block coordinates. */
-	if (coord_calc(d, ba, &bc) != EOK)
+	if (coord_calc(disk, ba, &bc) != EOK)
 		return EINVAL;
 
 	/* New value for Drive/Head register */
 	drv_head =
-	    ((disk_id != 0) ? DHR_DRV : 0) |
-	    ((d->amode != am_chs) ? DHR_LBA : 0) |
+	    ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0) |
+	    ((disk->amode != am_chs) ? DHR_LBA : 0) |
 	    (bc.h & 0x0f);
 
-	fibril_mutex_lock(&d->lock);
+	fibril_mutex_lock(&disk->lock);
 
 	/* Program a Read Sectors operation. */
 
 	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
-		fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
 		return EIO;
 	}
@@ -901,5 +900,5 @@
 
 	if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
-		fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
 		return EIO;
 	}
@@ -908,9 +907,9 @@
 	coord_sc_program(&bc, 1);
 
-	pio_write_8(&cmd->command, d->amode == am_lba48 ?
+	pio_write_8(&cmd->command, disk->amode == am_lba48 ?
 	    CMD_READ_SECTORS_EXT : CMD_READ_SECTORS);
 
 	if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
-		fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
 		return EIO;
 	}
@@ -919,5 +918,5 @@
 		/* Read data from the device buffer. */
 
-		for (i = 0; i < disk[disk_id].block_size / 2; i++) {
+		for (i = 0; i < disk->block_size / 2; i++) {
 			data = pio_read_16(&cmd->data_port);
 			((uint16_t *) buf)[i] = data;
@@ -928,5 +927,5 @@
 		return EIO;
 
-	fibril_mutex_unlock(&d->lock);
+	fibril_mutex_unlock(&disk->lock);
 	return EOK;
 }
@@ -934,5 +933,5 @@
 /** Write a physical block to the device.
  *
- * @param disk_id	Device index (0 or 1)
+ * @param disk		Disk
  * @param ba		Address of the first block.
  * @param cnt		Number of blocks to transfer.
@@ -941,5 +940,5 @@
  * @return EOK on success, EIO on error.
  */
-static int ata_rcmd_write(int disk_id, uint64_t ba, size_t cnt,
+static int ata_rcmd_write(disk_t *disk, uint64_t ba, size_t cnt,
     const void *buf)
 {
@@ -947,28 +946,25 @@
 	uint8_t status;
 	uint8_t drv_head;
-	disk_t *d;
 	block_coord_t bc;
 
-	d = &disk[disk_id];
-	
 	/* Silence warning. */
 	memset(&bc, 0, sizeof(bc));
 
 	/* Compute block coordinates. */
-	if (coord_calc(d, ba, &bc) != EOK)
+	if (coord_calc(disk, ba, &bc) != EOK)
 		return EINVAL;
 
 	/* New value for Drive/Head register */
 	drv_head =
-	    ((disk_id != 0) ? DHR_DRV : 0) |
-	    ((d->amode != am_chs) ? DHR_LBA : 0) |
+	    ((disk_dev_idx(disk) != 0) ? DHR_DRV : 0) |
+	    ((disk->amode != am_chs) ? DHR_LBA : 0) |
 	    (bc.h & 0x0f);
 
-	fibril_mutex_lock(&d->lock);
+	fibril_mutex_lock(&disk->lock);
 
 	/* Program a Write Sectors operation. */
 
 	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_BSY) != EOK) {
-		fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
 		return EIO;
 	}
@@ -977,5 +973,5 @@
 
 	if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_DRDY) != EOK) {
-		fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
 		return EIO;
 	}
@@ -984,9 +980,9 @@
 	coord_sc_program(&bc, 1);
 
-	pio_write_8(&cmd->command, d->amode == am_lba48 ?
+	pio_write_8(&cmd->command, disk->amode == am_lba48 ?
 	    CMD_WRITE_SECTORS_EXT : CMD_WRITE_SECTORS);
 
 	if (wait_status(0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
-		fibril_mutex_unlock(&d->lock);
+		fibril_mutex_unlock(&disk->lock);
 		return EIO;
 	}
@@ -995,10 +991,10 @@
 		/* Write data to the device buffer. */
 
-		for (i = 0; i < disk[disk_id].block_size / 2; i++) {
+		for (i = 0; i < disk->block_size / 2; i++) {
 			pio_write_16(&cmd->data_port, ((uint16_t *) buf)[i]);
 		}
 	}
 
-	fibril_mutex_unlock(&d->lock);
+	fibril_mutex_unlock(&disk->lock);
 
 	if (status & SR_ERR)
Index: uspace/srv/bd/ata_bd/ata_bd.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/bd/ata_bd/ata_bd.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,4 +36,5 @@
 #define __ATA_BD_H__
 
+#include <bd_srv.h>
 #include <sys/types.h>
 #include <fibril_synch.h>
@@ -117,4 +118,6 @@
 	fibril_mutex_t lock;
 	service_id_t service_id;
+	int disk_id;
+	bd_srvs_t bds;
 } disk_t;
 
Index: uspace/srv/bd/file_bd/file_bd.c
===================================================================
--- uspace/srv/bd/file_bd/file_bd.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/bd/file_bd/file_bd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,7 +41,7 @@
 #include <stdio.h>
 #include <unistd.h>
-#include <ipc/bd.h>
 #include <async.h>
 #include <as.h>
+#include <bd_srv.h>
 #include <fibril_synch.h>
 #include <loc.h>
@@ -62,4 +62,5 @@
 
 static service_id_t service_id;
+static bd_srvs_t bd_srvs;
 static fibril_mutex_t dev_lock;
 
@@ -67,6 +68,20 @@
 static int file_bd_init(const char *fname);
 static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *);
-static int file_bd_read_blocks(uint64_t ba, size_t cnt, void *buf);
-static int file_bd_write_blocks(uint64_t ba, size_t cnt, const void *buf);
+
+static int file_bd_open(bd_srvs_t *, bd_srv_t *);
+static int file_bd_close(bd_srv_t *);
+static int file_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
+static int file_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
+static int file_bd_get_block_size(bd_srv_t *, size_t *);
+static int file_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
+
+static bd_ops_t file_bd_ops = {
+	.open = file_bd_open,
+	.close = file_bd_close,
+	.read_blocks = file_bd_read_blocks,
+	.write_blocks = file_bd_write_blocks,
+	.get_block_size = file_bd_get_block_size,
+	.get_num_blocks = file_bd_get_num_blocks
+};
 
 int main(int argc, char **argv)
@@ -139,4 +154,7 @@
 static int file_bd_init(const char *fname)
 {
+	bd_srvs_init(&bd_srvs);
+	bd_srvs.ops = &file_bd_ops;
+	
 	async_set_client_connection(file_bd_connection);
 	int rc = loc_server_register(NAME);
@@ -170,79 +188,28 @@
 static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	void *fs_va = NULL;
-	ipc_callid_t callid;
-	ipc_call_t call;
-	sysarg_t method;
-	size_t comm_size;
-	unsigned int flags;
-	int retval;
-	uint64_t ba;
-	size_t cnt;
-
-	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	async_answer_0(iid, EOK);
-
-	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	(void) async_share_out_finalize(callid, &fs_va);
-	if (fs_va == AS_MAP_FAILED) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	while (true) {
-		callid = async_get_call(&call);
-		method = IPC_GET_IMETHOD(call);
-		
-		if (!method) {
-			/* The other side has hung up. */
-			async_answer_0(callid, EOK);
-			return;
-		}
-		
-		switch (method) {
-		case BD_READ_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = file_bd_read_blocks(ba, cnt, fs_va);
-			break;
-		case BD_WRITE_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = file_bd_write_blocks(ba, cnt, fs_va);
-			break;
-		case BD_GET_BLOCK_SIZE:
-			async_answer_1(callid, EOK, block_size);
-			continue;
-		case BD_GET_NUM_BLOCKS:
-			async_answer_2(callid, EOK, LOWER32(num_blocks),
-			    UPPER32(num_blocks));
-			continue;
-		default:
-			retval = EINVAL;
-			break;
-		}
-		async_answer_0(callid, retval);
-	}
+	bd_conn(iid, icall, &bd_srvs);
+}
+
+/** Open device. */
+static int file_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
+{
+	return EOK;
+}
+
+/** Close device. */
+static int file_bd_close(bd_srv_t *bd)
+{
+	return EOK;
 }
 
 /** Read blocks from the device. */
-static int file_bd_read_blocks(uint64_t ba, size_t cnt, void *buf)
+static int file_bd_read_blocks(bd_srv_t *bd, uint64_t ba, size_t cnt, void *buf,
+    size_t size)
 {
 	size_t n_rd;
 	int rc;
+
+	if (size < cnt * block_size)
+		return EINVAL;
 
 	/* Check whether access is within device address bounds. */
@@ -279,8 +246,12 @@
 
 /** Write blocks to the device. */
-static int file_bd_write_blocks(uint64_t ba, size_t cnt, const void *buf)
+static int file_bd_write_blocks(bd_srv_t *bd, uint64_t ba, size_t cnt,
+    const void *buf, size_t size)
 {
 	size_t n_wr;
 	int rc;
+
+	if (size < cnt * block_size)
+		return EINVAL;
 
 	/* Check whether access is within device address bounds. */
@@ -318,4 +289,18 @@
 }
 
+/** Get device block size. */
+static int file_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
+{
+	*rsize = block_size;
+	return EOK;
+}
+
+/** Get number of blocks on device. */
+static int file_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
+{
+	*rnb = num_blocks;
+	return EOK;
+}
+
 /**
  * @}
Index: uspace/srv/bd/gxe_bd/gxe_bd.c
===================================================================
--- uspace/srv/bd/gxe_bd/gxe_bd.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/bd/gxe_bd/gxe_bd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -39,7 +39,7 @@
 #include <libarch/ddi.h>
 #include <ddi.h>
-#include <ipc/bd.h>
 #include <async.h>
 #include <as.h>
+#include <bd_srv.h>
 #include <fibril_synch.h>
 #include <loc.h>
@@ -65,4 +65,5 @@
 };
 
+/** GXE disk hardware registers */
 typedef struct {
 	uint32_t offset_lo;
@@ -83,25 +84,49 @@
 
 	uint8_t buffer[512];
+} gxe_bd_hw_t;
+
+/** GXE block device soft state */
+typedef struct {
+	/** Block device service structure */
+	bd_srvs_t bds;
+	int disk_id;
 } gxe_bd_t;
 
-
 static const size_t block_size = 512;
-static size_t comm_size;
 
 static uintptr_t dev_physical = 0x13000000;
-static gxe_bd_t *dev;
+static gxe_bd_hw_t *dev;
 
 static service_id_t service_id[MAX_DISKS];
 
 static fibril_mutex_t dev_lock[MAX_DISKS];
+
+static gxe_bd_t gxe_bd[MAX_DISKS];
 
 static int gxe_bd_init(void);
 static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *);
-static int gxe_bd_read_blocks(int disk_id, uint64_t ba, unsigned cnt,
-    void *buf);
-static int gxe_bd_write_blocks(int disk_id, uint64_t ba, unsigned cnt,
-    const void *buf);
 static int gxe_bd_read_block(int disk_id, uint64_t ba, void *buf);
 static int gxe_bd_write_block(int disk_id, uint64_t ba, const void *buf);
+
+static int gxe_bd_open(bd_srvs_t *, bd_srv_t *);
+static int gxe_bd_close(bd_srv_t *);
+static int gxe_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
+static int gxe_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
+static int gxe_bd_get_block_size(bd_srv_t *, size_t *);
+static int gxe_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
+
+static bd_ops_t gxe_bd_ops = {
+	.open = gxe_bd_open,
+	.close = gxe_bd_close,
+	.read_blocks = gxe_bd_read_blocks,
+	.write_blocks = gxe_bd_write_blocks,
+	.get_block_size = gxe_bd_get_block_size,
+	.get_num_blocks = gxe_bd_get_num_blocks
+};
+
+static gxe_bd_t *bd_srv_gxe(bd_srv_t *bd)
+{
+	return (gxe_bd_t *) bd->srvs->sarg;
+}
 
 int main(int argc, char **argv)
@@ -130,5 +155,5 @@
 	
 	void *vaddr;
-	rc = pio_enable((void *) dev_physical, sizeof(gxe_bd_t), &vaddr);
+	rc = pio_enable((void *) dev_physical, sizeof(gxe_bd_hw_t), &vaddr);
 	if (rc != EOK) {
 		printf("%s: Could not initialize device I/O space.\n", NAME);
@@ -140,4 +165,8 @@
 	for (unsigned int i = 0; i < MAX_DISKS; i++) {
 		char name[16];
+		
+		bd_srvs_init(&gxe_bd[i].bds);
+		gxe_bd[i].bds.ops = &gxe_bd_ops;
+		gxe_bd[i].bds.sarg = (void *)&gxe_bd[i];
 		
 		snprintf(name, 16, "%s/disk%u", NAMESPACE, i);
@@ -157,13 +186,5 @@
 static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	void *fs_va = NULL;
-	ipc_callid_t callid;
-	ipc_call_t call;
-	sysarg_t method;
 	service_id_t dsid;
-	unsigned int flags;
-	int retval;
-	uint64_t ba;
-	unsigned cnt;
 	int disk_id, i;
 
@@ -182,73 +203,28 @@
 	}
 
-	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	async_answer_0(iid, EOK);
-
-	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	if (comm_size < block_size) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	(void) async_share_out_finalize(callid, &fs_va);
-	if (fs_va == AS_MAP_FAILED) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	while (true) {
-		callid = async_get_call(&call);
-		method = IPC_GET_IMETHOD(call);
-		
-		if (!method) {
-			/* The other side has hung up. */
-			async_answer_0(callid, EOK);
-			return;
-		}
-		
-		switch (method) {
-		case BD_READ_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = gxe_bd_read_blocks(disk_id, ba, cnt, fs_va);
-			break;
-		case BD_WRITE_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = gxe_bd_write_blocks(disk_id, ba, cnt, fs_va);
-			break;
-		case BD_GET_BLOCK_SIZE:
-			async_answer_1(callid, EOK, block_size);
-			continue;
-		case BD_GET_NUM_BLOCKS:
-			retval = ENOTSUP;
-			break;
-		default:
-			retval = EINVAL;
-			break;
-		}
-		async_answer_0(callid, retval);
-	}
+	bd_conn(iid, icall, &gxe_bd[disk_id].bds);
+}
+
+/** Open device. */
+static int gxe_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
+{
+	return EOK;
+}
+
+/** Close device. */
+static int gxe_bd_close(bd_srv_t *bd)
+{
+	return EOK;
 }
 
 /** Read multiple blocks from the device. */
-static int gxe_bd_read_blocks(int disk_id, uint64_t ba, unsigned cnt,
-    void *buf) {
-
+static int gxe_bd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
+    void *buf, size_t size)
+{
+	int disk_id = bd_srv_gxe(bd)->disk_id;
 	int rc;
+
+	if (size < cnt * block_size)
+		return EINVAL;
 
 	while (cnt > 0) {
@@ -266,8 +242,12 @@
 
 /** Write multiple blocks to the device. */
-static int gxe_bd_write_blocks(int disk_id, uint64_t ba, unsigned cnt,
-    const void *buf) {
-
+static int gxe_bd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
+    const void *buf, size_t size)
+{
+	int disk_id = bd_srv_gxe(bd)->disk_id;
 	int rc;
+
+	if (size < cnt * block_size)
+		return EINVAL;
 
 	while (cnt > 0) {
@@ -282,4 +262,17 @@
 
 	return EOK;
+}
+
+/** Get device block size. */
+static int gxe_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
+{
+	*rsize = block_size;
+	return EOK;
+}
+
+/** Get number of blocks on device. */
+static int gxe_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
+{
+	return ENOTSUP;
 }
 
Index: uspace/srv/bd/part/guid_part/guid_part.c
===================================================================
--- uspace/srv/bd/part/guid_part/guid_part.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/bd/part/guid_part/guid_part.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,7 +47,7 @@
 #include <stdlib.h>
 #include <unistd.h>
-#include <ipc/bd.h>
 #include <async.h>
 #include <as.h>
+#include <bd_srv.h>
 #include <fibril_synch.h>
 #include <loc.h>
@@ -55,5 +55,5 @@
 #include <sys/typefmt.h>
 #include <inttypes.h>
-#include <libblock.h>
+#include <block.h>
 #include <loc.h>
 #include <errno.h>
@@ -83,4 +83,6 @@
 	/** Service representing the partition (outbound device) */
 	service_id_t dsid;
+	/** Block device service structure */
+	bd_srvs_t bds;
 	/** Points to next partition structure. */
 	struct part *next;
@@ -100,7 +102,26 @@
 static void gpt_pte_to_part(const gpt_entry_t *pte, part_t *part);
 static void gpt_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-static int gpt_bd_read(part_t *p, aoff64_t ba, size_t cnt, void *buf);
-static int gpt_bd_write(part_t *p, aoff64_t ba, size_t cnt, const void *buf);
 static int gpt_bsa_translate(part_t *p, aoff64_t ba, size_t cnt, aoff64_t *gba);
+
+static int gpt_bd_open(bd_srvs_t *, bd_srv_t *);
+static int gpt_bd_close(bd_srv_t *);
+static int gpt_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
+static int gpt_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
+static int gpt_bd_get_block_size(bd_srv_t *, size_t *);
+static int gpt_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
+
+static bd_ops_t gpt_bd_ops = {
+	.open = gpt_bd_open,
+	.close = gpt_bd_close,
+	.read_blocks = gpt_bd_read_blocks,
+	.write_blocks = gpt_bd_write_blocks,
+	.get_block_size = gpt_bd_get_block_size,
+	.get_num_blocks = gpt_bd_get_num_blocks
+};
+
+static part_t *bd_srv_part(bd_srv_t *bd)
+{
+	return (part_t *)bd->srvs->sarg;
+}
 
 int main(int argc, char **argv)
@@ -304,4 +325,8 @@
 	}
 
+	bd_srvs_init(&part->bds);
+	part->bds.ops = &gpt_bd_ops;
+	part->bds.sarg = part;
+
 	part->dsid = 0;
 	part->next = NULL;
@@ -310,14 +335,5 @@
 static void gpt_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	size_t comm_size;
-	void *fs_va = NULL;
-	ipc_callid_t callid;
-	ipc_call_t call;
-	sysarg_t method;
 	service_id_t dh;
-	unsigned int flags;
-	int retval;
-	aoff64_t ba;
-	size_t cnt;
 	part_t *part;
 
@@ -341,68 +357,28 @@
 	assert(part->present == true);
 
-	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	async_answer_0(iid, EOK);
-
-	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	(void) async_share_out_finalize(callid, &fs_va);
-	if (fs_va == AS_MAP_FAILED) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	while (true) {
-		callid = async_get_call(&call);
-		method = IPC_GET_IMETHOD(call);
-		
-		if (!method) {
-			/* The other side has hung up. */
-			async_answer_0(callid, EOK);
-			return;
-		}
-		
-		switch (method) {
-		case BD_READ_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = gpt_bd_read(part, ba, cnt, fs_va);
-			break;
-		case BD_WRITE_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = gpt_bd_write(part, ba, cnt, fs_va);
-			break;
-		case BD_GET_BLOCK_SIZE:
-			async_answer_1(callid, EOK, block_size);
-			continue;
-		case BD_GET_NUM_BLOCKS:
-			async_answer_2(callid, EOK, LOWER32(part->length),
-			    UPPER32(part->length));
-			continue;
-		default:
-			retval = EINVAL;
-			break;
-		}
-		async_answer_0(callid, retval);
-	}
+	bd_conn(iid, icall, &part->bds);
+}
+
+/** Open device. */
+static int gpt_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
+{
+	return EOK;
+}
+
+/** Close device. */
+static int gpt_bd_close(bd_srv_t *bd)
+{
+	return EOK;
 }
 
 /** Read blocks from partition. */
-static int gpt_bd_read(part_t *p, aoff64_t ba, size_t cnt, void *buf)
-{
+static int gpt_bd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt, void *buf,
+    size_t size)
+{
+	part_t *p = bd_srv_part(bd);
 	aoff64_t gba;
+
+	if (cnt * block_size < size)
+		return EINVAL;
 
 	if (gpt_bsa_translate(p, ba, cnt, &gba) != EOK)
@@ -413,7 +389,12 @@
 
 /** Write blocks to partition. */
-static int gpt_bd_write(part_t *p, aoff64_t ba, size_t cnt, const void *buf)
-{
+static int gpt_bd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
+    const void *buf, size_t size)
+{
+	part_t *p = bd_srv_part(bd);
 	aoff64_t gba;
+
+	if (cnt * block_size < size)
+		return EINVAL;
 
 	if (gpt_bsa_translate(p, ba, cnt, &gba) != EOK)
@@ -422,4 +403,21 @@
 	return block_write_direct(indev_sid, gba, cnt, buf);
 }
+
+/** Get device block size. */
+static int gpt_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
+{
+	*rsize = block_size;
+	return EOK;
+}
+
+/** Get number of blocks on device. */
+static int gpt_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
+{
+	part_t *part = bd_srv_part(bd);
+
+	*rnb = part->length;
+	return EOK;
+}
+
 
 /** Translate block segment address with range checking. */
Index: uspace/srv/bd/part/mbr_part/mbr_part.c
===================================================================
--- uspace/srv/bd/part/mbr_part/mbr_part.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/bd/part/mbr_part/mbr_part.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -44,5 +44,5 @@
  *
  * Referemces:
- *	
+ *
  * The source of MBR structures for this driver have been the following
  * Wikipedia articles:
@@ -57,7 +57,7 @@
 #include <stdlib.h>
 #include <unistd.h>
-#include <ipc/bd.h>
 #include <async.h>
 #include <as.h>
+#include <bd_srv.h>
 #include <fibril_synch.h>
 #include <loc.h>
@@ -65,5 +65,5 @@
 #include <sys/typefmt.h>
 #include <inttypes.h>
-#include <libblock.h>
+#include <block.h>
 #include <errno.h>
 #include <bool.h>
@@ -100,4 +100,6 @@
 	/** Device representing the partition (outbound device) */
 	service_id_t dsid;
+	/** Block device service sturcture */
+	bd_srvs_t bds;
 	/** Points to next partition structure. */
 	struct part *next;
@@ -140,5 +142,5 @@
 
 /** Partitioned device (inbound device) */
-static service_id_t indef_sid;
+static service_id_t indev_sid;
 
 /** List of partitions. This structure is an empty head. */
@@ -150,7 +152,26 @@
 static void mbr_pte_to_part(uint32_t base, const pt_entry_t *pte, part_t *part);
 static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-static int mbr_bd_read(part_t *p, uint64_t ba, size_t cnt, void *buf);
-static int mbr_bd_write(part_t *p, uint64_t ba, size_t cnt, const void *buf);
 static int mbr_bsa_translate(part_t *p, uint64_t ba, size_t cnt, uint64_t *gba);
+
+static int mbr_bd_open(bd_srvs_t *, bd_srv_t *);
+static int mbr_bd_close(bd_srv_t *);
+static int mbr_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
+static int mbr_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
+static int mbr_bd_get_block_size(bd_srv_t *, size_t *);
+static int mbr_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
+
+static bd_ops_t mbr_bd_ops = {
+	.open = mbr_bd_open,
+	.close = mbr_bd_close,
+	.read_blocks = mbr_bd_read_blocks,
+	.write_blocks = mbr_bd_write_blocks,
+	.get_block_size = mbr_bd_get_block_size,
+	.get_num_blocks = mbr_bd_get_num_blocks
+};
+
+static part_t *bd_srv_part(bd_srv_t *bd)
+{
+	return (part_t *)bd->srvs->sarg;
+}
 
 int main(int argc, char **argv)
@@ -183,5 +204,5 @@
 	part_t *part;
 
-	rc = loc_service_get_id(dev_name, &indef_sid, 0);
+	rc = loc_service_get_id(dev_name, &indev_sid, 0);
 	if (rc != EOK) {
 		printf(NAME ": could not resolve device `%s'.\n", dev_name);
@@ -189,5 +210,5 @@
 	}
 
-	rc = block_init(EXCHANGE_SERIALIZE, indef_sid, 2048);
+	rc = block_init(EXCHANGE_SERIALIZE, indev_sid, 2048);
 	if (rc != EOK)  {
 		printf(NAME ": could not init libblock.\n");
@@ -197,5 +218,5 @@
 	/* Determine and verify block size. */
 
-	rc = block_get_bsize(indef_sid, &block_size);
+	rc = block_get_bsize(indev_sid, &block_size);
 	if (rc != EOK) {
 		printf(NAME ": error getting block size.\n");
@@ -281,5 +302,5 @@
 	 */
 
-	rc = block_read_direct(indef_sid, 0, 1, brb);
+	rc = block_read_direct(indev_sid, 0, 1, brb);
 	if (rc != EOK) {
 		printf(NAME ": Failed reading MBR block.\n");
@@ -332,5 +353,5 @@
 		 */
 		ba = cp.start_addr;
-		rc = block_read_direct(indef_sid, ba, 1, brb);
+		rc = block_read_direct(indev_sid, ba, 1, brb);
 		if (rc != EOK) {
 			printf(NAME ": Failed reading EBR block at %"
@@ -381,4 +402,8 @@
 	part->present = (pte->ptype != PT_UNUSED) ? true : false;
 
+	bd_srvs_init(&part->bds);
+	part->bds.ops = &mbr_bd_ops;
+	part->bds.sarg = part;
+
 	part->dsid = 0;
 	part->next = NULL;
@@ -387,14 +412,5 @@
 static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	size_t comm_size;
-	void *fs_va = NULL;
-	ipc_callid_t callid;
-	ipc_call_t call;
-	sysarg_t method;
 	service_id_t dh;
-	unsigned int flags;
-	int retval;
-	uint64_t ba;
-	size_t cnt;
 	part_t *part;
 
@@ -417,85 +433,65 @@
 
 	assert(part->present == true);
-
-	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	async_answer_0(iid, EOK);
-
-	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	(void) async_share_out_finalize(callid, &fs_va);
-	if (fs_va == AS_MAP_FAILED) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	while (1) {
-		callid = async_get_call(&call);
-		method = IPC_GET_IMETHOD(call);
-		
-		if (!method) {
-			/* The other side has hung up. */
-			async_answer_0(callid, EOK);
-			return;
-		}
-		
-		switch (method) {
-		case BD_READ_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = mbr_bd_read(part, ba, cnt, fs_va);
-			break;
-		case BD_WRITE_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = mbr_bd_write(part, ba, cnt, fs_va);
-			break;
-		case BD_GET_BLOCK_SIZE:
-			async_answer_1(callid, EOK, block_size);
-			continue;
-		case BD_GET_NUM_BLOCKS:
-			async_answer_2(callid, EOK, LOWER32(part->length),
-			    UPPER32(part->length));
-			continue;
-		default:
-			retval = EINVAL;
-			break;
-		}
-		async_answer_0(callid, retval);
-	}
+	bd_conn(iid, icall, &part->bds);
+}
+
+/** Open device. */
+static int mbr_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
+{
+	return EOK;
+}
+
+/** Close device. */
+static int mbr_bd_close(bd_srv_t *bd)
+{
+	return EOK;
 }
 
 /** Read blocks from partition. */
-static int mbr_bd_read(part_t *p, uint64_t ba, size_t cnt, void *buf)
-{
-	uint64_t gba;
+static int mbr_bd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt, void *buf,
+    size_t size)
+{
+	part_t *p = bd_srv_part(bd);
+	aoff64_t gba;
+
+	if (cnt * block_size < size)
+		return EINVAL;
 
 	if (mbr_bsa_translate(p, ba, cnt, &gba) != EOK)
 		return ELIMIT;
 
-	return block_read_direct(indef_sid, gba, cnt, buf);
+	return block_read_direct(indev_sid, gba, cnt, buf);
 }
 
 /** Write blocks to partition. */
-static int mbr_bd_write(part_t *p, uint64_t ba, size_t cnt, const void *buf)
-{
-	uint64_t gba;
+static int mbr_bd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
+    const void *buf, size_t size)
+{
+	part_t *p = bd_srv_part(bd);
+	aoff64_t gba;
+
+	if (cnt * block_size < size)
+		return EINVAL;
 
 	if (mbr_bsa_translate(p, ba, cnt, &gba) != EOK)
 		return ELIMIT;
 
-	return block_write_direct(indef_sid, gba, cnt, buf);
+	return block_write_direct(indev_sid, gba, cnt, buf);
+}
+
+/** Get device block size. */
+static int mbr_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
+{
+	*rsize = block_size;
+	return EOK;
+}
+
+/** Get number of blocks on device. */
+static int mbr_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
+{
+	part_t *part = bd_srv_part(bd);
+
+	*rnb = part->length;
+	return EOK;
 }
 
Index: uspace/srv/bd/rd/rd.c
===================================================================
--- uspace/srv/bd/rd/rd.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/bd/rd/rd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -43,4 +43,5 @@
 #include <sysinfo.h>
 #include <as.h>
+#include <bd_srv.h>
 #include <ddi.h>
 #include <align.h>
@@ -53,5 +54,4 @@
 #include <stdio.h>
 #include <loc.h>
-#include <ipc/bd.h>
 #include <macros.h>
 #include <inttypes.h>
@@ -68,6 +68,10 @@
 static const size_t block_size = 512;
 
-static int rd_read_blocks(uint64_t ba, size_t cnt, void *buf);
-static int rd_write_blocks(uint64_t ba, size_t cnt, const void *buf);
+static int rd_open(bd_srvs_t *, bd_srv_t *);
+static int rd_close(bd_srv_t *);
+static int rd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
+static int rd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
+static int rd_get_block_size(bd_srv_t *, size_t *);
+static int rd_get_num_blocks(bd_srv_t *, aoff64_t *);
 
 /** This rwlock protects the ramdisk's data.
@@ -78,102 +82,37 @@
  *
  */
-fibril_rwlock_t rd_lock;
-
-/** Handle one connection to ramdisk.
- *
- * @param iid   Hash of the request that opened the connection.
- * @param icall Call data of the request that opened the connection.
- */
-static void rd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int retval;
-	void *fs_va = NULL;
-	uint64_t ba;
-	size_t cnt;
-	size_t comm_size;
-	
-	/*
-	 * Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	async_answer_0(iid, EOK);
-	
-	/*
-	 * Now we wait for the client to send us its communication as_area.
-	 */
-	unsigned int flags;
-	if (async_share_out_receive(&callid, &comm_size, &flags)) {
-		(void) async_share_out_finalize(callid, &fs_va);
-		if (fs_va == AS_MAP_FAILED) {
-			async_answer_0(callid, EHANGUP);
-			return;
-		}
-	} else {
-		/*
-		 * The client doesn't speak the same protocol.
-		 * At this point we can't handle protocol variations.
-		 * Close the connection.
-		 */
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-	
-	while (true) {
-		callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			/*
-			 * The other side has hung up.
-			 * Exit the fibril.
-			 */
-			async_answer_0(callid, EOK);
-			return;
-		}
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case BD_READ_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = rd_read_blocks(ba, cnt, fs_va);
-			break;
-		case BD_WRITE_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = rd_write_blocks(ba, cnt, fs_va);
-			break;
-		case BD_GET_BLOCK_SIZE:
-			async_answer_1(callid, EOK, block_size);
-			continue;
-		case BD_GET_NUM_BLOCKS:
-			async_answer_2(callid, EOK, LOWER32(rd_size / block_size),
-			    UPPER32(rd_size / block_size));
-			continue;
-		default:
-			/*
-			 * The client doesn't speak the same protocol.
-			 * Instead of closing the connection, we just ignore
-			 * the call. This can be useful if the client uses a
-			 * newer version of the protocol.
-			 */
-			retval = EINVAL;
-			break;
-		}
-		async_answer_0(callid, retval);
-	}
+static fibril_rwlock_t rd_lock;
+
+static bd_ops_t rd_bd_ops = {
+	.open = rd_open,
+	.close = rd_close,
+	.read_blocks = rd_read_blocks,
+	.write_blocks = rd_write_blocks,
+	.get_block_size = rd_get_block_size,
+	.get_num_blocks = rd_get_num_blocks
+};
+
+static bd_srvs_t bd_srvs;
+
+static void rd_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	bd_conn(iid, icall, &bd_srvs);
+}
+
+/** Open device. */
+static int rd_open(bd_srvs_t *bds, bd_srv_t *bd)
+{
+	return EOK;
+}
+
+/** Close device. */
+static int rd_close(bd_srv_t *bd)
+{
+	return EOK;
 }
 
 /** Read blocks from the device. */
-static int rd_read_blocks(uint64_t ba, size_t cnt, void *buf)
+static int rd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt, void *buf,
+    size_t size)
 {
 	if ((ba + cnt) * block_size > rd_size) {
@@ -183,5 +122,5 @@
 	
 	fibril_rwlock_read_lock(&rd_lock);
-	memcpy(buf, rd_addr + ba * block_size, block_size * cnt);
+	memcpy(buf, rd_addr + ba * block_size, min(block_size * cnt, size));
 	fibril_rwlock_read_unlock(&rd_lock);
 	
@@ -190,5 +129,6 @@
 
 /** Write blocks to the device. */
-static int rd_write_blocks(uint64_t ba, size_t cnt, const void *buf)
+static int rd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
+    const void *buf, size_t size)
 {
 	if ((ba + cnt) * block_size > rd_size) {
@@ -198,5 +138,5 @@
 	
 	fibril_rwlock_write_lock(&rd_lock);
-	memcpy(rd_addr + ba * block_size, buf, block_size * cnt);
+	memcpy(rd_addr + ba * block_size, buf, min(block_size * cnt, size));
 	fibril_rwlock_write_unlock(&rd_lock);
 	
@@ -235,5 +175,8 @@
 	    (void *) addr_phys, size);
 	
-	async_set_client_connection(rd_connection);
+	bd_srvs_init(&bd_srvs);
+	bd_srvs.ops = &rd_bd_ops;
+	
+	async_set_client_connection(rd_client_conn);
 	ret = loc_server_register(NAME);
 	if (ret != EOK) {
@@ -254,4 +197,18 @@
 }
 
+/** Get device block size. */
+static int rd_get_block_size(bd_srv_t *bd, size_t *rsize)
+{
+	*rsize = block_size;
+	return EOK;
+}
+
+/** Get number of blocks on device. */
+static int rd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
+{
+	*rnb = rd_size / block_size;
+	return EOK;
+}
+
 int main(int argc, char **argv)
 {
Index: uspace/srv/bd/sata_bd/Makefile
===================================================================
--- uspace/srv/bd/sata_bd/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/bd/sata_bd/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2012 Petr Jerman
+# 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 = sata_bd
+
+SOURCES = \
+	sata_bd.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/bd/sata_bd/sata_bd.c
===================================================================
--- uspace/srv/bd/sata_bd/sata_bd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/bd/sata_bd/sata_bd.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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 bd
+ * @{
+ */
+
+/**
+ * @file
+ * @brief SATA disk driver
+ *
+ */
+
+#include <sys/types.h>
+#include <bd_srv.h>
+#include <errno.h>
+#include <stdio.h>
+#include <str.h>
+#include <loc.h>
+#include <macros.h>
+
+#include <device/ahci.h>
+#include "sata_bd.h"
+
+#define NAME       "sata_bd"
+#define NAMESPACE  "bd"
+
+/** Maximum number of disks handled */
+#define MAXDISKS  256
+
+static sata_bd_dev_t disk[MAXDISKS];
+static int disk_count;
+
+static int sata_bd_open(bd_srvs_t *, bd_srv_t *);
+static int sata_bd_close(bd_srv_t *);
+static int sata_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
+static int sata_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
+static int sata_bd_get_block_size(bd_srv_t *, size_t *);
+static int sata_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
+
+static bd_ops_t sata_bd_ops = {
+	.open = sata_bd_open,
+	.close = sata_bd_close,
+	.read_blocks = sata_bd_read_blocks,
+	.write_blocks = sata_bd_write_blocks,
+	.get_block_size = sata_bd_get_block_size,
+	.get_num_blocks = sata_bd_get_num_blocks
+};
+
+static sata_bd_dev_t *bd_srv_sata(bd_srv_t *bd)
+{
+	return (sata_bd_dev_t *) bd->srvs->sarg;
+}
+
+/** Find SATA devices in device tree.
+ *
+ *  @param Device manager handle describing container for searching.  
+ *
+ *  @return EOK if succeed, error code otherwise.
+ *
+ */
+static int scan_device_tree(devman_handle_t funh)
+{
+	devman_handle_t devh;
+	devman_handle_t *cfuns;
+	size_t count, i;
+	int rc;
+		
+	/* If device is SATA, add device to the disk array. */
+	disk[disk_count].sess = ahci_get_sess(funh, &disk[disk_count].dev_name);
+	if(disk[disk_count].sess != NULL) {
+		
+		ahci_get_sata_device_name(disk[disk_count].sess,
+		    SATA_DEV_NAME_LENGTH, disk[disk_count].sata_dev_name);
+		
+		ahci_get_block_size(disk[disk_count].sess,
+		    &disk[disk_count].block_size);
+		
+		ahci_get_num_blocks(disk[disk_count].sess, &disk[disk_count].blocks);
+		
+		bd_srvs_init(&disk[disk_count].bds);
+		disk[disk_count].bds.ops = &sata_bd_ops;
+		disk[disk_count].bds.sarg = &disk[disk_count];
+		
+		printf("Device %s - %s , blocks: %lu, block_size: %lu\n", 
+		    disk[disk_count].dev_name, disk[disk_count].sata_dev_name,
+			    (long unsigned int) disk[disk_count].blocks,
+				(long unsigned int) disk[disk_count].block_size);
+
+		++disk_count;
+	}
+	
+	/* search children */
+	rc = devman_fun_get_child(funh, &devh);
+	if (rc == ENOENT)
+		return EOK;
+
+	if (rc != EOK) {
+		printf(NAME ": Failed getting child device for function %s.\n", "xxx");
+		return rc;
+	}
+
+	rc = devman_dev_get_functions(devh, &cfuns, &count);
+	if (rc != EOK) {
+		printf(NAME ": Failed getting list of functions for device %s.\n",
+		    "xxx");
+		return rc;
+	}
+
+	for (i = 0; i < count; i++)
+		scan_device_tree(cfuns[i]);
+
+	free(cfuns);
+	return EOK;
+}
+
+/** Find sata devices in device tree from root.
+ *
+ *  @return EOK if succeed, error code otherwise.
+ *
+ */
+static int get_sata_disks()
+{
+	devman_handle_t root_fun;
+	int rc;
+	
+	disk_count = 0;
+
+	rc = devman_fun_get_handle("/", &root_fun, 0);
+	if (rc != EOK) {
+		printf(NAME ": Error resolving root function.\n");
+		return EIO;
+	}
+	
+	scan_device_tree(root_fun);
+	
+	return EOK;
+}
+
+/** Block device connection handler. */
+static void sata_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	service_id_t dsid;
+	int disk_id, i;
+
+	/* Get the device service ID. */
+	dsid = IPC_GET_ARG1(*icall);
+
+	/* Determine which disk device is the client connecting to. */
+	disk_id = -1;
+	for (i = 0; i < MAXDISKS; i++)
+		if (disk[i].service_id == dsid)
+			disk_id = i;
+
+	if (disk_id < 0) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	bd_conn(iid, icall, &disk[disk_id].bds);
+}
+
+/** Open device. */
+static int sata_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
+{
+	return EOK;
+}
+
+/** Close device. */
+static int sata_bd_close(bd_srv_t *bd)
+{
+	return EOK;
+}
+
+/** Read blocks from partition. */
+static int sata_bd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt, void *buf,
+    size_t size)
+{
+	sata_bd_dev_t *sbd = bd_srv_sata(bd);
+
+	if (size < cnt * sbd->block_size)
+		return EINVAL;
+
+	return ahci_read_blocks(sbd->sess, ba, cnt, buf);
+}
+
+/** Write blocks to partition. */
+static int sata_bd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
+    const void *buf, size_t size)
+{
+	sata_bd_dev_t *sbd = bd_srv_sata(bd);
+
+	if (size < cnt * sbd->block_size)
+		return EINVAL;
+
+	return ahci_write_blocks(sbd->sess, ba, cnt, (void *)buf);
+}
+
+/** Get device block size. */
+static int sata_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
+{
+	sata_bd_dev_t *sbd = bd_srv_sata(bd);
+
+	*rsize = sbd->block_size;
+	return EOK;
+}
+
+/** Get number of blocks on device. */
+static int sata_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
+{
+	sata_bd_dev_t *sbd = bd_srv_sata(bd);
+
+	*rnb = sbd->blocks;
+	return EOK;
+}
+
+
+int main(int argc, char **argv)
+{
+	int rc;
+	
+	async_set_client_connection(sata_bd_connection);
+	rc = loc_server_register(NAME);
+	if (rc < 0) {
+		printf(NAME ": Unable to register driver.\n");
+		return rc;
+	}
+	
+	rc = get_sata_disks();
+	if (rc != EOK) {
+		return rc;
+	}
+
+	for(int i=0; i < disk_count; i++) {
+		char name[1024];
+		snprintf(name, 1024, "%s/%s", NAMESPACE, disk[i].dev_name);
+		rc = loc_service_register(name, &disk[i].service_id);
+		if (rc != EOK) {
+			printf(NAME ": Unable to register device %s.\n", name);
+			return rc;
+		}
+	}
+		
+	printf(NAME ": Accepting connections\n");
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/bd/sata_bd/sata_bd.h
===================================================================
--- uspace/srv/bd/sata_bd/sata_bd.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/bd/sata_bd/sata_bd.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012 Petr Jerman
+ * 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 bd
+ * @{
+ */
+/** @file SATA block device driver definitions.
+ */
+
+#ifndef __SATA_BD_H__
+#define __SATA_BD_H__
+
+#define SATA_DEV_NAME_LENGTH 256
+
+#include <async.h>
+#include <bd_srv.h>
+#include <loc.h>
+#include <sys/types.h>
+
+/** SATA Block Device. */
+typedef struct {
+	/** Device name in device tree. */
+	char *dev_name;
+	/** SATA Device name. */
+	char sata_dev_name[SATA_DEV_NAME_LENGTH];
+	/** Session to device methods. */
+	async_sess_t *sess;
+	/** Loc service id. */
+	service_id_t service_id;
+	/** Number of blocks. */
+	uint64_t blocks;
+	/** Size of block. */
+	size_t block_size;
+	/** Block device server structure */
+	bd_srvs_t bds;
+} sata_bd_dev_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/devman/devman.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -66,50 +66,78 @@
 /* hash table operations */
 
-static hash_index_t devices_hash(unsigned long key[])
-{
-	return key[0] % DEVICE_BUCKETS;
-}
-
-static int devman_devices_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
-{
-	dev_node_t *dev = hash_table_get_instance(item, dev_node_t, devman_dev);
-	return (dev->handle == (devman_handle_t) key[0]);
-}
-
-static int devman_functions_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
-{
-	fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devman_fun);
-	return (fun->handle == (devman_handle_t) key[0]);
-}
-
-static int loc_functions_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
-{
-	fun_node_t *fun = hash_table_get_instance(item, fun_node_t, loc_fun);
-	return (fun->service_id == (service_id_t) key[0]);
-}
-
-static void devices_remove_callback(link_t *item)
-{
-}
-
-static hash_table_operations_t devman_devices_ops = {
-	.hash = devices_hash,
-	.compare = devman_devices_compare,
-	.remove_callback = devices_remove_callback
+static inline size_t handle_key_hash(void *key)
+{
+	devman_handle_t handle = *(devman_handle_t*)key;
+	return handle;
+}
+
+static size_t devman_devices_hash(const ht_link_t *item)
+{
+	dev_node_t *dev = hash_table_get_inst(item, dev_node_t, devman_dev);
+	return handle_key_hash(&dev->handle);
+}
+
+static size_t devman_functions_hash(const ht_link_t *item)
+{
+	fun_node_t *fun = hash_table_get_inst(item, fun_node_t, devman_fun);
+	return handle_key_hash(&fun->handle);
+}
+
+static bool devman_devices_key_equal(void *key, const ht_link_t *item)
+{
+	devman_handle_t handle = *(devman_handle_t*)key;
+	dev_node_t *dev = hash_table_get_inst(item, dev_node_t, devman_dev);
+	return dev->handle == handle;
+}
+
+static bool devman_functions_key_equal(void *key, const ht_link_t *item)
+{
+	devman_handle_t handle = *(devman_handle_t*)key;
+	fun_node_t *fun = hash_table_get_inst(item, fun_node_t, devman_fun);
+	return fun->handle == handle;
+}
+
+static inline size_t service_id_key_hash(void *key)
+{
+	service_id_t service_id = *(service_id_t*)key;
+	return service_id;
+}
+
+static size_t loc_functions_hash(const ht_link_t *item)
+{
+	fun_node_t *fun = hash_table_get_inst(item, fun_node_t, loc_fun);
+	return service_id_key_hash(&fun->service_id);
+}
+
+static bool loc_functions_key_equal(void *key, const ht_link_t *item)
+{
+	service_id_t service_id = *(service_id_t*)key;
+	fun_node_t *fun = hash_table_get_inst(item, fun_node_t, loc_fun);
+	return fun->service_id == service_id;
+}
+
+
+static hash_table_ops_t devman_devices_ops = {
+	.hash = devman_devices_hash,
+	.key_hash = handle_key_hash,
+	.key_equal = devman_devices_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
 };
 
-static hash_table_operations_t devman_functions_ops = {
-	.hash = devices_hash,
-	.compare = devman_functions_compare,
-	.remove_callback = devices_remove_callback
+static hash_table_ops_t devman_functions_ops = {
+	.hash = devman_functions_hash,
+	.key_hash = handle_key_hash,
+	.key_equal = devman_functions_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
 };
 
-static hash_table_operations_t loc_devices_ops = {
-	.hash = devices_hash,
-	.compare = loc_functions_compare,
-	.remove_callback = devices_remove_callback
+static hash_table_ops_t loc_devices_ops = {
+	.hash = loc_functions_hash,
+	.key_hash = service_id_key_hash,
+	.key_equal = loc_functions_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
 };
 
@@ -151,5 +179,5 @@
 	fibril_mutex_unlock(&drivers_list->drivers_mutex);
 
-	log_msg(LVL_NOTE, "Driver `%s' was added to the list of available "
+	log_msg(LOG_DEFAULT, LVL_NOTE, "Driver `%s' was added to the list of available "
 	    "drivers.", drv->name);
 }
@@ -242,5 +270,5 @@
 bool read_match_ids(const char *conf_path, match_id_list_t *ids)
 {
-	log_msg(LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path);
 	
 	bool suc = false;
@@ -252,5 +280,5 @@
 	fd = open(conf_path, O_RDONLY);
 	if (fd < 0) {
-		log_msg(LVL_ERROR, "Unable to open `%s' for reading: %s.",
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to open `%s' for reading: %s.",
 		    conf_path, str_error(fd));
 		goto cleanup;
@@ -261,5 +289,5 @@
 	lseek(fd, 0, SEEK_SET);
 	if (len == 0) {
-		log_msg(LVL_ERROR, "Configuration file '%s' is empty.",
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Configuration file '%s' is empty.",
 		    conf_path);
 		goto cleanup;
@@ -268,5 +296,5 @@
 	buf = malloc(len + 1);
 	if (buf == NULL) {
-		log_msg(LVL_ERROR, "Memory allocation failed when parsing file "
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Memory allocation failed when parsing file "
 		    "'%s'.", conf_path);
 		goto cleanup;
@@ -275,5 +303,5 @@
 	ssize_t read_bytes = read_all(fd, buf, len);
 	if (read_bytes <= 0) {
-		log_msg(LVL_ERROR, "Unable to read file '%s' (%zd).", conf_path,
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to read file '%s' (%zd).", conf_path,
 		    read_bytes);
 		goto cleanup;
@@ -314,5 +342,5 @@
 bool get_driver_info(const char *base_path, const char *name, driver_t *drv)
 {
-	log_msg(LVL_DEBUG, "get_driver_info(base_path=\"%s\", name=\"%s\")",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "get_driver_info(base_path=\"%s\", name=\"%s\")",
 	    base_path, name);
 	
@@ -346,5 +374,5 @@
 	struct stat s;
 	if (stat(drv->binary_path, &s) == ENOENT) { /* FIXME!! */
-		log_msg(LVL_ERROR, "Driver not found at path `%s'.",
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Driver not found at path `%s'.",
 		    drv->binary_path);
 		goto cleanup;
@@ -374,5 +402,5 @@
 int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path)
 {
-	log_msg(LVL_DEBUG, "lookup_available_drivers(dir=\"%s\")", dir_path);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "lookup_available_drivers(dir=\"%s\")", dir_path);
 	
 	int drv_cnt = 0;
@@ -408,5 +436,5 @@
 	dev_node_t *dev;
 	
-	log_msg(LVL_DEBUG, "create_root_nodes()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "create_root_nodes()");
 	
 	fibril_rwlock_write_lock(&tree->rwlock);
@@ -495,5 +523,5 @@
 void attach_driver(dev_tree_t *tree, dev_node_t *dev, driver_t *drv)
 {
-	log_msg(LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")",
 	    dev->pfun->pathname, drv->name);
 	
@@ -520,5 +548,5 @@
 	assert(drv != NULL);
 	
-	log_msg(LVL_DEBUG, "detach_driver(dev=\"%s\",drv=\"%s\")",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "detach_driver(dev=\"%s\",drv=\"%s\")",
 	    dev->pfun->pathname, drv->name);
 	
@@ -545,9 +573,9 @@
 	assert(fibril_mutex_is_locked(&drv->driver_mutex));
 	
-	log_msg(LVL_DEBUG, "start_driver(drv=\"%s\")", drv->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "start_driver(drv=\"%s\")", drv->name);
 	
 	rc = task_spawnl(NULL, drv->binary_path, drv->binary_path, NULL);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Spawning driver `%s' (%s) failed: %s.",
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Spawning driver `%s' (%s) failed: %s.",
 		    drv->name, drv->binary_path, str_error(rc));
 		return false;
@@ -594,5 +622,5 @@
 	link_t *link;
 
-	log_msg(LVL_DEBUG, "pass_devices_to_driver(driver=\"%s\")",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "pass_devices_to_driver(driver=\"%s\")",
 	    driver->name);
 
@@ -614,5 +642,5 @@
 		}
 
-		log_msg(LVL_DEBUG, "pass_devices_to_driver: dev->refcnt=%d\n",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "pass_devices_to_driver: dev->refcnt=%d\n",
 		    (int)atomic_get(&dev->refcnt));
 		dev_add_ref(dev);
@@ -650,5 +678,5 @@
 	 * immediately and possibly started here as well.
 	 */
-	log_msg(LVL_DEBUG, "Driver `%s' enters running state.", driver->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Driver `%s' enters running state.", driver->name);
 	driver->state = DRIVER_RUNNING;
 
@@ -667,5 +695,5 @@
 void initialize_running_driver(driver_t *driver, dev_tree_t *tree)
 {
-	log_msg(LVL_DEBUG, "initialize_running_driver(driver=\"%s\")",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "initialize_running_driver(driver=\"%s\")",
 	    driver->name);
 	
@@ -761,5 +789,5 @@
 	 * access any structures that would affect driver_t.
 	 */
-	log_msg(LVL_DEBUG, "add_device(drv=\"%s\", dev=\"%s\")",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "add_device(drv=\"%s\", dev=\"%s\")",
 	    drv->name, dev->pfun->name);
 	
@@ -827,5 +855,5 @@
 	driver_t *drv = find_best_match_driver(drivers_list, dev);
 	if (drv == NULL) {
-		log_msg(LVL_ERROR, "No driver found for device `%s'.",
+		log_msg(LOG_DEFAULT, LVL_ERROR, "No driver found for device `%s'.",
 		    dev->pfun->pathname);
 		return false;
@@ -867,5 +895,5 @@
 	assert(dev != NULL);
 	
-	log_msg(LVL_DEBUG, "driver_dev_remove(%p)", dev);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_dev_remove(%p)", dev);
 	
 	fibril_rwlock_read_lock(&tree->rwlock);
@@ -890,5 +918,5 @@
 	assert(dev != NULL);
 	
-	log_msg(LVL_DEBUG, "driver_dev_gone(%p)", dev);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_dev_gone(%p)", dev);
 	
 	fibril_rwlock_read_lock(&tree->rwlock);
@@ -911,5 +939,5 @@
 	devman_handle_t handle;
 	
-	log_msg(LVL_DEBUG, "driver_fun_online(%p)", fun);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_fun_online(%p)", fun);
 
 	fibril_rwlock_read_lock(&tree->rwlock);
@@ -939,5 +967,5 @@
 	devman_handle_t handle;
 	
-	log_msg(LVL_DEBUG, "driver_fun_offline(%p)", fun);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_fun_offline(%p)", fun);
 
 	fibril_rwlock_read_lock(&tree->rwlock);
@@ -970,14 +998,11 @@
 bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list)
 {
-	log_msg(LVL_DEBUG, "init_device_tree()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "init_device_tree()");
 	
 	tree->current_handle = 0;
 	
-	hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1,
-	    &devman_devices_ops);
-	hash_table_create(&tree->devman_functions, DEVICE_BUCKETS, 1,
-	    &devman_functions_ops);
-	hash_table_create(&tree->loc_functions, DEVICE_BUCKETS, 1,
-	    &loc_devices_ops);
+	hash_table_create(&tree->devman_devices, 0, 0, &devman_devices_ops);
+	hash_table_create(&tree->devman_functions, 0, 0, &devman_functions_ops);
+	hash_table_create(&tree->loc_functions, 0, 0, &loc_devices_ops);
 	
 	fibril_rwlock_initialize(&tree->rwlock);
@@ -1013,5 +1038,4 @@
 	list_initialize(&dev->functions);
 	link_initialize(&dev->driver_devices);
-	link_initialize(&dev->devman_dev);
 	
 	return dev;
@@ -1052,5 +1076,4 @@
 }
 
-
 /** Find the device node structure of the device witch has the specified handle.
  *
@@ -1061,14 +1084,11 @@
 dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
 {
-	unsigned long key = handle;
-	link_t *link;
-	
 	assert(fibril_rwlock_is_locked(&tree->rwlock));
 	
-	link = hash_table_find(&tree->devman_devices, &key);
+	ht_link_t *link = hash_table_find(&tree->devman_devices, &handle);
 	if (link == NULL)
 		return NULL;
 	
-	return hash_table_get_instance(link, dev_node_t, devman_dev);
+	return hash_table_get_inst(link, dev_node_t, devman_dev);
 }
 
@@ -1142,8 +1162,7 @@
 	fun->state = FUN_INIT;
 	atomic_set(&fun->refcnt, 0);
+	fibril_mutex_initialize(&fun->busy_lock);
 	link_initialize(&fun->dev_functions);
 	list_initialize(&fun->match_ids.ids);
-	link_initialize(&fun->devman_fun);
-	link_initialize(&fun->loc_fun);
 	
 	return fun;
@@ -1186,4 +1205,16 @@
 }
 
+/** Make function busy for reconfiguration operations. */
+void fun_busy_lock(fun_node_t *fun)
+{
+	fibril_mutex_lock(&fun->busy_lock);
+}
+
+/** Mark end of reconfiguration operation. */
+void fun_busy_unlock(fun_node_t *fun)
+{
+	fibril_mutex_unlock(&fun->busy_lock);
+}
+
 /** Find the function node with the specified handle.
  *
@@ -1194,15 +1225,13 @@
 fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
 {
-	unsigned long key = handle;
-	link_t *link;
 	fun_node_t *fun;
 	
 	assert(fibril_rwlock_is_locked(&tree->rwlock));
 	
-	link = hash_table_find(&tree->devman_functions, &key);
+	ht_link_t *link = hash_table_find(&tree->devman_functions, &handle);
 	if (link == NULL)
 		return NULL;
 	
-	fun = hash_table_get_instance(link, fun_node_t, devman_fun);
+	fun = hash_table_get_inst(link, fun_node_t, devman_fun);
 	
 	return fun;
@@ -1249,5 +1278,5 @@
 	fun->pathname = (char *) malloc(pathsize);
 	if (fun->pathname == NULL) {
-		log_msg(LVL_ERROR, "Failed to allocate device path.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to allocate device path.");
 		return false;
 	}
@@ -1277,11 +1306,10 @@
 	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
 	
-	log_msg(LVL_DEBUG, "insert_dev_node(dev=%p, pfun=%p [\"%s\"])",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "insert_dev_node(dev=%p, pfun=%p [\"%s\"])",
 	    dev, pfun, pfun->pathname);
 
 	/* Add the node to the handle-to-node map. */
 	dev->handle = ++tree->current_handle;
-	unsigned long key = dev->handle;
-	hash_table_insert(&tree->devman_devices, &key, &dev->devman_dev);
+	hash_table_insert(&tree->devman_devices, &dev->devman_dev);
 
 	/* Add the node to the list of its parent's children. */
@@ -1301,9 +1329,8 @@
 	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
 	
-	log_msg(LVL_DEBUG, "remove_dev_node(dev=%p)", dev);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "remove_dev_node(dev=%p)", dev);
 	
 	/* Remove node from the handle-to-node map. */
-	unsigned long key = dev->handle;
-	hash_table_remove(&tree->devman_devices, &key, 1);
+	hash_table_remove(&tree->devman_devices, &dev->handle);
 	
 	/* Unlink from parent function. */
@@ -1346,6 +1373,5 @@
 	/* Add the node to the handle-to-node map. */
 	fun->handle = ++tree->current_handle;
-	unsigned long key = fun->handle;
-	hash_table_insert(&tree->devman_functions, &key, &fun->devman_fun);
+	hash_table_insert(&tree->devman_functions, &fun->devman_fun);
 
 	/* Add the node to the list of its parent's children. */
@@ -1367,6 +1393,5 @@
 	
 	/* Remove the node from the handle-to-node map. */
-	unsigned long key = fun->handle;
-	hash_table_remove(&tree->devman_functions, &key, 1);
+	hash_table_remove(&tree->devman_functions, &fun->handle);
 	
 	/* Remove the node from the list of its parent's children. */
@@ -1481,11 +1506,9 @@
 {
 	fun_node_t *fun = NULL;
-	link_t *link;
-	unsigned long key = (unsigned long) service_id;
 	
 	fibril_rwlock_read_lock(&tree->rwlock);
-	link = hash_table_find(&tree->loc_functions, &key);
+	ht_link_t *link = hash_table_find(&tree->loc_functions, &service_id);
 	if (link != NULL) {
-		fun = hash_table_get_instance(link, fun_node_t, loc_fun);
+		fun = hash_table_get_inst(link, fun_node_t, loc_fun);
 		fun_add_ref(fun);
 	}
@@ -1499,6 +1522,5 @@
 	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
 	
-	unsigned long key = (unsigned long) fun->service_id;
-	hash_table_insert(&tree->loc_functions, &key, &fun->loc_fun);
+	hash_table_insert(&tree->loc_functions, &fun->loc_fun);
 }
 
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/devman/devman.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -52,5 +52,4 @@
 
 #define MATCH_EXT ".ma"
-#define DEVICE_BUCKETS 256
 
 #define LOC_DEVICE_NAMESPACE "devices"
@@ -151,5 +150,5 @@
 	 * Used by the hash table of devices indexed by devman device handles.
 	 */
-	link_t devman_dev;
+	ht_link_t devman_dev;
 	
 	/**
@@ -174,4 +173,6 @@
 	/** State */
 	fun_state_t state;
+	/** Locked while performing reconfiguration operations */
+	fibril_mutex_t busy_lock;
 	
 	/** The global unique identifier of the function */
@@ -202,10 +203,10 @@
 	 * Used by the hash table of functions indexed by devman device handles.
 	 */
-	link_t devman_fun;
+	ht_link_t devman_fun;
 	
 	/**
 	 * Used by the hash table of functions indexed by service IDs.
 	 */
-	link_t loc_fun;
+	ht_link_t loc_fun;
 };
 
@@ -279,4 +280,5 @@
 extern void dev_add_ref(dev_node_t *);
 extern void dev_del_ref(dev_node_t *);
+
 extern dev_node_t *find_dev_node_no_lock(dev_tree_t *tree,
     devman_handle_t handle);
@@ -290,4 +292,6 @@
 extern void fun_add_ref(fun_node_t *);
 extern void fun_del_ref(fun_node_t *);
+extern void fun_busy_lock(fun_node_t *);
+extern void fun_busy_unlock(fun_node_t *);
 extern fun_node_t *find_fun_node_no_lock(dev_tree_t *tree,
     devman_handle_t handle);
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/devman/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -73,5 +73,5 @@
 	char *drv_name = NULL;
 
-	log_msg(LVL_DEBUG, "devman_driver_register");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_driver_register");
 	
 	/* Get driver name. */
@@ -82,5 +82,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "The `%s' driver is trying to register.",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "The `%s' driver is trying to register.",
 	    drv_name);
 	
@@ -88,5 +88,5 @@
 	driver = find_driver(&drivers_list, drv_name);
 	if (driver == NULL) {
-		log_msg(LVL_ERROR, "No driver named `%s' was found.", drv_name);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "No driver named `%s' was found.", drv_name);
 		free(drv_name);
 		drv_name = NULL;
@@ -102,5 +102,5 @@
 	if (driver->sess) {
 		/* We already have a connection to the driver. */
-		log_msg(LVL_ERROR, "Driver '%s' already started.\n",
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Driver '%s' already started.\n",
 		    driver->name);
 		fibril_mutex_unlock(&driver->driver_mutex);
@@ -112,5 +112,5 @@
 	case DRIVER_NOT_STARTED:
 		/* Somebody started the driver manually. */
-		log_msg(LVL_NOTE, "Driver '%s' started manually.\n",
+		log_msg(LOG_DEFAULT, LVL_NOTE, "Driver '%s' started manually.\n",
 		    driver->name);
 		driver->state = DRIVER_STARTING;
@@ -125,5 +125,5 @@
 	
 	/* Create connection to the driver. */
-	log_msg(LVL_DEBUG, "Creating connection to the `%s' driver.",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Creating connection to the `%s' driver.",
 	    driver->name);
 	driver->sess = async_callback_receive(EXCHANGE_PARALLEL);
@@ -136,5 +136,5 @@
 	async_sess_args_set(driver->sess, DRIVER_DEVMAN, 0, 0);
 	
-	log_msg(LVL_NOTE,
+	log_msg(LOG_DEFAULT, LVL_NOTE,
 	    "The `%s' driver was successfully registered as running.",
 	    driver->name);
@@ -147,5 +147,5 @@
 	fid_t fid = fibril_create(init_running_drv, driver);
 	if (fid == 0) {
-		log_msg(LVL_ERROR, "Failed to create initialization fibril " \
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to create initialization fibril " \
 		    "for driver `%s'.", driver->name);
 		fibril_mutex_unlock(&driver->driver_mutex);
@@ -176,5 +176,5 @@
 	callid = async_get_call(&call);
 	if (DEVMAN_ADD_MATCH_ID != IPC_GET_IMETHOD(call)) {
-		log_msg(LVL_ERROR, 
+		log_msg(LOG_DEFAULT, LVL_ERROR, 
 		    "Invalid protocol when trying to receive match id.");
 		async_answer_0(callid, EINVAL); 
@@ -184,5 +184,5 @@
 	
 	if (match_id == NULL) {
-		log_msg(LVL_ERROR, "Failed to allocate match id.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to allocate match id.");
 		async_answer_0(callid, ENOMEM);
 		return ENOMEM;
@@ -198,5 +198,5 @@
 	if (rc != EOK) {
 		delete_match_id(match_id);
-		log_msg(LVL_ERROR, "Failed to receive match id string: %s.",
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to receive match id string: %s.",
 		    str_error(rc));
 		return rc;
@@ -205,5 +205,5 @@
 	list_append(&match_id->link, &match_ids->ids);
 	
-	log_msg(LVL_DEBUG, "Received match id `%s', score %d.",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Received match id `%s', score %d.",
 	    match_id->id, match_id->score);
 	return rc;
@@ -248,5 +248,5 @@
 	if (fun->state == FUN_ON_LINE) {
 		fibril_rwlock_write_unlock(&device_tree.rwlock);
-		log_msg(LVL_WARN, "Function %s is already on line.",
+		log_msg(LOG_DEFAULT, LVL_WARN, "Function %s is already on line.",
 		    fun->pathname);
 		return EOK;
@@ -264,5 +264,5 @@
 	}
 	
-	log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname);
 	
 	if (fun->ftype == fun_inner) {
@@ -282,5 +282,5 @@
 		fid_t assign_fibril = fibril_create(assign_driver_fibril, dev);
 		if (assign_fibril == 0) {
-			log_msg(LVL_ERROR, "Failed to create fibril for "
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to create fibril for "
 			    "assigning driver.");
 			/* XXX Cleanup */
@@ -305,5 +305,5 @@
 	if (fun->state == FUN_OFF_LINE) {
 		fibril_rwlock_write_unlock(&device_tree.rwlock);
-		log_msg(LVL_WARN, "Function %s is already off line.",
+		log_msg(LOG_DEFAULT, LVL_WARN, "Function %s is already off line.",
 		    fun->pathname);
 		return EOK;
@@ -311,5 +311,5 @@
 	
 	if (fun->ftype == fun_inner) {
-		log_msg(LVL_DEBUG, "Offlining inner function %s.",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Offlining inner function %s.",
 		    fun->pathname);
 		
@@ -359,5 +359,5 @@
 		if (rc != EOK) {
 			fibril_rwlock_write_unlock(&device_tree.rwlock);
-			log_msg(LVL_ERROR, "Failed unregistering tree service.");
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Failed unregistering tree service.");
 			return EIO;
 		}
@@ -391,5 +391,5 @@
 	if (ftype != fun_inner && ftype != fun_exposed) {
 		/* Unknown function type */
-		log_msg(LVL_ERROR, 
+		log_msg(LOG_DEFAULT, LVL_ERROR, 
 		    "Unknown function type %d provided by driver.",
 		    (int) ftype);
@@ -419,5 +419,7 @@
 	
 	/* Check that function with same name is not there already. */
-	if (find_fun_node_in_device(tree, pdev, fun_name) != NULL) {
+	fun_node_t *tfun = find_fun_node_in_device(tree, pdev, fun_name);
+	if (tfun) {
+		fun_del_ref(tfun);	/* drop the new unwanted reference */
 		fibril_rwlock_write_unlock(&tree->rwlock);
 		dev_del_ref(pdev);
@@ -430,10 +432,20 @@
 	
 	fun_node_t *fun = create_fun_node();
+	/* One reference for creation, one for us */
+	fun_add_ref(fun);
 	fun_add_ref(fun);
 	fun->ftype = ftype;
+	
+	/*
+	 * We can lock the function here even when holding the tree because
+	 * we know it cannot be held by anyone else yet.
+	 */
+	fun_busy_lock(fun);
 	
 	if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
 		dev_del_ref(pdev);
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
 		delete_fun_node(fun);
 		async_answer_0(callid, ENOMEM);
@@ -448,8 +460,13 @@
 	rc = online_function(fun);
 	if (rc != EOK) {
-		/* XXX clean up */
+		/* XXX Set some failed state? */
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
 		async_answer_0(callid, rc);
 		return;
 	}
+	
+	fun_busy_unlock(fun);
+	fun_del_ref(fun);
 	
 	/* Return device handle to parent's driver. */
@@ -490,8 +507,8 @@
 	if (rc == EOK) {
 		loc_service_add_to_cat(fun->service_id, cat_id);
-		log_msg(LVL_NOTE, "Function `%s' added to category `%s'.",
+		log_msg(LOG_DEFAULT, LVL_NOTE, "Function `%s' added to category `%s'.",
 		    fun->pathname, cat_name);
 	} else {
-		log_msg(LVL_ERROR, "Failed adding function `%s' to category "
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding function `%s' to category "
 		    "`%s'.", fun->pathname, cat_name);
 	}
@@ -512,5 +529,5 @@
 	int rc;
 	
-	log_msg(LVL_DEBUG, "devman_drv_fun_online()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_drv_fun_online()");
 	
 	fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
@@ -519,8 +536,11 @@
 		return;
 	}
+	
+	fun_busy_lock(fun);
 	
 	fibril_rwlock_read_lock(&device_tree.rwlock);
 	if (fun->dev == NULL || fun->dev->drv != drv) {
 		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		fun_busy_unlock(fun);
 		fun_del_ref(fun);
 		async_answer_0(iid, ENOENT);
@@ -531,4 +551,5 @@
 	rc = online_function(fun);
 	if (rc != EOK) {
+		fun_busy_unlock(fun);
 		fun_del_ref(fun);
 		async_answer_0(iid, (sysarg_t) rc);
@@ -536,4 +557,5 @@
 	}
 	
+	fun_busy_unlock(fun);
 	fun_del_ref(fun);
 	
@@ -557,6 +579,9 @@
 	}
 	
+	fun_busy_lock(fun);
+	
 	fibril_rwlock_write_lock(&device_tree.rwlock);
 	if (fun->dev == NULL || fun->dev->drv != drv) {
+		fun_busy_unlock(fun);
 		fun_del_ref(fun);
 		async_answer_0(iid, ENOENT);
@@ -567,4 +592,5 @@
 	rc = offline_function(fun);
 	if (rc != EOK) {
+		fun_busy_unlock(fun);
 		fun_del_ref(fun);
 		async_answer_0(iid, (sysarg_t) rc);
@@ -572,4 +598,5 @@
 	}
 	
+	fun_busy_unlock(fun);
 	fun_del_ref(fun);
 	async_answer_0(iid, (sysarg_t) EOK);
@@ -589,11 +616,15 @@
 	}
 	
+	fun_busy_lock(fun);
+	
 	fibril_rwlock_write_lock(&tree->rwlock);
 	
-	log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);
 	
 	/* Check function state */
 	if (fun->state == FUN_REMOVED) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
+		fun_busy_unlock(fun);
+		fun_del_ref(fun);
 		async_answer_0(callid, ENOENT);
 		return;
@@ -622,5 +653,5 @@
 			/* Verify that driver succeeded and removed all functions */
 			if (gone_rc != EOK || !list_empty(&dev->functions)) {
-				log_msg(LVL_ERROR, "Driver did not remove "
+				log_msg(LOG_DEFAULT, LVL_ERROR, "Driver did not remove "
 				    "functions for device that is gone. "
 				    "Device node is now defunct.");
@@ -636,4 +667,6 @@
 				if (gone_rc == EOK)
 					gone_rc = ENOTSUP;
+				fun_busy_unlock(fun);
+				fun_del_ref(fun);
 				async_answer_0(callid, gone_rc);
 				return;
@@ -659,7 +692,8 @@
 			rc = loc_service_unregister(fun->service_id);
 			if (rc != EOK) {
-				log_msg(LVL_ERROR, "Failed unregistering tree "
+				log_msg(LOG_DEFAULT, LVL_ERROR, "Failed unregistering tree "
 				    "service.");
 				fibril_rwlock_write_unlock(&tree->rwlock);
+				fun_busy_unlock(fun);
 				fun_del_ref(fun);
 				async_answer_0(callid, EIO);
@@ -671,4 +705,5 @@
 	remove_fun_node(&device_tree, fun);
 	fibril_rwlock_write_unlock(&tree->rwlock);
+	fun_busy_unlock(fun);
 	
 	/* Delete ref added when inserting function into tree */
@@ -677,5 +712,5 @@
 	fun_del_ref(fun);
 	
-	log_msg(LVL_DEBUG, "devman_remove_function() succeeded.");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_remove_function() succeeded.");
 	async_answer_0(callid, EOK);
 }
@@ -691,5 +726,5 @@
 	
 	initialize_running_driver(driver, &device_tree);
-	log_msg(LVL_DEBUG, "The `%s` driver was successfully initialized.",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "The `%s` driver was successfully initialized.",
 	    driver->name);
 	return 0;
@@ -707,5 +742,5 @@
 	client = async_get_client_data();
 	if (client == NULL) {
-		log_msg(LVL_ERROR, "Failed to allocate client data.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to allocate client data.");
 		return;
 	}
@@ -1194,5 +1229,5 @@
 	 */
 	if (dev == NULL) {
-		log_msg(LVL_ERROR, "IPC forwarding failed - no device or "
+		log_msg(LOG_DEFAULT, LVL_ERROR, "IPC forwarding failed - no device or "
 		    "function with handle %" PRIun " was found.", handle);
 		async_answer_0(iid, ENOENT);
@@ -1201,5 +1236,5 @@
 
 	if (fun == NULL && !drv_to_parent) {
-		log_msg(LVL_ERROR, NAME ": devman_forward error - cannot "
+		log_msg(LOG_DEFAULT, LVL_ERROR, NAME ": devman_forward error - cannot "
 		    "connect to handle %" PRIun ", refers to a device.",
 		    handle);
@@ -1229,5 +1264,5 @@
 	
 	if (driver == NULL) {
-		log_msg(LVL_ERROR, "IPC forwarding refused - " \
+		log_msg(LOG_DEFAULT, LVL_ERROR, "IPC forwarding refused - " \
 		    "the device %" PRIun " is not in usable state.", handle);
 		async_answer_0(iid, ENOENT);
@@ -1242,5 +1277,5 @@
 	
 	if (!driver->sess) {
-		log_msg(LVL_ERROR,
+		log_msg(LOG_DEFAULT, LVL_ERROR,
 		    "Could not forward to driver `%s'.", driver->name);
 		async_answer_0(iid, EINVAL);
@@ -1249,9 +1284,9 @@
 
 	if (fun != NULL) {
-		log_msg(LVL_DEBUG,
+		log_msg(LOG_DEFAULT, LVL_DEBUG,
 		    "Forwarding request for `%s' function to driver `%s'.",
 		    fun->pathname, driver->name);
 	} else {
-		log_msg(LVL_DEBUG,
+		log_msg(LOG_DEFAULT, LVL_DEBUG,
 		    "Forwarding request for `%s' device to driver `%s'.",
 		    dev->pfun->pathname, driver->name);
@@ -1285,5 +1320,5 @@
 	
 	if (fun == NULL || fun->dev == NULL || fun->dev->drv == NULL) {
-		log_msg(LVL_WARN, "devman_connection_loc(): function "
+		log_msg(LOG_DEFAULT, LVL_WARN, "devman_connection_loc(): function "
 		    "not found.\n");
 		fibril_rwlock_read_unlock(&device_tree.rwlock);
@@ -1303,5 +1338,5 @@
 	async_exchange_end(exch);
 	
-	log_msg(LVL_DEBUG,
+	log_msg(LOG_DEFAULT, LVL_DEBUG,
 	    "Forwarding loc service request for `%s' function to driver `%s'.",
 	    fun->pathname, driver->name);
@@ -1359,5 +1394,5 @@
 static bool devman_init(void)
 {
-	log_msg(LVL_DEBUG, "devman_init - looking for available drivers.");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_init - looking for available drivers.");
 	
 	/* Initialize list of available drivers. */
@@ -1365,13 +1400,13 @@
 	if (lookup_available_drivers(&drivers_list,
 	    DRIVER_DEFAULT_STORE) == 0) {
-		log_msg(LVL_FATAL, "No drivers found.");
+		log_msg(LOG_DEFAULT, LVL_FATAL, "No drivers found.");
 		return false;
 	}
 	
-	log_msg(LVL_DEBUG, "devman_init - list of drivers has been initialized.");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_init - list of drivers has been initialized.");
 	
 	/* Create root device node. */
 	if (!init_device_tree(&device_tree, &drivers_list)) {
-		log_msg(LVL_FATAL, "Failed to initialize device tree.");
+		log_msg(LOG_DEFAULT, LVL_FATAL, "Failed to initialize device tree.");
 		return false;
 	}
@@ -1393,5 +1428,5 @@
 	printf("%s: HelenOS Device Manager\n", NAME);
 	
-	int rc = log_init(NAME, LVL_WARN);
+	int rc = log_init(NAME);
 	if (rc != EOK) {
 		printf("%s: Error initializing logging subsystem.\n", NAME);
@@ -1405,5 +1440,5 @@
 	
 	if (!devman_init()) {
-		log_msg(LVL_ERROR, "Error while initializing service.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error while initializing service.");
 		return -1;
 	}
@@ -1412,5 +1447,5 @@
 	rc = service_register(SERVICE_DEVMAN);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering as a service.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering as a service.");
 		return rc;
 	}
Index: uspace/srv/fs/cdfs/cdfs_ops.c
===================================================================
--- uspace/srv/fs/cdfs/cdfs_ops.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/cdfs/cdfs_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,6 +37,8 @@
  */
 
+#include "cdfs_ops.h"
 #include <bool.h>
 #include <adt/hash_table.h>
+#include <adt/hash.h>
 #include <malloc.h>
 #include <mem.h>
@@ -44,5 +46,5 @@
 #include <libfs.h>
 #include <errno.h>
-#include <libblock.h>
+#include <block.h>
 #include <str.h>
 #include <byteorder.h>
@@ -50,21 +52,9 @@
 #include "cdfs.h"
 #include "cdfs_endian.h"
-#include "cdfs_ops.h"
 
 /** Standard CD-ROM block size */
 #define BLOCK_SIZE  2048
 
-/** Implicit node cache size
- *
- * More nodes can be actually cached if the files remain
- * opended.
- *
- */
-#define NODE_CACHE_SIZE  200
-
-#define NODES_BUCKETS  256
-
-#define NODES_KEY_SRVC   0
-#define NODES_KEY_INDEX  1
+#define NODE_CACHE_SIZE 200
 
 /** All root nodes have index 0 */
@@ -205,5 +195,5 @@
 	service_id_t service_id;  /**< Service ID of block device */
 	
-	link_t nh_link;           /**< Nodes hash table link */
+	ht_link_t nh_link;        /**< Nodes hash table link */
 	cdfs_dentry_type_t type;  /**< Dentry type */
 	
@@ -226,31 +216,36 @@
 static hash_table_t nodes;
 
-static hash_index_t nodes_hash(unsigned long key[])
-{
-	return key[NODES_KEY_INDEX] % NODES_BUCKETS;
-}
-
-static int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	cdfs_node_t *node =
-	    hash_table_get_instance(item, cdfs_node_t, nh_link);
-	
-	switch (keys) {
-	case 1:
-		return (node->service_id == key[NODES_KEY_SRVC]);
-	case 2:
-		return ((node->service_id == key[NODES_KEY_SRVC]) &&
-		    (node->index == key[NODES_KEY_INDEX]));
-	default:
-		assert((keys == 1) || (keys == 2));
-	}
-	
-	return 0;
-}
-
-static void nodes_remove_callback(link_t *item)
-{
-	cdfs_node_t *node =
-	    hash_table_get_instance(item, cdfs_node_t, nh_link);
+/* 
+ * Hash table support functions.
+ */
+
+typedef struct {
+	service_id_t service_id;
+    fs_index_t index;
+} ht_key_t;
+
+static size_t nodes_key_hash(void *k)
+{
+	ht_key_t *key = (ht_key_t*)k;
+	return hash_combine(key->service_id, key->index);
+}
+
+static size_t nodes_hash(const ht_link_t *item)
+{
+	cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
+	return hash_combine(node->service_id, node->index);
+}
+
+static bool nodes_key_equal(void *k, const ht_link_t *item)
+{
+	cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
+	ht_key_t *key = (ht_key_t*)k;
+	
+	return key->service_id == node->service_id && key->index == node->index;
+}
+
+static void nodes_remove_callback(ht_link_t *item)
+{
+	cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
 	
 	assert(node->type == CDFS_DIRECTORY);
@@ -268,7 +263,9 @@
 
 /** Nodes hash table operations */
-static hash_table_operations_t nodes_ops = {
+static hash_table_ops_t nodes_ops = {
 	.hash = nodes_hash,
-	.compare = nodes_compare,
+	.key_hash = nodes_key_hash,
+	.key_equal = nodes_key_equal,
+	.equal = NULL,
 	.remove_callback = nodes_remove_callback
 };
@@ -277,13 +274,13 @@
     fs_index_t index)
 {
-	unsigned long key[] = {
-		[NODES_KEY_SRVC] = service_id,
-		[NODES_KEY_INDEX] = index
+	ht_key_t key = {
+		.index = index,
+		.service_id = service_id
 	};
 	
-	link_t *link = hash_table_find(&nodes, key);
+	ht_link_t *link = hash_table_find(&nodes, &key);
 	if (link) {
 		cdfs_node_t *node =
-		    hash_table_get_instance(link, cdfs_node_t, nh_link);
+		    hash_table_get_inst(link, cdfs_node_t, nh_link);
 		
 		*rfn = FS_NODE(node);
@@ -311,5 +308,4 @@
 	node->opened = 0;
 	
-	link_initialize(&node->nh_link);
 	list_initialize(&node->cs_list);
 }
@@ -353,10 +349,5 @@
 	
 	/* Insert the new node into the nodes hash table. */
-	unsigned long key[] = {
-		[NODES_KEY_SRVC] = node->service_id,
-		[NODES_KEY_INDEX] = node->index
-	};
-	
-	hash_table_insert(&nodes, key, &node->nh_link);
+	hash_table_insert(&nodes, &node->nh_link);
 	
 	*rfn = FS_NODE(node);
@@ -508,13 +499,13 @@
 static fs_node_t *get_cached_node(service_id_t service_id, fs_index_t index)
 {
-	unsigned long key[] = {
-		[NODES_KEY_SRVC] = service_id,
-		[NODES_KEY_INDEX] = index
+	ht_key_t key = {
+		.index = index,
+		.service_id = service_id
 	};
 	
-	link_t *link = hash_table_find(&nodes, key);
+	ht_link_t *link = hash_table_find(&nodes, &key);
 	if (link) {
 		cdfs_node_t *node =
-		    hash_table_get_instance(link, cdfs_node_t, nh_link);
+		    hash_table_get_inst(link, cdfs_node_t, nh_link);
 		return FS_NODE(node);
 	}
@@ -802,11 +793,19 @@
 }
 
+static bool rm_service_id_nodes(ht_link_t *item, void *arg) 
+{
+	service_id_t service_id = *(service_id_t*)arg;
+	cdfs_node_t *node = hash_table_get_inst(item, cdfs_node_t, nh_link);
+	
+	if (node->service_id == service_id) {
+		hash_table_remove_item(&nodes, &node->nh_link);
+	}
+	
+	return true;
+}
+
 static void cdfs_instance_done(service_id_t service_id)
 {
-	unsigned long key[] = {
-		[NODES_KEY_SRVC] = service_id
-	};
-	
-	hash_table_remove(&nodes, key, 1);
+	hash_table_apply(&nodes, rm_service_id_nodes, &service_id);
 	block_cache_fini(service_id);
 	block_fini(service_id);
@@ -822,15 +821,15 @@
     size_t *rbytes)
 {
-	unsigned long key[] = {
-		[NODES_KEY_SRVC] = service_id,
-		[NODES_KEY_INDEX] = index
+	ht_key_t key = {
+		.index = index,
+		.service_id = service_id
 	};
 	
-	link_t *link = hash_table_find(&nodes, key);
+	ht_link_t *link = hash_table_find(&nodes, &key);
 	if (link == NULL)
 		return ENOENT;
 	
 	cdfs_node_t *node =
-	    hash_table_get_instance(link, cdfs_node_t, nh_link);
+	    hash_table_get_inst(link, cdfs_node_t, nh_link);
 	
 	if (!node->processed) {
@@ -912,34 +911,31 @@
 }
 
+static bool cache_remove_closed(ht_link_t *item, void *arg)
+{
+	size_t *premove_cnt = (size_t*)arg;
+	
+	/* Some nodes were requested to be removed from the cache. */
+	if (0 < *premove_cnt) {
+		cdfs_node_t *node =	hash_table_get_inst(item, cdfs_node_t, nh_link);
+
+		if (!node->opened) {
+			hash_table_remove_item(&nodes, item);
+			
+			--nodes_cached;
+			--*premove_cnt;
+		}
+	}
+	
+	/* Only continue if more nodes were requested to be removed. */
+	return 0 < *premove_cnt;
+}
+
 static void cleanup_cache(service_id_t service_id)
 {
 	if (nodes_cached > NODE_CACHE_SIZE) {
-		size_t remove = nodes_cached - NODE_CACHE_SIZE;
-		
-		// FIXME: this accesses the internals of the hash table
-		//        and should be rewritten in a clean way
-		
-		for (hash_index_t chain = 0; chain < nodes.entries; chain++) {
-			for (link_t *link = nodes.entry[chain].head.next;
-			    link != &nodes.entry[chain].head;
-			    link = link->next) {
-				if (remove == 0)
-					return;
-				
-				cdfs_node_t *node =
-				    hash_table_get_instance(link, cdfs_node_t, nh_link);
-				if (node->opened == 0) {
-					link_t *tmp = link;
-					link = link->prev;
-					
-					list_remove(tmp);
-					nodes.op->remove_callback(tmp);
-					nodes_cached--;
-					remove--;
-					
-					continue;
-				}
-			}
-		}
+		size_t remove_cnt = nodes_cached - NODE_CACHE_SIZE;
+		
+		if (0 < remove_cnt)
+			hash_table_apply(&nodes, cache_remove_closed, &remove_cnt);
 	}
 }
@@ -951,15 +947,15 @@
 		return EOK;
 	
-	unsigned long key[] = {
-		[NODES_KEY_SRVC] = service_id,
-		[NODES_KEY_INDEX] = index
+	ht_key_t key = {
+		.index = index,
+		.service_id = service_id
 	};
 	
-	link_t *link = hash_table_find(&nodes, key);
+	ht_link_t *link = hash_table_find(&nodes, &key);
 	if (link == 0)
 		return ENOENT;
 	
 	cdfs_node_t *node =
-	    hash_table_get_instance(link, cdfs_node_t, nh_link);
+	    hash_table_get_inst(link, cdfs_node_t, nh_link);
 	
 	assert(node->opened > 0);
@@ -1007,5 +1003,5 @@
 bool cdfs_init(void)
 {
-	if (!hash_table_create(&nodes, NODES_BUCKETS, 2, &nodes_ops))
+	if (!hash_table_create(&nodes, 0, 0, &nodes_ops))
 		return false;
 	
Index: uspace/srv/fs/exfat/exfat.h
===================================================================
--- uspace/srv/fs/exfat/exfat.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/exfat/exfat.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -106,7 +106,7 @@
 typedef struct {
 	/** Used indices (position) hash table link. */
-	link_t		uph_link;
+	ht_link_t		uph_link;
 	/** Used indices (index) hash table link. */
-	link_t		uih_link;
+	ht_link_t		uih_link;
 
 	fibril_mutex_t	lock;
Index: uspace/srv/fs/exfat/exfat_bitmap.c
===================================================================
--- uspace/srv/fs/exfat/exfat_bitmap.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/exfat/exfat_bitmap.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -39,5 +39,5 @@
 #include "../../vfs/vfs.h"
 #include <libfs.h>
-#include <libblock.h>
+#include <block.h>
 #include <errno.h>
 #include <byteorder.h>
Index: uspace/srv/fs/exfat/exfat_directory.c
===================================================================
--- uspace/srv/fs/exfat/exfat_directory.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/exfat/exfat_directory.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -39,5 +39,5 @@
 #include "exfat_directory.h"
 #include "exfat_fat.h"
-#include <libblock.h>
+#include <block.h>
 #include <errno.h>
 #include <byteorder.h>
Index: uspace/srv/fs/exfat/exfat_fat.c
===================================================================
--- uspace/srv/fs/exfat/exfat_fat.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/exfat/exfat_fat.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,5 +42,5 @@
 #include "../../vfs/vfs.h"
 #include <libfs.h>
-#include <libblock.h>
+#include <block.h>
 #include <errno.h>
 #include <byteorder.h>
Index: uspace/srv/fs/exfat/exfat_fat.h
===================================================================
--- uspace/srv/fs/exfat/exfat_fat.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/exfat/exfat_fat.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,5 +37,5 @@
 #include "../../vfs/vfs.h"
 #include <stdint.h>
-#include <libblock.h>
+#include <block.h>
 
 #define EXFAT_ROOT_IDX		0
Index: uspace/srv/fs/exfat/exfat_idx.c
===================================================================
--- uspace/srv/fs/exfat/exfat_idx.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/exfat/exfat_idx.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,4 +41,5 @@
 #include <str.h>
 #include <adt/hash_table.h>
+#include <adt/hash.h>
 #include <adt/list.h>
 #include <assert.h>
@@ -91,4 +92,5 @@
 	if (lock)
 		fibril_mutex_lock(&unused_lock);
+
 	list_foreach(unused_list, l) {
 		u = list_get_instance(l, unused_t, link);
@@ -112,70 +114,48 @@
 static hash_table_t up_hash;
 
-#define UPH_BUCKETS_LOG	12
-#define UPH_BUCKETS	(1 << UPH_BUCKETS_LOG)
-
-#define UPH_SID_KEY	0
-#define UPH_PFC_KEY	1
-#define UPH_PDI_KEY	2
-
-static hash_index_t pos_hash(unsigned long key[])
-{
-	service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
-	exfat_cluster_t pfc = (exfat_cluster_t)key[UPH_PFC_KEY];
-	unsigned pdi = (unsigned)key[UPH_PDI_KEY];
-
-	hash_index_t h;
-
-	/*
-	 * The least significant half of all bits are the least significant bits
-	 * of the parent node's first cluster.
-	 *
-	 * The least significant half of the most significant half of all bits
-	 * are the least significant bits of the node's dentry index within the
-	 * parent directory node.
-	 *
-	 * The most significant half of the most significant half of all bits
-	 * are the least significant bits of the device handle.
-	 */
-	h = pfc & ((1 << (UPH_BUCKETS_LOG / 2)) - 1);
-	h |= (pdi & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
-	    (UPH_BUCKETS_LOG / 2); 
-	h |= (service_id & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
-	    (3 * (UPH_BUCKETS_LOG / 4));
-
-	return h;
-}
-
-static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
+typedef struct {
+	service_id_t service_id;
 	exfat_cluster_t pfc;
 	unsigned pdi;
-	exfat_idx_t *fidx = list_get_instance(item, exfat_idx_t, uph_link);
-
-	switch (keys) {
-	case 1:
-		return (service_id == fidx->service_id);
-	case 3:
-		pfc = (exfat_cluster_t) key[UPH_PFC_KEY];
-		pdi = (unsigned) key[UPH_PDI_KEY];
-		return (service_id == fidx->service_id) && (pfc == fidx->pfc) &&
-		    (pdi == fidx->pdi);
-	default:
-		assert((keys == 1) || (keys == 3));
-	}
-
-	return 0;
-}
-
-static void pos_remove_callback(link_t *item)
-{
-	/* nothing to do */
-}
-
-static hash_table_operations_t uph_ops = {
+} pos_key_t;
+
+static inline size_t pos_key_hash(void *key)
+{
+	pos_key_t *pos = (pos_key_t*)key;
+	
+	size_t hash = 0;
+	hash = hash_combine(pos->pfc, pos->pdi);
+	return hash_combine(hash, pos->service_id);
+}
+
+static size_t pos_hash(const ht_link_t *item)
+{
+	exfat_idx_t *fidx = hash_table_get_inst(item, exfat_idx_t, uph_link);
+	
+	pos_key_t pkey = {
+		.service_id = fidx->service_id,
+		.pfc = fidx->pfc,
+		.pdi = fidx->pdi,
+	};
+	
+	return pos_key_hash(&pkey);
+}
+
+static bool pos_key_equal(void *key, const ht_link_t *item)
+{
+	pos_key_t *pos = (pos_key_t*)key;
+	exfat_idx_t *fidx = hash_table_get_inst(item, exfat_idx_t, uph_link);
+	
+	return pos->service_id == fidx->service_id
+		&& pos->pdi == fidx->pdi
+		&& pos->pfc == fidx->pfc;
+}
+
+static hash_table_ops_t uph_ops = {
 	.hash = pos_hash,
-	.compare = pos_compare,
-	.remove_callback = pos_remove_callback,
+	.key_hash = pos_key_hash,
+	.key_equal = pos_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL,
 };
 
@@ -186,54 +166,41 @@
 static hash_table_t ui_hash;
 
-#define UIH_BUCKETS_LOG	12
-#define UIH_BUCKETS	(1 << UIH_BUCKETS_LOG)
-
-#define UIH_SID_KEY	0
-#define UIH_INDEX_KEY	1
-
-static hash_index_t idx_hash(unsigned long key[])
-{
-	service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
-	fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY];
-
-	hash_index_t h;
-
-	h = service_id & ((1 << (UIH_BUCKETS_LOG / 2)) - 1);
-	h |= (index & ((1 << (UIH_BUCKETS_LOG / 2)) - 1)) <<
-	    (UIH_BUCKETS_LOG / 2);
-
-	return h;
-}
-
-static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
+typedef struct {
+	service_id_t service_id;
 	fs_index_t index;
-	exfat_idx_t *fidx = list_get_instance(item, exfat_idx_t, uih_link);
-
-	switch (keys) {
-	case 1:
-		return (service_id == fidx->service_id);
-	case 2:
-		index = (fs_index_t) key[UIH_INDEX_KEY];
-		return (service_id == fidx->service_id) &&
-		    (index == fidx->index);
-	default:
-		assert((keys == 1) || (keys == 2));
-	}
-
-	return 0;
-}
-
-static void idx_remove_callback(link_t *item)
-{
-	exfat_idx_t *fidx = list_get_instance(item, exfat_idx_t, uih_link);
+} idx_key_t;
+
+static size_t idx_key_hash(void *key_arg)
+{
+	idx_key_t *key = (idx_key_t*)key_arg;
+	return hash_combine(key->service_id, key->index);
+}
+
+static size_t idx_hash(const ht_link_t *item)
+{
+	exfat_idx_t *fidx = hash_table_get_inst(item, exfat_idx_t, uih_link);
+	return hash_combine(fidx->service_id, fidx->index);
+}
+
+static bool idx_key_equal(void *key_arg, const ht_link_t *item)
+{
+	exfat_idx_t *fidx = hash_table_get_inst(item, exfat_idx_t, uih_link);
+	idx_key_t *key = (idx_key_t*)key_arg;
+	
+	return key->index == fidx->index && key->service_id == fidx->service_id;
+}
+
+static void idx_remove_callback(ht_link_t *item)
+{
+	exfat_idx_t *fidx = hash_table_get_inst(item, exfat_idx_t, uih_link);
 
 	free(fidx);
 }
 
-static hash_table_operations_t uih_ops = {
+static hash_table_ops_t uih_ops = {
 	.hash = idx_hash,
-	.compare = idx_compare,
+	.key_hash = idx_key_hash,
+	.key_equal = idx_key_equal,
+	.equal = NULL,
 	.remove_callback = idx_remove_callback,
 };
@@ -376,6 +343,4 @@
 	}
 		
-	link_initialize(&fidx->uph_link);
-	link_initialize(&fidx->uih_link);
 	fibril_mutex_initialize(&fidx->lock);
 	fidx->service_id = service_id;
@@ -400,10 +365,5 @@
 	}
 		
-	unsigned long ikey[] = {
-		[UIH_SID_KEY] = service_id,
-		[UIH_INDEX_KEY] = fidx->index,
-	};
-	
-	hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
+	hash_table_insert(&ui_hash, &fidx->uih_link);
 	fibril_mutex_lock(&fidx->lock);
 	fibril_mutex_unlock(&used_lock);
@@ -417,15 +377,15 @@
 {
 	exfat_idx_t *fidx;
-	link_t *l;
-	unsigned long pkey[] = {
-		[UPH_SID_KEY] = service_id,
-		[UPH_PFC_KEY] = pfc,
-		[UPH_PDI_KEY] = pdi,
+	
+	pos_key_t pos_key = {
+		.service_id = service_id,
+		.pfc = pfc,
+		.pdi = pdi,
 	};
 
 	fibril_mutex_lock(&used_lock);
-	l = hash_table_find(&up_hash, pkey);
+	ht_link_t *l = hash_table_find(&up_hash, &pos_key);
 	if (l) {
-		fidx = hash_table_get_instance(l, exfat_idx_t, uph_link);
+		fidx = hash_table_get_inst(l, exfat_idx_t, uph_link);
 	} else {
 		int rc;
@@ -437,14 +397,9 @@
 		}
 		
-		unsigned long ikey[] = {
-			[UIH_SID_KEY] = service_id,
-			[UIH_INDEX_KEY] = fidx->index,
-		};
-	
 		fidx->pfc = pfc;
 		fidx->pdi = pdi;
 
-		hash_table_insert(&up_hash, pkey, &fidx->uph_link);
-		hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
+		hash_table_insert(&up_hash, &fidx->uph_link);
+		hash_table_insert(&ui_hash, &fidx->uih_link);
 	}
 	fibril_mutex_lock(&fidx->lock);
@@ -456,12 +411,6 @@
 void exfat_idx_hashin(exfat_idx_t *idx)
 {
-	unsigned long pkey[] = {
-		[UPH_SID_KEY] = idx->service_id,
-		[UPH_PFC_KEY] = idx->pfc,
-		[UPH_PDI_KEY] = idx->pdi,
-	};
-
-	fibril_mutex_lock(&used_lock);
-	hash_table_insert(&up_hash, pkey, &idx->uph_link);
+	fibril_mutex_lock(&used_lock);
+	hash_table_insert(&up_hash, &idx->uph_link);
 	fibril_mutex_unlock(&used_lock);
 }
@@ -469,12 +418,6 @@
 void exfat_idx_hashout(exfat_idx_t *idx)
 {
-	unsigned long pkey[] = {
-		[UPH_SID_KEY] = idx->service_id,
-		[UPH_PFC_KEY] = idx->pfc,
-		[UPH_PDI_KEY] = idx->pdi,
-	};
-
-	fibril_mutex_lock(&used_lock);
-	hash_table_remove(&up_hash, pkey, 3);
+	fibril_mutex_lock(&used_lock);
+	hash_table_remove_item(&up_hash, &idx->uph_link);
 	fibril_mutex_unlock(&used_lock);
 }
@@ -484,14 +427,14 @@
 {
 	exfat_idx_t *fidx = NULL;
-	link_t *l;
-	unsigned long ikey[] = {
-		[UIH_SID_KEY] = service_id,
-		[UIH_INDEX_KEY] = index,
+
+	idx_key_t idx_key = {
+		.service_id = service_id,
+		.index = index,
 	};
 
 	fibril_mutex_lock(&used_lock);
-	l = hash_table_find(&ui_hash, ikey);
+	ht_link_t *l = hash_table_find(&ui_hash, &idx_key);
 	if (l) {
-		fidx = hash_table_get_instance(l, exfat_idx_t, uih_link);
+		fidx = hash_table_get_inst(l, exfat_idx_t, uih_link);
 		fibril_mutex_lock(&fidx->lock);
 	}
@@ -507,10 +450,8 @@
 void exfat_idx_destroy(exfat_idx_t *idx)
 {
-	unsigned long ikey[] = {
-		[UIH_SID_KEY] = idx->service_id,
-		[UIH_INDEX_KEY] = idx->index,
+	idx_key_t idx_key = {
+		.service_id = idx->service_id,
+		.index = idx->index,
 	};
-	service_id_t service_id = idx->service_id;
-	fs_index_t index = idx->index;
 
 	/* TODO: assert(idx->pfc == FAT_CLST_RES0); */
@@ -523,8 +464,8 @@
 	 * the index hash only.
 	 */
-	hash_table_remove(&ui_hash, ikey, 2);
+	hash_table_remove(&ui_hash, &idx_key);
 	fibril_mutex_unlock(&used_lock);
 	/* Release the VFS index. */
-	exfat_index_free(service_id, index);
+	exfat_index_free(idx_key.service_id, idx_key.index);
 	/* The index structure itself is freed in idx_remove_callback(). */
 }
@@ -532,7 +473,7 @@
 int exfat_idx_init(void)
 {
-	if (!hash_table_create(&up_hash, UPH_BUCKETS, 3, &uph_ops)) 
+	if (!hash_table_create(&up_hash, 0, 0, &uph_ops)) 
 		return ENOMEM;
-	if (!hash_table_create(&ui_hash, UIH_BUCKETS, 2, &uih_ops)) {
+	if (!hash_table_create(&ui_hash, 0, 0, &uih_ops)) {
 		hash_table_destroy(&up_hash);
 		return ENOMEM;
@@ -544,4 +485,5 @@
 {
 	/* We assume the hash tables are empty. */
+	assert(hash_table_empty(&up_hash) && hash_table_empty(&ui_hash));
 	hash_table_destroy(&up_hash);
 	hash_table_destroy(&ui_hash);
@@ -568,13 +510,30 @@
 }
 
+static bool rm_pos_service_id(ht_link_t *item, void *arg)
+{
+	service_id_t service_id = *(service_id_t*)arg;
+	exfat_idx_t *fidx = hash_table_get_inst(item, exfat_idx_t, uph_link);
+
+	if (fidx->service_id == service_id) {
+		hash_table_remove_item(&up_hash, item);
+	}
+	
+	return true;
+}
+
+static bool rm_idx_service_id(ht_link_t *item, void *arg)
+{
+	service_id_t service_id = *(service_id_t*)arg;
+	exfat_idx_t *fidx = hash_table_get_inst(item, exfat_idx_t, uih_link);
+
+	if (fidx->service_id == service_id) {
+		hash_table_remove_item(&ui_hash, item);
+	}
+	
+	return true;
+}
+
 void exfat_idx_fini_by_service_id(service_id_t service_id)
 {
-	unsigned long ikey[] = {
-		[UIH_SID_KEY] = service_id 
-	};
-	unsigned long pkey[] = {
-		[UPH_SID_KEY] = service_id 
-	};
-
 	/*
 	 * Remove this instance's index structure from up_hash and ui_hash.
@@ -583,6 +542,6 @@
 	 */
 	fibril_mutex_lock(&used_lock);
-	hash_table_remove(&up_hash, pkey, 1);
-	hash_table_remove(&ui_hash, ikey, 1);
+	hash_table_apply(&up_hash, rm_pos_service_id, &service_id);
+	hash_table_apply(&ui_hash, rm_idx_service_id, &service_id);
 	fibril_mutex_unlock(&used_lock);
 
Index: uspace/srv/fs/exfat/exfat_ops.c
===================================================================
--- uspace/srv/fs/exfat/exfat_ops.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/exfat/exfat_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -45,5 +45,5 @@
 #include "../../vfs/vfs.h"
 #include <libfs.h>
-#include <libblock.h>
+#include <block.h>
 #include <ipc/services.h>
 #include <ipc/loc.h>
@@ -54,4 +54,5 @@
 #include <byteorder.h>
 #include <adt/hash_table.h>
+#include <adt/hash.h>
 #include <adt/list.h>
 #include <assert.h>
Index: uspace/srv/fs/ext2fs/ext2fs_ops.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -39,5 +39,5 @@
 #include "../../vfs/vfs.h"
 #include <libfs.h>
-#include <libblock.h>
+#include <block.h>
 #include <libext2.h>
 #include <ipc/services.h>
@@ -49,4 +49,5 @@
 #include <byteorder.h>
 #include <adt/hash_table.h>
+#include <adt/hash.h>
 #include <adt/list.h>
 #include <assert.h>
@@ -62,8 +63,4 @@
 #define EXT2FS_NODE(node)	((node) ? (ext2fs_node_t *) (node)->data : NULL)
 #define EXT2FS_DBG(format, ...) {if (false) printf("ext2fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);}
-#define OPEN_NODES_KEYS 2
-#define OPEN_NODES_DEV_HANDLE_KEY 0
-#define OPEN_NODES_INODE_KEY 1
-#define OPEN_NODES_BUCKETS 256
 
 typedef struct ext2fs_instance {
@@ -78,5 +75,5 @@
 	ext2_inode_ref_t *inode_ref;
 	fs_node_t *fs_node;
-	link_t link;
+	ht_link_t link;
 	unsigned int references;
 } ext2fs_node_t;
@@ -122,36 +119,44 @@
 static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
 
-/* Hash table interface for open nodes hash table */
-static hash_index_t open_nodes_hash(unsigned long key[])
-{
-	/* TODO: This is very simple and probably can be improved */
-	return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS;
-}
-
-static int open_nodes_compare(unsigned long key[], hash_count_t keys, 
-    link_t *item)
-{
-	ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link);
-	assert(keys > 0);
-	if (enode->instance->service_id !=
-	    ((service_id_t) key[OPEN_NODES_DEV_HANDLE_KEY])) {
-		return false;
-	}
-	if (keys == 1) {
-		return true;
-	}
-	assert(keys == 2);
-	return (enode->inode_ref->index == key[OPEN_NODES_INODE_KEY]);
-}
-
-static void open_nodes_remove_cb(link_t *link)
-{
-	/* We don't use remove callback for this hash table */
-}
-
-static hash_table_operations_t open_nodes_ops = {
+/* 
+ * Hash table interface for open nodes hash table 
+ */
+
+typedef struct {
+	service_id_t service_id;
+	fs_index_t index;
+} node_key_t;
+
+static size_t open_nodes_key_hash(void *key)
+{
+	node_key_t *node_key = (node_key_t*)key;
+	return hash_combine(node_key->service_id, node_key->index);
+}
+
+static size_t open_nodes_hash(const ht_link_t *item)
+{
+	ext2fs_node_t *enode = hash_table_get_inst(item, ext2fs_node_t, link);
+
+	assert(enode->instance);
+	assert(enode->inode_ref);
+	
+	return hash_combine(enode->instance->service_id, enode->inode_ref->index);
+}
+
+static bool open_nodes_key_equal(void *key, const ht_link_t *item)
+{
+	node_key_t *node_key = (node_key_t*)key;
+	ext2fs_node_t *enode = hash_table_get_inst(item, ext2fs_node_t, link);
+	
+	return node_key->service_id == enode->instance->service_id
+		&& node_key->index == enode->inode_ref->index;
+}
+
+static hash_table_ops_t open_nodes_ops = {
 	.hash = open_nodes_hash,
-	.compare = open_nodes_compare,
-	.remove_callback = open_nodes_remove_cb,
+	.key_hash = open_nodes_key_hash,
+	.key_equal = open_nodes_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL,
 };
 
@@ -161,6 +166,5 @@
 int ext2fs_global_init(void)
 {
-	if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
-	    OPEN_NODES_KEYS, &open_nodes_ops)) {
+	if (!hash_table_create(&open_nodes, 0, 0, &open_nodes_ops)) {
 		return ENOMEM;
 	}
@@ -316,12 +320,12 @@
 	
 	/* Check if the node is not already open */
-	unsigned long key[] = {
-		[OPEN_NODES_DEV_HANDLE_KEY] = inst->service_id,
-		[OPEN_NODES_INODE_KEY] = index,
+	node_key_t key = {
+		.service_id = inst->service_id,
+		.index = index
 	};
-	link_t *already_open = hash_table_find(&open_nodes, key);
+	ht_link_t *already_open = hash_table_find(&open_nodes, &key);
 
 	if (already_open) {
-		enode = hash_table_get_instance(already_open, ext2fs_node_t, link);
+		enode = hash_table_get_inst(already_open, ext2fs_node_t, link);
 		*rfn = enode->fs_node;
 		enode->references++;
@@ -357,10 +361,9 @@
 	enode->references = 1;
 	enode->fs_node = node;
-	link_initialize(&enode->link);
 	
 	node->data = enode;
 	*rfn = node;
 	
-	hash_table_insert(&open_nodes, key, &enode->link);
+	hash_table_insert(&open_nodes, &enode->link);
 	inst->open_nodes_count++;
 	
@@ -408,15 +411,15 @@
 int ext2fs_node_put_core(ext2fs_node_t *enode)
 {
-	int rc;
-
-	unsigned long key[] = {
-		[OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->service_id,
-		[OPEN_NODES_INODE_KEY] = enode->inode_ref->index,
+	node_key_t key = {
+		.service_id = enode->instance->service_id,
+		.index = enode->inode_ref->index
 	};
-	hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS);
+
+	hash_table_remove(&open_nodes, &key);
+	
 	assert(enode->instance->open_nodes_count > 0);
 	enode->instance->open_nodes_count--;
 
-	rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
+	int rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
 	if (rc != EOK) {
 		EXT2FS_DBG("ext2_filesystem_put_inode_ref failed");
Index: uspace/srv/fs/ext4fs/Makefile
===================================================================
--- uspace/srv/fs/ext4fs/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/ext4fs/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2012 Frantisek Princ
+# 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 = $(LIBBLOCK_PREFIX)/libblock.a $(LIBFS_PREFIX)/libfs.a $(LIBEXT4_PREFIX)/libext4.a
+EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX) -I$(LIBEXT4_PREFIX)
+BINARY = ext4fs
+
+SOURCES = \
+	ext4fs.c \
+	ext4fs_ops.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/fs/ext4fs/ext4fs.c
===================================================================
--- uspace/srv/fs/ext4fs/ext4fs.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/ext4fs/ext4fs.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 fs
+ * @{
+ */
+/**
+ * @file  ext4fs.c
+ * @brief Ext4 file system driver for HelenOS.
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <libfs.h>
+#include <ns.h>
+#include <stdio.h>
+#include <task.h>
+#include <ipc/services.h>
+#include "ext4fs.h"
+#include "../../vfs/vfs.h"
+
+#define NAME  "ext4fs"
+
+vfs_info_t ext4fs_vfs_info = {
+	.name = NAME,
+	.instance = 0
+};
+
+int main(int argc, char **argv)
+{
+	printf("%s: HelenOS ext4 file system server\n", NAME);
+	
+	if (argc == 3) {
+		if (!str_cmp(argv[1], "--instance"))
+			ext4fs_vfs_info.instance = strtol(argv[2], NULL, 10);
+		else {
+			printf("%s: Unrecognized parameters\n", NAME);
+			return 1;
+		}
+	}
+	
+	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+	    SERVICE_VFS, 0, 0);
+	if (!vfs_sess) {
+		printf("%s: Failed to connect to VFS\n", NAME);
+		return 2;
+	}
+	
+	int rc = ext4fs_global_init();
+	if (rc != EOK) {
+		printf("%s: Global initialization failed\n", NAME);
+		return rc;
+	}
+	
+	rc = fs_register(vfs_sess, &ext4fs_vfs_info, &ext4fs_ops,
+	    &ext4fs_libfs_ops);
+	if (rc != EOK) {
+		printf("%s: Failed to register file system\n", NAME);
+		return rc;
+	}
+	
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
+	async_manager();
+	
+	/* Not reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/ext4fs/ext4fs.h
===================================================================
--- uspace/srv/fs/ext4fs/ext4fs.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/ext4fs/ext4fs.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 fs
+ * @{
+ */
+
+#ifndef EXT4FS_EXT4FS_H_
+#define EXT4FS_EXT4FS_H_
+
+#include <libfs.h>
+
+extern vfs_out_ops_t ext4fs_ops;
+extern libfs_ops_t ext4fs_libfs_ops;
+
+extern int ext4fs_global_init(void);
+extern int ext4fs_global_fini(void);
+
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/ext4fs/ext4fs_ops.c
===================================================================
--- uspace/srv/fs/ext4fs/ext4fs_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/ext4fs/ext4fs_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1484 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2012 Frantisek Princ
+ * 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 fs
+ * @{
+ */
+/**
+ * @file  ext4fs_ops.c
+ * @brief VFS operations for ext4 filesystem.
+ */
+
+#include <errno.h>
+#include <fibril_synch.h>
+#include <libext4.h>
+#include <libfs.h>
+#include <macros.h>
+#include <malloc.h>
+#include <adt/hash_table.h>
+#include <adt/hash.h>
+#include <ipc/loc.h>
+#include "ext4fs.h"
+#include "../../vfs/vfs.h"
+
+#define EXT4FS_NODE(node) \
+	((node) ? (ext4fs_node_t *) (node)->data : NULL)
+
+/**
+ * Type for holding an instance of mounted partition.
+ */
+typedef struct ext4fs_instance {
+	link_t link;
+	service_id_t service_id;
+	ext4_filesystem_t *filesystem;
+	unsigned int open_nodes_count;
+} ext4fs_instance_t;
+
+/**
+ * Type for wrapping common fs_node and add some useful pointers.
+ */
+typedef struct ext4fs_node {
+	ext4fs_instance_t *instance;
+	ext4_inode_ref_t *inode_ref;
+	fs_node_t *fs_node;
+	ht_link_t link;
+	unsigned int references;
+} ext4fs_node_t;
+
+/* Forward declarations of auxiliary functions */
+
+static int ext4fs_read_directory(ipc_callid_t, aoff64_t, size_t,
+    ext4fs_instance_t *, ext4_inode_ref_t *, size_t *);
+static int ext4fs_read_file(ipc_callid_t, aoff64_t, size_t, ext4fs_instance_t *,
+    ext4_inode_ref_t *, size_t *);
+static bool ext4fs_is_dots(const uint8_t *, size_t);
+static int ext4fs_instance_get(service_id_t, ext4fs_instance_t **);
+static int ext4fs_node_get_core(fs_node_t **, ext4fs_instance_t *, fs_index_t);
+static int ext4fs_node_put_core(ext4fs_node_t *);
+
+/* Forward declarations of ext4 libfs operations. */
+
+static int ext4fs_root_get(fs_node_t **, service_id_t);
+static int ext4fs_match(fs_node_t **, fs_node_t *, const char *);
+static int ext4fs_node_get(fs_node_t **, service_id_t, fs_index_t);
+static int ext4fs_node_open(fs_node_t *);
+static int ext4fs_node_put(fs_node_t *);
+static int ext4fs_create_node(fs_node_t **, service_id_t, int);
+static int ext4fs_destroy_node(fs_node_t *);
+static int ext4fs_link(fs_node_t *, fs_node_t *, const char *);
+static int ext4fs_unlink(fs_node_t *, fs_node_t *, const char *);
+static int ext4fs_has_children(bool *, fs_node_t *);
+static fs_index_t ext4fs_index_get(fs_node_t *);
+static aoff64_t ext4fs_size_get(fs_node_t *);
+static unsigned ext4fs_lnkcnt_get(fs_node_t *);
+static bool ext4fs_is_directory(fs_node_t *);
+static bool ext4fs_is_file(fs_node_t *node);
+static service_id_t ext4fs_service_get(fs_node_t *node);
+
+/* Static variables */
+
+static LIST_INITIALIZE(instance_list);
+static FIBRIL_MUTEX_INITIALIZE(instance_list_mutex);
+static hash_table_t open_nodes;
+static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
+
+/* Hash table interface for open nodes hash table */
+
+typedef struct {
+	service_id_t service_id;
+	fs_index_t index;
+} node_key_t;
+
+static size_t open_nodes_key_hash(void *key_arg)
+{
+	node_key_t *key = (node_key_t *)key_arg;
+	return hash_combine(key->service_id, key->index);
+}
+
+static size_t open_nodes_hash(const ht_link_t *item)
+{
+	ext4fs_node_t *enode = hash_table_get_inst(item, ext4fs_node_t, link);
+	return hash_combine(enode->instance->service_id, enode->inode_ref->index);	
+}
+
+static bool open_nodes_key_equal(void *key_arg, const ht_link_t *item)
+{
+	node_key_t *key = (node_key_t *)key_arg;
+	ext4fs_node_t *enode = hash_table_get_inst(item, ext4fs_node_t, link);
+	
+	return key->service_id == enode->instance->service_id
+		&& key->index == enode->inode_ref->index;
+}
+
+static hash_table_ops_t open_nodes_ops = {
+	.hash = open_nodes_hash,
+	.key_hash = open_nodes_key_hash,
+	.key_equal = open_nodes_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL,
+};
+
+/** Basic initialization of the driver.
+ *
+ * This is only needed to create the hash table
+ * for storing open nodes.
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_global_init(void)
+{
+	if (!hash_table_create(&open_nodes, 0, 0, &open_nodes_ops))
+		return ENOMEM;
+	
+	return EOK;
+}
+
+/* Finalization of the driver.
+ *
+ * This is only needed to destroy the hash table.
+ *
+ * @return Error code
+ */
+int ext4fs_global_fini(void)
+{
+	hash_table_destroy(&open_nodes);
+	return EOK;
+}
+
+/*
+ * Ext4 libfs operations.
+ */
+
+/** Get instance from internal table by service_id.
+ *
+ * @param service_id Device identifier
+ * @param inst       Output instance if successful operation
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_instance_get(service_id_t service_id, ext4fs_instance_t **inst)
+{
+	fibril_mutex_lock(&instance_list_mutex);
+	
+	if (list_empty(&instance_list)) {
+		fibril_mutex_unlock(&instance_list_mutex);
+		return EINVAL;
+	}
+	
+	list_foreach(instance_list, link) {
+		ext4fs_instance_t *tmp =
+		    list_get_instance(link, ext4fs_instance_t, link);
+		
+		if (tmp->service_id == service_id) {
+			*inst = tmp;
+			fibril_mutex_unlock(&instance_list_mutex);
+			return EOK;
+		}
+	}
+	
+	fibril_mutex_unlock(&instance_list_mutex);
+	return EINVAL;
+}
+
+/** Get root node of filesystem specified by service_id.
+ * 
+ * @param rfn        Output pointer to loaded node
+ * @param service_id Device to load root node from
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_root_get(fs_node_t **rfn, service_id_t service_id)
+{
+	return ext4fs_node_get(rfn, service_id, EXT4_INODE_ROOT_INDEX);
+}
+
+/** Check if specified name (component) matches with any directory entry.
+ * 
+ * If match is found, load and return matching node.
+ *
+ * @param rfn       Output pointer to node if operation successful
+ * @param pfn       Parent directory node
+ * @param component Name to check directory for
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
+{
+	ext4fs_node_t *eparent = EXT4FS_NODE(pfn);
+	ext4_filesystem_t *fs = eparent->instance->filesystem;
+	
+	if (!ext4_inode_is_type(fs->superblock, eparent->inode_ref->inode,
+	    EXT4_INODE_MODE_DIRECTORY))
+		return ENOTDIR;
+	
+	/* Try to find entry */
+	ext4_directory_search_result_t result;
+	int rc = ext4_directory_find_entry(&result, eparent->inode_ref,
+	    component);
+	if (rc != EOK) {
+		if (rc == ENOENT) {
+			*rfn = NULL;
+			return EOK;
+		}
+		
+		return rc;
+	}
+	
+	/* Load node from search result */
+	uint32_t inode = ext4_directory_entry_ll_get_inode(result.dentry);
+	rc = ext4fs_node_get_core(rfn, eparent->instance, inode);
+	if (rc != EOK)
+		return rc;
+	
+	/* Destroy search result structure */
+	return ext4_directory_destroy_result(&result);
+}
+
+/** Get node specified by index
+ *
+ * It's wrapper for node_put_core operation
+ *
+ * @param rfn        Output pointer to loaded node if operation successful
+ * @param service_id Device identifier
+ * @param index      Node index (here i-node number)
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
+{
+	ext4fs_instance_t *inst;
+	int rc = ext4fs_instance_get(service_id, &inst);
+	if (rc != EOK)
+		return rc;
+	
+	return ext4fs_node_get_core(rfn, inst, index);
+}
+
+/** Main function for getting node from the filesystem. 
+ *
+ * @param rfn   Output point to loaded node if operation successful
+ * @param inst  Instance of filesystem
+ * @param index Index of node (i-node number)
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_node_get_core(fs_node_t **rfn, ext4fs_instance_t *inst,
+    fs_index_t index)
+{
+	fibril_mutex_lock(&open_nodes_lock);
+	
+	/* Check if the node is not already open */
+	node_key_t key = {
+		.service_id = inst->service_id,
+		.index = index
+	};
+	
+	ht_link_t *already_open = hash_table_find(&open_nodes, &key);
+	ext4fs_node_t *enode = NULL;
+	if (already_open) {
+		enode = hash_table_get_inst(already_open, ext4fs_node_t, link);
+		*rfn = enode->fs_node;
+		enode->references++;
+		
+		fibril_mutex_unlock(&open_nodes_lock);
+		return EOK;
+	}
+	
+	/* Prepare new enode */
+	enode = malloc(sizeof(ext4fs_node_t));
+	if (enode == NULL) {
+		fibril_mutex_unlock(&open_nodes_lock);
+		return ENOMEM;
+	}
+	
+	/* Prepare new fs_node and initialize */
+	fs_node_t *fs_node = malloc(sizeof(fs_node_t));
+	if (fs_node == NULL) {
+		free(enode);
+		fibril_mutex_unlock(&open_nodes_lock);
+		return ENOMEM;
+	}
+	
+	fs_node_initialize(fs_node);
+	
+	/* Load i-node from filesystem */
+	ext4_inode_ref_t *inode_ref;
+	int rc = ext4_filesystem_get_inode_ref(inst->filesystem, index,
+	    &inode_ref);
+	if (rc != EOK) {
+		free(enode);
+		free(fs_node);
+		fibril_mutex_unlock(&open_nodes_lock);
+		return rc;
+	}
+	
+	/* Initialize enode */
+	enode->inode_ref = inode_ref;
+	enode->instance = inst;
+	enode->references = 1;
+	enode->fs_node = fs_node;
+	
+	fs_node->data = enode;
+	*rfn = fs_node;
+	
+	hash_table_insert(&open_nodes, &enode->link);
+	inst->open_nodes_count++;
+	
+	fibril_mutex_unlock(&open_nodes_lock);
+	
+	return EOK;
+}
+
+/** Put previously loaded node.
+ *
+ * @param enode Node to put back
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_node_put_core(ext4fs_node_t *enode)
+{
+	hash_table_remove_item(&open_nodes, &enode->link);
+	assert(enode->instance->open_nodes_count > 0);
+	enode->instance->open_nodes_count--;
+	
+	/* Put inode back in filesystem */
+	int rc = ext4_filesystem_put_inode_ref(enode->inode_ref);
+	if (rc != EOK)
+		return rc;
+	
+	/* Destroy data structure */
+	free(enode->fs_node);
+	free(enode);
+	
+	return EOK;
+}
+
+/** Open node.
+ *
+ * This operation is stateless in this driver.
+ *
+ * @param fn Node to open
+ *
+ * @return EOK
+ *
+ */
+int ext4fs_node_open(fs_node_t *fn)
+{
+	/* Stateless operation */
+	return EOK;
+}
+
+/** Put previously loaded node.
+ *
+ * A wrapper for node_put_core operation
+ *
+ * @param fn Node to put back
+ * @return Error code
+ *
+ */
+int ext4fs_node_put(fs_node_t *fn)
+{
+	fibril_mutex_lock(&open_nodes_lock);
+	
+	ext4fs_node_t *enode = EXT4FS_NODE(fn);
+	assert(enode->references > 0);
+	enode->references--;
+	if (enode->references == 0) {
+		int rc = ext4fs_node_put_core(enode);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&open_nodes_lock);
+			return rc;
+		}
+	}
+	
+	fibril_mutex_unlock(&open_nodes_lock);
+	
+	return EOK;
+}
+
+/** Create new node in filesystem.
+ *
+ * @param rfn        Output pointer to newly created node if successful
+ * @param service_id Device identifier, where the filesystem is
+ * @param flags      Flags for specification of new node parameters
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
+{
+	/* Allocate enode */
+	ext4fs_node_t *enode;
+	enode = malloc(sizeof(ext4fs_node_t));
+	if (enode == NULL)
+		return ENOMEM;
+	
+	/* Allocate fs_node */
+	fs_node_t *fs_node;
+	fs_node = malloc(sizeof(fs_node_t));
+	if (fs_node == NULL) {
+		free(enode);
+		return ENOMEM;
+	}
+	
+	/* Load instance */
+	ext4fs_instance_t *inst;
+	int rc = ext4fs_instance_get(service_id, &inst);
+	if (rc != EOK) {
+		free(enode);
+		free(fs_node);
+		return rc;
+	}
+	
+	/* Allocate new i-node in filesystem */
+	ext4_inode_ref_t *inode_ref;
+	rc = ext4_filesystem_alloc_inode(inst->filesystem, &inode_ref, flags);
+	if (rc != EOK) {
+		free(enode);
+		free(fs_node);
+		return rc;
+	}
+	
+	/* Do some interconnections in references */
+	enode->inode_ref = inode_ref;
+	enode->instance = inst;
+	enode->references = 1;
+	
+	fibril_mutex_lock(&open_nodes_lock);
+	hash_table_insert(&open_nodes, &enode->link);
+	fibril_mutex_unlock(&open_nodes_lock);
+	inst->open_nodes_count++;
+	
+	enode->inode_ref->dirty = true;
+	
+	fs_node_initialize(fs_node);
+	fs_node->data = enode;
+	enode->fs_node = fs_node;
+	*rfn = fs_node;
+	
+	return EOK;
+}
+
+/** Destroy existing node.
+ *
+ * @param fs Node to destroy
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_destroy_node(fs_node_t *fn)
+{
+	/* If directory, check for children */
+	bool has_children;
+	int rc = ext4fs_has_children(&has_children, fn);
+	if (rc != EOK) {
+		ext4fs_node_put(fn);
+		return rc;
+	}
+	
+	if (has_children) {
+		ext4fs_node_put(fn);
+		return EINVAL;
+	}
+	
+	ext4fs_node_t *enode = EXT4FS_NODE(fn);
+	ext4_inode_ref_t *inode_ref = enode->inode_ref;
+	
+	/* Release data blocks */
+	rc = ext4_filesystem_truncate_inode(inode_ref, 0);
+	if (rc != EOK) {
+		ext4fs_node_put(fn);
+		return rc;
+	}
+	
+	/*
+	 * TODO: Sset real deletion time when it will be supported.
+	 * Temporary set fake deletion time.
+	 */
+	ext4_inode_set_deletion_time(inode_ref->inode, 0xdeadbeef);
+	inode_ref->dirty = true;
+	
+	/* Free inode */
+	rc = ext4_filesystem_free_inode(inode_ref);
+	if (rc != EOK) {
+		ext4fs_node_put(fn);
+		return rc;
+	}
+	
+	return ext4fs_node_put(fn);
+}
+
+/** Link the specfied node to directory.
+ *
+ * @param pfn  Parent node to link in
+ * @param cfn  Node to be linked
+ * @param name Name which will be assigned to directory entry
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
+{
+	/* Check maximum name length */
+	if (str_size(name) > EXT4_DIRECTORY_FILENAME_LEN)
+		return ENAMETOOLONG;
+	
+	ext4fs_node_t *parent = EXT4FS_NODE(pfn);
+	ext4fs_node_t *child = EXT4FS_NODE(cfn);
+	ext4_filesystem_t *fs = parent->instance->filesystem;
+	
+	/* Add entry to parent directory */
+	int rc = ext4_directory_add_entry(parent->inode_ref, name,
+	    child->inode_ref);
+	if (rc != EOK)
+		return rc;
+	
+	/* Fill new dir -> add '.' and '..' entries */
+	if (ext4_inode_is_type(fs->superblock, child->inode_ref->inode,
+	    EXT4_INODE_MODE_DIRECTORY)) {
+		rc = ext4_directory_add_entry(child->inode_ref, ".",
+		    child->inode_ref);
+		if (rc != EOK) {
+			ext4_directory_remove_entry(parent->inode_ref, name);
+			return rc;
+		}
+		
+		rc = ext4_directory_add_entry(child->inode_ref, "..",
+		    parent->inode_ref);
+		if (rc != EOK) {
+			ext4_directory_remove_entry(parent->inode_ref, name);
+			ext4_directory_remove_entry(child->inode_ref, ".");
+			return rc;
+		}
+		
+		/* Initialize directory index if supported */
+		if (ext4_superblock_has_feature_compatible(fs->superblock,
+		    EXT4_FEATURE_COMPAT_DIR_INDEX)) {
+			rc = ext4_directory_dx_init(child->inode_ref);
+			if (rc != EOK)
+				return rc;
+			
+			ext4_inode_set_flag(child->inode_ref->inode,
+			    EXT4_INODE_FLAG_INDEX);
+			child->inode_ref->dirty = true;
+		}
+	
+		uint16_t parent_links =
+		    ext4_inode_get_links_count(parent->inode_ref->inode);
+		parent_links++;
+		ext4_inode_set_links_count(parent->inode_ref->inode, parent_links);
+		
+		parent->inode_ref->dirty = true;
+	}
+	
+	uint16_t child_links =
+	    ext4_inode_get_links_count(child->inode_ref->inode);
+	child_links++;
+	ext4_inode_set_links_count(child->inode_ref->inode, child_links);
+	
+	child->inode_ref->dirty = true;
+	
+	return EOK;
+}
+
+/** Unlink node from specified directory.
+ *
+ * @param pfn  Parent node to delete node from
+ * @param cfn  Child node to be unlinked from directory
+ * @param name Name of entry that will be removed
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *name)
+{
+	bool has_children;
+	int rc = ext4fs_has_children(&has_children, cfn);
+	if (rc != EOK)
+		return rc;
+	
+	/* Cannot unlink non-empty node */
+	if (has_children)
+		return ENOTEMPTY;
+	
+	/* Remove entry from parent directory */
+	ext4_inode_ref_t *parent = EXT4FS_NODE(pfn)->inode_ref;
+	rc = ext4_directory_remove_entry(parent, name);
+	if (rc != EOK)
+		return rc;
+	
+	/* Decrement links count */
+	ext4_inode_ref_t *child_inode_ref = EXT4FS_NODE(cfn)->inode_ref;
+	
+	uint32_t lnk_count =
+	    ext4_inode_get_links_count(child_inode_ref->inode);
+	lnk_count--;
+	
+	/* If directory - handle links from parent */
+	if ((lnk_count <= 1) && (ext4fs_is_directory(cfn))) {
+		assert(lnk_count == 1);
+		
+		lnk_count--;
+		
+		ext4_inode_ref_t *parent_inode_ref = EXT4FS_NODE(pfn)->inode_ref;
+		
+		uint32_t parent_lnk_count = ext4_inode_get_links_count(
+		    parent_inode_ref->inode);
+		
+		parent_lnk_count--;
+		ext4_inode_set_links_count(parent_inode_ref->inode, parent_lnk_count);
+		
+		parent->dirty = true;
+	}
+
+	/*
+	 * TODO: Update timestamps of the parent
+	 * (when we have wall-clock time).
+	 *
+	 * ext4_inode_set_change_inode_time(parent->inode, (uint32_t) now);
+	 * ext4_inode_set_modification_time(parent->inode, (uint32_t) now);
+	 * parent->dirty = true;
+	 */
+	
+	/*
+	 * TODO: Update timestamp for inode.
+	 *
+	 * ext4_inode_set_change_inode_time(child_inode_ref->inode,
+	 *     (uint32_t) now);
+	 */
+	
+	ext4_inode_set_links_count(child_inode_ref->inode, lnk_count);
+	child_inode_ref->dirty = true;
+	
+	return EOK;
+}
+
+/** Check if specified node has children.
+ *
+ * For files is response allways false and check is executed only for directories.
+ *
+ * @param has_children Output value for response
+ * @param fn           Node to check
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_has_children(bool *has_children, fs_node_t *fn)
+{
+	ext4fs_node_t *enode = EXT4FS_NODE(fn);
+	ext4_filesystem_t *fs = enode->instance->filesystem;
+	
+	/* Check if node is directory */
+	if (!ext4_inode_is_type(fs->superblock, enode->inode_ref->inode,
+	    EXT4_INODE_MODE_DIRECTORY)) {
+		*has_children = false;
+		return EOK;
+	}
+	
+	ext4_directory_iterator_t it;
+	int rc = ext4_directory_iterator_init(&it, enode->inode_ref, 0);
+	if (rc != EOK)
+		return rc;
+	
+	/* Find a non-empty directory entry */
+	bool found = false;
+	while (it.current != NULL) {
+		if (it.current->inode != 0) {
+			uint16_t name_size =
+			    ext4_directory_entry_ll_get_name_length(fs->superblock,
+			    it.current);
+			if (!ext4fs_is_dots(it.current->name, name_size)) {
+				found = true;
+				break;
+			}
+		}
+		
+		rc = ext4_directory_iterator_next(&it);
+		if (rc != EOK) {
+			ext4_directory_iterator_fini(&it);
+			return rc;
+		}
+	}
+	
+	rc = ext4_directory_iterator_fini(&it);
+	if (rc != EOK)
+		return rc;
+	
+	*has_children = found;
+	
+	return EOK;
+}
+
+/** Unpack index number from node.
+ *
+ * @param fn Node to load index from
+ *
+ * @return Index number of i-node
+ *
+ */
+fs_index_t ext4fs_index_get(fs_node_t *fn)
+{
+	ext4fs_node_t *enode = EXT4FS_NODE(fn);
+	return enode->inode_ref->index;
+}
+
+/** Get real size of file / directory.
+ *
+ * @param fn Node to get size of
+ *
+ * @return Real size of node
+ *
+ */
+aoff64_t ext4fs_size_get(fs_node_t *fn)
+{
+	ext4fs_node_t *enode = EXT4FS_NODE(fn);
+	ext4_superblock_t *sb = enode->instance->filesystem->superblock;
+	return ext4_inode_get_size(sb, enode->inode_ref->inode);
+}
+
+/** Get number of links to specified node.
+ *
+ * @param fn Node to get links to
+ *
+ * @return Number of links
+ *
+ */
+unsigned ext4fs_lnkcnt_get(fs_node_t *fn)
+{
+	ext4fs_node_t *enode = EXT4FS_NODE(fn);
+	uint32_t lnkcnt = ext4_inode_get_links_count(enode->inode_ref->inode);
+	
+	if (ext4fs_is_directory(fn)) {
+		if (lnkcnt > 1)
+			return 1;
+		else
+			return 0;
+	}
+	
+	/* For regular files return real links count */
+	return lnkcnt;
+}
+
+/** Check if node is directory.
+ *
+ * @param fn Node to check
+ *
+ * @return Result of check
+ *
+ */
+bool ext4fs_is_directory(fs_node_t *fn)
+{
+	ext4fs_node_t *enode = EXT4FS_NODE(fn);
+	ext4_superblock_t *sb = enode->instance->filesystem->superblock;
+	
+	return ext4_inode_is_type(sb, enode->inode_ref->inode,
+	    EXT4_INODE_MODE_DIRECTORY);
+}
+
+/** Check if node is regular file.
+ *
+ * @param fn Node to check
+ *
+ * @return Result of check
+ *
+ */
+bool ext4fs_is_file(fs_node_t *fn)
+{
+	ext4fs_node_t *enode = EXT4FS_NODE(fn);
+	ext4_superblock_t *sb = enode->instance->filesystem->superblock;
+	
+	return ext4_inode_is_type(sb, enode->inode_ref->inode,
+	    EXT4_INODE_MODE_FILE);
+}
+
+/** Extract device identifier from node.
+ *
+ * @param node Node to extract id from
+ *
+ * @return id of device, where is the filesystem
+ *
+ */
+service_id_t ext4fs_service_get(fs_node_t *fn)
+{
+	ext4fs_node_t *enode = EXT4FS_NODE(fn);
+	return enode->instance->service_id;
+}
+
+/*
+ * libfs operations.
+ */
+libfs_ops_t ext4fs_libfs_ops = {
+	.root_get = ext4fs_root_get,
+	.match = ext4fs_match,
+	.node_get = ext4fs_node_get,
+	.node_open = ext4fs_node_open,
+	.node_put = ext4fs_node_put,
+	.create = ext4fs_create_node,
+	.destroy = ext4fs_destroy_node,
+	.link = ext4fs_link,
+	.unlink = ext4fs_unlink,
+	.has_children = ext4fs_has_children,
+	.index_get = ext4fs_index_get,
+	.size_get = ext4fs_size_get,
+	.lnkcnt_get = ext4fs_lnkcnt_get,
+	.is_directory = ext4fs_is_directory,
+	.is_file = ext4fs_is_file,
+	.service_get = ext4fs_service_get
+};
+
+/*
+ * VFS operations.
+ */
+
+/** Mount operation.
+ *
+ * Try to mount specified filesystem from device.
+ *
+ * @param service_id Identifier of device
+ * @param opts       Mount options
+ * @param index      Output value - index of root node
+ * @param size       Output value - size of root node
+ * @param lnkcnt     Output value - link count of root node
+ *
+ * @return Error code
+ *
+ */
+static int ext4fs_mounted(service_id_t service_id, const char *opts,
+    fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
+	/* Allocate libext4 filesystem structure */
+	ext4_filesystem_t *fs = (ext4_filesystem_t *)
+	    malloc(sizeof(ext4_filesystem_t));
+	if (fs == NULL)
+		return ENOMEM;
+	
+	/* Allocate instance structure */
+	ext4fs_instance_t *inst = (ext4fs_instance_t *)
+	    malloc(sizeof(ext4fs_instance_t));
+	if (inst == NULL) {
+		free(fs);
+		return ENOMEM;
+	}
+	
+	enum cache_mode cmode;
+	if (str_cmp(opts, "wtcache") == 0)
+		cmode = CACHE_MODE_WT;
+	else
+		cmode = CACHE_MODE_WB;
+	
+	/* Initialize the filesystem */
+	int rc = ext4_filesystem_init(fs, service_id, cmode);
+	if (rc != EOK) {
+		free(fs);
+		free(inst);
+		return rc;
+	}
+	
+	/* Do some sanity checking */
+	rc = ext4_filesystem_check_sanity(fs);
+	if (rc != EOK) {
+		ext4_filesystem_fini(fs);
+		free(fs);
+		free(inst);
+		return rc;
+	}
+	
+	/* Check flags */
+	bool read_only;
+	rc = ext4_filesystem_check_features(fs, &read_only);
+	if (rc != EOK) {
+		ext4_filesystem_fini(fs);
+		free(fs);
+		free(inst);
+		return rc;
+	}
+	
+	/* Initialize instance */
+	link_initialize(&inst->link);
+	inst->service_id = service_id;
+	inst->filesystem = fs;
+	inst->open_nodes_count = 0;
+	
+	/* Read root node */
+	fs_node_t *root_node;
+	rc = ext4fs_node_get_core(&root_node, inst, EXT4_INODE_ROOT_INDEX);
+	if (rc != EOK) {
+		ext4_filesystem_fini(fs);
+		free(fs);
+		free(inst);
+		return rc;
+	}
+	
+	/* Add instance to the list */
+	fibril_mutex_lock(&instance_list_mutex);
+	list_append(&inst->link, &instance_list);
+	fibril_mutex_unlock(&instance_list_mutex);
+	
+	ext4fs_node_t *enode = EXT4FS_NODE(root_node);
+	
+	*index = EXT4_INODE_ROOT_INDEX;
+	*size = ext4_inode_get_size(fs->superblock, enode->inode_ref->inode);
+	*lnkcnt = 1;
+	
+	ext4fs_node_put(root_node);
+	
+	return EOK;
+}
+
+/** Unmount operation.
+ *
+ * Correctly release the filesystem.
+ *
+ * @param service_id Device to be unmounted
+ *
+ * @return Error code
+ *
+ */
+static int ext4fs_unmounted(service_id_t service_id)
+{
+	ext4fs_instance_t *inst;
+	int rc = ext4fs_instance_get(service_id, &inst);
+	if (rc != EOK)
+		return rc;
+	
+	fibril_mutex_lock(&open_nodes_lock);
+	
+	if (inst->open_nodes_count != 0) {
+		fibril_mutex_unlock(&open_nodes_lock);
+		return EBUSY;
+	}
+	
+	/* Remove the instance from the list */
+	fibril_mutex_lock(&instance_list_mutex);
+	list_remove(&inst->link);
+	fibril_mutex_unlock(&instance_list_mutex);
+	
+	fibril_mutex_unlock(&open_nodes_lock);
+	
+	return ext4_filesystem_fini(inst->filesystem);
+}
+
+/** Read bytes from node.
+ *
+ * @param service_id Device to read data from
+ * @param index      Number of node to read from
+ * @param pos        Position where the read should be started
+ * @param rbytes     Output value, where the real size was returned
+ *
+ * @return Error code
+ *
+ */
+static int ext4fs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
+	/*
+	 * Receive the read request.
+	 */
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+	
+	ext4fs_instance_t *inst;
+	int rc = ext4fs_instance_get(service_id, &inst);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	/* Load i-node */
+	ext4_inode_ref_t *inode_ref;
+	rc = ext4_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	/* Read from i-node by type */
+	if (ext4_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
+	    EXT4_INODE_MODE_FILE)) {
+		rc = ext4fs_read_file(callid, pos, size, inst, inode_ref,
+		    rbytes);
+	} else if (ext4_inode_is_type(inst->filesystem->superblock,
+	    inode_ref->inode, EXT4_INODE_MODE_DIRECTORY)) {
+		rc = ext4fs_read_directory(callid, pos, size, inst, inode_ref,
+		    rbytes);
+	} else {
+		/* Other inode types not supported */
+		async_answer_0(callid, ENOTSUP);
+		rc = ENOTSUP;
+	}
+	
+	ext4_filesystem_put_inode_ref(inode_ref);
+	
+	return rc;
+}
+
+/** Check if filename is dot or dotdot (reserved names).
+ *
+ * @param name      Name to check
+ * @param name_size Length of string name
+ *
+ * @return Result of the check
+ *
+ */
+bool ext4fs_is_dots(const uint8_t *name, size_t name_size)
+{
+	if ((name_size == 1) && (name[0] == '.'))
+		return true;
+	
+	if ((name_size == 2) && (name[0] == '.') && (name[1] == '.'))
+		return true;
+	
+	return false;
+}
+
+/** Read data from directory.
+ *
+ * @param callid    IPC id of call (for communication)
+ * @param pos       Position to start reading from
+ * @param size      How many bytes to read
+ * @param inst      Filesystem instance
+ * @param inode_ref Node to read data from
+ * @param rbytes    Output value to return real number of bytes was read
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_read_directory(ipc_callid_t callid, aoff64_t pos, size_t size,
+    ext4fs_instance_t *inst, ext4_inode_ref_t *inode_ref, size_t *rbytes)
+{
+	ext4_directory_iterator_t it;
+	int rc = ext4_directory_iterator_init(&it, inode_ref, pos);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	/*
+	 * Find next interesting directory entry.
+	 * We want to skip . and .. entries
+	 * as these are not used in HelenOS
+	 */
+	bool found = false;
+	while (it.current != NULL) {
+		if (it.current->inode == 0)
+			goto skip;
+		
+		uint16_t name_size = ext4_directory_entry_ll_get_name_length(
+		    inst->filesystem->superblock, it.current);
+		
+		/* Skip . and .. */
+		if (ext4fs_is_dots(it.current->name, name_size))
+			goto skip;
+		
+		/*
+		 * The on-disk entry does not contain \0 at the end
+		 * end of entry name, so we copy it to new buffer
+		 * and add the \0 at the end
+		 */
+		uint8_t *buf = malloc(name_size + 1);
+		if (buf == NULL) {
+			ext4_directory_iterator_fini(&it);
+			async_answer_0(callid, ENOMEM);
+			return ENOMEM;
+		}
+		
+		memcpy(buf, &it.current->name, name_size);
+		*(buf + name_size) = 0;
+		found = true;
+		
+		(void) async_data_read_finalize(callid, buf, name_size + 1);
+		free(buf);
+		break;
+		
+skip:
+		rc = ext4_directory_iterator_next(&it);
+		if (rc != EOK) {
+			ext4_directory_iterator_fini(&it);
+			async_answer_0(callid, rc);
+			return rc;
+		}
+	}
+	
+	uint64_t next;
+	if (found) {
+		rc = ext4_directory_iterator_next(&it);
+		if (rc != EOK)
+			return rc;
+		
+		next = it.current_offset;
+	}
+	
+	rc = ext4_directory_iterator_fini(&it);
+	if (rc != EOK)
+		return rc;
+	
+	/* Prepare return values */
+	if (found) {
+		*rbytes = next - pos;
+		return EOK;
+	} else {
+		async_answer_0(callid, ENOENT);
+		return ENOENT;
+	}
+}
+
+/** Read data from file.
+ *
+ * @param callid    IPC id of call (for communication)
+ * @param pos       Position to start reading from
+ * @param size      How many bytes to read
+ * @param inst      Filesystem instance
+ * @param inode_ref Node to read data from
+ * @param rbytes    Output value to return real number of bytes was read
+ *
+ * @return Error code
+ *
+ */
+int ext4fs_read_file(ipc_callid_t callid, aoff64_t pos, size_t size,
+    ext4fs_instance_t *inst, ext4_inode_ref_t *inode_ref, size_t *rbytes)
+{
+	ext4_superblock_t *sb = inst->filesystem->superblock;
+	uint64_t file_size = ext4_inode_get_size(sb, inode_ref->inode);
+	
+	if (pos >= file_size) {
+		/* Read 0 bytes successfully */
+		async_data_read_finalize(callid, NULL, 0);
+		*rbytes = 0;
+		return EOK;
+	}
+	
+	/* For now, we only read data from one block at a time */
+	uint32_t block_size = ext4_superblock_get_block_size(sb);
+	aoff64_t file_block = pos / block_size;
+	uint32_t offset_in_block = pos % block_size;
+	uint32_t bytes = min(block_size - offset_in_block, size);
+	
+	/* Handle end of file */
+	if (pos + bytes > file_size)
+		bytes = file_size - pos;
+	
+	/* Get the real block number */
+	uint32_t fs_block;
+	int rc = ext4_filesystem_get_inode_data_block_index(inode_ref,
+	    file_block, &fs_block);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	/*
+	 * Check for sparse file.
+	 * If ext4_filesystem_get_inode_data_block_index returned
+	 * fs_block == 0, it means that the given block is not allocated for the
+	 * file and we need to return a buffer of zeros
+	 */
+	uint8_t *buffer;
+	if (fs_block == 0) {
+		buffer = malloc(bytes);
+		if (buffer == NULL) {
+			async_answer_0(callid, ENOMEM);
+			return ENOMEM;
+		}
+		
+		memset(buffer, 0, bytes);
+		
+		async_data_read_finalize(callid, buffer, bytes);
+		*rbytes = bytes;
+		
+		free(buffer);
+		return EOK;
+	}
+	
+	/* Usual case - we need to read a block from device */
+	block_t *block;
+	rc = block_get(&block, inst->service_id, fs_block, BLOCK_FLAGS_NONE);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	assert(offset_in_block + bytes <= block_size);
+	async_data_read_finalize(callid, block->data + offset_in_block, bytes);
+	
+	rc = block_put(block);
+	if (rc != EOK)
+		return rc;
+	
+	*rbytes = bytes;
+	return EOK;
+}
+
+/** Write bytes to file
+ *
+ * @param service_id Device identifier
+ * @param index      I-node number of file
+ * @param pos        Position in file to start reading from
+ * @param wbytes     Output value - real number of written bytes
+ * @param nsize      Output value - new size of i-node
+ *
+ * @return Error code
+ *
+ */
+static int ext4fs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
+	fs_node_t *fn;
+	int rc = ext4fs_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	
+	ipc_callid_t callid;
+	size_t len;
+	if (!async_data_write_receive(&callid, &len)) {
+		ext4fs_node_put(fn);
+		async_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+	
+	ext4fs_node_t *enode = EXT4FS_NODE(fn);
+	ext4_filesystem_t *fs = enode->instance->filesystem;
+	
+	uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
+	
+	/* Prevent writing to more than one block */
+	uint32_t bytes = min(len, block_size - (pos % block_size));
+	
+	int flags = BLOCK_FLAGS_NONE;
+	if (bytes == block_size)
+		flags = BLOCK_FLAGS_NOREAD;
+	
+	uint32_t iblock =  pos / block_size;
+	uint32_t fblock;
+	
+	/* Load inode */
+	ext4_inode_ref_t *inode_ref = enode->inode_ref;
+	rc = ext4_filesystem_get_inode_data_block_index(inode_ref, iblock,
+	    &fblock);
+	if (rc != EOK) {
+		ext4fs_node_put(fn);
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	/* Check for sparse file */
+	if (fblock == 0) {
+		if ((ext4_superblock_has_feature_incompatible(fs->superblock,
+		    EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
+		    (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
+			uint32_t last_iblock =
+			    ext4_inode_get_size(fs->superblock, inode_ref->inode) /
+			    block_size;
+			
+			while (last_iblock < iblock) {
+				rc = ext4_extent_append_block(inode_ref, &last_iblock,
+				    &fblock, true);
+				if (rc != EOK) {
+					ext4fs_node_put(fn);
+					async_answer_0(callid, rc);
+					return rc;
+				}
+			}
+			
+			rc = ext4_extent_append_block(inode_ref, &last_iblock,
+			    &fblock, false);
+			if (rc != EOK) {
+				ext4fs_node_put(fn);
+				async_answer_0(callid, rc);
+				return rc;
+			}
+		} else {
+			rc = ext4_balloc_alloc_block(inode_ref, &fblock);
+			if (rc != EOK) {
+				ext4fs_node_put(fn);
+				async_answer_0(callid, rc);
+				return rc;
+			}
+			
+			rc = ext4_filesystem_set_inode_data_block_index(inode_ref,
+			    iblock, fblock);
+			if (rc != EOK) {
+				ext4_balloc_free_block(inode_ref, fblock);
+				ext4fs_node_put(fn);
+				async_answer_0(callid, rc);
+				return rc;
+			}
+		}
+		
+		flags = BLOCK_FLAGS_NOREAD;
+		inode_ref->dirty = true;
+	}
+	
+	/* Load target block */
+	block_t *write_block;
+	rc = block_get(&write_block, service_id, fblock, flags);
+	if (rc != EOK) {
+		ext4fs_node_put(fn);
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	if (flags == BLOCK_FLAGS_NOREAD)
+		memset(write_block->data, 0, block_size);
+	
+	rc = async_data_write_finalize(callid, write_block->data +
+	    (pos % block_size), bytes);
+	if (rc != EOK) {
+		ext4fs_node_put(fn);
+		return rc;
+	}
+	
+	write_block->dirty = true;
+	
+	rc = block_put(write_block);
+	if (rc != EOK) {
+		ext4fs_node_put(fn);
+		return rc;
+	}
+	
+	/* Do some counting */
+	uint32_t old_inode_size = ext4_inode_get_size(fs->superblock,
+	    inode_ref->inode);
+	if (pos + bytes > old_inode_size) {
+		ext4_inode_set_size(inode_ref->inode, pos + bytes);
+		inode_ref->dirty = true;
+	}
+	
+	*nsize = ext4_inode_get_size(fs->superblock, inode_ref->inode);
+	*wbytes = bytes;
+	
+	return ext4fs_node_put(fn);
+}
+
+/** Truncate file.
+ *
+ * Only the direction to shorter file is supported.
+ *
+ * @param service_id Device identifier
+ * @param index      Index if node to truncated
+ * @param new_size   New size of file
+ *
+ * @return Error code
+ *
+ */
+static int ext4fs_truncate(service_id_t service_id, fs_index_t index,
+    aoff64_t new_size)
+{
+	fs_node_t *fn;
+	int rc = ext4fs_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	
+	ext4fs_node_t *enode = EXT4FS_NODE(fn);
+	ext4_inode_ref_t *inode_ref = enode->inode_ref;
+	
+	rc = ext4_filesystem_truncate_inode(inode_ref, new_size);
+	ext4fs_node_put(fn);
+	
+	return rc;
+}
+
+/** Close file.
+ *
+ * @param service_id Device identifier
+ * @param index      I-node number
+ *
+ * @return Error code
+ *
+ */
+static int ext4fs_close(service_id_t service_id, fs_index_t index)
+{
+	return EOK;
+}
+
+/** Destroy node specified by index.
+ *
+ * @param service_id Device identifier
+ * @param index      I-node to destroy
+ *
+ * @return Error code
+ *
+ */
+static int ext4fs_destroy(service_id_t service_id, fs_index_t index)
+{
+	fs_node_t *fn;
+	int rc = ext4fs_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	
+	/* Destroy the inode */
+	return ext4fs_destroy_node(fn);
+}
+
+/** Enforce inode synchronization (write) to device.
+ *
+ * @param service_id Device identifier
+ * @param index      I-node number.
+ *
+ */
+static int ext4fs_sync(service_id_t service_id, fs_index_t index)
+{
+	fs_node_t *fn;
+	int rc = ext4fs_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	
+	ext4fs_node_t *enode = EXT4FS_NODE(fn);
+	enode->inode_ref->dirty = true;
+	
+	return ext4fs_node_put(fn);
+}
+
+/** VFS operations
+ *
+ */
+vfs_out_ops_t ext4fs_ops = {
+	.mounted = ext4fs_mounted,
+	.unmounted = ext4fs_unmounted,
+	.read = ext4fs_read,
+	.write = ext4fs_write,
+	.truncate = ext4fs_truncate,
+	.close = ext4fs_close,
+	.destroy = ext4fs_destroy,
+	.sync = ext4fs_sync
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/fat/fat.h
===================================================================
--- uspace/srv/fs/fat/fat.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/fat/fat.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -190,7 +190,7 @@
 typedef struct {
 	/** Used indices (position) hash table link. */
-	link_t		uph_link;
+	ht_link_t		uph_link;
 	/** Used indices (index) hash table link. */
-	link_t		uih_link;
+	ht_link_t		uih_link;
 
 	fibril_mutex_t	lock;
Index: uspace/srv/fs/fat/fat_directory.c
===================================================================
--- uspace/srv/fs/fat/fat_directory.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/fat/fat_directory.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,5 +38,5 @@
 #include "fat_directory.h"
 #include "fat_fat.h"
-#include <libblock.h>
+#include <block.h>
 #include <errno.h>
 #include <byteorder.h>
Index: uspace/srv/fs/fat/fat_fat.c
===================================================================
--- uspace/srv/fs/fat/fat_fat.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/fat/fat_fat.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -42,5 +42,5 @@
 #include "../../vfs/vfs.h"
 #include <libfs.h>
-#include <libblock.h>
+#include <block.h>
 #include <errno.h>
 #include <byteorder.h>
Index: uspace/srv/fs/fat/fat_fat.h
===================================================================
--- uspace/srv/fs/fat/fat_fat.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/fat/fat_fat.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,5 +37,5 @@
 #include "../../vfs/vfs.h"
 #include <stdint.h>
-#include <libblock.h>
+#include <block.h>
 
 #define FAT1		0
Index: uspace/srv/fs/fat/fat_idx.c
===================================================================
--- uspace/srv/fs/fat/fat_idx.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/fat/fat_idx.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,4 +41,5 @@
 #include <str.h>
 #include <adt/hash_table.h>
+#include <adt/hash.h>
 #include <adt/list.h>
 #include <assert.h>
@@ -58,6 +59,6 @@
  */
 typedef struct {
-	link_t		link;
-	service_id_t	service_id;
+	link_t link;
+	service_id_t service_id;
 
 	/** Next unassigned index. */
@@ -97,5 +98,5 @@
 			return u;
 	}
-	
+
 	if (lock)
 		fibril_mutex_unlock(&unused_lock);
@@ -113,70 +114,48 @@
 static hash_table_t up_hash;
 
-#define UPH_BUCKETS_LOG	12
-#define UPH_BUCKETS	(1 << UPH_BUCKETS_LOG)
-
-#define UPH_SID_KEY	0
-#define UPH_PFC_KEY	1
-#define UPH_PDI_KEY	2
-
-static hash_index_t pos_hash(unsigned long key[])
-{
-	service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
-	fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY];
-	unsigned pdi = (unsigned)key[UPH_PDI_KEY];
-
-	hash_index_t h;
-
-	/*
-	 * The least significant half of all bits are the least significant bits
-	 * of the parent node's first cluster.
-	 *
-	 * The least significant half of the most significant half of all bits
-	 * are the least significant bits of the node's dentry index within the
-	 * parent directory node.
-	 *
-	 * The most significant half of the most significant half of all bits
-	 * are the least significant bits of the device handle.
-	 */
-	h = pfc & ((1 << (UPH_BUCKETS_LOG / 2)) - 1);
-	h |= (pdi & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
-	    (UPH_BUCKETS_LOG / 2); 
-	h |= (service_id & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
-	    (3 * (UPH_BUCKETS_LOG / 4));
-
-	return h;
-}
-
-static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	service_id_t service_id = (service_id_t)key[UPH_SID_KEY];
+typedef struct {
+	service_id_t service_id;
 	fat_cluster_t pfc;
 	unsigned pdi;
-	fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uph_link);
-
-	switch (keys) {
-	case 1:
-		return (service_id == fidx->service_id);
-	case 3:
-		pfc = (fat_cluster_t) key[UPH_PFC_KEY];
-		pdi = (unsigned) key[UPH_PDI_KEY];
-		return (service_id == fidx->service_id) && (pfc == fidx->pfc) &&
-		    (pdi == fidx->pdi);
-	default:
-		assert((keys == 1) || (keys == 3));
-	}
-
-	return 0;
-}
-
-static void pos_remove_callback(link_t *item)
-{
-	/* nothing to do */
-}
-
-static hash_table_operations_t uph_ops = {
+} pos_key_t;
+
+static inline size_t pos_key_hash(void *key)
+{
+	pos_key_t *pos = (pos_key_t*)key;
+	
+	size_t hash = 0;
+	hash = hash_combine(pos->pfc, pos->pdi);
+	return hash_combine(hash, pos->service_id);
+}
+
+static size_t pos_hash(const ht_link_t *item)
+{
+	fat_idx_t *fidx = hash_table_get_inst(item, fat_idx_t, uph_link);
+	
+	pos_key_t pkey = {
+		.service_id = fidx->service_id,
+		.pfc = fidx->pfc,
+		.pdi = fidx->pdi,
+	};
+	
+	return pos_key_hash(&pkey);
+}
+
+static bool pos_key_equal(void *key, const ht_link_t *item)
+{
+	pos_key_t *pos = (pos_key_t*)key;
+	fat_idx_t *fidx = hash_table_get_inst(item, fat_idx_t, uph_link);
+	
+	return pos->service_id == fidx->service_id
+		&& pos->pdi == fidx->pdi
+		&& pos->pfc == fidx->pfc;
+}
+
+static hash_table_ops_t uph_ops = {
 	.hash = pos_hash,
-	.compare = pos_compare,
-	.remove_callback = pos_remove_callback,
+	.key_hash = pos_key_hash,
+	.key_equal = pos_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL,
 };
 
@@ -187,54 +166,41 @@
 static hash_table_t ui_hash;
 
-#define UIH_BUCKETS_LOG	12
-#define UIH_BUCKETS	(1 << UIH_BUCKETS_LOG)
-
-#define UIH_SID_KEY	0
-#define UIH_INDEX_KEY	1
-
-static hash_index_t idx_hash(unsigned long key[])
-{
-	service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
-	fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY];
-
-	hash_index_t h;
-
-	h = service_id & ((1 << (UIH_BUCKETS_LOG / 2)) - 1);
-	h |= (index & ((1 << (UIH_BUCKETS_LOG / 2)) - 1)) <<
-	    (UIH_BUCKETS_LOG / 2);
-
-	return h;
-}
-
-static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	service_id_t service_id = (service_id_t)key[UIH_SID_KEY];
+typedef struct {
+	service_id_t service_id;
 	fs_index_t index;
-	fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link);
-
-	switch (keys) {
-	case 1:
-		return (service_id == fidx->service_id);
-	case 2:
-		index = (fs_index_t) key[UIH_INDEX_KEY];
-		return (service_id == fidx->service_id) &&
-		    (index == fidx->index);
-	default:
-		assert((keys == 1) || (keys == 2));
-	}
-
-	return 0;
-}
-
-static void idx_remove_callback(link_t *item)
-{
-	fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link);
+} idx_key_t;
+
+static size_t idx_key_hash(void *key_arg)
+{
+	idx_key_t *key = (idx_key_t*)key_arg;
+	return hash_combine(key->service_id, key->index);
+}
+
+static size_t idx_hash(const ht_link_t *item)
+{
+	fat_idx_t *fidx = hash_table_get_inst(item, fat_idx_t, uih_link);
+	return hash_combine(fidx->service_id, fidx->index);
+}
+
+static bool idx_key_equal(void *key_arg, const ht_link_t *item)
+{
+	fat_idx_t *fidx = hash_table_get_inst(item, fat_idx_t, uih_link);
+	idx_key_t *key = (idx_key_t*)key_arg;
+	
+	return key->index == fidx->index && key->service_id == fidx->service_id;
+}
+
+static void idx_remove_callback(ht_link_t *item)
+{
+	fat_idx_t *fidx = hash_table_get_inst(item, fat_idx_t, uih_link);
 
 	free(fidx);
 }
 
-static hash_table_operations_t uih_ops = {
+static hash_table_ops_t uih_ops = {
 	.hash = idx_hash,
-	.compare = idx_compare,
+	.key_hash = idx_key_hash,
+	.key_equal = idx_key_equal,
+	.equal = NULL,
 	.remove_callback = idx_remove_callback,
 };
@@ -377,6 +343,4 @@
 	}
 		
-	link_initialize(&fidx->uph_link);
-	link_initialize(&fidx->uih_link);
 	fibril_mutex_initialize(&fidx->lock);
 	fidx->service_id = service_id;
@@ -401,10 +365,5 @@
 	}
 		
-	unsigned long ikey[] = {
-		[UIH_SID_KEY] = service_id,
-		[UIH_INDEX_KEY] = fidx->index,
-	};
-	
-	hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
+	hash_table_insert(&ui_hash, &fidx->uih_link);
 	fibril_mutex_lock(&fidx->lock);
 	fibril_mutex_unlock(&used_lock);
@@ -418,15 +377,15 @@
 {
 	fat_idx_t *fidx;
-	link_t *l;
-	unsigned long pkey[] = {
-		[UPH_SID_KEY] = service_id,
-		[UPH_PFC_KEY] = pfc,
-		[UPH_PDI_KEY] = pdi,
+
+	pos_key_t pos_key = {
+		.service_id = service_id,
+		.pfc = pfc,
+		.pdi = pdi,
 	};
 
 	fibril_mutex_lock(&used_lock);
-	l = hash_table_find(&up_hash, pkey);
+	ht_link_t *l = hash_table_find(&up_hash, &pos_key);
 	if (l) {
-		fidx = hash_table_get_instance(l, fat_idx_t, uph_link);
+		fidx = hash_table_get_inst(l, fat_idx_t, uph_link);
 	} else {
 		int rc;
@@ -438,14 +397,9 @@
 		}
 		
-		unsigned long ikey[] = {
-			[UIH_SID_KEY] = service_id,
-			[UIH_INDEX_KEY] = fidx->index,
-		};
-	
 		fidx->pfc = pfc;
 		fidx->pdi = pdi;
 
-		hash_table_insert(&up_hash, pkey, &fidx->uph_link);
-		hash_table_insert(&ui_hash, ikey, &fidx->uih_link);
+		hash_table_insert(&up_hash, &fidx->uph_link);
+		hash_table_insert(&ui_hash, &fidx->uih_link);
 	}
 	fibril_mutex_lock(&fidx->lock);
@@ -457,12 +411,6 @@
 void fat_idx_hashin(fat_idx_t *idx)
 {
-	unsigned long pkey[] = {
-		[UPH_SID_KEY] = idx->service_id,
-		[UPH_PFC_KEY] = idx->pfc,
-		[UPH_PDI_KEY] = idx->pdi,
-	};
-
-	fibril_mutex_lock(&used_lock);
-	hash_table_insert(&up_hash, pkey, &idx->uph_link);
+	fibril_mutex_lock(&used_lock);
+	hash_table_insert(&up_hash, &idx->uph_link);
 	fibril_mutex_unlock(&used_lock);
 }
@@ -470,12 +418,6 @@
 void fat_idx_hashout(fat_idx_t *idx)
 {
-	unsigned long pkey[] = {
-		[UPH_SID_KEY] = idx->service_id,
-		[UPH_PFC_KEY] = idx->pfc,
-		[UPH_PDI_KEY] = idx->pdi,
-	};
-
-	fibril_mutex_lock(&used_lock);
-	hash_table_remove(&up_hash, pkey, 3);
+	fibril_mutex_lock(&used_lock);
+	hash_table_remove_item(&up_hash, &idx->uph_link);
 	fibril_mutex_unlock(&used_lock);
 }
@@ -485,14 +427,14 @@
 {
 	fat_idx_t *fidx = NULL;
-	link_t *l;
-	unsigned long ikey[] = {
-		[UIH_SID_KEY] = service_id,
-		[UIH_INDEX_KEY] = index,
+
+	idx_key_t idx_key = {
+		.service_id = service_id,
+		.index = index,
 	};
 
 	fibril_mutex_lock(&used_lock);
-	l = hash_table_find(&ui_hash, ikey);
+	ht_link_t *l = hash_table_find(&ui_hash, &idx_key);
 	if (l) {
-		fidx = hash_table_get_instance(l, fat_idx_t, uih_link);
+		fidx = hash_table_get_inst(l, fat_idx_t, uih_link);
 		fibril_mutex_lock(&fidx->lock);
 	}
@@ -508,10 +450,8 @@
 void fat_idx_destroy(fat_idx_t *idx)
 {
-	unsigned long ikey[] = {
-		[UIH_SID_KEY] = idx->service_id,
-		[UIH_INDEX_KEY] = idx->index,
+	idx_key_t idx_key = {
+		.service_id = idx->service_id,
+		.index = idx->index,
 	};
-	service_id_t service_id = idx->service_id;
-	fs_index_t index = idx->index;
 
 	assert(idx->pfc == FAT_CLST_RES0);
@@ -523,8 +463,8 @@
 	 * the index hash only.
 	 */
-	hash_table_remove(&ui_hash, ikey, 2);
+	hash_table_remove(&ui_hash, &idx_key);
 	fibril_mutex_unlock(&used_lock);
 	/* Release the VFS index. */
-	fat_index_free(service_id, index);
+	fat_index_free(idx_key.service_id, idx_key.index);
 	/* The index structure itself is freed in idx_remove_callback(). */
 }
@@ -532,7 +472,7 @@
 int fat_idx_init(void)
 {
-	if (!hash_table_create(&up_hash, UPH_BUCKETS, 3, &uph_ops)) 
+	if (!hash_table_create(&up_hash, 0, 0, &uph_ops)) 
 		return ENOMEM;
-	if (!hash_table_create(&ui_hash, UIH_BUCKETS, 2, &uih_ops)) {
+	if (!hash_table_create(&ui_hash, 0, 0, &uih_ops)) {
 		hash_table_destroy(&up_hash);
 		return ENOMEM;
@@ -544,4 +484,5 @@
 {
 	/* We assume the hash tables are empty. */
+	assert(hash_table_empty(&up_hash) && hash_table_empty(&ui_hash));
 	hash_table_destroy(&up_hash);
 	hash_table_destroy(&ui_hash);
@@ -568,13 +509,30 @@
 }
 
+static bool rm_pos_service_id(ht_link_t *item, void *arg)
+{
+	service_id_t service_id = *(service_id_t*)arg;
+	fat_idx_t *fidx = hash_table_get_inst(item, fat_idx_t, uph_link);
+
+	if (fidx->service_id == service_id) {
+		hash_table_remove_item(&up_hash, item);
+	}
+	
+	return true;
+}
+
+static bool rm_idx_service_id(ht_link_t *item, void *arg)
+{
+	service_id_t service_id = *(service_id_t*)arg;
+	fat_idx_t *fidx = hash_table_get_inst(item, fat_idx_t, uih_link);
+
+	if (fidx->service_id == service_id) {
+		hash_table_remove_item(&ui_hash, item);
+	}
+	
+	return true;
+}
+
 void fat_idx_fini_by_service_id(service_id_t service_id)
 {
-	unsigned long ikey[] = {
-		[UIH_SID_KEY] = service_id
-	};
-	unsigned long pkey[] = {
-		[UPH_SID_KEY] = service_id
-	};
-
 	/*
 	 * Remove this instance's index structure from up_hash and ui_hash.
@@ -583,6 +541,6 @@
 	 */
 	fibril_mutex_lock(&used_lock);
-	hash_table_remove(&up_hash, pkey, 1);
-	hash_table_remove(&ui_hash, ikey, 1);
+	hash_table_apply(&up_hash, rm_pos_service_id, &service_id);
+	hash_table_apply(&ui_hash, rm_idx_service_id, &service_id);
 	fibril_mutex_unlock(&used_lock);
 
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/fat/fat_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -43,5 +43,5 @@
 #include "../../vfs/vfs.h"
 #include <libfs.h>
-#include <libblock.h>
+#include <block.h>
 #include <ipc/services.h>
 #include <ipc/loc.h>
Index: uspace/srv/fs/locfs/locfs_ops.c
===================================================================
--- uspace/srv/fs/locfs/locfs_ops.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/locfs/locfs_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -61,5 +61,5 @@
 	async_sess_t *sess;       /**< If NULL, the structure is incomplete. */
 	size_t refcount;
-	link_t link;
+	ht_link_t link;
 	fibril_condvar_t cv;      /**< Broadcast when completed. */
 } service_t;
@@ -71,28 +71,33 @@
 static FIBRIL_MUTEX_INITIALIZE(services_mutex);
 
-#define SERVICES_KEYS        1
-#define SERVICES_KEY_HANDLE  0
-#define SERVICES_BUCKETS     256
-
 /* Implementation of hash table interface for the nodes hash table. */
-static hash_index_t services_hash(unsigned long key[])
-{
-	return key[SERVICES_KEY_HANDLE] % SERVICES_BUCKETS;
-}
-
-static int services_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	service_t *dev = hash_table_get_instance(item, service_t, link);
-	return (dev->service_id == (service_id_t) key[SERVICES_KEY_HANDLE]);
-}
-
-static void services_remove_callback(link_t *item)
-{
-	free(hash_table_get_instance(item, service_t, link));
-}
-
-static hash_table_operations_t services_ops = {
+
+static size_t services_key_hash(void *key)
+{
+	return *(service_id_t*)key;
+}
+
+static size_t services_hash(const ht_link_t *item)
+{
+	service_t *dev = hash_table_get_inst(item, service_t, link);
+	return dev->service_id;
+}
+
+static bool services_key_equal(void *key, const ht_link_t *item)
+{
+	service_t *dev = hash_table_get_inst(item, service_t, link);
+	return (dev->service_id == *(service_id_t*)key);
+}
+
+static void services_remove_callback(ht_link_t *item)
+{
+	free(hash_table_get_inst(item, service_t, link));
+}
+
+static hash_table_ops_t services_ops = {
 	.hash = services_hash,
-	.compare = services_compare,
+	.key_hash = services_key_hash,
+	.key_equal = services_key_equal,
+	.equal = NULL, 
 	.remove_callback = services_remove_callback
 };
@@ -229,12 +234,8 @@
 		/* Device node */
 		
-		unsigned long key[] = {
-			[SERVICES_KEY_HANDLE] = (unsigned long) node->service_id
-		};
-		link_t *lnk;
-		
 		fibril_mutex_lock(&services_mutex);
+		ht_link_t *lnk;
 restart:
-		lnk = hash_table_find(&services, key);
+		lnk = hash_table_find(&services, &node->service_id);
 		if (lnk == NULL) {
 			service_t *dev = (service_t *) malloc(sizeof(service_t));
@@ -256,5 +257,5 @@
 			 * below.
 			 */
-			hash_table_insert(&services, key, &dev->link);
+			hash_table_insert(&services, &dev->link);
 			
 			/*
@@ -279,5 +280,5 @@
 				 * entry and free the device structure.
 				 */
-				hash_table_remove(&services, key, SERVICES_KEYS);
+				hash_table_remove(&services, &node->service_id);
 				fibril_mutex_unlock(&services_mutex);
 				
@@ -288,5 +289,5 @@
 			dev->sess = sess;
 		} else {
-			service_t *dev = hash_table_get_instance(lnk, service_t, link);
+			service_t *dev = hash_table_get_inst(lnk, service_t, link);
 			
 			if (!dev->sess) {
@@ -450,6 +451,5 @@
 bool locfs_init(void)
 {
-	if (!hash_table_create(&services, SERVICES_BUCKETS,
-	    SERVICES_KEYS, &services_ops))
+	if (!hash_table_create(&services, 0,  0, &services_ops))
 		return false;
 	
@@ -555,10 +555,7 @@
 		/* Device node */
 		
-		unsigned long key[] = {
-			[SERVICES_KEY_HANDLE] = (unsigned long) index
-		};
-		
 		fibril_mutex_lock(&services_mutex);
-		link_t *lnk = hash_table_find(&services, key);
+		service_id_t service_index = index;
+		ht_link_t *lnk = hash_table_find(&services, &service_index);
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&services_mutex);
@@ -566,5 +563,5 @@
 		}
 		
-		service_t *dev = hash_table_get_instance(lnk, service_t, link);
+		service_t *dev = hash_table_get_inst(lnk, service_t, link);
 		assert(dev->sess);
 		
@@ -621,10 +618,8 @@
 	if (type == LOC_OBJECT_SERVICE) {
 		/* Device node */
-		unsigned long key[] = {
-			[SERVICES_KEY_HANDLE] = (unsigned long) index
-		};
 		
 		fibril_mutex_lock(&services_mutex);
-		link_t *lnk = hash_table_find(&services, key);
+		service_id_t service_index = index;
+		ht_link_t *lnk = hash_table_find(&services, &service_index);
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&services_mutex);
@@ -632,5 +627,5 @@
 		}
 		
-		service_t *dev = hash_table_get_instance(lnk, service_t, link);
+		service_t *dev = hash_table_get_inst(lnk, service_t, link);
 		assert(dev->sess);
 		
@@ -691,10 +686,8 @@
 	
 	if (type == LOC_OBJECT_SERVICE) {
-		unsigned long key[] = {
-			[SERVICES_KEY_HANDLE] = (unsigned long) index
-		};
 		
 		fibril_mutex_lock(&services_mutex);
-		link_t *lnk = hash_table_find(&services, key);
+		service_id_t service_index = index;
+		ht_link_t *lnk = hash_table_find(&services, &service_index);
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&services_mutex);
@@ -702,5 +695,5 @@
 		}
 		
-		service_t *dev = hash_table_get_instance(lnk, service_t, link);
+		service_t *dev = hash_table_get_inst(lnk, service_t, link);
 		assert(dev->sess);
 		dev->refcount--;
@@ -708,5 +701,6 @@
 		if (dev->refcount == 0) {
 			async_hangup(dev->sess);
-			hash_table_remove(&services, key, SERVICES_KEYS);
+			service_id_t service_index = index;
+			hash_table_remove(&services, &service_index);
 		}
 		
@@ -732,10 +726,8 @@
 	
 	if (type == LOC_OBJECT_SERVICE) {
-		unsigned long key[] = {
-			[SERVICES_KEY_HANDLE] = (unsigned long) index
-		};
-		
+
 		fibril_mutex_lock(&services_mutex);
-		link_t *lnk = hash_table_find(&services, key);
+		service_id_t service_index = index;
+		ht_link_t *lnk = hash_table_find(&services, &service_index);
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&services_mutex);
@@ -743,5 +735,5 @@
 		}
 		
-		service_t *dev = hash_table_get_instance(lnk, service_t, link);
+		service_t *dev = hash_table_get_inst(lnk, service_t, link);
 		assert(dev->sess);
 		
Index: uspace/srv/fs/mfs/mfs.h
===================================================================
--- uspace/srv/fs/mfs/mfs.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/mfs/mfs.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,5 +36,5 @@
 #include <minix.h>
 #include <macros.h>
-#include <libblock.h>
+#include <block.h>
 #include <libfs.h>
 #include <adt/list.h>
@@ -142,5 +142,5 @@
 	unsigned refcnt;
 	fs_node_t *fsnode;
-	link_t link;
+	ht_link_t link;
 };
 
Index: uspace/srv/fs/mfs/mfs_ops.c
===================================================================
--- uspace/srv/fs/mfs/mfs_ops.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/mfs/mfs_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,10 +35,7 @@
 #include <align.h>
 #include <adt/hash_table.h>
+#include <adt/hash.h>
 #include "mfs.h"
 
-#define OPEN_NODES_KEYS 2
-#define OPEN_NODES_SERVICE_KEY 0
-#define OPEN_NODES_INODE_KEY 1
-#define OPEN_NODES_BUCKETS 256
 
 static bool check_magic_number(uint16_t magic, bool *native,
@@ -61,8 +58,4 @@
 static int mfs_unlink(fs_node_t *, fs_node_t *, const char *name);
 static int mfs_destroy_node(fs_node_t *fn);
-static hash_index_t open_nodes_hash(unsigned long key[]);
-static int open_nodes_compare(unsigned long key[], hash_count_t keys,
-    link_t *item);
-static void open_nodes_remove_cb(link_t *link);
 static int mfs_node_get(fs_node_t **rfn, service_id_t service_id,
     fs_index_t index);
@@ -95,38 +88,40 @@
 
 /* Hash table interface for open nodes hash table */
-static hash_index_t
-open_nodes_hash(unsigned long key[])
-{
-	/* TODO: This is very simple and probably can be improved */
-	return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS;
-}
-
-static int
-open_nodes_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
-{
-	struct mfs_node *mnode = hash_table_get_instance(item, struct mfs_node, link);
-	assert(keys > 0);
-	if (mnode->instance->service_id !=
-	    ((service_id_t) key[OPEN_NODES_SERVICE_KEY])) {
-		return false;
-	}
-	if (keys == 1) {
-		return true;
-	}
-	assert(keys == 2);
-	return (mnode->ino_i->index == key[OPEN_NODES_INODE_KEY]);
-}
-
-static void
-open_nodes_remove_cb(link_t *link)
-{
-	/* We don't use remove callback for this hash table */
-}
-
-static hash_table_operations_t open_nodes_ops = {
+
+typedef struct {
+	service_id_t service_id;
+	fs_index_t index;
+} node_key_t;
+
+static size_t
+open_nodes_key_hash(void *key)
+{
+	node_key_t *node_key = (node_key_t*)key;
+	return hash_combine(node_key->service_id, node_key->index);
+}
+
+static size_t
+open_nodes_hash(const ht_link_t *item)
+{
+	struct mfs_node *m = hash_table_get_inst(item, struct mfs_node, link);
+	return hash_combine(m->instance->service_id, m->ino_i->index);
+}
+
+static bool
+open_nodes_key_equal(void *key, const ht_link_t *item)
+{
+	node_key_t *node_key = (node_key_t*)key;
+	struct mfs_node *mnode = hash_table_get_inst(item, struct mfs_node, link);
+
+	return node_key->service_id == mnode->instance->service_id
+		&& node_key->index == mnode->ino_i->index;
+}
+
+static hash_table_ops_t open_nodes_ops = {
 	.hash = open_nodes_hash,
-	.compare = open_nodes_compare,
-	.remove_callback = open_nodes_remove_cb,
+	.key_hash = open_nodes_key_hash,
+	.key_equal = open_nodes_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL,
 };
 
@@ -134,6 +129,5 @@
 mfs_global_init(void)
 {
-	if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
-	    OPEN_NODES_KEYS, &open_nodes_ops)) {
+	if (!hash_table_create(&open_nodes, 0, 0, &open_nodes_ops)) {
 		return ENOMEM;
 	}
@@ -406,13 +400,6 @@
 	mnode->refcnt = 1;
 
-	link_initialize(&mnode->link);
-
-	unsigned long key[] = {
-		[OPEN_NODES_SERVICE_KEY] = inst->service_id,
-		[OPEN_NODES_INODE_KEY] = inum,
-	};
-
 	fibril_mutex_lock(&open_nodes_lock);
-	hash_table_insert(&open_nodes, key, &mnode->link);
+	hash_table_insert(&open_nodes, &mnode->link);
 	fibril_mutex_unlock(&open_nodes_lock);
 	inst->open_nodes_cnt++;
@@ -513,9 +500,5 @@
 	mnode->refcnt--;
 	if (mnode->refcnt == 0) {
-		unsigned long key[] = {
-			[OPEN_NODES_SERVICE_KEY] = mnode->instance->service_id,
-			[OPEN_NODES_INODE_KEY] = mnode->ino_i->index
-		};
-		hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS);
+		hash_table_remove_item(&open_nodes, &mnode->link);
 		assert(mnode->instance->open_nodes_cnt > 0);
 		mnode->instance->open_nodes_cnt--;
@@ -576,12 +559,13 @@
 
 	/* Check if the node is not already open */
-	unsigned long key[] = {
-		[OPEN_NODES_SERVICE_KEY] = inst->service_id,
-		[OPEN_NODES_INODE_KEY] = index,
+	node_key_t key = {
+		.service_id = inst->service_id,
+		.index = index
 	};
-	link_t *already_open = hash_table_find(&open_nodes, key);
+	
+	ht_link_t *already_open = hash_table_find(&open_nodes, &key);
 
 	if (already_open) {
-		mnode = hash_table_get_instance(already_open, struct mfs_node, link);
+		mnode = hash_table_get_inst(already_open, struct mfs_node, link);
 		*rfn = mnode->fsnode;
 		mnode->refcnt++;
@@ -614,5 +598,4 @@
 	mnode->ino_i = ino_i;
 	mnode->refcnt = 1;
-	link_initialize(&mnode->link);
 
 	mnode->instance = inst;
@@ -621,5 +604,5 @@
 	*rfn = node;
 
-	hash_table_insert(&open_nodes, key, &mnode->link);
+	hash_table_insert(&open_nodes, &mnode->link);
 	inst->open_nodes_cnt++;
 
Index: uspace/srv/fs/tmpfs/tmpfs.h
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/tmpfs/tmpfs.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -62,5 +62,5 @@
 	fs_index_t index;	/**< TMPFS node index. */
 	service_id_t service_id;/**< Service ID of block device. */
-	link_t nh_link;		/**< Nodes hash table link. */
+	ht_link_t nh_link;		/**< Nodes hash table link. */
 	tmpfs_dentry_type_t type;
 	unsigned lnkcnt;	/**< Link count. */
Index: uspace/srv/fs/tmpfs/tmpfs_dump.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_dump.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/tmpfs/tmpfs_dump.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -44,8 +44,10 @@
 #include <sys/types.h>
 #include <as.h>
-#include <libblock.h>
+#include <block.h>
 #include <byteorder.h>
 
 #define TMPFS_COMM_SIZE		1024
+
+static uint8_t tmpfs_buf[TMPFS_COMM_SIZE];
 
 struct rdentry {
@@ -68,5 +70,5 @@
 		uint32_t size;
 		
-		if (block_seqread(dsid, bufpos, buflen, pos, &entry,
+		if (block_seqread(dsid, tmpfs_buf, bufpos, buflen, pos, &entry,
 		    sizeof(entry)) != EOK)
 			return false;
@@ -88,5 +90,5 @@
 			}
 			
-			if (block_seqread(dsid, bufpos, buflen, pos, fname,
+			if (block_seqread(dsid, tmpfs_buf, bufpos, buflen, pos, fname,
 			    entry.len) != EOK) {
 				(void) ops->destroy(fn);
@@ -104,5 +106,5 @@
 			free(fname);
 			
-			if (block_seqread(dsid, bufpos, buflen, pos, &size,
+			if (block_seqread(dsid, tmpfs_buf, bufpos, buflen, pos, &size,
 			    sizeof(size)) != EOK)
 				return false;
@@ -116,5 +118,5 @@
 			
 			nodep->size = size;
-			if (block_seqread(dsid, bufpos, buflen, pos, nodep->data,
+			if (block_seqread(dsid, tmpfs_buf, bufpos, buflen, pos, nodep->data,
 			    size) != EOK)
 				return false;
@@ -132,5 +134,5 @@
 			}
 			
-			if (block_seqread(dsid, bufpos, buflen, pos, fname,
+			if (block_seqread(dsid, tmpfs_buf, bufpos, buflen, pos, fname,
 			    entry.len) != EOK) {
 				(void) ops->destroy(fn);
@@ -176,5 +178,5 @@
 	
 	char tag[6];
-	if (block_seqread(dsid, &bufpos, &buflen, &pos, tag, 5) != EOK)
+	if (block_seqread(dsid, tmpfs_buf, &bufpos, &buflen, &pos, tag, 5) != EOK)
 		goto error;
 	
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -50,4 +50,5 @@
 #include <sys/types.h>
 #include <adt/hash_table.h>
+#include <adt/hash.h>
 #include <as.h>
 #include <libfs.h>
@@ -55,6 +56,4 @@
 #define min(a, b)		((a) < (b) ? (a) : (b))
 #define max(a, b)		((a) > (b) ? (a) : (b))
-
-#define NODES_BUCKETS	256
 
 /** All root nodes have index 0. */
@@ -142,35 +141,36 @@
 hash_table_t nodes;
 
-#define NODES_KEY_DEV	0	
-#define NODES_KEY_INDEX	1
-
-/* Implementation of hash table interface for the nodes hash table. */
-static hash_index_t nodes_hash(unsigned long key[])
-{
-	return key[NODES_KEY_INDEX] % NODES_BUCKETS;
-}
-
-static int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t,
-	    nh_link);
-	
-	switch (keys) {
-	case 1:
-		return (nodep->service_id == key[NODES_KEY_DEV]);
-	case 2:	
-		return ((nodep->service_id == key[NODES_KEY_DEV]) &&
-		    (nodep->index == key[NODES_KEY_INDEX]));
-	default:
-		assert((keys == 1) || (keys == 2));
-	}
-
-	return 0;
-}
-
-static void nodes_remove_callback(link_t *item)
-{
-	tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t,
-	    nh_link);
+/* 
+ * Implementation of hash table interface for the nodes hash table. 
+ */
+
+typedef struct {
+	service_id_t service_id;
+	fs_index_t index;
+} node_key_t;
+
+static size_t nodes_key_hash(void *k)
+{
+	node_key_t *key = (node_key_t *)k;
+	return hash_combine(key->service_id, key->index);
+}
+
+static size_t nodes_hash(const ht_link_t *item)
+{
+	tmpfs_node_t *nodep = hash_table_get_inst(item, tmpfs_node_t, nh_link);
+	return hash_combine(nodep->service_id, nodep->index);
+}
+
+static bool nodes_key_equal(void *key_arg, const ht_link_t *item)
+{
+	tmpfs_node_t *node = hash_table_get_inst(item, tmpfs_node_t, nh_link);
+	node_key_t *key = (node_key_t *)key_arg;
+	
+	return key->service_id == node->service_id && key->index == node->index;
+}
+
+static void nodes_remove_callback(ht_link_t *item)
+{
+	tmpfs_node_t *nodep = hash_table_get_inst(item, tmpfs_node_t, nh_link);
 
 	while (!list_empty(&nodep->cs_list)) {
@@ -192,7 +192,9 @@
 
 /** TMPFS nodes hash table operations. */
-hash_table_operations_t nodes_ops = {
+hash_table_ops_t nodes_ops = {
 	.hash = nodes_hash,
-	.compare = nodes_compare,
+	.key_hash = nodes_key_hash,
+	.key_equal = nodes_key_equal,
+	.equal = NULL,
 	.remove_callback = nodes_remove_callback
 };
@@ -207,5 +209,4 @@
 	nodep->size = 0;
 	nodep->data = NULL;
-	link_initialize(&nodep->nh_link);
 	list_initialize(&nodep->cs_list);
 }
@@ -220,5 +221,5 @@
 bool tmpfs_init(void)
 {
-	if (!hash_table_create(&nodes, NODES_BUCKETS, 2, &nodes_ops))
+	if (!hash_table_create(&nodes, 0, 0, &nodes_ops))
 		return false;
 	
@@ -238,17 +239,18 @@
 }
 
+static bool rm_service_id_nodes(ht_link_t *item, void *arg)
+{
+	service_id_t sid = *(service_id_t*)arg;
+	tmpfs_node_t *node = hash_table_get_inst(item, tmpfs_node_t, nh_link);
+	
+	if (node->service_id == sid) {
+		hash_table_remove_item(&nodes, &node->nh_link);
+	}
+	return true;
+}
+
 static void tmpfs_instance_done(service_id_t service_id)
-{
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = service_id
-	};
-	/*
-	 * Here we are making use of one special feature of our hash table
-	 * implementation, which allows to remove more items based on a partial
-	 * key match. In the following, we are going to remove all nodes
-	 * matching our device handle. The nodes_remove_callback() function will
-	 * take care of resource deallocation.
-	 */
-	hash_table_remove(&nodes, key, 1);
+{	
+	hash_table_apply(&nodes, rm_service_id_nodes, &service_id);
 }
 
@@ -272,12 +274,14 @@
 int tmpfs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
 {
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = service_id,
-		[NODES_KEY_INDEX] = index
+	node_key_t key = {
+		.service_id = service_id,
+		.index = index
 	};
-	link_t *lnk = hash_table_find(&nodes, key);
+	
+	ht_link_t *lnk = hash_table_find(&nodes, &key);
+	
 	if (lnk) {
 		tmpfs_node_t *nodep;
-		nodep = hash_table_get_instance(lnk, tmpfs_node_t, nh_link);
+		nodep = hash_table_get_inst(lnk, tmpfs_node_t, nh_link);
 		*rfn = FS_NODE(nodep);
 	} else {
@@ -331,9 +335,5 @@
 
 	/* Insert the new node into the nodes hash table. */
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = nodep->service_id,
-		[NODES_KEY_INDEX] = nodep->index
-	};
-	hash_table_insert(&nodes, key, &nodep->nh_link);
+	hash_table_insert(&nodes, &nodep->nh_link);
 	*rfn = FS_NODE(nodep);
 	return EOK;
@@ -346,10 +346,6 @@
 	assert(!nodep->lnkcnt);
 	assert(list_empty(&nodep->cs_list));
-
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = nodep->service_id,
-		[NODES_KEY_INDEX] = nodep->index
-	};
-	hash_table_remove(&nodes, key, 2);
+	
+	hash_table_remove_item(&nodes, &nodep->nh_link);
 
 	/*
@@ -476,14 +472,14 @@
 	 * Lookup the respective TMPFS node.
 	 */
-	link_t *hlp;
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = service_id,
-		[NODES_KEY_INDEX] = index
+	node_key_t key = {
+		.service_id = service_id,
+		.index = index
 	};
-	hlp = hash_table_find(&nodes, key);
+	
+	ht_link_t *hlp = hash_table_find(&nodes, &key);
 	if (!hlp)
 		return ENOENT;
-	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
-	    nh_link);
+	
+	tmpfs_node_t *nodep = hash_table_get_inst(hlp, tmpfs_node_t, nh_link);
 	
 	/*
@@ -538,14 +534,15 @@
 	 * Lookup the respective TMPFS node.
 	 */
-	link_t *hlp;
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = service_id,
-		[NODES_KEY_INDEX] = index
+	node_key_t key = {
+		.service_id = service_id,
+		.index = index
 	};
-	hlp = hash_table_find(&nodes, key);
+	
+	ht_link_t *hlp = hash_table_find(&nodes, &key);
+	
 	if (!hlp)
 		return ENOENT;
-	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
-	    nh_link);
+	
+	tmpfs_node_t *nodep = hash_table_get_inst(hlp, tmpfs_node_t, nh_link);
 
 	/*
@@ -600,12 +597,14 @@
 	 * Lookup the respective TMPFS node.
 	 */
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = service_id,
-		[NODES_KEY_INDEX] = index
+	node_key_t key = {
+		.service_id = service_id,
+		.index = index
 	};
-	link_t *hlp = hash_table_find(&nodes, key);
+	
+	ht_link_t *hlp = hash_table_find(&nodes, &key);
+	
 	if (!hlp)
 		return ENOENT;
-	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, nh_link);
+	tmpfs_node_t *nodep = hash_table_get_inst(hlp, tmpfs_node_t, nh_link);
 	
 	if (size == nodep->size)
@@ -636,13 +635,13 @@
 static int tmpfs_destroy(service_id_t service_id, fs_index_t index)
 {
-	link_t *hlp;
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = service_id,
-		[NODES_KEY_INDEX] = index
+	node_key_t key = {
+		.service_id = service_id,
+		.index = index
 	};
-	hlp = hash_table_find(&nodes, key);
+	
+	ht_link_t *hlp = hash_table_find(&nodes, &key);
 	if (!hlp)
 		return ENOENT;
-	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
+	tmpfs_node_t *nodep = hash_table_get_inst(hlp, tmpfs_node_t,
 	    nh_link);
 	return tmpfs_destroy_node(FS_NODE(nodep));
Index: uspace/srv/fs/udf/Makefile
===================================================================
--- uspace/srv/fs/udf/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# Copyright (c) 2012 Julia Medvedeva
+# 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 = $(LIBBLOCK_PREFIX)/libblock.a $(LIBFS_PREFIX)/libfs.a
+EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX)
+BINARY = udf
+
+SOURCES = \
+	udf.c \
+	udf_volume.c \
+	udf_ops.c \
+	udf_osta.c \
+	udf_cksum.c \
+	udf_file.c \
+	udf_idx.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/fs/udf/udf.c
===================================================================
--- uspace/srv/fs/udf/udf.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2006 Martin Decky
+ * Copyright (c) 2008 Jakub Jermar
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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 fs
+ * @{
+ */
+/**
+ * @file udf.c
+ * @brief UDF 1.02 file system driver for HelenOS.
+ */
+
+#include <ipc/services.h>
+#include <ns.h>
+#include <async.h>
+#include <errno.h>
+#include <unistd.h>
+#include <task.h>
+#include <libfs.h>
+#include <str.h>
+#include <io/log.h>
+#include "../../vfs/vfs.h"
+#include "udf.h"
+#include "udf_idx.h"
+
+#define NAME  "udf"
+
+vfs_info_t udf_vfs_info = {
+	.name = NAME,
+	.concurrent_read_write = false,
+	.write_retains_size = false,
+	.instance = 0,
+};
+
+int main(int argc, char *argv[])
+{
+	log_init(NAME);
+	log_msg(LOG_DEFAULT, LVL_NOTE, "HelenOS UDF 1.02 file system server");
+	
+	if (argc == 3) {
+		if (!str_cmp(argv[1], "--instance"))
+			udf_vfs_info.instance = strtol(argv[2], NULL, 10);
+		else {
+			log_msg(LOG_DEFAULT, LVL_FATAL, "Unrecognized parameters");
+			return 1;
+		}
+	}
+	
+	async_sess_t *vfs_sess =
+	    service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_VFS, 0, 0);
+	if (!vfs_sess) {
+		log_msg(LOG_DEFAULT, LVL_FATAL, "Failed to connect to VFS");
+		return 2;
+	}
+	
+	int rc = fs_register(vfs_sess, &udf_vfs_info, &udf_ops,
+	    &udf_libfs_ops);
+	if (rc != EOK)
+		goto err;
+	
+	rc = udf_idx_init();
+	if (rc != EOK)
+		goto err;
+	
+	log_msg(LOG_DEFAULT, LVL_NOTE, "Accepting connections");
+	task_retval(0);
+	async_manager();
+	
+	/* Not reached */
+	return 0;
+	
+err:
+	log_msg(LOG_DEFAULT, LVL_FATAL, "Failed to register file system (%d)", rc);
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf.h
===================================================================
--- uspace/srv/fs/udf/udf.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2008 Jakub Jermar
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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 fs
+ * @{
+ */
+
+#ifndef UDF_UDF_H_
+#define UDF_UDF_H_
+
+#include <fibril_synch.h>
+#include <libfs.h>
+#include <atomic.h>
+#include <sys/types.h>
+#include <bool.h>
+#include "../../vfs/vfs.h"
+#include "udf_types.h"
+#include <adt/hash_table.h>
+
+#define UDF_NODE(node) \
+	((node) ? (udf_node_t *) (node)->data : NULL)
+
+#define FS_NODE(node) \
+	((node) ? (fs_node_t *) ((node)->fs_node) : NULL)
+
+#define BS_BLOCK     0
+#define MIN_SIZE     512
+#define MAX_SIZE     8192
+#define DEFAULT_VOL  0
+
+#define NODE_DIR   0
+#define NODE_FILE  1
+
+#define MAX_FILE_NAME_LEN  512
+
+#define MIN_FID_LEN  38
+
+#define SPACE_TABLE   0
+#define SPACE_BITMAP  1
+
+typedef struct udf_partition {
+	/* Partition info */
+	uint16_t number;
+	uint32_t access_type;
+	uint32_t start;
+	uint32_t lenght;
+} udf_partition_t;
+
+typedef struct udf_lvolume {
+	udf_partition_t **partitions;
+	size_t partition_cnt;
+	uint32_t logical_block_size;
+	fs_index_t root_dir;
+} udf_lvolume_t;
+
+typedef struct {
+	service_id_t service_id;
+	size_t open_nodes_count;
+	udf_charspec_t charset;
+	
+	uint32_t sector_size;
+	udf_lvolume_t *volumes;
+	udf_partition_t *partitions;
+	size_t partition_cnt;
+	udf_unallocated_space_descriptor_t *uasd;
+	uint64_t uaspace_start;
+	uint64_t uaspace_lenght;
+	uint8_t space_type;
+} udf_instance_t;
+
+typedef struct udf_allocator {
+	uint32_t length;
+	uint32_t position;
+} udf_allocator_t;
+
+typedef struct udf_node {
+	udf_instance_t *instance;
+	fs_node_t *fs_node;
+	fibril_mutex_t lock;
+	
+	fs_index_t index;  /* FID logical block */
+	ht_link_t link;
+	size_t ref_cnt;
+	size_t link_cnt;
+	
+	uint8_t type;  /* 1 - file, 0 - directory */
+	uint64_t data_size;
+	uint8_t *data;
+	udf_allocator_t *allocators;
+	size_t alloc_size;
+} udf_node_t;
+
+extern vfs_out_ops_t udf_ops;
+extern libfs_ops_t udf_libfs_ops;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_cksum.c
===================================================================
--- uspace/srv/fs/udf/udf_cksum.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf_cksum.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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 fs
+ * @{
+ */
+/**
+ * @file udf_cksum.c
+ * @brief Implementation of various checksum functions.
+ */
+
+#include "udf_cksum.h"
+
+/** CRC 010041 */
+static uint16_t crc_table[256] = {
+	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+	0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
+	0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
+	0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
+	0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
+	0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
+	0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
+	0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
+	0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
+	0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
+	0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
+	0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
+	0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
+	0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
+	0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
+	0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
+	0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
+	0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
+	0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
+	0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
+	0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
+	0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+	0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
+	0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
+	0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
+	0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
+	0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
+	0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
+	0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
+	0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
+	0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
+	0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
+};
+
+/** Unicode checksum
+ *
+ */
+uint16_t udf_unicode_cksum(uint16_t *buf, size_t len)
+{
+	uint16_t crc = 0;
+	
+	while (len-- > 0) {
+		/*
+		 * Take high order byte first (corresponds to a big endian
+		 * byte stream).
+		 */
+		crc = crc_table[(crc >> 8 ^ (*buf >> 8)) & 0xff] ^ (crc << 8);
+		crc = crc_table[(crc >> 8 ^ (*buf++ & 0xff)) & 0xff] ^ (crc << 8);
+	}
+	
+	return crc;
+}
+
+/** Calculate descriptor tag checksum
+ *
+ */
+uint8_t udf_tag_checksum(uint8_t *tag)
+{
+	uint8_t result = 0;
+	
+	for (size_t i = 0; i < UDF_TAG_SIZE; i++) {
+		if (i == 4)
+			continue;
+		
+		result = (result + tag[i]) % 256;
+	}
+	
+	return result;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_cksum.h
===================================================================
--- uspace/srv/fs/udf/udf_cksum.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf_cksum.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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 fs
+ * @{
+ */
+
+#ifndef UDF_CKSUM_H_
+#define UDF_CKSUM_H_
+
+#include <sys/types.h>
+#include <bool.h>
+
+#define UDF_TAG_SIZE  16
+
+extern uint16_t udf_unicode_cksum(uint16_t *, size_t);
+extern uint8_t udf_tag_checksum(uint8_t *);
+
+#endif /* UDF_CKSUM_H_ */
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_file.c
===================================================================
--- uspace/srv/fs/udf/udf_file.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf_file.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,627 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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 fs
+ * @{
+ */
+/**
+ * @file udf_file.c
+ * @brief Implementation of file operations. Reading and writing functions.
+ */
+
+#include <block.h>
+#include <libfs.h>
+#include <errno.h>
+#include <malloc.h>
+#include <inttypes.h>
+#include <io/log.h>
+#include <mem.h>
+#include "udf.h"
+#include "udf_file.h"
+#include "udf_cksum.h"
+#include "udf_volume.h"
+
+/** Read extended allocator in allocation sequence
+ *
+ * @paran node     UDF node
+ * @param icb_flag Type of allocators in sequence.
+ *                 According to ECMA 167 4/14.8.8
+ * @param pos      Position with which we read
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+static int udf_read_extended_allocator(udf_node_t *node, uint16_t icb_flag,
+    uint32_t pos)
+{
+	block_t *block = NULL;
+	int rc = block_get(&block, node->instance->service_id, pos,
+	    BLOCK_FLAGS_NONE);
+	if (rc != EOK)
+		return rc;
+	
+	udf_ext_ad_t *exd = (udf_ext_ad_t *) block->data;
+	uint32_t start = node->instance->partitions[
+	    FLE16(exd->extent_location.partition_num)].start +
+	    FLE32(exd->extent_location.lblock_num);
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG,
+	    "Extended allocator: start=%d, block_num=%d, len=%d", start,
+	    FLE32(exd->extent_location.lblock_num), FLE32(exd->info_length));
+	
+	uint32_t len = FLE32(exd->info_length);
+	block_put(block);
+	
+	return udf_read_allocation_sequence(node, NULL, icb_flag, start, len);
+}
+
+/** Read ICB sequence of allocators in (Extended) File entry descriptor
+ *
+ * @parem node     UDF node
+ * @param af       (Extended) File entry descriptor
+ * @param icb_flag Type of allocators in sequence.
+ *                 According to ECMA 167 4/14.8.8
+ * @param start_alloc Offset of the allocator
+ * @param len         Length of sequence
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_read_allocation_sequence(udf_node_t *node, uint8_t *af,
+    uint16_t icb_flag, uint32_t start_alloc, uint32_t len)
+{
+	node->alloc_size = 0;
+	
+	switch (icb_flag) {
+	case UDF_SHORT_AD:
+		log_msg(LOG_DEFAULT, LVL_DEBUG,
+		    "ICB: sequence of allocation descriptors - icbflag = short_ad_t");
+		
+		/*
+		 * Identify number of current partition. Virtual partition
+		 * could placed inside of physical partition. It means that same
+		 * sector could be inside of both partition physical and virtual.
+		 */
+		size_t pd_num = (size_t) -1;
+		size_t min_start = 0;
+		
+		for (size_t i = 0; i < node->instance->partition_cnt; i++) {
+			if ((node->index >= node->instance->partitions[i].start) &&
+			    (node->index < node->instance->partitions[i].start +
+			    node->instance->partitions[i].lenght)) {
+				if (node->instance->partitions[i].start >= min_start) {
+					min_start = node->instance->partitions[i].start;
+					pd_num = i;
+				}
+			}
+		}
+		
+		if (pd_num == (size_t) -1)
+			return ENOENT;
+		
+		/*
+		 * According to doc, in this we should stop our loop if pass
+		 * all allocators. Count of items in sequence of allocators
+		 * cnt = len / sizeof(udf_long_ad_t)
+		 * But in case of Blu-Ray data len could be zero.
+		 * It means that we have only two conditions for stopping
+		 * which we check inside of loop.
+		 */
+		
+		while (true) {
+			udf_short_ad_t *short_d =
+			    (udf_short_ad_t *) (af + start_alloc +
+			    node->alloc_size * sizeof(udf_short_ad_t));
+			
+			if (FLE32(short_d->length) == 0)
+				break;
+			
+			/*
+			 * ECMA 167 4/12 - next sequence of allocation descriptors
+			 * condition according to 167 4/14.6.8
+			 */
+			if (FLE32(short_d->length) >> 30 == 3) {
+				udf_read_extended_allocator(node, icb_flag,
+				    node->instance->partitions[pd_num].start +
+				    FLE32(short_d->position));
+				break;
+			}
+			
+			node->allocators = realloc(node->allocators,
+			    (node->alloc_size + 1) * sizeof(udf_allocator_t));
+			node->allocators[node->alloc_size].length =
+			    EXT_LENGTH(FLE32(short_d->length));
+			node->allocators[node->alloc_size].position =
+			    node->instance->partitions[pd_num].start + FLE32(short_d->position);
+			node->alloc_size++;
+		}
+		
+		node->allocators = realloc(node->allocators,
+		    node->alloc_size * sizeof(udf_allocator_t));
+		break;
+		
+	case UDF_LONG_AD:
+		log_msg(LOG_DEFAULT, LVL_DEBUG,
+		    "ICB: sequence of allocation descriptors - icbflag = long_ad_t");
+		
+		while (true) {
+			udf_long_ad_t *long_d =
+			    (udf_long_ad_t *) (af + start_alloc +
+			    node->alloc_size * sizeof(udf_long_ad_t));
+			
+			if (FLE32(long_d->length) == 0)
+				break;
+			
+			uint32_t pos_long_ad = udf_long_ad_to_pos(node->instance, long_d);
+			
+			/*
+			 * ECMA 167 4/12 - next sequence of allocation descriptors
+			 * condition according to 167 4/14.6.8
+			 */
+			if (FLE32(long_d->length) >> 30 == 3) {
+				udf_read_extended_allocator(node, icb_flag, pos_long_ad);
+				break;
+			}
+			
+			node->allocators = realloc(node->allocators,
+			    (node->alloc_size + 1) * sizeof(udf_allocator_t));
+			node->allocators[node->alloc_size].length =
+			    EXT_LENGTH(FLE32(long_d->length));
+			node->allocators[node->alloc_size].position = pos_long_ad;
+			
+			node->alloc_size++;
+		}
+		
+		node->allocators = realloc(node->allocators,
+		    node->alloc_size * sizeof(udf_allocator_t));
+		break;
+		
+	case UDF_EXTENDED_AD:
+		log_msg(LOG_DEFAULT, LVL_DEBUG,
+		    "ICB: sequence of allocation descriptors - icbflag = extended_ad_t");
+		break;
+		
+	case UDF_DATA_AD:
+		log_msg(LOG_DEFAULT, LVL_DEBUG,
+		    "ICB: sequence of allocation descriptors - icbflag = 3, node contains data itself");
+		
+		node->data = malloc(node->data_size);
+		if (!node->data)
+			return ENOMEM;
+		
+		memcpy(node->data, (af + start_alloc), node->data_size);
+		node->alloc_size = 0;
+		break;
+	}
+	
+	return EOK;
+}
+
+/** Read ICB sequence of descriptors
+ *
+ * Read sequence of descriptors (file entry descriptors or
+ * extended file entry descriptors). Each descriptor contains
+ * sequence of allocators.
+ *
+ * @param node    UDF node
+ *
+ * @return    EOK on success or a negative error code.
+ */
+int udf_read_icb(udf_node_t *node)
+{
+	while (true) {
+		fs_index_t pos = node->index;
+		
+		block_t *block = NULL;
+		int rc = block_get(&block, node->instance->service_id, pos,
+		    BLOCK_FLAGS_NONE);
+		if (rc != EOK)
+			return rc;
+		
+		udf_descriptor_tag_t *data = (udf_descriptor_tag_t *) block->data;
+		if (data->checksum != udf_tag_checksum((uint8_t *) data)) {
+			block_put(block);
+			return EINVAL;
+		}
+		
+		/* One sector size descriptors */
+		switch (FLE16(data->id)) {
+		case UDF_FILE_ENTRY:
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "ICB: File entry descriptor found");
+			
+			udf_file_entry_descriptor_t *file =
+			    (udf_file_entry_descriptor_t *) block->data;
+			uint16_t icb_flag = FLE16(file->icbtag.flags) & UDF_ICBFLAG_MASK;
+			node->data_size = FLE64(file->info_lenght);
+			node->type = (file->icbtag.file_type == UDF_ICBTYPE_DIR) ? NODE_DIR : NODE_FILE;
+			
+			rc = udf_read_allocation_sequence(node, (uint8_t *) file, icb_flag,
+			    FLE32(file->ea_lenght) + UDF_FE_OFFSET, FLE32(file->ad_lenght));
+			block_put(block);
+			return rc;
+			
+		case UDF_EFILE_ENTRY:
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "ICB: Extended file entry descriptor found");
+			
+			udf_extended_file_entry_descriptor_t *efile =
+			    (udf_extended_file_entry_descriptor_t *) block->data;
+			icb_flag = FLE16(efile->icbtag.flags) & UDF_ICBFLAG_MASK;
+			node->data_size = FLE64(efile->info_lenght);
+			node->type = (efile->icbtag.file_type == UDF_ICBTYPE_DIR) ? NODE_DIR : NODE_FILE;
+			
+			rc = udf_read_allocation_sequence(node, (uint8_t *) efile, icb_flag,
+			    FLE32(efile->ea_lenght) + UDF_EFE_OFFSET, FLE32(efile->ad_lenght));
+			block_put(block);
+			return rc;
+			
+		case UDF_ICB_TERMINAL:
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "ICB: Terminal entry descriptor found");
+			block_put(block);
+			return EOK;
+		}
+		
+		pos++;
+		
+		rc = block_put(block);
+		if (rc != EOK)
+			return rc;
+	}
+	
+	return EOK;
+}
+
+/** Read data from disk - filling UDF node by allocators
+ *
+ * @param node UDF node
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_node_get_core(udf_node_t *node)
+{
+	node->link_cnt = 1;
+	return udf_read_icb(node);
+}
+
+/** Read directory entry if all FIDs is saved inside of descriptor
+ *
+ * @param fid  Returned value
+ * @param node UDF node
+ * @param pos  Number of FID which we need to find
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+static int udf_get_fid_in_data(udf_file_identifier_descriptor_t **fid,
+    udf_node_t *node, aoff64_t pos)
+{
+	size_t fid_sum = 0;
+	size_t n = 0;
+	
+	while (node->data_size - fid_sum >= MIN_FID_LEN) {
+		udf_descriptor_tag_t *desc =
+		    (udf_descriptor_tag_t *) (node->data + fid_sum);
+		if (desc->checksum != udf_tag_checksum((uint8_t *) desc)) {
+			if (fid_sum == 0)
+				return EINVAL;
+			else
+				return ENOENT;
+		}
+		
+		*fid = (udf_file_identifier_descriptor_t *)
+		    (node->data + fid_sum);
+		
+		/* According to ECMA 167 4/14.4.9 */
+		size_t padding = 4 * (((*fid)->lenght_file_id +
+		    FLE16((*fid)->lenght_iu) + 38 + 3) / 4) -
+		    ((*fid)->lenght_file_id + FLE16((*fid)->lenght_iu) + 38);
+		size_t size_fid = (*fid)->lenght_file_id +
+		    FLE16((*fid)->lenght_iu) + padding + 38;
+		
+		fid_sum += size_fid;
+		
+		/* aAcording to ECMA 167 4/8.6 */
+		if (((*fid)->lenght_file_id != 0) &&
+		    (((*fid)->file_characteristics & 4) == 0)) {
+			n++;
+			
+			if (n == pos + 1)
+				return EOK;
+		}
+	}
+	
+	return ENOENT;
+}
+
+/** Read directory entry
+ *
+ * @param fid   Returned value
+ * @param block Returned value
+ * @param node  UDF node
+ * @param pos   Number of FID which we need to find
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_get_fid(udf_file_identifier_descriptor_t **fid, block_t **block,
+    udf_node_t *node, aoff64_t pos)
+{
+	if (node->data == NULL)
+		return udf_get_fid_in_allocator(fid, block, node, pos);
+	
+	return udf_get_fid_in_data(fid, node, pos);
+}
+
+/** Read directory entry if all FIDS is saved in allocators.
+ *
+ * @param fid   Returned value
+ * @param block Returned value
+ * @param node  UDF node
+ * @param pos   Number of FID which we need to find
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_get_fid_in_allocator(udf_file_identifier_descriptor_t **fid,
+    block_t **block, udf_node_t *node, aoff64_t pos)
+{
+	void *buf = malloc(node->instance->sector_size);
+	
+	// FIXME: Check for NULL return value
+	
+	size_t j = 0;
+	size_t n = 0;
+	size_t len = 0;
+	
+	while (j < node->alloc_size) {
+		size_t i = 0;
+		while (i * node->instance->sector_size < node->allocators[j].length) {
+			int rc = block_get(block, node->instance->service_id,
+			    node->allocators[j].position + i, BLOCK_FLAGS_NONE);
+			if (rc != EOK) {
+				// FIXME: Memory leak
+				return rc;
+			}
+			
+			/*
+			 * Last item in allocator is a part of sector. We take
+			 * this fragment and join it to part of sector in next allocator.
+			 */
+			if ((node->allocators[j].length / node->instance->sector_size == i) &&
+			    (node->allocators[j].length - i * node->instance->sector_size <
+			    MIN_FID_LEN)) {
+				size_t len = node->allocators[j].length - i * node->instance->sector_size;
+				memcpy(buf, (*block)->data, len);
+				block_put(*block);
+				*block = NULL;
+				break;
+			}
+			
+			rc = udf_get_fid_in_sector(fid, block, node, pos, &n, &buf, &len);
+			if (rc == EOK) {
+				// FIXME: Memory leak
+				return EOK;
+			}
+			
+			if (rc == EINVAL) {
+				// FIXME: Memory leak
+				return ENOENT;
+			}
+			
+			if (rc == ENOENT) {
+				if (block) {
+					rc = block_put(*block);
+					*block = NULL;
+					
+					if (rc != EOK)
+						return rc;
+				}
+			}
+			
+			i++;
+		}
+		
+		j++;
+	}
+	
+	if (buf)
+		free(buf);
+	
+	return ENOENT;
+}
+
+/** Read FIDs in sector inside of current allocator
+ *
+ * @param fid   Returned value.
+ * @param block Returned value
+ * @param node  UDF node
+ * @param pos   Number FID which we need to find
+ * @param n     Count of FIDs which we already have passed
+ * @param buf   Part of FID from last sector (current allocator or previous)
+ * @param len   Length of buf
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_get_fid_in_sector(udf_file_identifier_descriptor_t **fid,
+    block_t **block, udf_node_t *node, aoff64_t pos, size_t *n, void **buf,
+    size_t *len)
+{
+	void *fidbuf = malloc(node->instance->sector_size);
+	
+	// FIXME: Check for NULL return value
+	
+	bool buf_flag;
+	
+	if (*len > 0) {
+		memcpy(fidbuf, *buf, *len);
+		buf_flag = true;
+	} else
+		buf_flag = false;
+	
+	size_t fid_sum = 0;
+	while (node->instance->sector_size - fid_sum > 0) {
+		if (node->instance->sector_size - fid_sum >= MIN_FID_LEN) {
+			void *fid_data;
+			
+			if (buf_flag) {
+				memcpy((fidbuf + *len), (*block)->data,
+				    node->instance->sector_size - *len);
+				fid_data = fidbuf;
+			} else
+				fid_data = (*block)->data + fid_sum;
+			
+			udf_descriptor_tag_t *desc =
+			    (udf_descriptor_tag_t *) fid_data;
+			
+			if (desc->checksum != udf_tag_checksum((uint8_t *) desc)) {
+				if (fidbuf)
+					free(fidbuf);
+				
+				if (*buf) {
+					free(*buf);
+					*buf = NULL;
+					*len = 0;
+				}
+				
+				return EINVAL;
+			}
+			
+			*fid = (udf_file_identifier_descriptor_t *) fid_data;
+			
+			/* According to ECMA 167 4/14.4.9 */
+			size_t padding = 4 * (((*fid)->lenght_file_id +
+			    FLE16((*fid)->lenght_iu) + 38 + 3) / 4) -
+			    ((*fid)->lenght_file_id + FLE16((*fid)->lenght_iu) + 38);
+			size_t size_fid = (*fid)->lenght_file_id +
+			    FLE16((*fid)->lenght_iu) + padding + 38;
+			if (buf_flag)
+				fid_sum += size_fid - *len;
+			else
+				fid_sum += size_fid;
+			
+			/* According to ECMA 167 4/8.6 */
+			if (((*fid)->lenght_file_id != 0) &&
+			    (((*fid)->file_characteristics & 4) == 0)) {
+				(*n)++;
+				if (*n == pos + 1) {
+					if (fidbuf)
+						free(fidbuf);
+					
+					return EOK;
+				}
+			}
+			
+			if (fidbuf) {
+				buf_flag = false;
+				free(fidbuf);
+				fidbuf = NULL;
+			}
+			
+			if (*buf) {
+				free(*buf);
+				*buf = NULL;
+				*len = 0;
+			}
+		} else {
+			if (*buf)
+				free(*buf);
+			
+			*len = node->instance->sector_size - fid_sum;
+			*buf = malloc(*len);
+			buf_flag = false;
+			memcpy(*buf, ((*block)->data + fid_sum), *len);
+			
+			return ENOENT;
+		}
+	}
+	
+	return ENOENT;
+}
+
+/** Read file if it is saved in allocators.
+ *
+ * @param read_len Returned value. Length file or part file which we could read.
+ * @param callid
+ * @param node     UDF node
+ * @param pos      Position in file since we have to read.
+ * @param len      Length of data for reading
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_read_file(size_t *read_len, ipc_callid_t callid, udf_node_t *node,
+    aoff64_t pos, size_t len)
+{
+	size_t i = 0;
+	size_t l = 0;
+	
+	while (i < node->alloc_size) {
+		if (pos >= l + node->allocators[i].length) {
+			l += node->allocators[i].length;
+			i++;
+		} else
+			break;
+	}
+	
+	size_t sector_cnt = ALL_UP(l, node->instance->sector_size);
+	size_t sector_num = pos / node->instance->sector_size;
+	
+	block_t *block = NULL;
+	int rc = block_get(&block, node->instance->service_id,
+	    node->allocators[i].position + (sector_num - sector_cnt),
+	    BLOCK_FLAGS_NONE);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	size_t sector_pos = pos % node->instance->sector_size;
+	
+	if (sector_pos + len < node->instance->sector_size)
+		*read_len = len;
+	else
+		*read_len = node->instance->sector_size - sector_pos;
+	
+	if (ALL_UP(node->allocators[i].length, node->instance->sector_size) ==
+	    sector_num - sector_cnt + 1) {
+		if (pos + len > node->allocators[i].length + l)
+			*read_len = node->allocators[i].length -
+			    (sector_num - sector_cnt) * node->instance->sector_size -
+			    sector_pos;
+		else
+			*read_len = len;
+	}
+	
+	async_data_read_finalize(callid, block->data + sector_pos, *read_len);
+	return block_put(block);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_file.h
===================================================================
--- uspace/srv/fs/udf/udf_file.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf_file.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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 fs
+ * @{
+ */
+
+#ifndef UDF_FILE_H_
+#define UDF_FILE_H_
+
+#include <sys/types.h>
+#include <ipc/loc.h>
+#include <block.h>
+#include "udf_types.h"
+
+#define UDF_TAG_FILESET  256
+#define UDF_TAG_FILEID   257
+
+#define UDF_ICB_TERMINAL   260
+#define UDF_FILE_ENTRY     261
+#define UDF_UASPACE_ENTRY  263
+#define UDF_SPACE_BITMAP   264
+#define UDF_EFILE_ENTRY    266
+
+#define UDF_FE_OFFSET   176
+#define UDF_EFE_OFFSET  216
+#define UDF_SB_OFFSET   24
+
+/* ECMA 4/14.11 */
+#define UDF_UASE_OFFSET  40
+
+/* ECMA 167 4/14.6.8 */
+#define UDF_ICBFLAG_MASK  7
+
+/* ECMA 167 4/17 */
+#define UDF_ICBTYPE_UASE  1
+#define UDF_ICBTYPE_DIR   4
+
+/* ECMA 167 4/14.6.8 */
+#define UDF_SHORT_AD     0
+#define UDF_LONG_AD      1
+#define UDF_EXTENDED_AD  2
+
+/* File in allocation descriptor */
+#define UDF_DATA_AD  3
+
+/* File Set Descriptor (ECMA 167 4/14.1) */
+typedef struct udf_fileset_descriptor {
+	udf_descriptor_tag_t tag;
+	udf_timestamp_t recording_date_and_time;
+	uint16_t interchange_level;
+	uint16_t max_interchange_level;
+	uint32_t charset_list;
+	uint32_t max_charset_list;
+	uint32_t fileset_number;
+	uint32_t fileset_descriptor_number;
+	udf_charspec_t logical_volume_id_charset;
+	udf_dstring logical_volume_id[128];
+	udf_charspec_t fileset_charset;
+	udf_dstring fileset_id[32];
+	udf_dstring copyright_file_id[32];
+	udf_dstring abstract_file_id[32];
+	udf_long_ad_t root_dir_icb;
+	udf_regid_t domain_id;
+	udf_long_ad_t next_extent;
+	udf_long_ad_t system_stream_dir_icb;
+	uint8_t reserved[32];
+} __attribute__((packed)) udf_fileset_descriptor_t;
+
+/* File identifier descriptor format (ECMA 167 4/14.4) */
+typedef struct udf_file_identifier_descriptor {
+	udf_descriptor_tag_t tag;
+	uint16_t file_version_number;
+	uint8_t file_characteristics;
+	uint8_t lenght_file_id;
+	udf_long_ad_t icb;
+	uint16_t lenght_iu;
+	uint8_t implementation_use[0];
+	udf_dstring file_id[0];
+}__attribute__((packed)) udf_file_identifier_descriptor_t;
+
+/* ICB tag - Information Control Block  (ECMA 167 4/14.6) */
+typedef struct udf_icbtag {
+	uint32_t prior_recorder_nimber;
+	uint16_t strategy_type;
+	uint8_t strategy_parameter[2];
+	uint16_t max_number;
+	uint8_t reserved[1];
+	uint8_t file_type;
+	udf_lb_addr_t parent_icb;
+	uint16_t flags;
+} __attribute__((packed)) udf_icbtag_t;
+
+/* File Entry format (ECMA 167 4/14.9) */
+typedef struct udf_file_entry_descriptor {
+	udf_descriptor_tag_t tag;
+	udf_icbtag_t icbtag;
+	uint32_t uid;
+	uint32_t gid;
+	uint32_t permission;
+	uint16_t file_link_count;
+	uint8_t record_format;
+	uint8_t record_display_attributes;
+	uint32_t record_lenght;
+	uint64_t info_lenght;
+	uint64_t lblocks_recorded;
+	udf_timestamp_t access_data_and_time;
+	udf_timestamp_t mod_data_and_time;
+	udf_timestamp_t attribute_data_and_time;
+	uint32_t checkpoint;
+	udf_long_ad_t extended_attribute_icb;
+	udf_regid_t implementation_id;
+	uint64_t unique_id;
+	uint32_t ea_lenght;
+	uint32_t ad_lenght;
+	uint8_t extended_attributes [0];
+	uint8_t allocation_descriptors[0];
+} __attribute__((packed)) udf_file_entry_descriptor_t;
+
+/* Extended File Entry format (ECMA 167 4/14.17) */
+typedef struct udf_extended_file_entry_descriptor {
+	udf_descriptor_tag_t tag;
+	udf_icbtag_t icbtag;
+	uint32_t uid;
+	uint32_t gid;
+	uint32_t permission;
+	uint16_t file_link_count;
+	uint8_t record_format;
+	uint8_t record_display_attributes;
+	uint32_t record_lenght;
+	uint64_t info_lenght;
+	uint64_t object_size;
+	uint64_t lblocks_recorded;
+	udf_timestamp_t access_data_and_time;
+	udf_timestamp_t mod_data_and_time;
+	udf_timestamp_t creation_data_and_time;
+	udf_timestamp_t attribute_data_and_time;
+	uint32_t checkpoint;
+	udf_long_ad_t extended_attribute_icb;
+	udf_regid_t implementation_id;
+	uint64_t unique_id;
+	uint32_t ea_lenght;
+	uint32_t ad_lenght;
+	uint8_t extended_attributes [0];
+	uint8_t allocation_descriptors[0];
+} __attribute__((packed)) udf_extended_file_entry_descriptor_t;
+
+/* Terminal Entry Descriptor (ECMA 167 4/14.8) */
+typedef struct terminal_entry_descriptor {
+	udf_descriptor_tag_t tag;
+	udf_icbtag_t icbtag;
+} __attribute__((packed)) udf_terminal_entry_descriptor;
+
+/* Unallocated Space Entry format (ECMA 167 4/14.11)*/
+typedef struct udf_unallocated_space_entry_descriptor {
+	udf_descriptor_tag_t tag;
+	udf_icbtag_t icbtag;
+	uint32_t ad_lenght;
+	uint8_t allocation_descriptors[0];
+}__attribute__((packed)) udf_unallocated_space_entry_descriptor_t;
+
+/* Space Bitmap Descriptor format (ECMA 167 4/14.12) */
+typedef struct udf_space_bitmap_descriptor {
+	udf_descriptor_tag_t tag;
+	uint32_t bits_number;
+	uint32_t byts_number;
+	uint8_t bitmap[0];
+}__attribute__((packed)) udf_space_bitmap_descriptor_t;
+
+extern int udf_node_get_core(udf_node_t *);
+extern int udf_read_icb(udf_node_t *);
+extern int udf_read_allocation_sequence(udf_node_t *, uint8_t *, uint16_t,
+    uint32_t, uint32_t);
+extern int udf_read_file(size_t *, ipc_callid_t, udf_node_t *, aoff64_t,
+    size_t);
+extern int udf_get_fid(udf_file_identifier_descriptor_t **, block_t **,
+    udf_node_t *, aoff64_t);
+extern int udf_get_fid_in_allocator(udf_file_identifier_descriptor_t **,
+    block_t **, udf_node_t *, aoff64_t);
+extern int udf_get_fid_in_sector(udf_file_identifier_descriptor_t **,
+    block_t **, udf_node_t *, aoff64_t, size_t *, void **, size_t *);
+
+#endif /* UDF_FILE_H_ */
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_idx.c
===================================================================
--- uspace/srv/fs/udf/udf_idx.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf_idx.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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 fs
+ * @{
+ */
+/**
+ * @file udf_idx.c
+ * @brief Very simple UDF hashtable for nodes
+ */
+
+#include "../../vfs/vfs.h"
+#include <errno.h>
+#include <str.h>
+#include <assert.h>
+#include <fibril_synch.h>
+#include <malloc.h>
+#include <adt/hash_table.h>
+#include <adt/hash.h>
+#include <adt/list.h>
+#include <bool.h>
+#include "udf_idx.h"
+#include "udf.h"
+
+static FIBRIL_MUTEX_INITIALIZE(udf_idx_lock);
+
+static hash_table_t udf_idx;
+
+typedef struct {
+	service_id_t service_id;
+	fs_index_t index;
+} udf_ht_key_t; 
+
+static size_t udf_idx_hash(const ht_link_t *item)
+{
+	udf_node_t *node = hash_table_get_inst(item, udf_node_t, link);
+	return hash_combine(node->instance->service_id, node->index);
+}
+
+static size_t udf_idx_key_hash(void *k)
+{
+	udf_ht_key_t *key = (udf_ht_key_t *) k;
+	return hash_combine(key->service_id, key->index);
+}
+
+static bool udf_idx_key_equal(void *k, const ht_link_t *item)
+{
+	udf_ht_key_t *key = (udf_ht_key_t *) k;
+	udf_node_t *node = hash_table_get_inst(item, udf_node_t, link);
+
+	return (key->service_id == node->instance->service_id) &&
+	    (key->index == node->index);
+}
+
+static hash_table_ops_t udf_idx_ops = {
+	.hash = udf_idx_hash,
+	.key_hash = udf_idx_key_hash,
+	.key_equal = udf_idx_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL 
+};
+
+/** Initialization of hash table
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_idx_init(void)
+{
+	if (!hash_table_create(&udf_idx, 0, 0, &udf_idx_ops))
+		return ENOMEM;
+	
+	return EOK;
+}
+
+/** Delete hash table
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_idx_fini(void)
+{
+	hash_table_destroy(&udf_idx);
+	return EOK;
+}
+
+/** Get node from hash table
+ *
+ * @param udfn     Returned value - UDF node
+ * @param instance UDF instance
+ * @param index    Absolute position of ICB (sector)
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_idx_get(udf_node_t **udfn, udf_instance_t *instance, fs_index_t index)
+{
+	fibril_mutex_lock(&udf_idx_lock);
+
+	udf_ht_key_t key = {
+		.service_id = instance->service_id,
+		.index = index
+	};
+	
+	ht_link_t *already_open = hash_table_find(&udf_idx, &key);
+	if (already_open) {
+		udf_node_t *node = hash_table_get_inst(already_open,
+		    udf_node_t, link);
+		node->ref_cnt++;
+		
+		*udfn = node;
+		
+		fibril_mutex_unlock(&udf_idx_lock);
+		return EOK;
+	}
+	
+	fibril_mutex_unlock(&udf_idx_lock);
+	return ENOENT;
+}
+
+/** Create new node in hash table
+ *
+ * @param udfn     Returned value - new UDF node
+ * @param instance UDF instance
+ * @param index    Absolute position of ICB (sector)
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_idx_add(udf_node_t **udfn, udf_instance_t *instance, fs_index_t index)
+{
+	fibril_mutex_lock(&udf_idx_lock);
+	
+	udf_node_t *udf_node = malloc(sizeof(udf_node_t));
+	if (udf_node == NULL) {
+		fibril_mutex_unlock(&udf_idx_lock);
+		return ENOMEM;
+	}
+	
+	fs_node_t *fs_node = malloc(sizeof(fs_node_t));
+	if (fs_node == NULL) {
+		free(udf_node);
+		fibril_mutex_unlock(&udf_idx_lock);
+		return ENOMEM;
+	}
+	
+	fs_node_initialize(fs_node);
+	
+	udf_node->index = index;
+	udf_node->instance = instance;
+	udf_node->ref_cnt = 1;
+	udf_node->link_cnt = 0;
+	udf_node->fs_node = fs_node;
+	udf_node->data = NULL;
+	udf_node->allocators = NULL;
+	
+	fibril_mutex_initialize(&udf_node->lock);
+	fs_node->data = udf_node;
+	
+	hash_table_insert(&udf_idx, &udf_node->link);
+	instance->open_nodes_count++;
+	
+	*udfn = udf_node;
+	
+	fibril_mutex_unlock(&udf_idx_lock);
+	return EOK;
+}
+
+/** Delete node from hash table
+ *
+ * @param node UDF node
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_idx_del(udf_node_t *node)
+{
+	assert(node->ref_cnt == 0);
+	
+	fibril_mutex_lock(&udf_idx_lock);
+	
+	hash_table_remove_item(&udf_idx, &node->link);
+	
+	assert(node->instance->open_nodes_count > 0);
+	node->instance->open_nodes_count--;
+	
+	free(node->fs_node);
+	free(node);
+	
+	fibril_mutex_unlock(&udf_idx_lock);
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_idx.h
===================================================================
--- uspace/srv/fs/udf/udf_idx.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf_idx.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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 fs
+ * @{
+ */
+
+#ifndef UDF_IDX_H_
+#define UDF_IDX_H_
+
+#include "udf.h"
+
+extern int udf_idx_init(void);
+extern int udf_idx_fini(void);
+extern int udf_idx_get(udf_node_t **, udf_instance_t *, fs_index_t);
+extern int udf_idx_add(udf_node_t **, udf_instance_t *, fs_index_t);
+extern int udf_idx_del(udf_node_t *);
+
+#endif /* UDF_IDX_H_ */
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_ops.c
===================================================================
--- uspace/srv/fs/udf/udf_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf_ops.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2008 Jakub Jermar
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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 fs
+ * @{
+ */
+/**
+ * @file udf_ops.c
+ * @brief Implementation of VFS operations for the UDF file system
+ *        server.
+ */
+
+#include <libfs.h>
+#include <block.h>
+#include <ipc/services.h>
+#include <ipc/loc.h>
+#include <macros.h>
+#include <async.h>
+#include <errno.h>
+#include <str.h>
+#include <byteorder.h>
+#include <adt/hash_table.h>
+#include <adt/list.h>
+#include <assert.h>
+#include <fibril_synch.h>
+#include <sys/mman.h>
+#include <align.h>
+#include <malloc.h>
+#include <inttypes.h>
+#include <io/log.h>
+#include "../../vfs/vfs.h"
+#include "udf.h"
+#include "udf_cksum.h"
+#include "udf_volume.h"
+#include "udf_idx.h"
+#include "udf_file.h"
+#include "udf_osta.h"
+
+/** Mutex protecting the list of cached free nodes. */
+static FIBRIL_MUTEX_INITIALIZE(ffn_mutex);
+
+/** List of cached free nodes. */
+static LIST_INITIALIZE(ffn_list);
+
+static int udf_node_get(fs_node_t **rfn, service_id_t service_id,
+    fs_index_t index)
+{
+	udf_instance_t *instance;
+	int rc = fs_instance_get(service_id, (void **) &instance);
+	if (rc != EOK)
+		return rc;
+	
+	udf_node_t *node;
+	rc = udf_idx_get(&node, instance, index);
+	if (rc != EOK) {
+		rc = udf_idx_add(&node, instance, index);
+		if (rc != EOK)
+			return rc;
+		
+		rc = udf_node_get_core(node);
+		if (rc != EOK) {
+			udf_idx_del(node);
+			return rc;
+		}
+	}
+	
+	*rfn = FS_NODE(node);
+	return EOK;
+}
+
+static int udf_root_get(fs_node_t **rfn, service_id_t service_id)
+{
+	udf_instance_t *instance;
+	int rc = fs_instance_get(service_id, (void **) &instance);
+	if (rc != EOK)
+		return rc;
+	
+	return udf_node_get(rfn, service_id,
+	    instance->volumes[DEFAULT_VOL].root_dir);
+}
+
+static service_id_t udf_service_get(fs_node_t *node)
+{
+	udf_node_t *udfn = UDF_NODE(node);
+	if (udfn)
+		return udfn->instance->service_id;
+	
+	return 0;
+}
+
+static int udf_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
+{
+	char *name = malloc(MAX_FILE_NAME_LEN + 1);
+	if (name == NULL)
+		return ENOMEM;
+	
+	block_t *block = NULL;
+	udf_file_identifier_descriptor_t *fid = NULL;
+	size_t pos = 0;
+	
+	while (udf_get_fid(&fid, &block, UDF_NODE(pfn), pos) == EOK) {
+		udf_long_ad_t long_ad = fid->icb;
+		
+		udf_to_unix_name(name, MAX_FILE_NAME_LEN,
+		    (char *) fid->implementation_use + FLE16(fid->lenght_iu),
+		    fid->lenght_file_id, &UDF_NODE(pfn)->instance->charset);
+		
+		if (stricmp(name, component) == 0) {
+			int rc = udf_node_get(rfn, udf_service_get(pfn),
+			    udf_long_ad_to_pos(UDF_NODE(pfn)->instance, &long_ad));
+			
+			if (block != NULL)
+				block_put(block);
+			
+			free(name);
+			return rc;
+		}
+		
+		if (block != NULL) {
+			int rc = block_put(block);
+			if (rc != EOK)
+				return rc;
+		}
+		
+		pos++;
+	}
+	
+	free(name);
+	return ENOENT;
+}
+
+static int udf_node_open(fs_node_t *fn)
+{
+	return EOK;
+}
+
+static int udf_node_put(fs_node_t *fn)
+{
+	udf_node_t *node = UDF_NODE(fn);
+	if (!node)
+		return EINVAL;
+	
+	fibril_mutex_lock(&node->lock);
+	node->ref_cnt--;
+	fibril_mutex_unlock(&node->lock);
+	
+	/* Delete node from hash table and memory */
+	if (!node->ref_cnt)
+		udf_idx_del(node);
+	
+	return EOK;
+}
+
+static int udf_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
+{
+	return ENOTSUP;
+}
+
+static int udf_destroy_node(fs_node_t *fn)
+{
+	return ENOTSUP;
+}
+
+static int udf_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
+{
+	return ENOTSUP;
+}
+
+static int udf_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
+{
+	return ENOTSUP;
+}
+
+static int udf_has_children(bool *has_children, fs_node_t *fn)
+{
+	*has_children = true;
+	return EOK;
+}
+
+static fs_index_t udf_index_get(fs_node_t *fn)
+{
+	udf_node_t *node = UDF_NODE(fn);
+	if (node)
+		return node->index;
+	
+	return 0;
+}
+
+static aoff64_t udf_size_get(fs_node_t *fn)
+{
+	udf_node_t *node = UDF_NODE(fn);
+	if (node)
+		return node->data_size;
+	
+	return 0;
+}
+
+static unsigned int udf_lnkcnt_get(fs_node_t *fn)
+{
+	udf_node_t *node = UDF_NODE(fn);
+	if (node)
+		return node->link_cnt;
+	
+	return 0;
+}
+
+static bool udf_is_directory(fs_node_t *fn)
+{
+	udf_node_t *node = UDF_NODE(fn);
+	if (node)
+		return node->type == NODE_DIR;
+	
+	return false;
+}
+
+static bool udf_is_file(fs_node_t *fn)
+{
+	udf_node_t *node = UDF_NODE(fn);
+	if (node)
+		return node->type == NODE_FILE;
+	
+	return false;
+}
+
+libfs_ops_t udf_libfs_ops = {
+	.root_get = udf_root_get,
+	.match = udf_match,
+	.node_get = udf_node_get,
+	.node_open = udf_node_open,
+	.node_put = udf_node_put,
+	.create = udf_create_node,
+	.destroy = udf_destroy_node,
+	.link = udf_link,
+	.unlink = udf_unlink,
+	.has_children = udf_has_children,
+	.index_get = udf_index_get,
+	.size_get = udf_size_get,
+	.lnkcnt_get = udf_lnkcnt_get,
+	.is_directory = udf_is_directory,
+	.is_file = udf_is_file,
+	.service_get = udf_service_get
+};
+
+static int udf_mounted(service_id_t service_id, const char *opts,
+    fs_index_t *index, aoff64_t *size, unsigned *linkcnt)
+{
+	enum cache_mode cmode;
+	
+	/* Check for option enabling write through. */
+	if (str_cmp(opts, "wtcache") == 0)
+		cmode = CACHE_MODE_WT;
+	else
+		cmode = CACHE_MODE_WB;
+	
+	udf_instance_t *instance = malloc(sizeof(udf_instance_t));
+	if (!instance)
+		return ENOMEM;
+	
+	instance->sector_size = 0;
+	
+	/* Check for block size. Will be enhanced later */
+	if (str_cmp(opts, "bs=512") == 0)
+		instance->sector_size = 512;
+	else if (str_cmp(opts, "bs=1024") == 0)
+		instance->sector_size = 1024;
+	else if (str_cmp(opts, "bs=2048") == 0)
+		instance->sector_size = 2048;
+	
+	/* initialize block cache */
+	int rc = block_init(EXCHANGE_SERIALIZE, service_id, MAX_SIZE);
+	if (rc != EOK)
+		return rc;
+	
+	rc = fs_instance_create(service_id, instance);
+	if (rc != EOK) {
+		free(instance);
+		block_fini(service_id);
+		return rc;
+	}
+	
+	instance->service_id = service_id;
+	instance->open_nodes_count = 0;
+	
+	/* Check Volume Recognition Sequence */
+	rc = udf_volume_recongnition(service_id);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_NOTE, "VRS failed");
+		fs_instance_destroy(service_id);
+		free(instance);
+		block_fini(service_id);
+		return rc;
+	}
+	
+	/* Search for Anchor Volume Descriptor */
+	udf_anchor_volume_descriptor_t avd;
+	rc = udf_get_anchor_volume_descriptor(service_id, &avd);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_NOTE, "Anchor read failed");
+		fs_instance_destroy(service_id);
+		free(instance);
+		block_fini(service_id);
+		return rc;
+	}
+	
+	log_msg(LOG_DEFAULT, LVL_DEBUG,
+	    "Volume: Anchor volume descriptor found. Sector size=%" PRIu32,
+	    instance->sector_size);
+	log_msg(LOG_DEFAULT, LVL_DEBUG,
+	    "Anchor: main sequence [length=%" PRIu32 " (bytes), start=%"
+	    PRIu32 " (sector)]", avd.main_extent.length,
+	    avd.main_extent.location);
+	log_msg(LOG_DEFAULT, LVL_DEBUG,
+	    "Anchor: reserve sequence [length=%" PRIu32 " (bytes), start=%"
+	    PRIu32 " (sector)]", avd.reserve_extent.length,
+	    avd.reserve_extent.location);
+	
+	/* Initialize the block cache */
+	rc = block_cache_init(service_id, instance->sector_size, 0, cmode);
+	if (rc != EOK) {
+		fs_instance_destroy(service_id);
+		free(instance);
+		block_fini(service_id);
+		return rc;
+	}
+	
+	/* Read Volume Descriptor Sequence */
+	rc = udf_read_volume_descriptor_sequence(service_id, avd.main_extent);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_NOTE, "Volume Descriptor Sequence read failed");
+		fs_instance_destroy(service_id);
+		free(instance);
+		block_cache_fini(service_id);
+		block_fini(service_id);
+		return rc;
+	}
+	
+	fs_node_t *rfn;
+	rc = udf_node_get(&rfn, service_id, instance->volumes[DEFAULT_VOL].root_dir);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_NOTE, "Can't create root node");
+		fs_instance_destroy(service_id);
+		free(instance);
+		block_cache_fini(service_id);
+		block_fini(service_id);
+		return rc;
+	}
+	
+	udf_node_t *node = UDF_NODE(rfn);
+	*index = instance->volumes[DEFAULT_VOL].root_dir;
+	*size = node->data_size;
+	*linkcnt = node->link_cnt;
+	
+	return EOK;
+}
+
+static int udf_unmounted(service_id_t service_id)
+{
+	fs_node_t *fn;
+	int rc = udf_root_get(&fn, service_id);
+	if (rc != EOK)
+		return rc;
+	
+	udf_node_t *nodep = UDF_NODE(fn);
+	udf_instance_t *instance = nodep->instance;
+	
+	/*
+	 * We expect exactly two references on the root node.
+	 * One for the udf_root_get() above and one created in
+	 * udf_mounted().
+	 */
+	if (nodep->ref_cnt != 2) {
+		udf_node_put(fn);
+		return EBUSY;
+	}
+	
+	/*
+	 * Put the root node twice.
+	 */
+	udf_node_put(fn);
+	udf_node_put(fn);
+	
+	fs_instance_destroy(service_id);
+	free(instance);
+	block_cache_fini(service_id);
+	block_fini(service_id);
+	
+	return EOK;
+}
+
+static int udf_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
+	udf_instance_t *instance;
+	int rc = fs_instance_get(service_id, (void **) &instance);
+	if (rc != EOK)
+		return rc;
+	
+	fs_node_t *rfn;
+	rc = udf_node_get(&rfn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	
+	udf_node_t *node = UDF_NODE(rfn);
+	
+	ipc_callid_t callid;
+	size_t len = 0;
+	if (!async_data_read_receive(&callid, &len)) {
+		async_answer_0(callid, EINVAL);
+		udf_node_put(rfn);
+		return EINVAL;
+	}
+	
+	if (node->type == NODE_FILE) {
+		if (pos >= node->data_size) {
+			*rbytes = 0;
+			async_data_read_finalize(callid, NULL, 0);
+			udf_node_put(rfn);
+			return EOK;
+		}
+		
+		size_t read_len = 0;
+		if (node->data == NULL)
+			rc = udf_read_file(&read_len, callid, node, pos, len);
+		else {
+			/* File in allocation descriptors area */
+			read_len = (len < node->data_size) ? len : node->data_size;
+			async_data_read_finalize(callid, node->data + pos, read_len);
+			rc = EOK;
+		}
+		
+		*rbytes = read_len;
+		(void) udf_node_put(rfn);
+		return rc;
+	} else {
+		block_t *block = NULL;
+		udf_file_identifier_descriptor_t *fid = NULL;
+		if (udf_get_fid(&fid, &block, node, pos) == EOK) {
+			char *name = malloc(MAX_FILE_NAME_LEN + 1);
+			
+			// FIXME: Check for NULL return value
+			
+			udf_to_unix_name(name, MAX_FILE_NAME_LEN,
+			    (char *) fid->implementation_use + FLE16(fid->lenght_iu),
+			    fid->lenght_file_id, &node->instance->charset);
+			
+			async_data_read_finalize(callid, name, str_size(name) + 1);
+			*rbytes = 1;
+			free(name);
+			udf_node_put(rfn);
+			
+			if (block != NULL)
+				return block_put(block);
+			
+			return EOK;
+		} else {
+			*rbytes = 0;
+			udf_node_put(rfn);
+			async_answer_0(callid, ENOENT);
+			return ENOENT;
+		}
+	}
+}
+
+static int udf_close(service_id_t service_id, fs_index_t index)
+{
+	return EOK;
+}
+
+static int udf_sync(service_id_t service_id, fs_index_t index)
+{
+	return ENOTSUP;
+}
+
+static int udf_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
+	return ENOTSUP;
+}
+
+static int udf_truncate(service_id_t service_id, fs_index_t index,
+    aoff64_t size)
+{
+	return ENOTSUP;
+}
+
+static int udf_destroy(service_id_t service_id, fs_index_t index)
+{
+	return ENOTSUP;
+}
+
+vfs_out_ops_t udf_ops = {
+	.mounted = udf_mounted,
+	.unmounted = udf_unmounted,
+	.read = udf_read,
+	.write = udf_write,
+	.truncate = udf_truncate,
+	.close = udf_close,
+	.destroy = udf_destroy,
+	.sync = udf_sync
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_osta.c
===================================================================
--- uspace/srv/fs/udf/udf_osta.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf_osta.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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.
+ */
+
+/*
+ * OSTA compliant Unicode compression, uncompression routines,
+ * file name translation routine for OS/2, Windows 95, Windows NT,
+ * Macintosh and UNIX.
+ * Copyright 1995 Micro Design International, Inc.
+ * Written by Jason M. Rinn.
+ * Micro Design International gives permission for the free use of the
+ * following source code.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+/**
+ * @file udf_osta.c
+ * @brief OSTA compliant functions.
+ */
+
+#include <malloc.h>
+#include <str.h>
+#include <macros.h>
+#include <errno.h>
+#include "udf_osta.h"
+#include "udf_cksum.h"
+
+/** Calculate length of UTF-16 string
+ *
+ * FIXME: This is wrong! UTF-16 is not a fixed-width encoding,
+ *        it is a variable-width encoding (mind the surrogate
+ *        pairs).
+ *
+ */
+static size_t utf16_length(uint16_t *string) {
+	size_t len = 0;
+	
+	while (*string++ != 0)
+		len++;
+	
+	return len;
+}
+
+/** Illegal UNIX characters are NULL and slash.
+ *
+ */
+static bool legal_check(uint16_t ch)
+{
+	if ((ch == 0x0000) || (ch == 0x002F))
+		return false;
+	
+	return true;
+}
+
+/** Convert OSTA CS0 compressed Unicode name to Unicode.
+ *
+ * The Unicode output will be in the byte order that the local compiler
+ * uses for 16-bit values.
+ *
+ * NOTE: This routine only performs error checking on the comp_id.
+ * It is up to the user to ensure that the Unicode buffer is large
+ * enough, and that the compressed Unicode name is correct.
+ *
+ * @param[in]  number_of_bytes Number of bytes read from media
+ * @param[in]  udf_compressed  Bytes read from media
+ * @param[out] unicode         Uncompressed unicode characters
+ * @param[in]  unicode_max_len Size of output array
+ *
+ * @return Number of Unicode characters which were uncompressed.
+ *
+ */
+static size_t udf_uncompress_unicode(size_t number_of_bytes,
+    uint8_t *udf_compressed, uint16_t *unicode, size_t unicode_max_len)
+{
+	/* Use udf_compressed to store current byte being read. */
+	uint8_t comp_id = udf_compressed[0];
+	
+	/* First check for valid compID. */
+	if ((comp_id != 8) && (comp_id != 16))
+		return 0;
+	
+	size_t unicode_idx = 0;
+	size_t byte_idx = 1;
+	
+	/* Loop through all the bytes. */
+	while ((byte_idx < number_of_bytes) && (unicode_idx < unicode_max_len)) {
+		if (comp_id == 16) {
+			/*
+			 * Move the first byte to the high bits of the
+			 * Unicode char.
+			 */
+			unicode[unicode_idx] = udf_compressed[byte_idx++] << 8;
+		} else
+			unicode[unicode_idx] = 0;
+		
+		if (byte_idx < number_of_bytes) {
+			/* Then the next byte to the low bits. */
+			unicode[unicode_idx] |= udf_compressed[byte_idx++];
+		}
+		
+		unicode_idx++;
+	}
+	
+	return unicode_idx;
+}
+
+/** Translate a long file name
+ *
+ * Translate a long file name to one using a MAXLEN and an illegal char set
+ * in accord with the OSTA requirements. Assumes the name has already been
+ * translated to Unicode.
+ *
+ * @param[out] new_name Translated name. Must be of length MAXLEN
+ * @param[in]  udf_name Name from UDF volume
+ * @param[in]  udf_len  Length of UDF Name
+ *
+ * @return Number of Unicode characters in translated name.
+ *
+ */
+size_t udf_translate_name(uint16_t *new_name, uint16_t *udf_name,
+    size_t udf_len)
+{
+	bool needs_crc = false;
+	bool has_ext = false;
+	size_t ext_idx = 0;
+	size_t new_idx = 0;
+	size_t new_ext_idx = 0;
+	
+	for (size_t idx = 0; idx < udf_len; idx++) {
+		uint16_t current = udf_name[idx];
+		
+		if ((!legal_check(current)) || (!ascii_check(current))) {
+			needs_crc = true;
+			
+			/*
+			 * Replace Illegal and non-displayable chars with
+			 * underscore.
+			 */
+			current = ILLEGAL_CHAR_MARK;
+			
+			/*
+			 * Skip any other illegal or non-displayable
+			 * characters.
+			 */
+			while ((idx + 1 < udf_len) &&
+			    (!legal_check(udf_name[idx + 1]) ||
+			    (!ascii_check(udf_name[idx + 1]))))
+				idx++;
+		}
+		
+		/* Record position of extension, if one is found. */
+		if ((current == PERIOD) && ((udf_len - idx - 1) <= EXT_SIZE)) {
+			if (udf_len == idx + 1) {
+				/* A trailing period is NOT an extension. */
+				has_ext = false;
+			} else {
+				has_ext = true;
+				ext_idx = idx;
+				new_ext_idx = new_idx;
+			}
+		}
+		
+		if (new_idx < MAXLEN)
+			new_name[new_idx++] = current;
+		else
+			needs_crc = true;
+	}
+	
+	if (needs_crc) {
+		uint16_t ext[EXT_SIZE];
+		size_t local_ext_idx = 0;
+		
+		if (has_ext) {
+			size_t max_filename_len;
+			
+			/* Translate extension, and store it in ext. */
+			for (size_t idx = 0; (idx < EXT_SIZE) &&
+			    (ext_idx + idx + 1 < udf_len); idx++) {
+				uint16_t current = udf_name[ext_idx + idx + 1];
+				
+				if ((!legal_check(current)) || (!ascii_check(current))) {
+					needs_crc = true;
+					
+					/*
+					 * Replace Illegal and non-displayable
+					 * chars with underscore.
+					 */
+					current = ILLEGAL_CHAR_MARK;
+					
+					/*
+					 * Skip any other illegal or
+					 * non-displayable characters.
+					 */
+					while ((idx + 1 < EXT_SIZE) &&
+					    ((!legal_check(udf_name[ext_idx + idx + 2])) ||
+					    (!ascii_check(udf_name[ext_idx + idx + 2]))))
+						idx++;
+				}
+				
+				ext[local_ext_idx++] = current;
+			}
+			
+			/*
+			 * Truncate filename to leave room for extension and
+			 * CRC.
+			 */
+			max_filename_len = ((MAXLEN - 5) - local_ext_idx - 1);
+			if (new_idx > max_filename_len)
+				new_idx = max_filename_len;
+			else
+				new_idx = new_ext_idx;
+		} else if (new_idx > MAXLEN - 5) {
+			/* If no extension, make sure to leave room for CRC. */
+			new_idx = MAXLEN - 5;
+		}
+		
+		/* Add mark for CRC. */
+		new_name[new_idx++] = CRC_MARK;
+		
+		/* Calculate CRC from original filename. */
+		uint16_t value_crc = udf_unicode_cksum(udf_name, udf_len);
+		
+		/* Convert 16-bits of CRC to hex characters. */
+		const char hex_char[] = "0123456789ABCDEF";
+		
+		new_name[new_idx++] = hex_char[(value_crc & 0xf000) >> 12];
+		new_name[new_idx++] = hex_char[(value_crc & 0x0f00) >> 8];
+		new_name[new_idx++] = hex_char[(value_crc & 0x00f0) >> 4];
+		new_name[new_idx++] = hex_char[(value_crc & 0x000f)];
+		
+		/* Place a translated extension at end, if found. */
+		if (has_ext) {
+			new_name[new_idx++] = PERIOD;
+			
+			for (size_t idx = 0; idx < local_ext_idx; idx++)
+				new_name[new_idx++] = ext[idx];
+		}
+	}
+	
+	return new_idx;
+}
+
+/** Decode from dchar to utf8
+ *
+ * @param result     Returned value - utf8 string
+ * @param result_len Length of output string
+ * @param id         Input string
+ * @param len        Length of input string
+ * @param chsp       Decode method
+ *
+ */
+void udf_to_unix_name(char *result, size_t result_len, char *id, size_t len,
+    udf_charspec_t *chsp)
+{
+	const char *osta_id = "OSTA Compressed Unicode";
+	size_t ucode_chars, nice_uchars;
+	
+	uint16_t *raw_name = malloc(MAX_BUF * sizeof(uint16_t));
+	uint16_t *unix_name = malloc(MAX_BUF * sizeof(uint16_t));
+	
+	// FIXME: Check for malloc returning NULL
+	
+	bool is_osta_typ0 = (chsp->type == 0) &&
+	    (str_cmp((char *) chsp->info, osta_id) == 0);
+	
+	if (is_osta_typ0) {
+		*raw_name = 0;
+		*unix_name = 0;
+		
+		ucode_chars =
+		    udf_uncompress_unicode(len, (uint8_t *) id, raw_name, MAX_BUF);
+		ucode_chars = min(ucode_chars, utf16_length(raw_name));
+		nice_uchars =
+		    udf_translate_name(unix_name, raw_name, ucode_chars);
+		
+		/* Output UTF-8 */
+		unix_name[nice_uchars] = 0;
+		utf16_to_str(result, result_len, unix_name);
+	} else {
+		/* Assume 8 bit char length byte Latin-1 */
+		str_ncpy(result, result_len, (char *) (id + 1),
+		    str_size((char *) (id + 1)));
+	}
+	
+	free(raw_name);
+	free(unix_name);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_osta.h
===================================================================
--- uspace/srv/fs/udf/udf_osta.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf_osta.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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.
+ */
+
+/*
+ * OSTA compliant Unicode compression, uncompression routines,
+ * file name translation routine for OS/2, Windows 95, Windows NT,
+ * Macintosh and UNIX.
+ * Copyright 1995 Micro Design International, Inc.
+ * Written by Jason M. Rinn.
+ * Micro Design International gives permission for the free use of the
+ * following source code.
+ */
+
+#ifndef UDF_OSTA_H_
+#define UDF_OSTA_H_
+
+#include <sys/types.h>
+#include <bool.h>
+#include "udf_types.h"
+
+#define MAXLEN    255
+#define MAX_BUF   1024
+#define EXT_SIZE  5
+
+#define ILLEGAL_CHAR_MARK  0x005F
+#define CRC_MARK           0x0023
+#define PERIOD             0x002E
+
+extern size_t udf_translate_name(uint16_t *, uint16_t *, size_t);
+extern void udf_to_unix_name(char *, size_t, char *, size_t, udf_charspec_t *);
+
+#endif /* UDF_OSTA_H_ */
Index: uspace/srv/fs/udf/udf_types.h
===================================================================
--- uspace/srv/fs/udf/udf_types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf_types.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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 fs
+ * @{
+ */
+/**
+ * @file udf_types.h
+ * @brief UDF common types
+ */
+
+#ifndef UDF_UDF_TYPES_H_
+#define UDF_UDF_TYPES_H_
+
+#include <sys/types.h>
+#include <bool.h>
+#include <byteorder.h>
+
+#define GET_LE16(x)  x = uint16_t_le2host(x)
+#define GET_LE32(x)  x = uint32_t_le2host(x)
+
+#define FLE16(x)  uint16_t_le2host(x)
+#define FLE32(x)  uint32_t_le2host(x)
+#define FLE64(x)  uint64_t_le2host(x)
+
+#define ALL_UP(n, b)  ((n) / (b) + ((n) % (b) != 0))
+
+#define EXT_LENGTH(x)  (x & 0x3FFFFFFF)
+
+typedef uint8_t udf_dstring;
+
+/* Timestamp descriptor (ECMA 167 1/7.3) */
+typedef struct udf_timestamp {
+	uint16_t type_and_tz;
+	uint16_t year;
+	uint8_t month;
+	uint8_t day;
+	uint8_t hour;
+	uint8_t min;
+	uint8_t sec;
+	uint8_t centisec;
+	uint8_t h_of_mcsec;
+	uint8_t mcsec;
+} __attribute__((packed)) udf_timestamp_t;
+
+/* Universal descriptor tag (ECMA 167 3/7.2) */
+typedef struct udf_descriptor_tag {
+	uint16_t id;
+	uint16_t version;
+	uint8_t checksum;
+	uint8_t reserved;
+	uint16_t serial;
+	uint16_t descriptor_crc;
+	uint16_t descriptor_crc_length;
+	uint32_t location;
+} __attribute__((packed)) udf_descriptor_tag_t;
+
+/* Entity descriptor (ECMA 167 1/7.4) */
+typedef struct udf_regid {
+	uint8_t flags;
+	uint8_t id[23];
+	uint8_t id_suffix[8];
+} __attribute__((packed)) udf_regid_t;
+
+/* Character set specification (ECMA 167 1/7.2.1) */
+typedef struct udf_charspec {
+	uint8_t type;
+	uint8_t info[63];
+} __attribute__((packed)) udf_charspec_t;
+
+/* Recorded address (ECMA 167 4/7.1) */
+typedef struct udf_lb_addr {
+	uint32_t lblock_num;     /* Relative to start of the partition (from 0) */
+	uint16_t partition_num;  /* Relative to logical volume or not? */
+} __attribute__((packed)) udf_lb_addr_t;
+
+/* Long Allocation Descriptor (ECMA 167 4/14.14.2) */
+typedef struct udf_long_ad {
+	uint32_t length;
+	udf_lb_addr_t location;
+	uint8_t implementation_use[6];
+} __attribute__((packed)) udf_long_ad_t;
+
+/* Short Allocation Descriptor (ECMA 167 4/14.14.1) */
+typedef struct udf_short_ad {
+	uint32_t length;
+	uint32_t position;
+} __attribute__((packed)) udf_short_ad_t;
+
+/* Extended Allocation Descriptor (ECMA 167 4/14.14.3) */
+typedef struct udf_ext_ad {
+	uint32_t extent_length;
+	uint32_t recorded_length;
+	uint32_t info_length;
+	udf_lb_addr_t extent_location;
+	uint8_t implementation_use[2];
+} __attribute__((packed)) udf_ext_ad_t;
+
+/* Extent descriptor (ECMA 167 3/7.1) */
+typedef struct udf_extent {
+	uint32_t length;    /* Bytes */
+	uint32_t location;  /* Sectors */
+} __attribute__((packed)) udf_extent_t;
+
+/* Terminating Descriptor (ECMA 167 3/10.9) */
+typedef struct udf_terminating_descriptor {
+	udf_descriptor_tag_t tag;
+	uint8_t reserved[496];
+} __attribute__((packed)) udf_terminating_descriptor_t;
+
+/* Unallocated Space Descriptor (ECMA 167 3/10.8) */
+typedef struct udf_unallocated_space_descriptor {
+	udf_descriptor_tag_t tag;
+	uint32_t sequence_number;
+	uint32_t allocation_descriptors_num;
+	udf_extent_t allocation_descriptors[0];
+} __attribute__((packed)) udf_unallocated_space_descriptor_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_volume.c
===================================================================
--- uspace/srv/fs/udf/udf_volume.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf_volume.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,850 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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 fs
+ * @{
+ */
+/**
+ * @file udf_volume.c
+ * @brief Implementation of volume recognition operations.
+ */
+
+#include <byteorder.h>
+#include <block.h>
+#include <libfs.h>
+#include <errno.h>
+#include <str.h>
+#include <malloc.h>
+#include <mem.h>
+#include <inttypes.h>
+#include <io/log.h>
+#include "udf.h"
+#include "udf_volume.h"
+#include "udf_osta.h"
+#include "udf_cksum.h"
+#include "udf_file.h"
+
+/** Convert long_ad to absolute sector position
+ *
+ * Convert address sector concerning origin of partition to position
+ * sector concerning origin of start of disk.
+ *
+ * @param instance UDF instance
+ * @param long_ad  UDF long address
+ *
+ * @return Position of sector concerning origin of start of disk.
+ *
+ */
+fs_index_t udf_long_ad_to_pos(udf_instance_t *instance, udf_long_ad_t *long_ad)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Long_Ad to Pos: "
+	    "partition_num=%" PRIu16 ", partition_block=%" PRIu32,
+	    FLE16(long_ad->location.partition_num),
+	    FLE32(long_ad->location.lblock_num));
+	
+	return instance->partitions[
+	    FLE16(long_ad->location.partition_num)].start +
+	    FLE32(long_ad->location.lblock_num);
+}
+
+/** Check type and version of VRS
+ *
+ * Not exactly clear which values could have type and version.
+ *
+ * @param service_id
+ * @param addr       Position sector with Volume Descriptor
+ * @param vd         Returned value - Volume Descriptor.
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+static int udf_volume_recongnition_structure_test(service_id_t service_id,
+    aoff64_t addr, udf_vrs_descriptor_t *vd)
+{
+	return block_read_bytes_direct(service_id, addr,
+	    sizeof(udf_vrs_descriptor_t), vd);
+}
+
+/** Read Volume Recognition Sequence
+ *
+ * It is a first udf data which we read.
+ * It stars from fixed address VRS_ADDR = 32768 (bytes)
+ *
+ * @param service_id
+ *
+ * @return    EOK on success or a negative error code.
+ */
+int udf_volume_recongnition(service_id_t service_id) 
+{
+	aoff64_t addr = VRS_ADDR;
+	bool nsr_found = false;
+
+	udf_vrs_descriptor_t *vd = malloc(sizeof(udf_vrs_descriptor_t));
+	if (!vd)
+		return ENOMEM;
+	
+	int rc = udf_volume_recongnition_structure_test(service_id, addr, vd);
+	if (rc != EOK) {
+		free(vd);
+		return rc;
+	}
+	
+	for (size_t i = 0; i < VRS_DEPTH; i++) {
+		addr += sizeof(udf_vrs_descriptor_t);
+		
+		rc = udf_volume_recongnition_structure_test(service_id, addr, vd);
+		if (rc != EOK) {
+			free(vd);
+			return rc;
+		}
+		
+		/*
+		 * UDF standard identifier. According to ECMA 167 2/9.1.2
+		 */
+		if ((str_lcmp(VRS_NSR2, (char *) vd->identifier, VRS_ID_LEN) == 0) ||
+		    (str_lcmp(VRS_NSR3, (char *) vd->identifier, VRS_ID_LEN) == 0)) {
+			nsr_found = true;
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "VRS: NSR found");
+			continue;
+		}
+		
+		if (str_lcmp(VRS_END, (char *) vd->identifier, VRS_ID_LEN) == 0) {
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "VRS: end found");
+			break;
+		}
+	}
+	
+	free(vd);
+	
+	if (nsr_found)
+		return EOK;
+	else
+		return EINVAL;
+}
+
+/** Convert descriptor tag fields from little-endian to current byte order
+ *
+ */
+static void udf_prepare_tag(udf_descriptor_tag_t *tag)
+{
+	GET_LE16(tag->id);
+	GET_LE16(tag->version);
+	GET_LE16(tag->serial);
+	GET_LE16(tag->descriptor_crc);
+	GET_LE16(tag->descriptor_crc_length);
+	GET_LE32(tag->location);
+}
+
+/** Read AVD by using one of default sector size from array
+ *
+ * @param service_id
+ * @param avd         Returned value - Anchor Volume Descriptor
+ * @param sector_size Expected sector size
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+static int udf_get_anchor_volume_descriptor_by_ssize(service_id_t service_id,
+    udf_anchor_volume_descriptor_t *avd, uint32_t sector_size)
+{
+	int rc = block_read_bytes_direct(service_id,
+	    UDF_AVDP_SECTOR * sector_size,
+	    sizeof(udf_anchor_volume_descriptor_t), avd);
+	if (rc != EOK)
+		return rc;
+	
+	if (avd->tag.checksum != udf_tag_checksum((uint8_t *) &avd->tag))
+		return EINVAL;
+	
+	// TODO: Should be tested in big-endian mode
+	udf_prepare_tag(&avd->tag);
+	
+	if (avd->tag.id != UDF_TAG_AVDP)
+		return EINVAL;
+	
+	GET_LE32(avd->main_extent.length);
+	GET_LE32(avd->main_extent.location);
+	GET_LE32(avd->reserve_extent.length);
+	GET_LE32(avd->reserve_extent.location);
+	
+	return EOK;
+}
+
+/** Identification of the sector size
+ *
+ * We try to read Anchor Volume Descriptor by using one item from
+ * sequence of default values. If we could read avd, we found sector size.
+ *
+ * @param service_id
+ * @param avd        Returned value - Anchor Volume Descriptor
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_get_anchor_volume_descriptor(service_id_t service_id,
+    udf_anchor_volume_descriptor_t *avd)
+{
+	uint32_t default_sector_size[] = {512, 1024, 2048, 4096, 8192, 0};
+	
+	udf_instance_t *instance;
+	int rc = fs_instance_get(service_id, (void **) &instance);
+	if (rc != EOK)
+		return rc;
+	
+	if (instance->sector_size) {
+		return udf_get_anchor_volume_descriptor_by_ssize(service_id, avd,
+		    instance->sector_size);
+	} else {
+		size_t i = 0;
+		while (default_sector_size[i] != 0) {
+			rc = udf_get_anchor_volume_descriptor_by_ssize(service_id, avd,
+			    default_sector_size[i]);
+			if (rc == EOK) {
+				instance->sector_size = default_sector_size[i];
+				return EOK;
+			}
+			
+			i++;
+		}
+	}
+	
+	return EINVAL;
+}
+
+/** Check on prevailing primary volume descriptor
+ *
+ * Some discs couldn't be rewritten and new information is identified
+ * by descriptors with same data as one of already created descriptors.
+ * We should find prevailing descriptor (descriptor with the highest number)
+ * and delete old descriptor.
+ *
+ * @param pvd  Array of primary volumes descriptors
+ * @param cnt  Count of items in array
+ * @param desc Descriptor which could prevail over one
+ *             of descriptors in array.
+ *
+ * @return True if desc prevails over some descriptor in array
+ *
+ */
+static bool udf_check_prevailing_pvd(udf_primary_volume_descriptor_t *pvd,
+    size_t cnt, udf_primary_volume_descriptor_t *desc)
+{
+	for (size_t i = 0; i < cnt; i++) {
+		/*
+		 * According to ECMA 167 3/8.4.3
+		 * PVD, each of which has same contents of the corresponding
+		 * Volume Identifier, Volume set identifier
+		 * and Descriptor char set field.
+		 */
+		if ((bcmp((uint8_t *) pvd[i].volume_id,
+		    (uint8_t *) desc->volume_id, 32) == 0) &&
+		    (bcmp((uint8_t *) pvd[i].volume_set_id,
+		    (uint8_t *) desc->volume_set_id, 128) == 0) &&
+		    (bcmp((uint8_t *) &pvd[i].descriptor_charset,
+		    (uint8_t *) &desc->descriptor_charset, 64) == 0) &&
+		    (FLE32(desc->sequence_number) > FLE32(pvd[i].sequence_number))) {
+			memcpy(&pvd[i], desc, sizeof(udf_primary_volume_descriptor_t));
+			return true;
+		}
+	}
+	
+	return false;
+}
+
+/** Check on prevailing logic volume descriptor
+ *
+ * Some discs couldn't be rewritten and new information is identified
+ * by descriptors with same data as one of already created descriptors.
+ * We should find  prevailing descriptor (descriptor with the highest number)
+ * and delete old descriptor.
+ *
+ * @param lvd  Array of logic volumes descriptors
+ * @param cnt  Count of items in array
+ * @param desc Descriptor which could prevail over one
+ *             of descriptors in array.
+ *
+ * @return True if desc prevails over some descriptor in array
+ *
+ */
+static bool udf_check_prevailing_lvd(udf_logical_volume_descriptor_t *lvd,
+    size_t cnt, udf_logical_volume_descriptor_t *desc)
+{
+	for (size_t i = 0; i < cnt; i++) {
+		/*
+		 * According to ECMA 167 3/8.4.3
+		 * LVD, each of which has same contents of the corresponding
+		 * Logic Volume Identifier and Descriptor char set field.
+		 */
+		if ((bcmp((uint8_t *) lvd[i].logical_volume_id,
+		    (uint8_t *) desc->logical_volume_id, 128) == 0) &&
+		    (bcmp((uint8_t *) &lvd[i].charset,
+		    (uint8_t *) &desc->charset, 64) == 0) &&
+		    (FLE32(desc->sequence_number) > FLE32(lvd[i].sequence_number))) {
+			memcpy(&lvd[i], desc, sizeof(udf_logical_volume_descriptor_t));
+			return true;
+		}
+	}
+	
+	return false;
+}
+
+/** Check on prevailing partition descriptor
+ *
+ * Some discs couldn't be rewritten and new information is identified
+ * by descriptors with same data as one of already created descriptors.
+ * We should find  prevailing descriptor (descriptor with the highest number)
+ * and delete old descriptor.
+ *
+ * @param pvd  Array of partition descriptors
+ * @param cnt  Count of items in array
+ * @param desc Descriptor which could prevail over one
+ *             of descriptors in array.
+ *
+ * @return True if desc prevails over some descriptor in array
+ *
+ */
+static bool udf_check_prevailing_pd(udf_partition_descriptor_t *pd, size_t cnt,
+    udf_partition_descriptor_t *desc)
+{
+	for (size_t i = 0; i < cnt; i++) {
+		/*
+		 * According to ECMA 167 3/8.4.3
+		 * Partition descriptors with identical Partition Number
+		 */
+		if ((FLE16(pd[i].number) == FLE16(desc->number)) &&
+		    (FLE32(desc->sequence_number) > FLE32(pd[i].sequence_number))) {
+			memcpy(&pd[i], desc, sizeof(udf_partition_descriptor_t));
+			return true;
+		}
+	}
+	
+	return false;
+}
+
+/** Read information about virtual partition
+ *
+ * Fill start and length fields for partition. This function quite similar of
+ * udf_read_icd. But in this we can meet only two descriptors and
+ * we have to read only one allocator.
+ *
+ * @param instance UDF instance
+ * @param pos      Position (Extended) File entry descriptor
+ * @param id       Index of partition in instance::partitions array
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+static int udf_read_virtual_partition(udf_instance_t *instance, uint32_t pos,
+    uint32_t id)
+{
+	block_t *block = NULL;
+	int rc = block_get(&block, instance->service_id, pos,
+	    BLOCK_FLAGS_NONE);
+	if (rc != EOK)
+		return rc;
+	
+	udf_descriptor_tag_t *desc = (udf_descriptor_tag_t *) (block->data);
+	if (desc->checksum != udf_tag_checksum((uint8_t *) desc)) {
+		block_put(block);
+		return EINVAL;
+	}
+	
+	/*
+	 * We think that we have only one allocator. It is means that virtual
+	 * partition, like physical, isn't fragmented.
+	 * According to doc the type of allocator is short_ad.
+	 */
+	switch (FLE16(desc->id)) {
+	case UDF_FILE_ENTRY:
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "ICB: File entry descriptor found");
+		
+		udf_file_entry_descriptor_t *fed =
+		    (udf_file_entry_descriptor_t *) block->data;
+		uint32_t start_alloc = FLE32(fed->ea_lenght) + UDF_FE_OFFSET;
+		udf_short_ad_t *short_d =
+		    (udf_short_ad_t *) ((uint8_t *) fed + start_alloc);
+		instance->partitions[id].start = FLE32(short_d->position);
+		instance->partitions[id].lenght = FLE32(short_d->length);
+		break;
+		
+	case UDF_EFILE_ENTRY:
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "ICB: Extended file entry descriptor found");
+		
+		udf_extended_file_entry_descriptor_t *efed =
+		    (udf_extended_file_entry_descriptor_t *) block->data;
+		start_alloc = FLE32(efed->ea_lenght) + UDF_EFE_OFFSET;
+		short_d = (udf_short_ad_t *) ((uint8_t *) efed + start_alloc);
+		instance->partitions[id].start = FLE32(short_d->position);
+		instance->partitions[id].lenght = FLE32(short_d->length);
+		break;
+	}
+	
+	return block_put(block);
+}
+
+/** Search partition in array of partitions
+ *
+ * Used only in function udf_fill_volume_info
+ *
+ * @param pd     Array of partitions
+ * @param pd_cnt Count items in array
+ * @param id     Number partition (not index) which we want to find
+ *
+ * @return Index of partition or (size_t) -1 if we didn't find anything
+ *
+ */
+static size_t udf_find_partition(udf_partition_descriptor_t *pd, size_t pd_cnt,
+    size_t id)
+{
+	for (size_t i = 0; i < pd_cnt; i++) {
+		if (FLE16(pd[i].number) == id)
+			return i;
+	}
+	
+	return (size_t) -1;
+}
+
+/** Fill instance structures by information about partitions and logic
+ *
+ * @param lvd      Array of logic volumes descriptors
+ * @param lvd_cnt  Count of items in lvd array
+ * @param pd       Array of partition descriptors
+ * @param pd_cnt   Count of items in pd array
+ * @param instance UDF instance
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+static int udf_fill_volume_info(udf_logical_volume_descriptor_t *lvd,
+    size_t lvd_cnt, udf_partition_descriptor_t *pd, size_t pd_cnt,
+    udf_instance_t *instance)
+{
+	instance->volumes = calloc(lvd_cnt, sizeof(udf_lvolume_t));
+	if (instance->volumes == NULL)
+		return ENOMEM;
+	
+	instance->partitions = calloc(pd_cnt, sizeof(udf_partition_t));
+	if (instance->partitions == NULL) {
+		free(instance->volumes);
+		return ENOMEM;
+	}
+	
+	instance->partition_cnt = pd_cnt;
+	
+	/*
+	 * Fill information about logical volumes. We will save
+	 * information about all partitions placed inside each volumes.
+	 */
+	
+	size_t vir_pd_cnt = 0;
+	for (size_t i = 0; i < lvd_cnt; i++) {
+		instance->volumes[i].partitions =
+		    calloc(FLE32(lvd[i].number_of_partitions_maps),
+		    sizeof(udf_partition_t *));
+		if (instance->volumes[i].partitions == NULL) {
+			// FIXME: Memory leak, cleanup code missing
+			return ENOMEM;
+		}
+		
+		instance->volumes[i].partition_cnt = 0;
+		instance->volumes[i].logical_block_size =
+		    FLE32(lvd[i].logical_block_size);
+		
+		/*
+		 * In theory we could have more than 1 logical volume. But now
+		 * for current work of driver we will think that it single and all
+		 * partitions from array pd belong to only first lvd
+		 */
+		
+		uint8_t *idx = lvd[i].partition_map;
+		for (size_t j = 0; j < FLE32(lvd[i].number_of_partitions_maps);
+		    j++) {
+			udf_type1_partition_map_t *pm1 =
+			    (udf_type1_partition_map_t *) idx;
+			
+			if (pm1->partition_map_type == 1) {
+				size_t pd_num = udf_find_partition(pd, pd_cnt,
+				    FLE16(pm1->partition_number));
+				if (pd_num == (size_t) -1) {
+					// FIXME: Memory leak, cleanup code missing
+					return ENOENT;
+				}
+				
+				/*
+				 * Fill information about physical partitions. We will save all
+				 * partitions (physical and virtual) inside one array
+				 * instance::partitions
+				 */
+				instance->partitions[j].access_type =
+				    FLE32(pd[pd_num].access_type);
+				instance->partitions[j].lenght =
+				    FLE32(pd[pd_num].length);
+				instance->partitions[j].number =
+				    FLE16(pm1->partition_number);
+				instance->partitions[j].start =
+				    FLE32(pd[pd_num].starting_location);
+				
+				instance->volumes[i].partitions[
+				    instance->volumes[i].partition_cnt] =
+				    &instance->partitions[j];
+				
+				log_msg(LOG_DEFAULT, LVL_DEBUG, "Volume[%" PRIun "]: partition [type %u] "
+				    "found and filled", i, pm1->partition_map_type);
+				
+				instance->volumes[i].partition_cnt++;
+				idx += pm1->partition_map_lenght;
+				continue;
+			}
+			
+			udf_type2_partition_map_t *pm2 =
+			    (udf_type2_partition_map_t *) idx;
+			
+			if (pm2->partition_map_type == 2) {
+				// TODO: check partition_ident for metadata_partition_map
+				
+				udf_metadata_partition_map_t *metadata =
+				    (udf_metadata_partition_map_t *) idx;
+				
+				log_msg(LOG_DEFAULT, LVL_DEBUG, "Metadata file location=%u",
+				    FLE32(metadata->metadata_fileloc));
+				
+				vir_pd_cnt++;
+				instance->partitions = realloc(instance->partitions,
+				    (pd_cnt + vir_pd_cnt) * sizeof(udf_partition_t));
+				if (instance->partitions == NULL) {
+					// FIXME: Memory leak, cleanup code missing
+					return ENOMEM;
+				}
+				
+				instance->partition_cnt++;
+				
+				size_t pd_num = udf_find_partition(pd, pd_cnt,
+				    FLE16(metadata->partition_number));
+				if (pd_num == (size_t) -1) {
+					// FIXME: Memory leak, cleanup code missing
+					return ENOENT;
+				}
+				
+				instance->partitions[j].number =
+				    FLE16(metadata->partition_number);
+				int rc = udf_read_virtual_partition(instance,
+				    FLE32(metadata->metadata_fileloc) +
+				    FLE32(pd[pd_num].starting_location), j);
+				if (rc != EOK) {
+					// FIXME: Memory leak, cleanup code missing
+					return rc;
+				}
+				
+				/* Virtual partition placed inside physical */
+				instance->partitions[j].start +=
+				    FLE32(pd[pd_num].starting_location);
+				
+				instance->volumes[i].partitions[
+				    instance->volumes[i].partition_cnt] =
+				    &instance->partitions[j];
+				
+				log_msg(LOG_DEFAULT, LVL_DEBUG, "Virtual partition: num=%d, start=%d",
+				    instance->partitions[j].number,
+				    instance->partitions[j].start);
+				log_msg(LOG_DEFAULT, LVL_DEBUG, "Volume[%" PRIun "]: partition [type %u] "
+				    "found and filled", i, pm2->partition_map_type);
+				
+				instance->volumes[i].partition_cnt++;
+				idx += metadata->partition_map_length;
+				continue;
+			}
+			
+			/* Not type 1 nor type 2 */
+			udf_general_type_t *pm = (udf_general_type_t *) idx;
+			
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Volume[%" PRIun "]: partition [type %u] "
+			    "found and skipped", i, pm->partition_map_type);
+			
+			idx += pm->partition_map_lenght;
+		}
+	}
+	
+	return EOK;
+}
+
+/** Read volume descriptors sequence
+ *
+ * @param service_id
+ * @param addr       UDF extent descriptor (ECMA 167 3/7.1)
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_read_volume_descriptor_sequence(service_id_t service_id,
+    udf_extent_t addr)
+{
+	udf_instance_t *instance;
+	int rc = fs_instance_get(service_id, (void **) &instance);
+	if (rc != EOK)
+		return rc;
+	
+	aoff64_t pos = addr.location;
+	aoff64_t end = pos + (addr.length / instance->sector_size) - 1;
+	
+	if (pos == end)
+		return EINVAL;
+	
+	size_t max_descriptors = ALL_UP(addr.length, instance->sector_size);
+	
+	udf_primary_volume_descriptor_t *pvd = calloc(max_descriptors,
+	    sizeof(udf_primary_volume_descriptor_t));
+	if (pvd == NULL)
+		return ENOMEM;
+	
+	udf_logical_volume_descriptor_t *lvd = calloc(max_descriptors,
+	    instance->sector_size);
+	if (lvd == NULL) {
+		free(pvd);
+		return ENOMEM;
+	}
+	
+	udf_partition_descriptor_t *pd = calloc(max_descriptors,
+	    sizeof(udf_partition_descriptor_t));
+	if (pd == NULL) {
+		free(pvd);
+		free(lvd);
+		return ENOMEM;
+	}
+	
+	size_t pvd_cnt = 0;
+	size_t lvd_cnt = 0;
+	size_t pd_cnt = 0;
+	
+	while (pos <= end) {
+		block_t *block = NULL;
+		rc = block_get(&block, service_id, pos, BLOCK_FLAGS_NONE);
+		if (rc != EOK) {
+			free(pvd);
+			free(lvd);
+			free(pd);
+			return rc;
+		}
+		
+		udf_volume_descriptor_t *vol =
+		    (udf_volume_descriptor_t *) block->data;
+		
+		switch (FLE16(vol->common.tag.id)) {
+		/* One sector size descriptors */
+		case UDF_TAG_PVD:
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Volume: Primary volume descriptor found");
+			
+			if (!udf_check_prevailing_pvd(pvd, pvd_cnt, &vol->volume)) {
+				memcpy(&pvd[pvd_cnt], &vol->volume,
+				    sizeof(udf_primary_volume_descriptor_t));
+				pvd_cnt++;
+			}
+			
+			pos++;
+			break;
+			
+		case UDF_TAG_VDP:
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Volume: Volume descriptor pointer found");
+			pos++;
+			break;
+			
+		case UDF_TAG_IUVD:
+			log_msg(LOG_DEFAULT, LVL_DEBUG,
+			    "Volume: Implementation use volume descriptor found");
+			pos++;
+			break;
+			
+		case UDF_TAG_PD:
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Volume: Partition descriptor found");
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Partition number: %u, contents: '%.6s', "
+			    "access type: %" PRIu32, FLE16(vol->partition.number),
+			    vol->partition.contents.id, FLE32(vol->partition.access_type));
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Partition start: %" PRIu32 " (sector), "
+			    "size: %" PRIu32 " (sectors)",
+			    FLE32(vol->partition.starting_location),
+			    FLE32(vol->partition.length));
+			
+			if (!udf_check_prevailing_pd(pd, pd_cnt, &vol->partition)) {
+				memcpy(&pd[pd_cnt], &vol->partition,
+				    sizeof(udf_partition_descriptor_t));
+				pd_cnt++;
+			}
+			
+			udf_partition_header_descriptor_t *phd =
+			    (udf_partition_header_descriptor_t *) vol->partition.contents_use;
+			if (FLE32(phd->unallocated_space_table.length)) {
+				log_msg(LOG_DEFAULT, LVL_DEBUG,
+				    "space table: length=%" PRIu32 ", pos=%" PRIu32,
+				    FLE32(phd->unallocated_space_table.length),
+				    FLE32(phd->unallocated_space_table.position));
+				
+				instance->space_type = SPACE_TABLE;
+				instance->uaspace_start =
+				    FLE32(vol->partition.starting_location) +
+				    FLE32(phd->unallocated_space_table.position);
+				instance->uaspace_lenght =
+				    FLE32(phd->unallocated_space_table.length);
+			}
+			
+			if (FLE32(phd->unallocated_space_bitmap.length)) {
+				log_msg(LOG_DEFAULT, LVL_DEBUG,
+				    "space bitmap: length=%" PRIu32 ", pos=%" PRIu32,
+				    FLE32(phd->unallocated_space_bitmap.length),
+				    FLE32(phd->unallocated_space_bitmap.position));
+				
+				instance->space_type = SPACE_BITMAP;
+				instance->uaspace_start =
+				    FLE32(vol->partition.starting_location) +
+				    FLE32(phd->unallocated_space_bitmap.position);
+				instance->uaspace_lenght =
+				    FLE32(phd->unallocated_space_bitmap.length);
+			}
+			
+			pos++;
+			break;
+			
+		/* Relative size descriptors */
+		case UDF_TAG_LVD:
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Volume: Logical volume descriptor found");
+			
+			aoff64_t sct =
+			    ALL_UP((sizeof(udf_logical_volume_descriptor_t) +
+			    FLE32(vol->logical.map_table_length)),
+			    sizeof(udf_common_descriptor_t));
+			pos += sct;
+			char tmp[130];
+			
+			udf_to_unix_name(tmp, 129,
+			    (char *) vol->logical.logical_volume_id, 128,
+			    &vol->logical.charset);
+			
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Logical Volume ID: '%s', "
+			    "logical block size: %" PRIu32 " (bytes)", tmp,
+			    FLE32(vol->logical.logical_block_size));
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Map table size: %" PRIu32 " (bytes), "
+			    "number of partition maps: %" PRIu32,
+			    FLE32(vol->logical.map_table_length),
+			    FLE32(vol->logical.number_of_partitions_maps));
+			
+			if (!udf_check_prevailing_lvd(lvd, lvd_cnt, &vol->logical)) {
+				memcpy(&lvd[lvd_cnt], &vol->logical,
+				    sizeof(udf_logical_volume_descriptor_t) +
+				    FLE32(vol->logical.map_table_length));
+				lvd_cnt++;
+			}
+			
+			break;
+			
+		case UDF_TAG_USD:
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Volume: Unallocated space descriptor found");
+			
+			sct = ALL_UP((sizeof(udf_unallocated_space_descriptor_t) +
+			    FLE32(vol->unallocated.allocation_descriptors_num)*
+			    sizeof(udf_extent_t)), sizeof(udf_common_descriptor_t));
+			instance->uaspace_start = pos;
+			instance->uaspace_lenght = sct;
+			instance->uasd = (udf_unallocated_space_descriptor_t *)
+			    malloc(sct * instance->sector_size);
+			if (instance->uasd == NULL) {
+				// FIXME: Memory leak, cleanup missing
+				return ENOMEM;
+			}
+			
+			memcpy(instance->uasd, block->data, instance->sector_size);
+			pos += sct;
+			break;
+			
+		case UDF_TAG_LVID:
+			log_msg(LOG_DEFAULT, LVL_DEBUG,
+			    "Volume: Logical volume integrity descriptor found");
+			
+			pos++;
+			break;
+			
+		case UDF_TAG_TD:
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Volume: Terminating descriptor found");
+			
+			/* Found terminating descriptor. Exiting */
+			pos = end + 1;
+			break;
+			
+		default:
+			pos++;
+		}
+		
+		rc = block_put(block);
+		if (rc != EOK) {
+			free(pvd);
+			free(lvd);
+			free(pd);
+			return rc;
+		}
+	}
+	
+	/* Fill the instance */
+	udf_fill_volume_info(lvd, lvd_cnt, pd, pd_cnt, instance);
+	
+	for (size_t i = 0; i < lvd_cnt; i++) {
+		pos = udf_long_ad_to_pos(instance,
+		    (udf_long_ad_t *) &lvd[i].logical_volume_conents_use);
+		
+		block_t *block = NULL;
+		rc = block_get(&block, instance->service_id, pos,
+		    BLOCK_FLAGS_NONE);
+		if (rc != EOK) {
+			// FIXME: Memory leak, cleanup missing
+			return rc;
+		}
+		
+		udf_descriptor_tag_t *desc = block->data;
+		
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "First tag ID=%" PRIu16, desc->id);
+		
+		if (desc->checksum != udf_tag_checksum((uint8_t *) desc)) {
+			// FIXME: Memory leak, cleanup missing
+			return EINVAL;
+		}
+		
+		udf_prepare_tag(desc);
+		
+		udf_fileset_descriptor_t *fd = block->data;
+		memcpy((uint8_t *) &instance->charset,
+		    (uint8_t *) &fd->fileset_charset, sizeof(fd->fileset_charset));
+		
+		instance->volumes[i].root_dir = udf_long_ad_to_pos(instance,
+		    &fd->root_dir_icb);
+	}
+	
+	free(pvd);
+	free(lvd);
+	free(pd);
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_volume.h
===================================================================
--- uspace/srv/fs/udf/udf_volume.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/fs/udf/udf_volume.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * 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 fs
+ * @{
+ */
+
+#ifndef UDF_UDF_VOLUME_H_
+#define UDF_UDF_VOLUME_H_
+
+#include <sys/types.h>
+#include <ipc/loc.h>
+#include "udf_types.h"
+
+/* Descriptor Tag Identifier (ECMA 167 3/7.2.1) */
+#define UDF_TAG_PVD   0x0001  /* Primary Volume Descriptor */
+#define UDF_TAG_AVDP  0x0002  /* Anchor Volume Descriptor */
+#define UDF_TAG_VDP   0x0003  /* Volume Descriptor Pointer */
+#define UDF_TAG_IUVD  0x0004  /* Implementation Use Volume Descriptor */
+#define UDF_TAG_PD    0x0005  /* Partition Descriptor */
+#define UDF_TAG_LVD   0x0006  /* Logical Volume Descriptor */
+#define UDF_TAG_USD   0x0007  /* Unallocated Space Descriptor */
+#define UDF_TAG_TD    0x0008  /* Terminating Descriptor */
+#define UDF_TAG_LVID  0x0009  /* Logical Volume Integrity Descriptor */
+
+/* Start adress of Anchor Volume Descriptor */
+#define UDF_AVDP_SECTOR  256
+
+/* Volume Recognition Sequence params */
+#define VRS_ADDR     32768
+#define VRS_TYPE     0
+#define VRS_VERSION  1
+#define VRS_BEGIN    "BEA01"
+#define VRS_END      "TEA01"
+#define VRS_NSR2     "NSR02"
+#define VRS_NSR3     "NSR03"
+#define VRS_DEPTH    10
+#define VRS_ID_LEN   5
+
+/* Volume Structure Descriptor (ECMA 167 2/9.1) */
+typedef struct udf_vrs_descriptor {
+	uint8_t type;           /* Structure type */
+	uint8_t identifier[5];  /* Standart identifier */
+	uint8_t version;        /* Structure version */
+	uint8_t data[2041];     /* Structure data */
+} __attribute__((packed)) udf_vrs_descriptor_t;
+
+/* Anchor volume descriptor (ECMA 167 3/10.2) */
+typedef struct udf_anchor_volume_descriptor {
+	udf_descriptor_tag_t tag;     /* Descriptor tag */
+	udf_extent_t main_extent;     /* Main Volume Descriptor Sequence Extent */
+	udf_extent_t reserve_extent;  /* Reserve Volume Descriptor Sequence Extent */
+	uint8_t reserved[480];        /* Structure data */
+} __attribute__((packed)) udf_anchor_volume_descriptor_t;
+
+/* Common Volume Descriptor */
+typedef struct udf_common_descriptor {
+	udf_descriptor_tag_t tag;
+	uint8_t reserved[496];
+} __attribute__((packed)) udf_common_descriptor_t;
+
+/* Volume Descriptor Pointer (ECMA 167 3/10.3) */
+typedef struct udf_volume_pointer_descriptor {
+	udf_descriptor_tag_t tag;
+	uint32_t sequence_number;
+	udf_extent_t next_sequence;
+	uint8_t reserved[484];
+} __attribute__((packed)) udf_volume_pointer_descriptor_t;
+
+/* Primary Volume Descriptor (ECMA 167 3/10.1) */
+typedef struct udf_primary_volume_descriptor {
+	udf_descriptor_tag_t tag;
+	uint32_t sequence_number;
+	uint32_t primary_volume_descriptor_num;
+	udf_dstring volume_id[32];
+	uint16_t max_sequence_number;
+	uint16_t interchange_level;
+	uint16_t max_interchange_level;
+	uint32_t charset_list;
+	uint32_t max_charset_list;
+	udf_dstring volume_set_id[128];
+	udf_charspec_t descriptor_charset;
+	udf_charspec_t explanatory_charset;
+	udf_extent_t volume_abstract;
+	udf_extent_t volume_copyright_notice;
+	udf_regid_t application_id;
+	udf_timestamp_t recording_data_and_time;
+	udf_regid_t implementation_id;
+	uint8_t implementation_use[64];
+	uint32_t predecessor_vds_location;
+	uint16_t flags;
+	uint8_t reserved[22];
+} __attribute__((packed)) udf_primary_volume_descriptor_t;
+
+
+/* Partition Descriptor (ECMA 167 3/10.5) */
+typedef struct udf_partition_descriptor {
+	udf_descriptor_tag_t tag;
+	uint32_t sequence_number;
+	uint16_t flags;
+	uint16_t number;
+	udf_regid_t contents;
+	uint8_t contents_use[128];
+	uint32_t access_type;
+	uint32_t starting_location;
+	uint32_t length;
+	udf_regid_t implementation_id;
+	uint8_t implementation_use[128];
+	uint8_t reserved[156];
+} __attribute__((packed)) udf_partition_descriptor_t;
+
+/* Logical Volume Descriptor (ECMA 167 3/10.6) */
+typedef struct udf_logical_volume_descriptor {
+	udf_descriptor_tag_t tag;
+	uint32_t sequence_number;
+	udf_charspec_t charset;
+	udf_dstring logical_volume_id[128];
+	uint32_t logical_block_size;
+	udf_regid_t domain_id;
+	uint8_t logical_volume_conents_use[16];
+	uint32_t map_table_length;
+	uint32_t number_of_partitions_maps;
+	udf_regid_t implementation_id;
+	uint8_t implementation_use[128];
+	udf_extent_t integrity_sequence_extent;
+	uint8_t partition_map[0];
+} __attribute__((packed)) udf_logical_volume_descriptor_t;
+
+typedef struct udf_volume_descriptor {
+	union {
+		udf_common_descriptor_t common;
+		udf_terminating_descriptor_t terminating;
+		udf_volume_pointer_descriptor_t pointer;
+		udf_partition_descriptor_t partition;
+		udf_logical_volume_descriptor_t logical;
+		udf_unallocated_space_descriptor_t unallocated;
+		udf_primary_volume_descriptor_t volume;
+	};
+} __attribute__((packed)) udf_volume_descriptor_t;
+
+typedef struct udf_general_type {
+	uint8_t partition_map_type;
+	uint8_t partition_map_lenght;
+} __attribute__((packed)) udf_general_type_t;
+
+typedef struct udf_type1_partition_map {
+	uint8_t partition_map_type;
+	uint8_t partition_map_lenght;
+	uint16_t volume_sequence_number;
+	uint16_t partition_number;
+} __attribute__((packed)) udf_type1_partition_map_t;
+
+typedef struct udf_type2_partition_map {
+	uint8_t partition_map_type;
+	uint8_t partition_map_length;
+	uint8_t reserved1[2];
+	udf_regid_t partition_ident;
+	uint16_t volume_sequence_number;
+	uint16_t partition_number;
+} __attribute__((packed)) udf_type2_partition_map_t;
+
+/* Metadata Partition Map (UDF 2.4.0 2.2.10) */
+typedef struct udf_metadata_partition_map {
+	uint8_t partition_map_type;
+	uint8_t partition_map_length;
+	uint8_t reserved1[2];
+	udf_regid_t partition_ident;
+	uint16_t volume_sequence_number;
+	uint16_t partition_number;
+	uint32_t metadata_fileloc;
+	uint32_t metadata_mirror_fileloc;
+	uint32_t metadata_bitmap_fileloc;
+	uint32_t alloc_unit_size;
+	uint16_t align_unit_size;
+	uint8_t flags;
+	uint8_t reserved2[5];
+} __attribute__((packed)) udf_metadata_partition_map_t;
+
+/* Partition Header Descriptor (ECMA 167 4/14.3) */
+typedef struct udf_partition_header_descriptor {
+	udf_short_ad_t unallocated_space_table;
+	udf_short_ad_t unallocated_space_bitmap;
+	udf_short_ad_t partition_integrity_table;
+	udf_short_ad_t freed_space_table;
+	udf_short_ad_t freed_space_bitmap;
+	uint8_t reserved[88];
+} __attribute__((packed)) udf_partition_header_descriptor_t;
+
+extern int udf_volume_recongnition(service_id_t);
+extern int udf_get_anchor_volume_descriptor(service_id_t,
+    udf_anchor_volume_descriptor_t *);
+extern int udf_read_volume_descriptor_sequence(service_id_t, udf_extent_t);
+extern fs_index_t udf_long_ad_to_pos(udf_instance_t *, udf_long_ad_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/compositor/Makefile
===================================================================
--- uspace/srv/hid/compositor/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/compositor/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,49 @@
+#
+# Copyright (c) 2012 Petr Koupy
+# 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 = $(LIBDRAW_PREFIX)/libdraw.a $(LIBSOFTREND_PREFIX)/libsoftrend.a \
+	$(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
+EXTRA_CFLAGS += -I$(LIBDRAW_PREFIX) -I$(LIBSOFTREND_PREFIX)
+BINARY = compositor
+
+SOURCES = \
+	compositor.c \
+	images.c
+
+IMAGES = \
+	gfx/helenos.tga \
+	gfx/nameic.tga
+
+PRE_DEPEND = images.c images.h
+EXTRA_CLEAN = images.c images.h
+
+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 a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/compositor/compositor.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,1818 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 compositor
+ * @{
+ */
+/** @file
+ */
+
+#include <sys/types.h>
+#include <bool.h>
+#include <errno.h>
+#include <str_error.h>
+#include <byteorder.h>
+#include <stdio.h>
+#include <libc.h>
+
+#include <align.h>
+#include <as.h>
+#include <malloc.h>
+
+#include <atomic.h>
+#include <fibril_synch.h>
+#include <adt/prodcons.h>
+#include <adt/list.h>
+#include <io/input.h>
+#include <ipc/graph.h>
+#include <ipc/window.h>
+
+#include <async.h>
+#include <loc.h>
+#include <devman.h>
+
+#include <event.h>
+#include <device/graph_dev.h>
+#include <io/keycode.h>
+#include <io/mode.h>
+#include <io/visualizer.h>
+#include <io/window.h>
+
+#include <transform.h>
+#include <rectangle.h>
+#include <surface.h>
+#include <cursor.h>
+#include <source.h>
+#include <drawctx.h>
+#include <codec/tga.h>
+
+#include "images.h"
+#include "compositor.h"
+
+#define NAME       "compositor"
+#define NAMESPACE  "comp"
+
+/* Until there is blitter support and some further optimizations, window
+ * animations are too slow to be practically usable. */
+#ifndef ANIMATE_WINDOW_TRANSFORMS
+#define ANIMATE_WINDOW_TRANSFORMS 0
+#endif
+
+static char *server_name;
+static sysarg_t coord_origin;
+static pixel_t bg_color;
+
+typedef struct {
+	link_t link;
+	sysarg_t id;
+	uint8_t state;
+	desktop_point_t pos;
+	sysarg_t btn_num;
+	desktop_point_t btn_pos;
+	desktop_vector_t accum;
+	sysarg_t grab_flags;
+	bool pressed;
+	cursor_t cursor;
+} pointer_t;
+
+static sysarg_t pointer_id = 0;
+static FIBRIL_MUTEX_INITIALIZE(pointer_list_mtx);
+static LIST_INITIALIZE(pointer_list);
+
+typedef struct {
+	link_t link;
+	service_id_t in_dsid;
+	service_id_t out_dsid;
+	prodcons_t queue;
+	transform_t transform;
+	double dx;
+	double dy;
+	double fx;
+	double fy;
+	double angle;
+	uint8_t opacity;
+	surface_t *surface;
+} window_t;
+
+static service_id_t winreg_id;
+static sysarg_t window_id = 0;
+static FIBRIL_MUTEX_INITIALIZE(window_list_mtx);
+static LIST_INITIALIZE(window_list);
+static double scale_back_x;
+static double scale_back_y;
+
+typedef struct {
+	link_t link;
+	service_id_t dsid;
+	vslmode_t mode;
+	async_sess_t *sess;
+	desktop_point_t pos;
+	surface_t *surface;
+} viewport_t;
+
+static FIBRIL_MUTEX_INITIALIZE(viewport_list_mtx);
+static LIST_INITIALIZE(viewport_list);
+
+/** Input server proxy */
+static input_t *input;
+
+static int comp_key_press(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
+static int comp_mouse_move(input_t *, int, int);
+static int comp_abs_move(input_t *, unsigned, unsigned, unsigned, unsigned);
+static int comp_mouse_button(input_t *, int, int);
+
+static input_ev_ops_t input_ev_ops = {
+	.key = comp_key_press,
+	.move = comp_mouse_move,
+	.abs_move = comp_abs_move,
+	.button = comp_mouse_button
+};
+
+static void input_disconnect(void);
+
+
+static pointer_t *input_pointer(input_t *input)
+{
+	return input->user;
+}
+
+static pointer_t *pointer_create()
+{
+	pointer_t *p = (pointer_t *) malloc(sizeof(pointer_t));
+	if (!p) {
+		return NULL;
+	}
+
+	link_initialize(&p->link);
+	p->pos.x = coord_origin;
+	p->pos.y = coord_origin;
+	p->btn_num = 1;
+	p->btn_pos = p->pos;
+	p->accum.x = 0;
+	p->accum.y = 0;
+	p->grab_flags = GF_EMPTY;
+	p->pressed = false;
+	p->state = 0;
+	cursor_init(&p->cursor, CURSOR_DECODER_EMBEDDED, NULL);
+
+	return p;
+}
+
+static void pointer_destroy(pointer_t *p)
+{
+	if (p) {
+		cursor_release(&p->cursor);
+		free(p);
+	}
+}
+
+static window_t *window_create()
+{
+	window_t *win = (window_t *) malloc(sizeof(window_t));
+	if (!win) {
+		return NULL;
+	}
+
+	link_initialize(&win->link);
+	prodcons_initialize(&win->queue);
+	transform_identity(&win->transform);
+	transform_translate(&win->transform, coord_origin, coord_origin);
+	win->dx = coord_origin;
+	win->dy = coord_origin;
+	win->fx = 1;
+	win->fy = 1;
+	win->angle = 0;
+	win->opacity = 255;
+	win->surface = NULL;
+
+	return win;
+}
+
+static void window_destroy(window_t *win)
+{
+	if (win) {
+		if (win->surface) {
+			surface_destroy(win->surface);
+		}
+		free(win);
+	}
+}
+
+static bool comp_coord_to_client(sysarg_t x_in, sysarg_t y_in, transform_t win_trans,
+    sysarg_t x_lim, sysarg_t y_lim, sysarg_t *x_out, sysarg_t *y_out)
+{
+	double x = x_in;
+	double y = y_in;
+	transform_invert(&win_trans);
+	transform_apply_affine(&win_trans, &x, &y);
+
+	/* Since client coordinate origin is (0, 0), it is necessary to check
+	 * coordinates to avoid underflow. Moreover, it is convenient to also
+	 * check against provided upper limits to determine whether the converted
+	 * coordinates are within the client window.  */
+	if (x < 0 || y < 0) {
+		return false;
+	} else {
+		(*x_out) = (sysarg_t) (x + 0.5);
+		(*y_out) = (sysarg_t) (y + 0.5);
+
+		if ((*x_out) >= x_lim || (*y_out) >= y_lim) {
+			return false;
+		} else {
+			return true;
+		}
+	}
+}
+
+static void comp_coord_from_client(sysarg_t x_in, sysarg_t y_in, transform_t win_trans,
+    sysarg_t *x_out, sysarg_t *y_out)
+{
+	double x = x_in;
+	double y = y_in;
+	transform_apply_affine(&win_trans, &x, &y);
+	
+	/* It is assumed that compositor coordinate origin is chosen in such way,
+	 * that underflow/overflow here would be unlikely. */
+	(*x_out) = (sysarg_t) (x + 0.5);
+	(*y_out) = (sysarg_t) (y + 0.5);
+}
+
+static void comp_coord_bounding_rect(sysarg_t x_in, sysarg_t y_in,
+    sysarg_t w_in, sysarg_t h_in, transform_t win_trans,
+    sysarg_t *x_out, sysarg_t *y_out, sysarg_t *w_out, sysarg_t *h_out)
+{
+	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, y_in, win_trans, &x[1], &y[1]);
+	comp_coord_from_client(x_in + w_in, y_in + h_in, win_trans, &x[2], &y[2]);
+	comp_coord_from_client(x_in, y_in + h_in, 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) {
+		(*x_out) = (x[i] < (*x_out)) ? x[i] : (*x_out);
+		(*y_out) = (y[i] < (*y_out)) ? y[i] : (*y_out);
+		(*w_out) = (x[i] > (*w_out)) ? x[i] : (*w_out);
+		(*h_out) = (y[i] > (*h_out)) ? y[i] : (*h_out);
+	}
+	(*w_out) -= (*x_out);
+	(*h_out) -= (*y_out);
+}
+
+static void comp_damage(sysarg_t x_dmg_glob, sysarg_t y_dmg_glob,
+    sysarg_t w_dmg_glob, sysarg_t h_dmg_glob)
+{
+	fibril_mutex_lock(&viewport_list_mtx);
+	fibril_mutex_lock(&window_list_mtx);
+	fibril_mutex_lock(&pointer_list_mtx);
+
+	list_foreach(viewport_list, link) {
+
+		/* Determine what part of the viewport must be updated. */
+		viewport_t *vp = list_get_instance(link, viewport_t, link);
+		sysarg_t x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp;
+		surface_get_resolution(vp->surface, &w_dmg_vp, &h_dmg_vp);
+		bool isec_vp = rectangle_intersect(
+		    x_dmg_glob, y_dmg_glob, w_dmg_glob, h_dmg_glob,
+		    vp->pos.x, vp->pos.y, w_dmg_vp, h_dmg_vp,
+		    &x_dmg_vp, &y_dmg_vp, &w_dmg_vp, &h_dmg_vp);
+
+		if (isec_vp) {
+
+			/* Paint background color. */
+			for (sysarg_t y = y_dmg_vp - vp->pos.y; y <  y_dmg_vp - vp->pos.y + h_dmg_vp; ++y) {
+				for (sysarg_t x = x_dmg_vp - vp->pos.x; x < x_dmg_vp - vp->pos.x + w_dmg_vp; ++x) {
+					surface_put_pixel(vp->surface, x, y, bg_color);
+				}
+			}
+
+			transform_t transform;
+			source_t source;
+			drawctx_t context;
+
+			source_init(&source);
+			source_set_filter(&source, filter_nearest);
+			drawctx_init(&context, vp->surface);
+			drawctx_set_compose(&context, compose_over);
+			drawctx_set_source(&context, &source);
+
+			/* For each window. */
+			for (link_t *link = window_list.head.prev;
+			    link != &window_list.head; link = link->prev) {
+
+				/* Determine what part of the window intersects with the
+				 * updated area of the current viewport. */
+				window_t *win = list_get_instance(link, window_t, link);
+				if (!win->surface) {
+					continue;
+				}
+				sysarg_t x_dmg_win, y_dmg_win, w_dmg_win, h_dmg_win;
+				surface_get_resolution(win->surface, &w_dmg_win, &h_dmg_win);
+				comp_coord_bounding_rect(0, 0, w_dmg_win, h_dmg_win, win->transform,
+				    &x_dmg_win, &y_dmg_win, &w_dmg_win, &h_dmg_win);
+				bool isec_win = rectangle_intersect(
+				    x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp,
+				    x_dmg_win, y_dmg_win, w_dmg_win, h_dmg_win,
+				    &x_dmg_win, &y_dmg_win, &w_dmg_win, &h_dmg_win);
+
+				if (isec_win) {
+					/* Prepare conversion from global coordinates to viewport
+					 * coordinates. */
+					transform = win->transform;
+					double_point_t pos;
+					pos.x = vp->pos.x;
+					pos.y = vp->pos.y;
+					transform_translate(&transform, -pos.x, -pos.y);
+
+					source_set_transform(&source, transform);				
+					source_set_texture(&source, win->surface, false);
+					source_set_alpha(&source, PIXEL(win->opacity, 0, 0, 0));
+
+					drawctx_transfer(&context,
+					    x_dmg_win - vp->pos.x, y_dmg_win - vp->pos.y, w_dmg_win, h_dmg_win);
+				}
+			}
+
+			list_foreach(pointer_list, link) {
+
+				/* Determine what part of the pointer intersects with the
+				 * updated area of the current viewport. */
+				pointer_t *ptr = list_get_instance(link, pointer_t, link);
+				sysarg_t x_dmg_ptr, y_dmg_ptr, w_dmg_ptr, h_dmg_ptr;
+				surface_t *sf_ptr = ptr->cursor.states[ptr->state];
+				surface_get_resolution(sf_ptr, &w_dmg_ptr, &h_dmg_ptr);
+				bool isec_ptr = rectangle_intersect(
+				    x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp,
+				    ptr->pos.x, ptr->pos.y, w_dmg_ptr, h_dmg_ptr,
+				    &x_dmg_ptr, &y_dmg_ptr, &w_dmg_ptr, &h_dmg_ptr);
+
+				if (isec_ptr) {
+					/* Pointer is currently painted directly by copying pixels.
+					 * However, it is possible to draw the painter similarly
+					 * as window by using drawctx_transfer. It would allow
+					 * more sophisticated control over drawing, but would also
+					 * cost more regarding the performance. */
+
+					pixel_t pix = 0;
+					sysarg_t x_vp = x_dmg_ptr - vp->pos.x;
+					sysarg_t y_vp = y_dmg_ptr - vp->pos.y;
+					sysarg_t x_ptr = x_dmg_ptr - ptr->pos.x;
+					sysarg_t y_ptr = y_dmg_ptr - ptr->pos.y;
+
+					for (sysarg_t y = 0; y < h_dmg_ptr; ++y) {
+						for (sysarg_t x = 0; x < w_dmg_ptr; ++x) {
+							pix = surface_get_pixel(sf_ptr, x_ptr + x, y_ptr + y);
+							if (ALPHA(pix) == 255) {
+								surface_put_pixel(vp->surface, x_vp + x, y_vp + y, pix);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	fibril_mutex_unlock(&pointer_list_mtx);
+	fibril_mutex_unlock(&window_list_mtx);
+
+	/* Notify visualizers about updated regions. */
+	list_foreach(viewport_list, link) {
+		viewport_t *vp = list_get_instance(link, viewport_t, link);
+		sysarg_t x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp;
+		surface_get_damaged_region(vp->surface, &x_dmg_vp, &y_dmg_vp, &w_dmg_vp, &h_dmg_vp);
+		surface_reset_damaged_region(vp->surface);
+		visualizer_update_damaged_region(
+		    vp->sess, x_dmg_vp, y_dmg_vp, w_dmg_vp, h_dmg_vp, 0, 0);
+	}
+
+	fibril_mutex_unlock(&viewport_list_mtx);
+}
+
+static void comp_window_get_event(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
+{
+	window_event_t *event = (window_event_t *) prodcons_consume(&win->queue);
+
+	ipc_callid_t callid;
+	size_t len;
+
+	if (!async_data_read_receive(&callid, &len)) {
+		async_answer_0(iid, EINVAL);
+		free(event);
+		return;
+	}
+	int rc = async_data_read_finalize(callid, event, len);
+	if (rc != EOK) {
+		async_answer_0(iid, ENOMEM);
+		free(event);
+		return;
+	}
+	async_answer_0(iid, EOK);
+	
+	free(event);
+}
+
+static void comp_window_damage(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
+{
+	sysarg_t x = IPC_GET_ARG1(*icall);
+	sysarg_t y = IPC_GET_ARG2(*icall);
+	sysarg_t width = IPC_GET_ARG3(*icall);
+	sysarg_t height = IPC_GET_ARG4(*icall);
+
+	if (width == 0 || height == 0) {
+		comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
+	} else {
+		fibril_mutex_lock(&window_list_mtx);
+		comp_coord_bounding_rect(x, y, width, height,
+		    win->transform, &x, &y, &width, &height);
+		fibril_mutex_unlock(&window_list_mtx);
+		comp_damage(x, y, width, height);
+	}
+
+	async_answer_0(iid, EOK);
+}
+
+static void comp_window_grab(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
+{
+	sysarg_t pos_id = IPC_GET_ARG1(*icall);
+	sysarg_t grab_flags = IPC_GET_ARG2(*icall);
+
+	fibril_mutex_lock(&pointer_list_mtx);
+	list_foreach(pointer_list, link) {
+		pointer_t *pointer = list_get_instance(link, pointer_t, link);
+		if (pointer->id == pos_id) {
+			pointer->grab_flags = grab_flags;
+			// TODO change pointer->state according to grab_flags
+			break;
+		}
+	}
+	fibril_mutex_unlock(&pointer_list_mtx);
+
+	if ((grab_flags & GF_RESIZE_X) || (grab_flags & GF_RESIZE_Y)) {
+		scale_back_x = 1;
+		scale_back_y = 1;
+	}
+
+	async_answer_0(iid, EOK);
+}
+
+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)) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	void *new_cell_storage;
+	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);
+	if (!new_surface) {
+		as_area_destroy(new_cell_storage);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	/* 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);
+
+	fibril_mutex_unlock(&window_list_mtx);
+
+	comp_damage(x, y, width, height);
+
+	async_answer_0(iid, EOK);
+}
+
+static void comp_window_close(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
+{
+	/* Stop managing the window. */
+	fibril_mutex_lock(&window_list_mtx);
+	list_remove(&win->link);
+	fibril_mutex_unlock(&window_list_mtx);
+
+	/* Calculate damage. */
+	sysarg_t x = 0;
+	sysarg_t y = 0;
+	sysarg_t width = 0;
+	sysarg_t height = 0;
+	if (win->surface) {
+		surface_get_resolution(win->surface, &width, &height);
+		comp_coord_bounding_rect(
+		    0, 0, width, height, win->transform, &x, &y, &width, &height);
+	}
+
+	/* Release window resources. */
+	loc_service_unregister(win->in_dsid);
+	loc_service_unregister(win->out_dsid);
+	while (!list_empty(&win->queue.list)) {
+		list_remove(list_first(&win->queue.list));
+	}
+	window_destroy(win);
+
+	comp_damage(x, y, width, height);
+
+	async_answer_0(iid, EOK);
+}
+
+static void comp_window_close_request(window_t *win, ipc_callid_t iid, ipc_call_t *icall)
+{
+    window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
+	if (event == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	link_initialize(&event->link);
+	event->type = ET_WINDOW_CLOSE;
+
+	prodcons_produce(&win->queue, &event->link);
+	async_answer_0(iid, EOK);
+}
+
+static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ipc_call_t call;
+	ipc_callid_t callid;
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*icall);
+
+	/* Allocate resources for new window and register it to the location service. */
+	if (service_id == winreg_id) {
+		async_answer_0(iid, EOK);
+
+		callid = async_get_call(&call);
+		if (IPC_GET_IMETHOD(call) == WINDOW_REGISTER) {
+			fibril_mutex_lock(&window_list_mtx);
+
+			window_t *win = window_create();
+			if (!win) {
+				async_answer_2(callid, ENOMEM, 0, 0);
+				return;
+			}
+
+			char name_in[LOC_NAME_MAXLEN + 1];
+			snprintf(name_in, LOC_NAME_MAXLEN, "%s%s/win%zuin", NAMESPACE,
+			    server_name, window_id);
+
+			char name_out[LOC_NAME_MAXLEN + 1];
+			snprintf(name_out, LOC_NAME_MAXLEN, "%s%s/win%zuout", NAMESPACE,
+			    server_name, window_id);
+
+			++window_id;
+
+			if (loc_service_register(name_in, &win->in_dsid) != EOK) {
+				window_destroy(win);
+				async_answer_2(callid, EINVAL, 0, 0);
+				return;
+			}
+
+			if (loc_service_register(name_out, &win->out_dsid) != EOK) {
+				loc_service_unregister(win->in_dsid);
+				window_destroy(win);
+				async_answer_2(callid, EINVAL, 0, 0);
+				return;
+			}
+
+			list_prepend(&win->link, &window_list);
+			
+			async_answer_2(callid, EOK, win->in_dsid, win->out_dsid);
+			fibril_mutex_unlock(&window_list_mtx);
+			return;
+		} else {
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+	}
+
+	/* Match the client with pre-allocated window. */
+	window_t *win = NULL;
+	fibril_mutex_lock(&window_list_mtx);
+	list_foreach(window_list, link) {
+		window_t *cur = list_get_instance(link, window_t, link);
+		if (cur->in_dsid == service_id || cur->out_dsid == service_id) {
+			win = cur;
+			break;
+		}
+	}
+	fibril_mutex_unlock(&window_list_mtx);
+
+	if (win) {
+		async_answer_0(iid, EOK);
+	} else {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	/* Each client establishes two separate connections. */
+	if (win->in_dsid == service_id) {
+		while (true) {
+			callid = async_get_call(&call);
+
+			if (!IPC_GET_IMETHOD(call)) {
+				async_answer_0(callid, EINVAL);
+				return;
+			}
+
+			switch (IPC_GET_IMETHOD(call)) {
+			case WINDOW_GET_EVENT:
+				comp_window_get_event(win, callid, &call);
+				break;
+			default:
+				async_answer_0(callid, EINVAL);
+			}
+		}
+	} else if (win->out_dsid == service_id) {
+		while (true) {
+			callid = async_get_call(&call);
+
+			if (!IPC_GET_IMETHOD(call)) {
+				async_answer_0(callid, EINVAL);
+				return;
+			}
+
+			switch (IPC_GET_IMETHOD(call)) {
+			case WINDOW_DAMAGE:
+				comp_window_damage(win, callid, &call);
+				break;
+			case WINDOW_GRAB:
+				comp_window_grab(win, callid, &call);
+				break;
+			case WINDOW_RESIZE:
+				comp_window_resize(win, callid, &call);
+				break;
+			case WINDOW_CLOSE:
+				comp_window_close(win, callid, &call);
+				break;
+			case WINDOW_CLOSE_REQUEST:
+				comp_window_close_request(win, callid, &call);
+				break;
+			default:
+				async_answer_0(callid, EINVAL);
+			}
+		}
+	}
+}
+
+static void comp_mode_change(viewport_t *vp, ipc_callid_t iid, ipc_call_t *icall)
+{
+	int rc;
+	sysarg_t mode_idx = IPC_GET_ARG2(*icall);
+	fibril_mutex_lock(&viewport_list_mtx);
+
+	/* Retrieve the mode that shall be set. */
+	vslmode_t new_mode;
+	rc = visualizer_get_mode(vp->sess, &new_mode, mode_idx);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&viewport_list_mtx);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	/* Create surface with respect to the retrieved mode. */
+	surface_t *new_surface = surface_create(new_mode.screen_width, 
+	    new_mode.screen_height, NULL, SURFACE_FLAG_SHARED);
+	if (!new_surface) {
+		fibril_mutex_unlock(&viewport_list_mtx);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	/* Try to set the mode and share out the surface. */
+	rc = visualizer_set_mode(vp->sess,
+		new_mode.index, new_mode.version, surface_direct_access(new_surface));
+	if (rc != EOK) {
+		surface_destroy(new_surface);
+		fibril_mutex_unlock(&viewport_list_mtx);
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	/* Destroy old surface and update viewport. */
+	surface_destroy(vp->surface);
+	vp->mode = new_mode;
+	vp->surface = new_surface;
+
+	fibril_mutex_unlock(&viewport_list_mtx);
+	async_answer_0(iid, EOK);
+
+	comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
+}
+
+static void viewport_destroy(viewport_t *vp)
+{
+	if (vp) {
+		visualizer_yield(vp->sess);
+		surface_destroy(vp->surface);
+		async_hangup(vp->sess);
+		free(vp);
+	}
+}
+
+static void comp_visualizer_disconnect(viewport_t *vp, ipc_callid_t iid, ipc_call_t *icall)
+{
+	/* Release viewport resources. */
+	fibril_mutex_lock(&viewport_list_mtx);
+	list_remove(&vp->link);
+	viewport_destroy(vp);
+
+	/* Terminate compositor if there are no more viewports. */
+	if (list_empty(&viewport_list)) {
+		fibril_mutex_unlock(&viewport_list_mtx);
+		loc_service_unregister(winreg_id);
+		input_disconnect();
+
+		/* Close all clients and their windows. */
+		fibril_mutex_lock(&window_list_mtx);
+		list_foreach(window_list, link) {
+			window_t *win = list_get_instance(link, window_t, link);
+			window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
+			if (event) {
+				link_initialize(&event->link);
+				event->type = WINDOW_CLOSE;
+				prodcons_produce(&win->queue, &event->link);
+			}
+		}
+		fibril_mutex_unlock(&window_list_mtx);
+
+		async_answer_0(iid, EOK);
+
+		/* All fibrils of the compositor will terminate soon. */
+	} else {
+		fibril_mutex_unlock(&viewport_list_mtx);
+		async_answer_0(iid, EOK);
+	}
+}
+
+static void vsl_notifications(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	viewport_t *vp = NULL;
+	fibril_mutex_lock(&viewport_list_mtx);
+	list_foreach(viewport_list, link) {
+		viewport_t *cur = list_get_instance(link, viewport_t, link);
+		if (cur->dsid == (service_id_t) IPC_GET_ARG1(*icall)) {
+			vp = cur;
+			break;
+		}
+	}
+	fibril_mutex_unlock(&viewport_list_mtx);
+
+	if (!vp) {
+		return;
+	}
+
+	/* Ignore parameters, the connection is already opened. */
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			async_hangup(vp->sess);
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case VISUALIZER_MODE_CHANGE:
+			comp_mode_change(vp, callid, &call);
+			break;
+		case VISUALIZER_DISCONNECT:
+			comp_visualizer_disconnect(vp, callid, &call);
+			return;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
+}
+
+static async_sess_t *vsl_connect(const char *svc)
+{
+	int rc;
+	async_sess_t *sess;
+	service_id_t dsid;
+	devman_handle_t handle;
+
+	rc = loc_service_get_id(svc, &dsid, 0);
+	if (rc != EOK) {
+		return NULL;
+	}
+
+	rc = devman_fun_sid_to_handle(dsid, &handle);
+	if (rc == EOK) {
+		sess = devman_device_connect(EXCHANGE_SERIALIZE, handle, 0);
+		if (sess == NULL) {
+			printf("%s: Unable to connect to visualizer %s\n", NAME, svc);
+			return NULL;
+		}
+		rc = graph_dev_connect(sess);
+		if (rc != EOK) {
+			return NULL;
+		}
+	} else if (rc == ENOENT) {
+		sess = loc_service_connect(EXCHANGE_SERIALIZE, dsid, 0);
+		if (sess == NULL) {
+			printf("%s: Unable to connect to visualizer %s\n", NAME, svc);
+			return NULL;
+		}
+	} else {
+		return NULL;
+	}
+
+	async_exch_t *exch = async_exchange_begin(sess);
+	rc = async_connect_to_me(exch, dsid, 0, 0, vsl_notifications, NULL);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_hangup(sess);
+		printf("%s: Unable to create callback connection to service %s (%s)\n",
+		    NAME, svc, str_error(rc));
+		return NULL;
+	}
+
+	return sess;
+}
+
+static viewport_t *viewport_create(const char *vsl_name)
+{
+	int rc;
+
+	viewport_t *vp = (viewport_t *) malloc(sizeof(viewport_t));
+	if (!vp) {
+		return NULL;
+	}
+
+	link_initialize(&vp->link);
+	vp->pos.x = coord_origin;
+	vp->pos.y = coord_origin;
+
+	/* Establish output bidirectional connection. */
+	vp->sess = vsl_connect(vsl_name);
+	rc = loc_service_get_id(vsl_name, &vp->dsid, 0);
+	if (vp->sess == NULL || rc != EOK) {
+		free(vp);
+		return NULL;
+	}
+
+	/* Claim the given visualizer. */
+	rc = visualizer_claim(vp->sess, 0);
+	if (rc != EOK) {
+		async_hangup(vp->sess);
+		free(vp);
+		printf("%s: Unable to claim visualizer (%s)\n", NAME, str_error(rc));
+		return NULL;
+	}
+
+	/* Retrieve the default mode. */
+	rc = visualizer_get_default_mode(vp->sess, &vp->mode);
+	if (rc != EOK) {
+		visualizer_yield(vp->sess);
+		async_hangup(vp->sess);
+		free(vp);
+		printf("%s: Unable to retrieve mode (%s)\n", NAME, str_error(rc));
+		return NULL;
+	}
+
+	/* Create surface with respect to the retrieved mode. */
+	vp->surface = surface_create(vp->mode.screen_width, vp->mode.screen_height,
+	    NULL, SURFACE_FLAG_SHARED);
+	if (vp->surface == NULL) {
+		visualizer_yield(vp->sess);
+		async_hangup(vp->sess);
+		free(vp);
+		printf("%s: Unable to create surface (%s)\n", NAME, str_error(rc));
+		return NULL;
+	}
+
+	/* Try to set the mode and share out the surface. */
+	rc = visualizer_set_mode(vp->sess,
+		vp->mode.index, vp->mode.version, surface_direct_access(vp->surface));
+	if (rc != EOK) {
+		visualizer_yield(vp->sess);
+		surface_destroy(vp->surface);
+		async_hangup(vp->sess);
+		free(vp);
+		printf("%s: Unable to set mode (%s)\n", NAME, str_error(rc));
+		return NULL;
+	}
+
+	return vp;
+}
+
+static void comp_post_event(window_event_t *event)
+{
+	fibril_mutex_lock(&window_list_mtx);
+	window_t *win = (window_t *) list_first(&window_list);
+	if (win) {
+		prodcons_produce(&win->queue, &event->link);
+	} else {
+		free(event);
+	}
+	fibril_mutex_unlock(&window_list_mtx);
+}
+
+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);
+	transform_scale(&scale, win->fx, win->fy);
+
+	transform_t rotate;
+	transform_identity(&rotate);
+	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)
+{
+	/* window_list_mtx locked by caller */
+
+	int dx = pointer->accum.x;
+	int dy = pointer->accum.y;
+	pointer->accum.x = 0;
+	pointer->accum.y = 0;
+
+	bool move = (pointer->grab_flags & GF_MOVE_X) || (pointer->grab_flags & GF_MOVE_Y);
+	bool scale = (pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_SCALE_Y);
+	bool resize = (pointer->grab_flags & GF_RESIZE_X) || (pointer->grab_flags & GF_RESIZE_Y);
+
+	sysarg_t width, height;
+	surface_get_resolution(win->surface, &width, &height);
+
+	if (move) {
+		double cx = 0;
+		double cy = 0;
+		if (pointer->grab_flags & GF_MOVE_X) {
+			cx = 1;
+		}
+		if (pointer->grab_flags & GF_MOVE_Y) {
+			cy = 1;
+		}
+
+		if (scale || resize) {
+			transform_t rotate;
+			transform_identity(&rotate);
+			transform_rotate(&rotate, win->angle);
+			transform_apply_linear(&rotate, &cx, &cy);
+		}
+		
+		cx = (cx < 0) ? (-1 * cx) : cx; 
+		cy = (cy < 0) ? (-1 * cy) : cy;
+
+		win->dx += (cx * dx);
+		win->dy += (cy * dy);
+	}
+
+	if (scale || resize) {
+		double _dx = dx;
+		double _dy = dy;
+		transform_t unrotate;
+		transform_identity(&unrotate);
+		transform_rotate(&unrotate, -win->angle);
+		transform_apply_linear(&unrotate, &_dx, &_dy);
+		_dx = (pointer->grab_flags & GF_MOVE_X) ? -_dx : _dx;
+		_dy = (pointer->grab_flags & GF_MOVE_Y) ? -_dy : _dy;
+
+		if ((pointer->grab_flags & GF_SCALE_X) || (pointer->grab_flags & GF_RESIZE_X)) {
+			double fx = 1.0 + (_dx / (width * win->fx));
+			if (fx > 0) {
+				win->fx *= fx;
+				scale_back_x *= fx;
+			}
+		}
+
+		if ((pointer->grab_flags & GF_SCALE_Y) || (pointer->grab_flags & GF_RESIZE_Y)) {
+			double fy = 1.0 + (_dy / (height * win->fy));
+			if (fy > 0) {
+				win->fy *= fy;
+				scale_back_y *= fy;
+			}
+		}
+	}
+
+	sysarg_t x1, y1, width1, height1;
+	sysarg_t x2, y2, width2, height2;
+	comp_coord_bounding_rect(0, 0, width, height, win->transform,
+	    &x1, &y1, &width1, &height1);
+	comp_recalc_transform(win);
+	comp_coord_bounding_rect(0, 0, width, height, win->transform,
+	    &x2, &y2, &width2, &height2);
+	rectangle_union(x1, y1, width1, height1, x2, y2, width2, height2,
+	    dmg_x, dmg_y, dmg_width, dmg_height);
+}
+
+static int comp_abs_move(input_t *input, unsigned x , unsigned y,
+    unsigned max_x, unsigned max_y)
+{
+	/* XXX TODO Use absolute coordinates directly */
+	
+	pointer_t *pointer = input_pointer(input);
+	
+	sysarg_t width, height;
+	
+	fibril_mutex_lock(&viewport_list_mtx);
+	if (list_empty(&viewport_list)) {
+		printf("No viewport found\n");
+		fibril_mutex_unlock(&viewport_list_mtx);
+		return EOK; /* XXX */
+	}
+	link_t *link = list_first(&viewport_list);
+	viewport_t *vp = list_get_instance(link, viewport_t, link);
+	surface_get_resolution(vp->surface, &width, &height);
+	desktop_point_t vp_pos = vp->pos;
+	fibril_mutex_unlock(&viewport_list_mtx);
+
+	desktop_point_t pos_in_viewport;
+	pos_in_viewport.x = x * width / max_x;
+	pos_in_viewport.y = y * height / max_y;
+	
+	/* Calculate offset from pointer */
+	fibril_mutex_lock(&pointer_list_mtx);
+	desktop_vector_t delta;
+	delta.x = (vp_pos.x + pos_in_viewport.x) - pointer->pos.x;
+	delta.y = (vp_pos.y + pos_in_viewport.y) - pointer->pos.y;
+	fibril_mutex_unlock(&pointer_list_mtx);
+	
+	return comp_mouse_move(input, delta.x, delta.y);
+}
+
+static int comp_mouse_move(input_t *input, int dx, int dy)
+{
+	pointer_t *pointer = input_pointer(input);
+
+	/* 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], 
+	     &cursor_width, &cursor_height);
+	pointer->pos.x += dx;
+	pointer->pos.y += dy;
+	fibril_mutex_unlock(&pointer_list_mtx);
+	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);
+	window_t *top = (window_t *) list_first(&window_list);
+	if (top && top->surface) {
+
+		if (pointer->grab_flags == GF_EMPTY) {
+			/* Notify top-level window about move event. */
+			bool within_client = false;
+			sysarg_t point_x, point_y;
+			sysarg_t width, height;
+			surface_get_resolution(top->surface, &width, &height);
+			within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
+			    top->transform, width, height, &point_x, &point_y);
+			fibril_mutex_unlock(&window_list_mtx);
+
+			if (within_client) {
+				window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
+				if (event) {
+					link_initialize(&event->link);
+					event->type = ET_POSITION_EVENT;
+					event->data.pos.pos_id = pointer->id;
+					event->data.pos.type = POS_UPDATE;
+					event->data.pos.btn_num = pointer->btn_num;
+					event->data.pos.hpos = point_x;
+					event->data.pos.vpos = point_y;
+					comp_post_event(event);
+				}
+			}
+		} else {
+			/* Pointer is grabbed by top-level window action. */
+			pointer->accum.x += dx;
+			pointer->accum.y += dy;
+#if ANIMATE_WINDOW_TRANSFORMS == 1
+			sysarg_t x, y, width, height;
+			comp_window_animate(pointer, top, &x, &y, &width, &height);
+#endif
+			fibril_mutex_unlock(&window_list_mtx);
+#if ANIMATE_WINDOW_TRANSFORMS == 1
+			comp_damage(x, y, width, height);
+#endif
+		}
+	} else {
+		fibril_mutex_unlock(&window_list_mtx);
+	}
+
+	return EOK;
+}
+
+static int comp_mouse_button(input_t *input, int bnum, int bpress)
+{
+	pointer_t *pointer = input_pointer(input);
+
+	if (bpress) {
+		pointer->btn_pos = pointer->pos;
+		pointer->btn_num = bnum;
+		pointer->pressed = true;
+
+		/* Check whether mouse press belongs to the top-level window. */
+		fibril_mutex_lock(&window_list_mtx);
+		window_t *win = (window_t *) list_first(&window_list);
+		if (!win || !win->surface) {
+			fibril_mutex_unlock(&window_list_mtx);
+			return EOK;
+		}
+		sysarg_t x, y, width, height;
+		surface_get_resolution(win->surface, &width, &height);
+		bool within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
+		    win->transform, width, height, &x, &y);
+		fibril_mutex_unlock(&window_list_mtx);
+
+		/* Send mouse press to the top-level window. */
+		if (within_client) {
+			window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
+			if (event) {
+				link_initialize(&event->link);
+				event->type = ET_POSITION_EVENT;
+				event->data.pos.pos_id = pointer->id;
+				event->data.pos.type = POS_PRESS;
+				event->data.pos.btn_num = bnum;
+				event->data.pos.hpos = x;
+				event->data.pos.vpos = y;
+				comp_post_event(event);
+			} else {
+				return ENOMEM;
+			}
+		}
+	} else if (pointer->pressed && pointer->btn_num == (unsigned)bnum) {
+		pointer->pressed = false;
+
+		fibril_mutex_lock(&window_list_mtx);
+		window_t *win = NULL;
+		sysarg_t point_x = 0;
+		sysarg_t point_y = 0;
+		sysarg_t width, height;
+		bool within_client = false;
+
+		/* Determine the window which the mouse release belongs to. */
+		list_foreach(window_list, link) {
+			win = list_get_instance(link, window_t, link);
+			if (win->surface) {
+				surface_get_resolution(win->surface, &width, &height);
+				within_client = comp_coord_to_client(pointer->pos.x, pointer->pos.y,
+				    win->transform, width, height, &point_x, &point_y);
+			}
+			if (within_client) {
+				break;
+			}
+		}
+
+		/* Check whether the window is top-level window. */
+		window_t *top = (window_t *) list_first(&window_list);
+		if (!win || !top) {
+			pointer->grab_flags = GF_EMPTY;
+			fibril_mutex_unlock(&window_list_mtx);
+			return EOK;
+		}
+
+		window_event_t *event = NULL;
+		sysarg_t dmg_x, dmg_y;
+		sysarg_t dmg_width = 0;
+		sysarg_t dmg_height = 0;
+
+		sysarg_t pre_x = 0; 
+		sysarg_t pre_y = 0;
+		sysarg_t pre_width = 0;
+		sysarg_t pre_height = 0;
+
+#if ANIMATE_WINDOW_TRANSFORMS == 0
+		if (pointer->grab_flags != GF_EMPTY) {
+			comp_window_animate(pointer, top, &pre_x, &pre_y, &pre_width, &pre_height);
+			dmg_x = pre_x;
+			dmg_y = pre_y;
+			dmg_width = pre_width;
+			dmg_height = pre_height;
+		}
+#endif
+
+		if ((pointer->grab_flags & GF_RESIZE_X) || (pointer->grab_flags & GF_RESIZE_Y)) {
+
+			surface_get_resolution(top->surface, &width, &height);
+			top->fx *= (1.0 / scale_back_x);
+			top->fy *= (1.0 / scale_back_y);
+			comp_recalc_transform(top);
+
+			/* Commit proper resize action. */
+			event = (window_event_t *) malloc(sizeof(window_event_t));
+			if (event) {
+				link_initialize(&event->link);
+				event->type = ET_WINDOW_RESIZE;
+
+				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->data.rsz.width =
+						((((int) width) + dx) >= 0) ? (width + dx) : 0;
+				} else {
+					event->data.rsz.width = width;
+				}
+
+				if (pointer->grab_flags & GF_RESIZE_Y) {
+					event->data.rsz.height =
+						((((int) height) + dy) >= 0) ? (height + dy) : 0;
+				} else {
+					event->data.rsz.height = height;
+				}
+			}
+
+			pointer->grab_flags = GF_EMPTY;
+
+		} else if (within_client && (pointer->grab_flags == GF_EMPTY) && (top == win)) {
+			
+			/* Notify top-level window about mouse release. */
+			event = (window_event_t *) malloc(sizeof(window_event_t));
+			if (event) {
+				link_initialize(&event->link);
+				event->type = ET_POSITION_EVENT;
+				event->data.pos.pos_id = pointer->id;
+				event->data.pos.type = POS_RELEASE;
+				event->data.pos.btn_num = bnum;
+				event->data.pos.hpos = point_x;
+				event->data.pos.vpos = point_y;
+			}
+			pointer->grab_flags = GF_EMPTY;
+			
+		} else if (within_client && (pointer->grab_flags == GF_EMPTY) && (bnum == 1)) {
+
+			/* Bring the window to the foreground. */
+			list_remove(&win->link);
+			list_prepend(&win->link, &window_list);
+			comp_coord_bounding_rect(0, 0, width, height, win->transform,
+			    &dmg_x, &dmg_y, &dmg_width, &dmg_height);
+			
+		} else {
+			pointer->grab_flags = GF_EMPTY;
+		}
+
+		fibril_mutex_unlock(&window_list_mtx);
+
+		if (dmg_width > 0 && dmg_height > 0) {
+			comp_damage(dmg_x, dmg_y, dmg_width, dmg_height);
+		}
+
+		if (event) {
+			comp_post_event(event);
+		}
+	}
+
+	return EOK;
+}
+
+static int comp_key_press(input_t *input, kbd_event_type_t type, keycode_t key,
+    keymod_t mods, wchar_t c)
+{
+	bool win_transform = (mods & KM_ALT) && (
+	    key == KC_W || key == KC_S || key == KC_A || key == KC_D ||
+	    key == KC_Q || key == KC_E || key == KC_R || key == KC_F);
+	bool win_resize = (mods & KM_ALT) && (
+	    key == KC_T || key == KC_G || key == KC_B || key == KC_N);
+	bool win_opacity = (mods & KM_ALT) && (
+	    key == KC_C || key == KC_V);
+	bool win_close = (mods & KM_ALT) && (key == KC_X);
+	bool win_switch = (mods & KM_ALT) && (key == KC_TAB);
+	bool viewport_move = (mods & KM_ALT) && (
+	    key == KC_I || key == KC_K || key == KC_J || key == KC_L);
+	bool viewport_change = (mods & KM_ALT) && (
+	    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);
+
+	if (filter) {
+		/* no-op */
+	} else if (win_transform) {
+		fibril_mutex_lock(&window_list_mtx);
+		window_t *win = (window_t *) list_first(&window_list);
+		if (win && win->surface) {
+			switch (key) {
+			case KC_W:
+				win->dy += -20;
+				break;
+			case KC_S:
+				win->dy += 20;
+				break;
+			case KC_A:
+				win->dx += -20;
+				break;
+			case KC_D:
+				win->dx += 20;
+				break;
+			case KC_Q:
+				win->angle += (PI / 2);
+				break;
+			case KC_E:
+				win->angle += -(PI / 2);
+				break;
+			case KC_R:
+				win->fx *= 0.95;
+				win->fy *= 0.95;
+				break;
+			case KC_F:
+				win->fx *= 1.05;
+				win->fy *= 1.05;
+				break;
+			default:
+				break;
+			}
+
+			/* Transform the window and calculate damage. */
+			sysarg_t x, y, width, height;
+			surface_get_resolution(win->surface, &width, &height);
+			sysarg_t x1, y1, width1, height1;
+			sysarg_t x2, y2, width2, height2;
+			comp_coord_bounding_rect(0, 0, width, height, win->transform,
+			    &x1, &y1, &width1, &height1);
+			comp_recalc_transform(win);
+			comp_coord_bounding_rect(0, 0, width, height, win->transform,
+			    &x2, &y2, &width2, &height2);
+			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);
+		} else {
+			fibril_mutex_unlock(&window_list_mtx);
+		}
+	} else if (win_resize) {
+		fibril_mutex_lock(&window_list_mtx);
+		window_t *win = (window_t *) list_first(&window_list);
+		if (win && win->surface) {
+			window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
+			if (event == NULL) {
+				fibril_mutex_unlock(&window_list_mtx);
+				return ENOMEM;
+			}
+
+			sysarg_t width, height;
+			surface_get_resolution(win->surface, &width, &height);
+
+			link_initialize(&event->link);
+			event->type = ET_WINDOW_RESIZE;
+
+			switch (key) {
+			case KC_T:
+				event->data.rsz.width = width;
+				event->data.rsz.height = (height >= 20) ? height - 20 : 0;
+				break;
+			case KC_G:
+				event->data.rsz.width = width;
+				event->data.rsz.height = height + 20;
+				break;
+			case KC_B:
+				event->data.rsz.width = (width >= 20) ? width - 20 : 0;;
+				event->data.rsz.height = height;
+				break;
+			case KC_N:
+				event->data.rsz.width = width + 20;
+				event->data.rsz.height = height;
+				break;
+			default:
+				event->data.rsz.width = 0;
+				event->data.rsz.height = 0;
+				break;
+			}
+
+			fibril_mutex_unlock(&window_list_mtx);
+			comp_post_event(event);
+		} else {
+			fibril_mutex_unlock(&window_list_mtx);
+		}
+	} else if (win_opacity) {
+		fibril_mutex_lock(&window_list_mtx);
+		window_t *win = (window_t *) list_first(&window_list);
+		if (win && win->surface) {
+			switch (key) {
+			case KC_C:
+				if (win->opacity > 0) {
+					win->opacity -= 5;
+				}
+				break;
+			case KC_V:
+				if (win->opacity < 255) {
+					win->opacity += 5;
+				}
+				break;
+			default:
+				break;
+			}
+
+			/* Calculate damage. */
+			sysarg_t x, y, width, height;
+			surface_get_resolution(win->surface, &width, &height);
+			comp_coord_bounding_rect(0, 0, width, height, win->transform,
+			    &x, &y, &width, &height);
+			fibril_mutex_unlock(&window_list_mtx);
+
+			comp_damage(x, y, width, height);
+		} else {
+			fibril_mutex_unlock(&window_list_mtx);
+		}
+	} else if (win_close) {
+		window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
+		if (event == NULL)
+			return ENOMEM;
+
+		link_initialize(&event->link);
+		event->type = ET_WINDOW_CLOSE;
+
+		comp_post_event(event);
+	} else if (win_switch) {
+		fibril_mutex_lock(&window_list_mtx);
+		if (!list_empty(&window_list)) {
+			window_t *win1 = (window_t *) list_first(&window_list);
+			list_remove(&win1->link);
+			list_append(&win1->link, &window_list);
+			window_t *win2 = (window_t *) list_first(&window_list);
+
+			sysarg_t x1 = 0;
+			sysarg_t y1 = 0;
+			sysarg_t width1 = 0;
+			sysarg_t height1 = 0;
+			if (win1->surface) {
+				sysarg_t width, height;
+				surface_get_resolution(win1->surface, &width, &height);
+				comp_coord_bounding_rect(0, 0, width, height, win1->transform,
+				    &x1, &y1, &width1, &height1);
+			}
+
+			sysarg_t x2 = 0;
+			sysarg_t y2 = 0;
+			sysarg_t width2 = 0;
+			sysarg_t height2 = 0;
+			if (win2->surface) {
+				sysarg_t width, height;
+				surface_get_resolution(win2->surface, &width, &height);
+				comp_coord_bounding_rect(0, 0, width, height, win2->transform,
+				    &x2, &y2, &width2, &height2);
+			}
+
+			sysarg_t x, y, width, 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);
+		} else {
+			fibril_mutex_unlock(&window_list_mtx);
+		}
+	} else if (viewport_move) {
+		fibril_mutex_lock(&viewport_list_mtx);
+		viewport_t *vp = (viewport_t *) list_first(&viewport_list);
+		if (vp) {
+			switch (key) {
+			case KC_I:
+				vp->pos.x += 0;
+				vp->pos.y += -20;
+				break;
+			case KC_K:
+				vp->pos.x += 0;
+				vp->pos.y += 20;
+				break;
+			case KC_J:
+				vp->pos.x += -20;
+				vp->pos.y += 0;
+				break;
+			case KC_L:
+				vp->pos.x += 20;
+				vp->pos.y += 0;
+				break;
+			default:
+				vp->pos.x += 0;
+				vp->pos.y += 0;
+				break;
+			}
+			
+			sysarg_t x = vp->pos.x;
+			sysarg_t y = vp->pos.y;
+			sysarg_t width, height;
+			surface_get_resolution(vp->surface, &width, &height);
+			fibril_mutex_unlock(&viewport_list_mtx);
+
+			comp_damage(x, y, width, height);
+		} else {
+			fibril_mutex_unlock(&viewport_list_mtx);
+		}
+	} else if (viewport_change) {
+		fibril_mutex_lock(&viewport_list_mtx);
+
+		viewport_t *vp;
+		switch (key) {
+		case KC_O:
+			vp = (viewport_t *) list_first(&viewport_list);
+			if (vp) {
+				list_remove(&vp->link);
+				list_append(&vp->link, &viewport_list);
+			}
+			break;
+		case KC_P:
+			vp = (viewport_t *) list_last(&viewport_list);
+			if (vp) {
+				list_remove(&vp->link);
+				list_prepend(&vp->link, &viewport_list);
+			}
+			break;
+		default:
+			break;
+		}
+
+		fibril_mutex_unlock(&viewport_list_mtx);
+	} 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();
+		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();
+		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 *helenos_win = window_create();
+		helenos_win->surface = decode_tga((void *) helenos_tga, helenos_tga_size, 0);
+		list_prepend(&helenos_win->link, &window_list);
+
+		window_t *nameic_win = window_create();
+		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));
+		if (event == NULL)
+			return ENOMEM;
+
+		link_initialize(&event->link);
+		event->type = ET_KEYBOARD_EVENT;
+		event->data.kbd.type = type;
+		event->data.kbd.key = key;
+		event->data.kbd.mods = mods;
+		event->data.kbd.c = c;
+
+		comp_post_event(event);
+	}
+
+	return EOK;
+}
+
+static int input_connect(const char *svc)
+{
+	async_sess_t *sess;
+	service_id_t dsid;
+
+	int rc = loc_service_get_id(svc, &dsid, 0);
+	if (rc != EOK) {
+		printf("%s: Input service %s not found\n", NAME, svc);
+		return rc;
+	}
+
+	sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
+	if (sess == NULL) {
+		printf("%s: Unable to connect to input service %s\n", NAME,
+		    svc);
+		return EIO;
+	}
+
+	fibril_mutex_lock(&pointer_list_mtx);
+	pointer_t *pointer = pointer_create();
+	if (pointer != NULL) {
+		pointer->id = pointer_id++;
+		list_append(&pointer->link, &pointer_list);
+	}
+	fibril_mutex_unlock(&pointer_list_mtx);
+
+	if (pointer == NULL) {
+		printf("%s: Cannot create pointer.\n", NAME);
+		async_hangup(sess);
+		return ENOMEM;
+	}
+
+	rc = input_open(sess, &input_ev_ops, pointer, &input);
+	if (rc != EOK) {
+		async_hangup(sess);
+		printf("%s: Unable to communicate with service %s (%s)\n",
+		    NAME, svc, str_error(rc));
+		return rc;
+	}
+
+	return EOK;
+}
+
+static void input_disconnect(void)
+{
+    	pointer_t *pointer = input->user;
+	input_close(input);
+	pointer_destroy(pointer);
+}
+
+static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
+{
+	comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
+}
+
+static int compositor_srv_init(char *input_svc, char *name)
+{
+	/* Coordinates of the central pixel. */
+	coord_origin = UINT32_MAX / 2;
+	
+	/* Color of the viewport background. Must be opaque. */
+	bg_color = PIXEL(255, 75, 70, 75);
+	
+	/* Register compositor server. */
+	async_set_client_connection(client_connection);
+	int rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		printf("%s: Unable to register server (%s)\n", NAME, str_error(rc));
+		return -1;
+	}
+	
+	/* Register interrupt handler to switch back from kconsole. */
+	async_set_interrupt_received(interrupt_received);
+	rc = event_subscribe(EVENT_KCONSOLE, 0);
+	if (rc != EOK) {
+		printf("%s: Failed to register kconsole notifications (%s)\n",
+		    NAME, str_error(rc));
+	}
+	
+	server_name = name;
+	
+	char svc[LOC_NAME_MAXLEN + 1];
+	snprintf(svc, LOC_NAME_MAXLEN, "%s/%s", NAMESPACE, server_name);
+	
+	service_id_t service_id;
+	rc = loc_service_register(svc, &service_id);
+	if (rc != EOK) {
+		printf("%s: Unable to register service %s\n", NAME, svc);
+		return rc;
+	}
+	
+	/* Prepare window registrator (entrypoint for clients). */
+	char winreg[LOC_NAME_MAXLEN + 1];
+	snprintf(winreg, LOC_NAME_MAXLEN, "%s%s/winreg", NAMESPACE, server_name);
+	if (loc_service_register(winreg, &winreg_id) != EOK) {
+		printf("%s: Unable to register service %s\n", NAME, winreg);
+		return -1;
+	}
+
+	/* Establish input bidirectional connection. */
+	rc = input_connect(input_svc);
+	if (rc != EOK)
+		return rc;
+
+	/* Create viewports and connect them to visualizers. */
+	category_id_t cat_id;
+	rc = loc_category_get_id("visualizer", &cat_id, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		input_disconnect();
+		return -1;
+	}
+	
+	service_id_t *svcs;
+	size_t svcs_cnt = 0;
+	rc = loc_category_get_svcs(cat_id, &svcs, &svcs_cnt);
+	if (rc != EOK || svcs_cnt == 0) {
+		input_disconnect();
+		return -1;
+	}
+	
+	for (size_t i = 0; i < svcs_cnt; ++i) {
+		char *svc_name;
+		rc = loc_service_get_name(svcs[i], &svc_name);
+		if (rc == EOK) {
+			viewport_t *vp = viewport_create(svc_name);
+			if (vp != NULL) {
+				list_append(&vp->link, &viewport_list);
+			}
+		}
+	}
+	
+	if (list_empty(&viewport_list)) {
+		input_disconnect();
+		return -1;
+	}
+	
+	comp_damage(0, 0, UINT32_MAX, UINT32_MAX);
+	
+	return EOK;
+}
+
+static void usage(char *name)
+{
+	printf("Usage: %s <input_dev> <server_name>\n", name);
+}
+
+int main(int argc, char *argv[])
+{
+	if (argc < 3) {
+		usage(argv[0]);
+		return 1;
+	}
+	
+	printf("%s: HelenOS Compositor server\n", NAME);
+	
+	int rc = compositor_srv_init(argv[1], argv[2]);
+	if (rc != EOK)
+		return rc;
+	
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
+	async_manager();
+	
+	/* Never reached */
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/srv/hid/compositor/compositor.h
===================================================================
--- uspace/srv/hid/compositor/compositor.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/compositor/compositor.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012 Petr Koupy
+ * 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 compositor
+ * @{
+ */
+/** @file
+ */
+
+#ifndef COMPOSITOR_COMPOSITOR_H_
+#define COMPOSITOR_COMPOSITOR_H_
+
+typedef native_t desktop_coord_t;
+typedef struct {
+	desktop_coord_t x;
+	desktop_coord_t y;
+} desktop_point_t;
+typedef desktop_point_t desktop_vector_t;
+
+/* TODO remove? */
+typedef struct {
+	double x;
+	double y;
+} double_point_t;
+typedef double_point_t double_vector_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/console/Makefile
===================================================================
--- uspace/srv/hid/console/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/console/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -29,31 +29,8 @@
 
 USPACE_PREFIX = ../../..
-LIBS = $(LIBFB_PREFIX)/libfb.a
-EXTRA_CFLAGS += -I$(LIBFB_PREFIX)
 BINARY = console
 
 SOURCES = \
-	console.c \
-	images.c
-
-IMAGES = \
-	gfx/helenos.tga \
-	gfx/nameic.tga \
-	gfx/cons_data.tga \
-	gfx/cons_dis.tga \
-	gfx/cons_dis_sel.tga \
-	gfx/cons_idle.tga \
-	gfx/cons_sel.tga \
-	gfx/cons_kernel.tga \
-	gfx/anim_1.tga \
-	gfx/anim_2.tga \
-	gfx/anim_3.tga \
-	gfx/anim_4.tga
-
-PRE_DEPEND = images.c images.h
-EXTRA_CLEAN = images.c images.h
+	console.c
 
 include $(USPACE_PREFIX)/Makefile.common
-
-images.c images.h: $(IMAGES)
-	$(ROOT_PATH)/tools/mkarray.py images CONSOLE_IMAGES $^
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/console/console.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,6 +36,5 @@
 #include <stdio.h>
 #include <adt/prodcons.h>
-#include <ipc/input.h>
-#include <ipc/console.h>
+#include <io/input.h>
 #include <ipc/vfs.h>
 #include <errno.h>
@@ -43,13 +42,13 @@
 #include <loc.h>
 #include <event.h>
+#include <io/con_srv.h>
+#include <io/kbd_event.h>
 #include <io/keycode.h>
-#include <screenbuffer.h>
-#include <fb.h>
-#include <imgmap.h>
+#include <io/chargrid.h>
+#include <io/output.h>
 #include <align.h>
 #include <malloc.h>
 #include <as.h>
 #include <fibril_synch.h>
-#include "images.h"
 #include "console.h"
 
@@ -57,63 +56,39 @@
 #define NAMESPACE  "term"
 
-#define CONSOLE_TOP     66
-#define CONSOLE_MARGIN  12
-
-#define STATE_START   100
-#define STATE_TOP     8
-#define STATE_SPACE   4
-#define STATE_WIDTH   48
-#define STATE_HEIGHT  48
-
-typedef enum {
-	CONS_DISCONNECTED = 0,
-	CONS_DISCONNECTED_SELECTED,
-	CONS_SELECTED,
-	CONS_IDLE,
-	CONS_DATA,
-	CONS_KERNEL,
-	CONS_LAST
-} console_state_t;
+#define UTF8_CHAR_BUFFER_SIZE  (STR_BOUNDS(1) + 1)
 
 typedef struct {
-	atomic_t refcnt;           /**< Connection reference count */
-	prodcons_t input_pc;       /**< Incoming keyboard events */
-	
-	fibril_mutex_t mtx;        /**< Lock protecting mutable fields */
-	
-	size_t index;              /**< Console index */
-	console_state_t state;     /**< Console state */
-	service_id_t dsid;         /**< Service handle */
-	
-	vp_handle_t state_vp;      /**< State icon viewport */
-	sysarg_t cols;             /**< Number of columns */
-	sysarg_t rows;             /**< Number of rows */
-	console_caps_t ccaps;      /**< Console capabilities */
-	
-	screenbuffer_t *frontbuf;  /**< Front buffer */
-	frontbuf_handle_t fbid;    /**< Front buffer handle */
+	atomic_t refcnt;      /**< Connection reference count */
+	prodcons_t input_pc;  /**< Incoming keyboard events */
+	
+	/**
+	 * Not yet sent bytes of last char event.
+	 */
+	char char_remains[UTF8_CHAR_BUFFER_SIZE];
+	size_t char_remains_len;  /**< Number of not yet sent bytes. */
+	
+	fibril_mutex_t mtx;  /**< Lock protecting mutable fields */
+	
+	size_t index;           /**< Console index */
+	service_id_t dsid;      /**< Service handle */
+	
+	sysarg_t cols;         /**< Number of columns */
+	sysarg_t rows;         /**< Number of rows */
+	console_caps_t ccaps;  /**< Console capabilities */
+	
+	chargrid_t *frontbuf;    /**< Front buffer */
+	frontbuf_handle_t fbid;  /**< Front buffer handle */
+	con_srvs_t srvs;         /**< Console service setup */
 } console_t;
 
-typedef enum {
-	GRAPHICS_NONE = 0,
-	GRAPHICS_BASIC = 1,
-	GRAPHICS_FULL = 2
-} graphics_state_t;
-
-/** Current console state */
-static graphics_state_t graphics_state = GRAPHICS_NONE;
-
-/** State icons */
-static imagemap_handle_t state_icons[CONS_LAST];
-
-/** Session to the input server */
-static async_sess_t *input_sess;
-
-/** Session to the framebuffer server */
-static async_sess_t *fb_sess;
-
-/** Framebuffer resolution */
-static sysarg_t xres;
-static sysarg_t yres;
+/** Input server proxy */
+static input_t *input;
+
+/** Session to the output server */
+static async_sess_t *output_sess;
+
+/** Output dimensions */
+static sysarg_t cols;
+static sysarg_t rows;
 
 /** Array of data for virtual consoles */
@@ -127,175 +102,91 @@
 static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
 
-static imgmap_t *logo_img;
-static imgmap_t *nameic_img;
-
-static imgmap_t *anim_1_img;
-static imgmap_t *anim_2_img;
-static imgmap_t *anim_3_img;
-static imgmap_t *anim_4_img;
-
-static imagemap_handle_t anim_1;
-static imagemap_handle_t anim_2;
-static imagemap_handle_t anim_3;
-static imagemap_handle_t anim_4;
-
-static sequence_handle_t anim_seq;
-
-static imgmap_t *cons_data_img;
-static imgmap_t *cons_dis_img;
-static imgmap_t *cons_dis_sel_img;
-static imgmap_t *cons_idle_img;
-static imgmap_t *cons_kernel_img;
-static imgmap_t *cons_sel_img;
-
-static vp_handle_t logo_vp;
-static imagemap_handle_t logo_handle;
-
-static vp_handle_t nameic_vp;
-static imagemap_handle_t nameic_handle;
-
-static vp_handle_t screen_vp;
-static vp_handle_t console_vp;
-
-struct {
-	sysarg_t x;
-	sysarg_t y;
-	
-	sysarg_t btn_x;
-	sysarg_t btn_y;
-	
-	bool pressed;
-} mouse;
-
-static void cons_redraw_state(console_t *cons)
-{
-	if (graphics_state == GRAPHICS_FULL) {
-		fibril_mutex_lock(&cons->mtx);
-		
-		fb_vp_imagemap_damage(fb_sess, cons->state_vp,
-		    state_icons[cons->state], 0, 0, STATE_WIDTH, STATE_HEIGHT);
-		
-		if ((cons->state != CONS_DISCONNECTED) &&
-		    (cons->state != CONS_KERNEL) &&
-		    (cons->state != CONS_DISCONNECTED_SELECTED)) {
-			char data[5];
-			snprintf(data, 5, "%zu", cons->index + 1);
-			
-			for (size_t i = 0; data[i] != 0; i++)
-				fb_vp_putchar(fb_sess, cons->state_vp, i + 2, 1, data[i]);
-		}
-		
-		fibril_mutex_unlock(&cons->mtx);
-	}
-}
-
-static void cons_kernel_sequence_start(console_t *cons)
-{
-	if (graphics_state == GRAPHICS_FULL) {
-		fibril_mutex_lock(&cons->mtx);
-		
-		fb_vp_sequence_start(fb_sess, cons->state_vp, anim_seq);
-		fb_vp_imagemap_damage(fb_sess, cons->state_vp,
-		    state_icons[cons->state], 0, 0, STATE_WIDTH, STATE_HEIGHT);
-		
-		fibril_mutex_unlock(&cons->mtx);
-	}
-}
-
-static void cons_update_state(console_t *cons, console_state_t state)
-{
-	bool update = false;
-	
-	fibril_mutex_lock(&cons->mtx);
-	
-	if (cons->state != state) {
-		cons->state = state;
-		update = true;
-	}
-	
-	fibril_mutex_unlock(&cons->mtx);
-	
-	if (update)
-		cons_redraw_state(cons);
-}
-
-static void cons_notify_data(console_t *cons)
+static int input_ev_key(input_t *, kbd_event_type_t, keycode_t, keymod_t, wchar_t);
+static int input_ev_move(input_t *, int, int);
+static int input_ev_abs_move(input_t *, unsigned, unsigned, unsigned, unsigned);
+static int input_ev_button(input_t *, int, int);
+
+static input_ev_ops_t input_ev_ops = {
+	.key = input_ev_key,
+	.move = input_ev_move,
+	.abs_move = input_ev_abs_move,
+	.button = input_ev_button
+};
+
+static int cons_open(con_srvs_t *, con_srv_t *);
+static int cons_close(con_srv_t *);
+static int cons_read(con_srv_t *, void *, size_t);
+static int cons_write(con_srv_t *, void *, size_t);
+static void cons_sync(con_srv_t *);
+static void cons_clear(con_srv_t *);
+static void cons_set_pos(con_srv_t *, sysarg_t col, sysarg_t row);
+static int cons_get_pos(con_srv_t *, sysarg_t *, sysarg_t *);
+static int cons_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
+static int cons_get_color_cap(con_srv_t *, console_caps_t *);
+static void cons_set_style(con_srv_t *, console_style_t);
+static void cons_set_color(con_srv_t *, console_color_t, console_color_t,
+    console_color_attr_t);
+static void cons_set_rgb_color(con_srv_t *, pixel_t, pixel_t);
+static void cons_set_cursor_visibility(con_srv_t *, bool);
+static int cons_get_event(con_srv_t *, kbd_event_t *);
+
+static con_ops_t con_ops = {
+	.open = cons_open,
+	.close = cons_close,
+	.read = cons_read,
+	.write = cons_write,
+	.sync = cons_sync,
+	.clear = cons_clear,
+	.set_pos = cons_set_pos,
+	.get_pos = cons_get_pos,
+	.get_size = cons_get_size,
+	.get_color_cap = cons_get_color_cap,
+	.set_style = cons_set_style,
+	.set_color = cons_set_color,
+	.set_rgb_color = cons_set_rgb_color,
+	.set_cursor_visibility = cons_set_cursor_visibility,
+	.get_event = cons_get_event
+};
+
+static console_t *srv_to_console(con_srv_t *srv)
+{
+	return srv->srvs->sarg;
+}
+
+static void cons_update(console_t *cons)
 {
 	fibril_mutex_lock(&switch_mtx);
-	
-	if (cons != active_console)
-		cons_update_state(cons, CONS_DATA);
-	
+	fibril_mutex_lock(&cons->mtx);
+	
+	if ((cons == active_console) && (active_console != kernel_console)) {
+		output_update(output_sess, cons->fbid);
+		output_cursor_update(output_sess, cons->fbid);
+	}
+	
+	fibril_mutex_unlock(&cons->mtx);
 	fibril_mutex_unlock(&switch_mtx);
 }
 
-static void cons_notify_connect(console_t *cons)
+static void cons_update_cursor(console_t *cons)
 {
 	fibril_mutex_lock(&switch_mtx);
-	
-	if (cons == active_console)
-		cons_update_state(cons, CONS_SELECTED);
-	else
-		cons_update_state(cons, CONS_IDLE);
-	
+	fibril_mutex_lock(&cons->mtx);
+	
+	if ((cons == active_console) && (active_console != kernel_console))
+		output_cursor_update(output_sess, cons->fbid);
+	
+	fibril_mutex_unlock(&cons->mtx);
 	fibril_mutex_unlock(&switch_mtx);
 }
 
-static void cons_notify_disconnect(console_t *cons)
+static void cons_damage(console_t *cons)
 {
 	fibril_mutex_lock(&switch_mtx);
-	
-	if (cons == active_console)
-		cons_update_state(cons, CONS_DISCONNECTED_SELECTED);
-	else
-		cons_update_state(cons, CONS_DISCONNECTED);
-	
-	fibril_mutex_unlock(&switch_mtx);
-}
-
-static void cons_update(console_t *cons)
-{
-	fibril_mutex_lock(&switch_mtx);
 	fibril_mutex_lock(&cons->mtx);
 	
 	if ((cons == active_console) && (active_console != kernel_console)) {
-		fb_vp_update(fb_sess, console_vp, cons->fbid);
-		fb_vp_cursor_update(fb_sess, console_vp, cons->fbid);
-	}
-	
-	fibril_mutex_unlock(&cons->mtx);
-	fibril_mutex_unlock(&switch_mtx);
-}
-
-static void cons_update_cursor(console_t *cons)
-{
-	fibril_mutex_lock(&switch_mtx);
-	fibril_mutex_lock(&cons->mtx);
-	
-	if ((cons == active_console) && (active_console != kernel_console))
-		fb_vp_cursor_update(fb_sess, console_vp, cons->fbid);
-	
-	fibril_mutex_unlock(&cons->mtx);
-	fibril_mutex_unlock(&switch_mtx);
-}
-
-static void cons_clear(console_t *cons)
-{
-	fibril_mutex_lock(&cons->mtx);
-	screenbuffer_clear(cons->frontbuf);
-	fibril_mutex_unlock(&cons->mtx);
-	
-	cons_update(cons);
-}
-
-static void cons_damage_all(console_t *cons)
-{
-	fibril_mutex_lock(&switch_mtx);
-	fibril_mutex_lock(&cons->mtx);
-	
-	if ((cons == active_console) && (active_console != kernel_console)) {
-		fb_vp_damage(fb_sess, console_vp, cons->fbid, 0, 0, cons->cols,
+		output_damage(output_sess, cons->fbid, 0, 0, cons->cols,
 		    cons->rows);
-		fb_vp_cursor_update(fb_sess, console_vp, cons->fbid);
+		output_cursor_update(output_sess, cons->fbid);
 	}
 	
@@ -314,7 +205,7 @@
 	
 	if (cons == kernel_console) {
-		fb_yield(fb_sess);
+		output_yield(output_sess);
 		if (!console_kcon()) {
-			fb_claim(fb_sess);
+			output_claim(output_sess);
 			fibril_mutex_unlock(&switch_mtx);
 			return;
@@ -323,23 +214,12 @@
 	
 	if (active_console == kernel_console)
-		fb_claim(fb_sess);
+		output_claim(output_sess);
 	
 	prev_console = active_console;
 	active_console = cons;
 	
-	if (prev_console->state == CONS_DISCONNECTED_SELECTED)
-		cons_update_state(prev_console, CONS_DISCONNECTED);
-	else
-		cons_update_state(prev_console, CONS_IDLE);
-	
-	if ((cons->state == CONS_DISCONNECTED) ||
-	    (cons->state == CONS_DISCONNECTED_SELECTED))
-		cons_update_state(cons, CONS_DISCONNECTED_SELECTED);
-	else
-		cons_update_state(cons, CONS_SELECTED);
-	
 	fibril_mutex_unlock(&switch_mtx);
 	
-	cons_damage_all(cons);
+	cons_damage(cons);
 }
 
@@ -347,170 +227,65 @@
 {
 	fibril_mutex_lock(&switch_mtx);
-
+	
 	console_t *active_uspace = active_console;
-	if (active_uspace == kernel_console) {
+	if (active_uspace == kernel_console)
 		active_uspace = prev_console;
-	}
+	
 	assert(active_uspace != kernel_console);
-
+	
 	fibril_mutex_unlock(&switch_mtx);
-
+	
 	return active_uspace;
 }
 
-static ssize_t limit(ssize_t val, ssize_t lo, ssize_t hi)
-{
-	if (val > hi)
-		return hi;
-	
-	if (val < lo)
-		return lo;
-	
-	return val;
-}
-
-static void cons_mouse_move(sysarg_t dx, sysarg_t dy)
-{
-	ssize_t sx = (ssize_t) dx;
-	ssize_t sy = (ssize_t) dy;
-	
-	mouse.x = limit(mouse.x + sx, 0, xres);
-	mouse.y = limit(mouse.y + sy, 0, yres);
-	
-	fb_pointer_update(fb_sess, mouse.x, mouse.y, true);
-}
-
-static console_t *cons_find_icon(sysarg_t x, sysarg_t y)
-{
-	sysarg_t status_start =
-	    STATE_START + (xres - 800) / 2 + CONSOLE_MARGIN;
-	
-	if ((y < STATE_TOP) || (y >= STATE_TOP + STATE_HEIGHT))
-		return NULL;
-	
-	if (x < status_start)
-		return NULL;
-	
-	if (x >= status_start + (STATE_WIDTH + STATE_SPACE) * CONSOLE_COUNT)
-		return NULL;
-	
-	if (((x - status_start) % (STATE_WIDTH + STATE_SPACE)) >= STATE_WIDTH)
-		return NULL;
-	
-	sysarg_t btn = (x - status_start) / (STATE_WIDTH + STATE_SPACE);
-	
-	if (btn < CONSOLE_COUNT)
-		return consoles + btn;
-	
-	return NULL;
-}
-
-/** Handle mouse click
- *
- * @param state Button state (true - pressed, false - depressed)
- *
- */
-static console_t *cons_mouse_button(bool state)
-{
-	if (graphics_state != GRAPHICS_FULL)
-		return NULL;
-	
-	if (state) {
-		console_t *cons = cons_find_icon(mouse.x, mouse.y);
-		if (cons != NULL) {
-			mouse.btn_x = mouse.x;
-			mouse.btn_y = mouse.y;
-			mouse.pressed = true;
-		}
-		
-		return NULL;
-	}
-	
-	if ((!state) && (!mouse.pressed))
-		return NULL;
-	
-	console_t *cons = cons_find_icon(mouse.x, mouse.y);
-	if (cons == cons_find_icon(mouse.btn_x, mouse.btn_y))
-		return cons;
-	
-	mouse.pressed = false;
-	return NULL;
-}
-
-static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			/* TODO: Handle hangup */
-			async_hangup(input_sess);
-			return;
-		}
-		
-		kbd_event_type_t type;
-		keycode_t key;
-		keymod_t mods;
-		wchar_t c;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case INPUT_EVENT_KEY:
-			type = IPC_GET_ARG1(call);
-			key = IPC_GET_ARG2(call);
-			mods = IPC_GET_ARG3(call);
-			c = IPC_GET_ARG4(call);
-			
-			if ((key >= KC_F1) && (key < KC_F1 + CONSOLE_COUNT) &&
-			    ((mods & KM_CTRL) == 0))
-				cons_switch(&consoles[key - KC_F1]);
-			else {
-				/* Got key press/release event */
-				kbd_event_t *event =
-				    (kbd_event_t *) malloc(sizeof(kbd_event_t));
-				if (event == NULL) {
-					async_answer_0(callid, ENOMEM);
-					break;
-				}
-				
-				link_initialize(&event->link);
-				event->type = type;
-				event->key = key;
-				event->mods = mods;
-				event->c = c;
-				
-				/*
-				 * Kernel console does not read events
-				 * from us, so we will redirect them
-				 * to the (last) active userspace console
-				 * if necessary.
-				 */
-				console_t *target_console = cons_get_active_uspace();
-				
-				prodcons_produce(&target_console->input_pc,
-				    &event->link);
-			}
-			
-			async_answer_0(callid, EOK);
-			break;
-		case INPUT_EVENT_MOVE:
-			cons_mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
-			async_answer_0(callid, EOK);
-			break;
-		case INPUT_EVENT_BUTTON:
-			/* Got pointer button press/release event */
-			if (IPC_GET_ARG1(call) == 1) {
-				console_t *cons =
-				    cons_mouse_button((bool) IPC_GET_ARG2(call));
-				if (cons != NULL)
-					cons_switch(cons);
-			}
-			async_answer_0(callid, EOK);
-			break;
-		default:
-			async_answer_0(callid, EINVAL);
-		}
-	}
+static int input_ev_key(input_t *input, kbd_event_type_t type, keycode_t key,
+    keymod_t mods, wchar_t c)
+{
+	if ((key >= KC_F1) && (key < KC_F1 + CONSOLE_COUNT) &&
+	    ((mods & KM_CTRL) == 0)) {
+		cons_switch(&consoles[key - KC_F1]);
+	} else {
+		/* Got key press/release event */
+		kbd_event_t *event =
+		    (kbd_event_t *) malloc(sizeof(kbd_event_t));
+		if (event == NULL) {
+			return ENOMEM;
+		}
+		
+		link_initialize(&event->link);
+		event->type = type;
+		event->key = key;
+		event->mods = mods;
+		event->c = c;
+		
+		/*
+		 * Kernel console does not read events
+		 * from us, so we will redirect them
+		 * to the (last) active userspace console
+		 * if necessary.
+		 */
+		console_t *target_console = cons_get_active_uspace();
+		
+		prodcons_produce(&target_console->input_pc,
+		    &event->link);
+	}
+	
+	return EOK;
+}
+
+static int input_ev_move(input_t *input, int dx, int dy)
+{
+	return EOK;
+}
+
+static int input_ev_abs_move(input_t *input, unsigned x , unsigned y,
+    unsigned max_x, unsigned max_y)
+{
+	return EOK;
+}
+
+static int input_ev_button(input_t *input, int bnum, int bpress)
+{
+	return EOK;
 }
 
@@ -524,16 +299,16 @@
 	switch (ch) {
 	case '\n':
-		updated = screenbuffer_newline(cons->frontbuf);
+		updated = chargrid_newline(cons->frontbuf);
 		break;
 	case '\r':
 		break;
 	case '\t':
-		updated = screenbuffer_tabstop(cons->frontbuf, 8);
+		updated = chargrid_tabstop(cons->frontbuf, 8);
 		break;
 	case '\b':
-		updated = screenbuffer_backspace(cons->frontbuf);
+		updated = chargrid_backspace(cons->frontbuf);
 		break;
 	default:
-		updated = screenbuffer_putchar(cons->frontbuf, ch, true);
+		updated = chargrid_putchar(cons->frontbuf, ch, true);
 	}
 	
@@ -544,8 +319,8 @@
 }
 
-static void cons_set_cursor(console_t *cons, sysarg_t col, sysarg_t row)
-{
-	fibril_mutex_lock(&cons->mtx);
-	screenbuffer_set_cursor(cons->frontbuf, col, row);
+static void cons_set_cursor_vis(console_t *cons, bool visible)
+{
+	fibril_mutex_lock(&cons->mtx);
+	chargrid_set_cursor_visibility(cons->frontbuf, visible);
 	fibril_mutex_unlock(&cons->mtx);
 	
@@ -553,111 +328,175 @@
 }
 
-static void cons_set_cursor_visibility(console_t *cons, bool visible)
-{
-	fibril_mutex_lock(&cons->mtx);
-	screenbuffer_set_cursor_visibility(cons->frontbuf, visible);
-	fibril_mutex_unlock(&cons->mtx);
-	
-	cons_update_cursor(cons);
-}
-
-static void cons_get_cursor(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
-{
-	sysarg_t col;
-	sysarg_t row;
-	
-	fibril_mutex_lock(&cons->mtx);
-	screenbuffer_get_cursor(cons->frontbuf, &col, &row);
-	fibril_mutex_unlock(&cons->mtx);
-	
-	async_answer_2(iid, EOK, col, row);
-}
-
-static void cons_write(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
-{
-	void *buf;
-	size_t size;
-	int rc = async_data_write_accept(&buf, false, 0, 0, 0, &size);
-	
-	if (rc != EOK) {
-		async_answer_0(iid, rc);
-		return;
-	}
-	
+static int cons_open(con_srvs_t *srvs, con_srv_t *srv)
+{
+	return EOK;
+}
+
+static int cons_close(con_srv_t *srv)
+{
+	return EOK;
+}
+
+static int cons_read(con_srv_t *srv, void *buf, size_t size)
+{
+	uint8_t *bbuf = buf;
+	console_t *cons = srv_to_console(srv);
+	size_t pos = 0;
+	
+	/*
+	 * Read input from keyboard and copy it to the buffer.
+	 * We need to handle situation when wchar is split by 2 following
+	 * reads.
+	 */
+	while (pos < size) {
+		/* Copy to the buffer remaining characters. */
+		while ((pos < size) && (cons->char_remains_len > 0)) {
+			bbuf[pos] = cons->char_remains[0];
+			pos++;
+			
+			/* Unshift the array. */
+			for (size_t i = 1; i < cons->char_remains_len; i++)
+				cons->char_remains[i - 1] = cons->char_remains[i];
+			
+			cons->char_remains_len--;
+		}
+		
+		/* Still not enough? Then get another key from the queue. */
+		if (pos < size) {
+			link_t *link = prodcons_consume(&cons->input_pc);
+			kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
+			
+			/* Accept key presses of printable chars only. */
+			if ((event->type == KEY_PRESS) && (event->c != 0)) {
+				wchar_t tmp[2] = { event->c, 0 };
+				wstr_to_str(cons->char_remains, UTF8_CHAR_BUFFER_SIZE, tmp);
+				cons->char_remains_len = str_size(cons->char_remains);
+			}
+			
+			free(event);
+		}
+	}
+
+	return size;
+}
+
+static int cons_write(con_srv_t *srv, void *data, size_t size)
+{
+	console_t *cons = srv_to_console(srv);
+
 	size_t off = 0;
 	while (off < size)
-		cons_write_char(cons, str_decode(buf, &off, size));
-	
-	async_answer_1(iid, EOK, size);
-	free(buf);
-	
-	cons_notify_data(cons);
-}
-
-static void cons_read(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_data_read_receive(&callid, &size)) {
-		async_answer_0(callid, EINVAL);
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	char *buf = (char *) malloc(size);
-	if (buf == NULL) {
-		async_answer_0(callid, ENOMEM);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	size_t pos = 0;
-	while (pos < size) {
-		link_t *link = prodcons_consume(&cons->input_pc);
-		kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
-		
-		if (event->type == KEY_PRESS) {
-			buf[pos] = event->c;
-			pos++;
-		}
-		
-		free(event);
-	}
-	
-	(void) async_data_read_finalize(callid, buf, size);
-	async_answer_1(iid, EOK, size);
-	free(buf);
-}
-
-static void cons_set_style(console_t *cons, console_style_t style)
-{
-	fibril_mutex_lock(&cons->mtx);
-	screenbuffer_set_style(cons->frontbuf, style);
-	fibril_mutex_unlock(&cons->mtx);
-}
-
-static void cons_set_color(console_t *cons, console_color_t bgcolor,
+		cons_write_char(cons, str_decode(data, &off, size));
+	return size;
+}
+
+static void cons_sync(con_srv_t *srv)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	cons_update(cons);
+}
+
+static void cons_clear(con_srv_t *srv)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	chargrid_clear(cons->frontbuf);
+	fibril_mutex_unlock(&cons->mtx);
+	
+	cons_update(cons);
+}
+
+static void cons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	chargrid_set_cursor(cons->frontbuf, col, row);
+	fibril_mutex_unlock(&cons->mtx);
+	
+	cons_update_cursor(cons);
+}
+
+static int cons_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	chargrid_get_cursor(cons->frontbuf, col, row);
+	fibril_mutex_unlock(&cons->mtx);
+	
+	return EOK;
+}
+
+static int cons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	*cols = cons->cols;
+	*rows = cons->rows;
+	fibril_mutex_unlock(&cons->mtx);
+	
+	return EOK;
+}
+
+static int cons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	*ccaps = cons->ccaps;
+	fibril_mutex_unlock(&cons->mtx);
+	
+	return EOK;
+}
+
+static void cons_set_style(con_srv_t *srv, console_style_t style)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	chargrid_set_style(cons->frontbuf, style);
+	fibril_mutex_unlock(&cons->mtx);
+}
+
+static void cons_set_color(con_srv_t *srv, console_color_t bgcolor,
     console_color_t fgcolor, console_color_attr_t attr)
 {
-	fibril_mutex_lock(&cons->mtx);
-	screenbuffer_set_color(cons->frontbuf, bgcolor, fgcolor, attr);
-	fibril_mutex_unlock(&cons->mtx);
-}
-
-static void cons_set_rgb_color(console_t *cons, pixel_t bgcolor,
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	chargrid_set_color(cons->frontbuf, bgcolor, fgcolor, attr);
+	fibril_mutex_unlock(&cons->mtx);
+}
+
+static void cons_set_rgb_color(con_srv_t *srv, pixel_t bgcolor,
     pixel_t fgcolor)
 {
-	fibril_mutex_lock(&cons->mtx);
-	screenbuffer_set_rgb_color(cons->frontbuf, bgcolor, fgcolor);
-	fibril_mutex_unlock(&cons->mtx);
-}
-
-static void cons_get_event(console_t *cons, ipc_callid_t iid, ipc_call_t *icall)
-{
+	console_t *cons = srv_to_console(srv);
+	
+	fibril_mutex_lock(&cons->mtx);
+	chargrid_set_rgb_color(cons->frontbuf, bgcolor, fgcolor);
+	fibril_mutex_unlock(&cons->mtx);
+}
+
+static void cons_set_cursor_visibility(con_srv_t *srv, bool visible)
+{
+	console_t *cons = srv_to_console(srv);
+	
+	cons_set_cursor_vis(cons, visible);
+}
+
+static int cons_get_event(con_srv_t *srv, kbd_event_t *event)
+{
+	console_t *cons = srv_to_console(srv);
 	link_t *link = prodcons_consume(&cons->input_pc);
-	kbd_event_t *event = list_get_instance(link, kbd_event_t, link);
-	
-	async_answer_4(iid, EOK, event->type, event->key, event->mods, event->c);
-	free(event);
+	kbd_event_t *kevent = list_get_instance(link, kbd_event_t, link);
+	
+	*event = *kevent;
+	free(kevent);
+	return EOK;
 }
 
@@ -681,78 +520,12 @@
 	}
 	
-	if (atomic_postinc(&cons->refcnt) == 0) {
-		cons_set_cursor_visibility(cons, true);
-		cons_notify_connect(cons);
-	}
-	
-	/* Accept the connection */
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			if (atomic_postdec(&cons->refcnt) == 1)
-				cons_notify_disconnect(cons);
-			
-			return;
-		}
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case VFS_OUT_READ:
-			cons_read(cons, callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			cons_write(cons, callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			cons_update(cons);
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_CLEAR:
-			cons_clear(cons);
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_GOTO:
-			cons_set_cursor(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call));
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_GET_POS:
-			cons_get_cursor(cons, callid, &call);
-			break;
-		case CONSOLE_GET_SIZE:
-			async_answer_2(callid, EOK, cons->cols, cons->rows);
-			break;
-		case CONSOLE_GET_COLOR_CAP:
-			async_answer_1(callid, EOK, cons->ccaps);
-			break;
-		case CONSOLE_SET_STYLE:
-			cons_set_style(cons, IPC_GET_ARG1(call));
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_SET_COLOR:
-			cons_set_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call),
-			    IPC_GET_ARG3(call));
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_SET_RGB_COLOR:
-			cons_set_rgb_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call));
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_CURSOR_VISIBILITY:
-			cons_set_cursor_visibility(cons, IPC_GET_ARG1(call));
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_GET_EVENT:
-			cons_get_event(cons, callid, &call);
-			break;
-		default:
-			async_answer_0(callid, EINVAL);
-		}
-	}
-}
-
-static async_sess_t *input_connect(const char *svc)
+	if (atomic_postinc(&cons->refcnt) == 0)
+		cons_set_cursor_vis(cons, true);
+	
+	con_conn(iid, icall, &cons->srvs);
+}
+
+
+static int input_connect(const char *svc)
 {
 	async_sess_t *sess;
@@ -760,26 +533,25 @@
 	
 	int rc = loc_service_get_id(svc, &dsid, 0);
-	if (rc == EOK) {
-		sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
-		if (sess == NULL) {
-			printf("%s: Unable to connect to input service %s\n", NAME,
-			    svc);
-			return NULL;
-		}
-	} else
-		return NULL;
-	
-	async_exch_t *exch = async_exchange_begin(sess);
-	rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL);
-	async_exchange_end(exch);
-	
+	if (rc != EOK) {
+		printf("%s: Input service %s not found\n", NAME, svc);
+		return rc;
+	}
+
+	sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0);
+	if (sess == NULL) {
+		printf("%s: Unable to connect to input service %s\n", NAME,
+		    svc);
+		return EIO;
+	}
+	
+	rc = input_open(sess, &input_ev_ops, NULL, &input);
 	if (rc != EOK) {
 		async_hangup(sess);
-		printf("%s: Unable to create callback connection to service %s (%s)\n",
+		printf("%s: Unable to communicate with service %s (%s)\n",
 		    NAME, svc, str_error(rc));
-		return NULL;
-	}
-	
-	return sess;
+		return rc;
+	}
+	
+	return EOK;
 }
 
@@ -789,5 +561,5 @@
 }
 
-static async_sess_t *fb_connect(const char *svc)
+static async_sess_t *output_connect(const char *svc)
 {
 	async_sess_t *sess;
@@ -798,5 +570,5 @@
 		sess = loc_service_connect(EXCHANGE_SERIALIZE, dsid, 0);
 		if (sess == NULL) {
-			printf("%s: Unable to connect to framebuffer service %s\n",
+			printf("%s: Unable to connect to output service %s\n",
 			    NAME, svc);
 			return NULL;
@@ -808,23 +580,21 @@
 }
 
-static bool console_srv_init(char *input_svc, char *fb_svc)
-{
-	/* Avoid double initialization */
-	if (graphics_state != GRAPHICS_NONE)
+static bool console_srv_init(char *input_svc, char *output_svc)
+{
+	int rc;
+	
+	/* Connect to input service */
+	rc = input_connect(input_svc);
+	if (rc != EOK)
 		return false;
 	
-	/* Connect to input service */
-	input_sess = input_connect(input_svc);
-	if (input_sess == NULL)
-		return false;
-	
-	/* Connect to framebuffer service */
-	fb_sess = fb_connect(fb_svc);
-	if (fb_sess == NULL)
+	/* Connect to output service */
+	output_sess = output_connect(output_svc);
+	if (output_sess == NULL)
 		return false;
 	
 	/* Register server */
 	async_set_client_connection(client_connection);
-	int rc = loc_server_register(NAME);
+	rc = loc_server_register(NAME);
 	if (rc != EOK) {
 		printf("%s: Unable to register server (%s)\n", NAME,
@@ -833,94 +603,9 @@
 	}
 	
-	fb_get_resolution(fb_sess, &xres, &yres);
-	
-	/* Initialize the screen */
-	screen_vp = fb_vp_create(fb_sess, 0, 0, xres, yres);
-	
-	if ((xres >= 800) && (yres >= 600)) {
-		logo_vp = fb_vp_create(fb_sess, xres - 66, 2, 64, 60);
-		logo_img = imgmap_decode_tga((void *) helenos_tga,
-		    helenos_tga_size, IMGMAP_FLAG_SHARED);
-		logo_handle = fb_imagemap_create(fb_sess, logo_img);
-		
-		nameic_vp = fb_vp_create(fb_sess, 5, 17, 100, 26);
-		nameic_img = imgmap_decode_tga((void *) nameic_tga,
-		    nameic_tga_size, IMGMAP_FLAG_SHARED);
-		nameic_handle = fb_imagemap_create(fb_sess, nameic_img);
-		
-		cons_data_img = imgmap_decode_tga((void *) cons_data_tga,
-		    cons_data_tga_size, IMGMAP_FLAG_SHARED);
-		cons_dis_img = imgmap_decode_tga((void *) cons_dis_tga,
-		    cons_dis_tga_size, IMGMAP_FLAG_SHARED);
-		cons_dis_sel_img = imgmap_decode_tga((void *) cons_dis_sel_tga,
-		    cons_dis_sel_tga_size, IMGMAP_FLAG_SHARED);
-		cons_idle_img = imgmap_decode_tga((void *) cons_idle_tga,
-		    cons_idle_tga_size, IMGMAP_FLAG_SHARED);
-		cons_kernel_img = imgmap_decode_tga((void *) cons_kernel_tga,
-		    cons_kernel_tga_size, IMGMAP_FLAG_SHARED);
-		cons_sel_img = imgmap_decode_tga((void *) cons_sel_tga,
-		    cons_sel_tga_size, IMGMAP_FLAG_SHARED);
-		
-		state_icons[CONS_DISCONNECTED] =
-		    fb_imagemap_create(fb_sess, cons_dis_img);
-		state_icons[CONS_DISCONNECTED_SELECTED] =
-		    fb_imagemap_create(fb_sess, cons_dis_sel_img);
-		state_icons[CONS_SELECTED] =
-		    fb_imagemap_create(fb_sess, cons_sel_img);
-		state_icons[CONS_IDLE] =
-		    fb_imagemap_create(fb_sess, cons_idle_img);
-		state_icons[CONS_DATA] =
-		    fb_imagemap_create(fb_sess, cons_data_img);
-		state_icons[CONS_KERNEL] =
-		    fb_imagemap_create(fb_sess, cons_kernel_img);
-		
-		anim_1_img = imgmap_decode_tga((void *) anim_1_tga,
-		    anim_1_tga_size, IMGMAP_FLAG_SHARED);
-		anim_2_img = imgmap_decode_tga((void *) anim_2_tga,
-		    anim_2_tga_size, IMGMAP_FLAG_SHARED);
-		anim_3_img = imgmap_decode_tga((void *) anim_3_tga,
-		    anim_3_tga_size, IMGMAP_FLAG_SHARED);
-		anim_4_img = imgmap_decode_tga((void *) anim_4_tga,
-		    anim_4_tga_size, IMGMAP_FLAG_SHARED);
-		
-		anim_1 = fb_imagemap_create(fb_sess, anim_1_img);
-		anim_2 = fb_imagemap_create(fb_sess, anim_2_img);
-		anim_3 = fb_imagemap_create(fb_sess, anim_3_img);
-		anim_4 = fb_imagemap_create(fb_sess, anim_4_img);
-		
-		anim_seq = fb_sequence_create(fb_sess);
-		fb_sequence_add_imagemap(fb_sess, anim_seq, anim_1);
-		fb_sequence_add_imagemap(fb_sess, anim_seq, anim_2);
-		fb_sequence_add_imagemap(fb_sess, anim_seq, anim_3);
-		fb_sequence_add_imagemap(fb_sess, anim_seq, anim_4);
-		
-		console_vp = fb_vp_create(fb_sess, CONSOLE_MARGIN, CONSOLE_TOP,
-		    xres - 2 * CONSOLE_MARGIN, yres - (CONSOLE_TOP + CONSOLE_MARGIN));
-		
-		fb_vp_clear(fb_sess, screen_vp);
-		fb_vp_imagemap_damage(fb_sess, logo_vp, logo_handle,
-		    0, 0, 64, 60);
-		fb_vp_imagemap_damage(fb_sess, nameic_vp, nameic_handle,
-		    0, 0, 100, 26);
-		
-		graphics_state = GRAPHICS_FULL;
-	} else {
-		console_vp = screen_vp;
-		graphics_state = GRAPHICS_BASIC;
-	}
-	
-	fb_vp_set_style(fb_sess, console_vp, STYLE_NORMAL);
-	fb_vp_clear(fb_sess, console_vp);
-	
-	sysarg_t cols;
-	sysarg_t rows;
-	fb_vp_get_dimensions(fb_sess, console_vp, &cols, &rows);
+	output_get_dimensions(output_sess, &cols, &rows);
+	output_set_style(output_sess, STYLE_NORMAL);
 	
 	console_caps_t ccaps;
-	fb_vp_get_caps(fb_sess, console_vp, &ccaps);
-	
-	mouse.x = xres / 2;
-	mouse.y = yres / 2;
-	mouse.pressed = false;
+	output_get_caps(output_sess, &ccaps);
 	
 	/* Inititalize consoles */
@@ -930,24 +615,8 @@
 		fibril_mutex_initialize(&consoles[i].mtx);
 		prodcons_initialize(&consoles[i].input_pc);
-		
-		if (graphics_state == GRAPHICS_FULL) {
-			/* Create state buttons */
-			consoles[i].state_vp =
-			    fb_vp_create(fb_sess, STATE_START + (xres - 800) / 2 +
-			    CONSOLE_MARGIN + i * (STATE_WIDTH + STATE_SPACE),
-			    STATE_TOP, STATE_WIDTH, STATE_HEIGHT);
-		}
-		
-		if (i == KERNEL_CONSOLE) {
-			consoles[i].state = CONS_KERNEL;
-			cons_redraw_state(&consoles[i]);
-			cons_kernel_sequence_start(&consoles[i]);
+		consoles[i].char_remains_len = 0;
+		
+		if (i == KERNEL_CONSOLE)
 			continue;
-		}
-		
-		if (i == 0)
-			consoles[i].state = CONS_DISCONNECTED_SELECTED;
-		else
-			consoles[i].state = CONS_DISCONNECTED;
 		
 		consoles[i].cols = cols;
@@ -955,5 +624,5 @@
 		consoles[i].ccaps = ccaps;
 		consoles[i].frontbuf =
-		    screenbuffer_create(cols, rows, SCREENBUFFER_FLAG_SHARED);
+		    chargrid_create(cols, rows, CHARGRID_FLAG_SHARED);
 		
 		if (consoles[i].frontbuf == NULL) {
@@ -962,5 +631,6 @@
 		}
 		
-		consoles[i].fbid = fb_frontbuf_create(fb_sess, consoles[i].frontbuf);
+		consoles[i].fbid = output_frontbuf_create(output_sess,
+		    consoles[i].frontbuf);
 		if (consoles[i].fbid == 0) {
 			printf("%s: Unable to create frontbuffer %zu\n", NAME, i);
@@ -968,5 +638,7 @@
 		}
 		
-		cons_redraw_state(&consoles[i]);
+		con_srvs_init(&consoles[i].srvs);
+		consoles[i].srvs.ops = &con_ops;
+		consoles[i].srvs.sarg = &consoles[i];
 		
 		char vc[LOC_NAME_MAXLEN + 1];
@@ -978,4 +650,6 @@
 		}
 	}
+	
+	cons_damage(active_console);
 	
 	/* Receive kernel notifications */
@@ -989,7 +663,7 @@
 }
 
-static void usage(void)
-{
-	printf("Usage: console <input_dev> <framebuffer_dev>\n");
+static void usage(char *name)
+{
+	printf("Usage: %s <input_dev> <output_dev>\n", name);
 }
 
@@ -997,5 +671,5 @@
 {
 	if (argc < 3) {
-		usage();
+		usage(argv[0]);
 		return -1;
 	}
@@ -1010,4 +684,5 @@
 	async_manager();
 	
+	/* Never reached */
 	return 0;
 }
Index: pace/srv/hid/fb/Makefile
===================================================================
--- uspace/srv/hid/fb/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,46 +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 = $(LIBFB_PREFIX)/libfb.a
-EXTRA_CFLAGS += -I$(LIBFB_PREFIX)
-BINARY = fb
-
-SOURCES = \
-	gfx/font-8x16.c \
-	ctl/serial.c \
-	port/ega.c \
-	port/kfb.c \
-	port/kchar.c \
-	port/niagara.c \
-	port/ski.c \
-	proto/vt100.c \
-	fb.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/hid/fb/ctl/serial.c
===================================================================
--- uspace/srv/hid/fb/ctl/serial.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,170 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * Copyright (c) 2008 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.
- */
-
-/** @file
- */
-
-#include <sys/types.h>
-#include <errno.h>
-#include <malloc.h>
-#include <screenbuffer.h>
-#include "../proto/vt100.h"
-#include "../fb.h"
-#include "serial.h"
-
-/** Draw the character at the specified position in viewport.
- *
- * @param state VT100 protocol state.
- * @param vp    Viewport.
- * @param col   Screen position relative to viewport.
- * @param row   Screen position relative to viewport.
- *
- */
-static void draw_vp_char(vt100_state_t *state, fbvp_t *vp, sysarg_t col,
-    sysarg_t row)
-{
-	sysarg_t x = vp->x + col;
-	sysarg_t y = vp->y + row;
-	
-	charfield_t *field = screenbuffer_field_at(vp->backbuf, col, row);
-	
-	vt100_goto(state, x, y);
-	vt100_set_attr(state, field->attrs);
-	vt100_putchar(state, field->ch);
-}
-
-static int serial_yield(fbdev_t *dev)
-{
-	vt100_state_t *state = (vt100_state_t *) dev->data;
-	return vt100_yield(state);
-}
-
-static int serial_claim(fbdev_t *dev)
-{
-	vt100_state_t *state = (vt100_state_t *) dev->data;
-	return vt100_claim(state);
-}
-
-static int serial_get_resolution(fbdev_t *dev, sysarg_t *width, sysarg_t *height)
-{
-	vt100_state_t *state = (vt100_state_t *) dev->data;
-	vt100_get_resolution(state, width, height);
-	return EOK;
-}
-
-static void serial_font_metrics(fbdev_t *dev, sysarg_t width, sysarg_t height,
-    sysarg_t *cols, sysarg_t *rows)
-{
-	*cols = width;
-	*rows = height;
-}
-
-static int serial_vp_create(fbdev_t *dev, fbvp_t *vp)
-{
-	vp->attrs.type = CHAR_ATTR_STYLE;
-	vp->attrs.val.style = STYLE_NORMAL;
-	vp->data = NULL;
-	
-	return EOK;
-}
-
-static void serial_vp_destroy(fbdev_t *dev, fbvp_t *vp)
-{
-	/* No-op */
-}
-
-static void serial_vp_clear(fbdev_t *dev, fbvp_t *vp)
-{
-	vt100_state_t *state = (vt100_state_t *) dev->data;
-	
-	for (sysarg_t row = 0; row < vp->rows; row++) {
-		for (sysarg_t col = 0; col < vp->cols; col++) {
-			charfield_t *field =
-			    screenbuffer_field_at(vp->backbuf, col, row);
-			
-			field->ch = 0;
-			field->attrs = vp->attrs;
-			
-			draw_vp_char(state, vp, col, row);
-		}
-	}
-}
-
-static console_caps_t serial_vp_get_caps(fbdev_t *dev, fbvp_t *vp)
-{
-	return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED);
-}
-
-static void serial_vp_cursor_update(fbdev_t *dev, fbvp_t *vp,
-    sysarg_t prev_col, sysarg_t prev_row, sysarg_t col, sysarg_t row,
-    bool visible)
-{
-	vt100_state_t *state = (vt100_state_t *) dev->data;
-	
-	vt100_goto(state, vp->x + col, vp->y + row);
-	vt100_cursor_visibility(state, visible);
-}
-
-static void serial_vp_char_update(fbdev_t *dev, fbvp_t *vp, sysarg_t col,
-    sysarg_t row)
-{
-	vt100_state_t *state = (vt100_state_t *) dev->data;
-	draw_vp_char(state, vp, col, row);
-}
-
-static fbdev_ops_t serial_ops = {
-	.yield = serial_yield,
-	.claim = serial_claim,
-	.get_resolution = serial_get_resolution,
-	.font_metrics = serial_font_metrics,
-	.vp_create = serial_vp_create,
-	.vp_destroy = serial_vp_destroy,
-	.vp_clear = serial_vp_clear,
-	.vp_get_caps = serial_vp_get_caps,
-	.vp_cursor_update = serial_vp_cursor_update,
-	.vp_char_update = serial_vp_char_update
-};
-
-int serial_init(vt100_putchar_t putchar_fn,
-    vt100_control_puts_t control_puts_fn)
-{
-	vt100_state_t *state =
-	    vt100_state_create(80, 24, putchar_fn, control_puts_fn);
-	if (state == NULL)
-		return ENOMEM;
-	
-	fbdev_t *dev = fbdev_register(&serial_ops, state);
-	if (dev == NULL)
-		return EINVAL;
-	
-	return EOK;
-}
-
-/** @}
- */
Index: pace/srv/hid/fb/ctl/serial.h
===================================================================
--- uspace/srv/hid/fb/ctl/serial.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,43 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * Copyright (c) 2008 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.
- */
-
-/** @file
- */
-
-#ifndef FB_CTL_SERIAL_H_
-#define FB_CTL_SERIAL_H_
-
-#include "../proto/vt100.h"
-
-extern int serial_init(vt100_putchar_t, vt100_control_puts_t);
-
-#endif
-
-/** @}
- */
Index: pace/srv/hid/fb/fb.c
===================================================================
--- uspace/srv/hid/fb/fb.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,1008 +1,0 @@
-/*
- * Copyright (c) 2011 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.
- */
-
-#include <sys/types.h>
-#include <bool.h>
-#include <loc.h>
-#include <errno.h>
-#include <stdio.h>
-#include <malloc.h>
-#include <inttypes.h>
-#include <as.h>
-#include <fb.h>
-#include <screenbuffer.h>
-#include "port/ega.h"
-#include "port/kchar.h"
-#include "port/kfb.h"
-#include "port/niagara.h"
-#include "port/ski.h"
-#include "fb.h"
-
-#define NAME       "fb"
-#define NAMESPACE  "hid"
-
-#define TICK_INTERVAL  250000
-
-static LIST_INITIALIZE(fbdevs);
-
-fbdev_t *fbdev_register(fbdev_ops_t *ops, void *data)
-{
-	sysarg_t index = 0;
-	
-	if (!list_empty(&fbdevs)) {
-		list_foreach(fbdevs, link) {
-			fbdev_t *dev = list_get_instance(link, fbdev_t, link);
-			if (index <= dev->index)
-				index = dev->index + 1;
-		}
-	}
-	
-	fbdev_t *dev = (fbdev_t *) malloc(sizeof(fbdev_t));
-	if (dev == NULL)
-		return NULL;
-	
-	link_initialize(&dev->link);
-	atomic_set(&dev->refcnt, 0);
-	dev->claimed = false;
-	dev->index = index;
-	list_initialize(&dev->vps);
-	list_initialize(&dev->frontbufs);
-	list_initialize(&dev->imagemaps);
-	list_initialize(&dev->sequences);
-	
-	dev->ops = *ops;
-	dev->data = data;
-	
-	char node[LOC_NAME_MAXLEN + 1];
-	snprintf(node, LOC_NAME_MAXLEN, "%s/%s%" PRIun, NAMESPACE, NAME,
-	    index);
-	
-	if (loc_service_register(node, &dev->dsid) != EOK) {
-		printf("%s: Unable to register device %s\n", NAME, node);
-		free(dev);
-		return NULL;
-	}
-	
-	list_append(&dev->link, &fbdevs);
-	return dev;
-}
-
-static void fbsrv_yield(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	assert(dev->ops.yield);
-	
-	if (dev->claimed) {
-		int rc = dev->ops.yield(dev);
-		if (rc == EOK)
-			dev->claimed = false;
-		
-		async_answer_0(iid, rc);
-	} else
-		async_answer_0(iid, ENOENT);
-}
-
-static void fbsrv_claim(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	assert(dev->ops.claim);
-	
-	if (!dev->claimed) {
-		int rc = dev->ops.claim(dev);
-		if (rc == EOK)
-			dev->claimed = true;
-		
-		async_answer_0(iid, rc);
-	} else
-		async_answer_0(iid, ENOENT);
-}
-
-static void fbsrv_get_resolution(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	assert(dev->ops.get_resolution);
-	
-	sysarg_t width;
-	sysarg_t height;
-	int rc = dev->ops.get_resolution(dev, &width, &height);
-	
-	async_answer_2(iid, rc, width, height);
-}
-
-static void fbsrv_pointer_update(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	if ((dev->claimed) && (dev->ops.pointer_update)) {
-		dev->ops.pointer_update(dev, IPC_GET_ARG1(*icall),
-		    IPC_GET_ARG2(*icall), IPC_GET_ARG3(*icall));
-		async_answer_0(iid, EOK);
-	} else
-		async_answer_0(iid, ENOTSUP);
-}
-
-static fbvp_t *resolve_vp(fbdev_t *dev, sysarg_t handle, ipc_callid_t iid)
-{
-	fbvp_t *vp = NULL;
-	list_foreach(dev->vps, link) {
-		fbvp_t *cur = list_get_instance(link, fbvp_t, link);
-		if (cur == (fbvp_t *) handle) {
-			vp = cur;
-			break;
-		}
-	}
-	
-	if (vp == NULL) {
-		async_answer_0(iid, ENOENT);
-		return NULL;
-	}
-	
-	return vp;
-}
-
-static frontbuf_t *resolve_frontbuf(fbdev_t *dev, sysarg_t handle, ipc_callid_t iid)
-{
-	frontbuf_t *frontbuf = NULL;
-	list_foreach(dev->frontbufs, link) {
-		frontbuf_t *cur = list_get_instance(link, frontbuf_t, link);
-		if (cur == (frontbuf_t *) handle) {
-			frontbuf = cur;
-			break;
-		}
-	}
-	
-	if (frontbuf == NULL) {
-		async_answer_0(iid, ENOENT);
-		return NULL;
-	}
-	
-	return frontbuf;
-}
-
-static imagemap_t *resolve_imagemap(fbdev_t *dev, sysarg_t handle, ipc_callid_t iid)
-{
-	imagemap_t *imagemap = NULL;
-	list_foreach(dev->imagemaps, link) {
-		imagemap_t *cur = list_get_instance(link, imagemap_t, link);
-		if (cur == (imagemap_t *) handle) {
-			imagemap = cur;
-			break;
-		}
-	}
-	
-	if (imagemap == NULL) {
-		async_answer_0(iid, ENOENT);
-		return NULL;
-	}
-	
-	return imagemap;
-}
-
-static sequence_t *resolve_sequence(fbdev_t *dev, sysarg_t handle, ipc_callid_t iid)
-{
-	sequence_t *sequence = NULL;
-	list_foreach(dev->sequences, link) {
-		sequence_t *cur = list_get_instance(link, sequence_t, link);
-		if (cur == (sequence_t *) handle) {
-			sequence = cur;
-			break;
-		}
-	}
-	
-	if (sequence == NULL) {
-		async_answer_0(iid, ENOENT);
-		return NULL;
-	}
-	
-	return sequence;
-}
-
-static void fbsrv_vp_create(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	assert(dev->ops.font_metrics);
-	assert(dev->ops.vp_create);
-	
-	fbvp_t *vp = (fbvp_t *) malloc(sizeof(fbvp_t));
-	if (vp == NULL) {
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	link_initialize(&vp->link);
-	
-	vp->x = IPC_GET_ARG1(*icall);
-	vp->y = IPC_GET_ARG2(*icall);
-	vp->width = IPC_GET_ARG3(*icall);
-	vp->height = IPC_GET_ARG4(*icall);
-	
-	dev->ops.font_metrics(dev, vp->width, vp->height, &vp->cols, &vp->rows);
-	
-	vp->cursor_active = false;
-	vp->cursor_flash = false;
-	
-	list_initialize(&vp->sequences);
-	
-	vp->backbuf = screenbuffer_create(vp->cols, vp->rows,
-	    SCREENBUFFER_FLAG_NONE);
-	if (vp->backbuf == NULL) {
-		free(vp);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	vp->top_row = 0;
-	
-	int rc = dev->ops.vp_create(dev, vp);
-	if (rc != EOK) {
-		free(vp);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	list_append(&vp->link, &dev->vps);
-	async_answer_1(iid, EOK, (sysarg_t) vp);
-}
-
-static void fbsrv_vp_destroy(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	assert(dev->ops.vp_destroy);
-	
-	fbvp_t *vp = resolve_vp(dev, IPC_GET_ARG1(*icall), iid);
-	if (vp == NULL)
-		return;
-	
-	if (dev->active_vp == vp) {
-		async_answer_0(iid, EPERM);
-		return;
-	}
-	
-	dev->ops.vp_destroy(dev, vp);
-	
-	list_remove(&vp->link);
-	free(vp->backbuf);
-	free(vp);
-	
-	async_answer_0(iid, EOK);
-}
-
-static void fbsrv_frontbuf_create(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	frontbuf_t *frontbuf = (frontbuf_t *) malloc(sizeof(frontbuf_t));
-	if (frontbuf == NULL) {
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	link_initialize(&frontbuf->link);
-	
-	ipc_callid_t callid;
-	if (!async_share_out_receive(&callid, &frontbuf->size,
-	    &frontbuf->flags)) {
-		free(frontbuf);
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	int rc = async_share_out_finalize(callid, &frontbuf->data);
-	if ((rc != EOK) || (frontbuf->data == AS_MAP_FAILED)) {
-		free(frontbuf);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	list_append(&frontbuf->link, &dev->frontbufs);
-	async_answer_1(iid, EOK, (sysarg_t) frontbuf);
-}
-
-static void fbsrv_frontbuf_destroy(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	frontbuf_t *frontbuf = resolve_frontbuf(dev, IPC_GET_ARG1(*icall), iid);
-	if (frontbuf == NULL)
-		return;
-	
-	list_remove(&frontbuf->link);
-	as_area_destroy(frontbuf->data);
-	free(frontbuf);
-	
-	async_answer_0(iid, EOK);
-}
-
-static void fbsrv_imagemap_create(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	imagemap_t *imagemap = (imagemap_t *) malloc(sizeof(imagemap_t));
-	if (imagemap == NULL) {
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	link_initialize(&imagemap->link);
-	link_initialize(&imagemap->seq_link);
-	
-	ipc_callid_t callid;
-	if (!async_share_out_receive(&callid, &imagemap->size,
-	    &imagemap->flags)) {
-		free(imagemap);
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	int rc = async_share_out_finalize(callid, &imagemap->data);
-	if ((rc != EOK) || (imagemap->data == AS_MAP_FAILED)) {
-		free(imagemap);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	list_append(&imagemap->link, &dev->imagemaps);
-	async_answer_1(iid, EOK, (sysarg_t) imagemap);
-}
-
-static void fbsrv_imagemap_destroy(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	imagemap_t *imagemap = resolve_imagemap(dev, IPC_GET_ARG1(*icall), iid);
-	if (imagemap == NULL)
-		return;
-	
-	list_remove(&imagemap->link);
-	list_remove(&imagemap->seq_link);
-	as_area_destroy(imagemap->data);
-	free(imagemap);
-	
-	async_answer_0(iid, EOK);
-}
-
-static void fbsrv_sequence_create(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	sequence_t *sequence = (sequence_t *) malloc(sizeof(sequence_t));
-	if (sequence == NULL) {
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	link_initialize(&sequence->link);
-	list_initialize(&sequence->imagemaps);
-	sequence->count = 0;
-	
-	list_append(&sequence->link, &dev->sequences);
-	async_answer_1(iid, EOK, (sysarg_t) sequence);
-}
-
-static void fbsrv_sequence_destroy(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	sequence_t *sequence = resolve_sequence(dev, IPC_GET_ARG1(*icall), iid);
-	if (sequence == NULL)
-		return;
-	
-	list_remove(&sequence->link);
-	free(sequence);
-	
-	async_answer_0(iid, EOK);
-}
-
-static void fbsrv_sequence_add_imagemap(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	sequence_t *sequence = resolve_sequence(dev, IPC_GET_ARG1(*icall), iid);
-	if (sequence == NULL)
-		return;
-	
-	imagemap_t *imagemap = resolve_imagemap(dev, IPC_GET_ARG2(*icall), iid);
-	if (imagemap == NULL)
-		return;
-	
-	if (list_member(&imagemap->seq_link, &sequence->imagemaps)) {
-		async_answer_0(iid, EEXISTS);
-		return;
-	}
-	
-	list_append(&imagemap->seq_link, &sequence->imagemaps);
-	sequence->count++;
-	
-	async_answer_0(iid, EOK);
-}
-
-static void fbsrv_vp_focus(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	fbvp_t *vp = resolve_vp(dev, IPC_GET_ARG1(*icall), iid);
-	if (vp == NULL)
-		return;
-	
-	if (dev->active_vp != vp)
-		dev->active_vp = vp;
-	
-	async_answer_0(iid, EOK);
-}
-
-static void fbsrv_vp_clear(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	assert(dev->ops.vp_clear);
-	
-	if ((dev->claimed) && (dev->active_vp)) {
-		screenbuffer_set_cursor_visibility(dev->active_vp->backbuf, false);
-		dev->ops.vp_clear(dev, dev->active_vp);
-		async_answer_0(iid, EOK);
-	} else
-		async_answer_0(iid, ENOENT);
-}
-
-static void fbsrv_vp_get_dimensions(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	if (dev->active_vp)
-		async_answer_2(iid, EOK, dev->active_vp->cols, dev->active_vp->rows);
-	else
-		async_answer_0(iid, ENOENT);
-}
-
-static void fbsrv_vp_get_caps(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	assert(dev->ops.vp_get_caps);
-	
-	if (dev->active_vp)
-		async_answer_1(iid, EOK,
-		    (sysarg_t) dev->ops.vp_get_caps(dev, dev->active_vp));
-	else
-		async_answer_0(iid, ENOENT);
-}
-
-static void fbsrv_vp_cursor_update(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	assert(dev->ops.vp_cursor_update);
-	
-	frontbuf_t *frontbuf = resolve_frontbuf(dev, IPC_GET_ARG1(*icall), iid);
-	if (frontbuf == NULL)
-		return;
-	
-	if ((dev->claimed) && (dev->active_vp)) {
-		screenbuffer_t *screenbuf = (screenbuffer_t *) frontbuf->data;
-		
-		sysarg_t prev_col;
-		sysarg_t prev_row;
-		sysarg_t col;
-		sysarg_t row;
-		
-		screenbuffer_get_cursor(dev->active_vp->backbuf,
-		    &prev_col, &prev_row);
-		screenbuffer_get_cursor(screenbuf, &col, &row);
-		screenbuffer_set_cursor(dev->active_vp->backbuf, col, row);
-		
-		bool visible = screenbuffer_get_cursor_visibility(screenbuf);
-		screenbuffer_set_cursor_visibility(dev->active_vp->backbuf, visible);
-		
-		if (visible)
-			dev->active_vp->cursor_active = true;
-		
-		dev->ops.vp_cursor_update(dev, dev->active_vp, prev_col, prev_row,
-		    col, row, visible);
-		async_answer_0(iid, EOK);
-	} else
-		async_answer_0(iid, ENOENT);
-}
-
-static void fbsrv_vp_cursor_flash(fbdev_t *dev)
-{
-	if ((dev->claimed) && (dev->ops.vp_cursor_flash)) {
-		list_foreach (dev->vps, link) {
-			fbvp_t *vp = list_get_instance(link, fbvp_t, link);
-			
-			if (vp->cursor_active) {
-				sysarg_t col;
-				sysarg_t row;
-				
-				screenbuffer_get_cursor(vp->backbuf, &col, &row);
-				vp->cursor_flash = !vp->cursor_flash;
-				dev->ops.vp_cursor_flash(dev, vp, col, row);
-			}
-		}
-	}
-}
-
-static void fbsrv_sequences_update(fbdev_t *dev)
-{
-	if ((dev->claimed) && (dev->ops.vp_imgmap_damage)) {
-		list_foreach (dev->vps, vp_link) {
-			fbvp_t *vp = list_get_instance(vp_link, fbvp_t, link);
-			
-			list_foreach (vp->sequences, seq_vp_link) {
-				sequence_vp_t *seq_vp =
-				    list_get_instance(seq_vp_link, sequence_vp_t, link);
-				
-				seq_vp->current++;
-				if (seq_vp->current >= seq_vp->seq->count)
-					seq_vp->current = 0;
-				
-				link_t *link =
-				    list_nth(&seq_vp->seq->imagemaps, seq_vp->current);
-				if (link != NULL) {
-					imagemap_t *imagemap =
-					    list_get_instance(link, imagemap_t, seq_link);
-					
-					imgmap_t *imgmap = (imgmap_t *) imagemap->data;
-					sysarg_t width;
-					sysarg_t height;
-					
-					imgmap_get_resolution(imgmap, &width, &height);
-					dev->ops.vp_imgmap_damage(dev, vp, imgmap,
-					    0, 0, width, height);
-				}
-			}
-		}
-	}
-}
-
-static void fbsrv_vp_set_style(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	if (dev->active_vp) {
-		dev->active_vp->attrs.type = CHAR_ATTR_STYLE;
-		dev->active_vp->attrs.val.style =
-		    (console_style_t) IPC_GET_ARG1(*icall);
-		async_answer_0(iid, EOK);
-	} else
-		async_answer_0(iid, ENOENT);
-}
-
-static void fbsrv_vp_set_color(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	if (dev->active_vp) {
-		dev->active_vp->attrs.type = CHAR_ATTR_INDEX;
-		dev->active_vp->attrs.val.index.bgcolor =
-		    (console_color_t) IPC_GET_ARG1(*icall);
-		dev->active_vp->attrs.val.index.fgcolor =
-		    (console_color_t) IPC_GET_ARG2(*icall);
-		dev->active_vp->attrs.val.index.attr =
-		    (console_color_attr_t) IPC_GET_ARG3(*icall);
-		async_answer_0(iid, EOK);
-	} else
-		async_answer_0(iid, ENOENT);
-}
-
-static void fbsrv_vp_set_rgb_color(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	if (dev->active_vp) {
-		dev->active_vp->attrs.type = CHAR_ATTR_RGB;
-		dev->active_vp->attrs.val.rgb.bgcolor = IPC_GET_ARG1(*icall);
-		dev->active_vp->attrs.val.rgb.fgcolor = IPC_GET_ARG2(*icall);
-		async_answer_0(iid, EOK);
-	} else
-		async_answer_0(iid, ENOENT);
-}
-
-static void fbsrv_vp_putchar(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	assert(dev->ops.vp_char_update);
-	
-	if ((dev->claimed) && (dev->active_vp)) {
-		charfield_t *field = screenbuffer_field_at(dev->active_vp->backbuf,
-		    IPC_GET_ARG1(*icall), IPC_GET_ARG2(*icall));
-		
-		field->ch = IPC_GET_ARG3(*icall);
-		
-		dev->ops.vp_char_update(dev, dev->active_vp, IPC_GET_ARG1(*icall),
-		    IPC_GET_ARG2(*icall));
-		async_answer_0(iid, EOK);
-	} else
-		async_answer_0(iid, ENOENT);
-}
-
-static bool fbsrv_vp_update_scroll(fbdev_t *dev, fbvp_t *vp,
-    screenbuffer_t *frontbuf)
-{
-	assert(dev->ops.vp_char_update);
-	
-	sysarg_t top_row = screenbuffer_get_top_row(frontbuf);
-	
-	if (vp->top_row == top_row)
-		return false;
-	
-	vp->top_row = top_row;
-	
-	for (sysarg_t y = 0; y < vp->rows; y++) {
-		for (sysarg_t x = 0; x < vp->cols; x++) {
-			charfield_t *front_field =
-			    screenbuffer_field_at(frontbuf, x, y);
-			charfield_t *back_field =
-			    screenbuffer_field_at(vp->backbuf, x, y);
-			bool update = false;
-			
-			if (front_field->ch != back_field->ch) {
-				back_field->ch = front_field->ch;
-				update = true;
-			}
-			
-			if (!attrs_same(front_field->attrs, back_field->attrs)) {
-				back_field->attrs = front_field->attrs;
-				update = true;
-			}
-			
-			front_field->flags &= ~CHAR_FLAG_DIRTY;
-			
-			if (update)
-				dev->ops.vp_char_update(dev, vp, x, y);
-		}
-	}
-	
-	return true;
-}
-
-static void fbsrv_vp_update(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	assert(dev->ops.vp_char_update);
-	
-	frontbuf_t *frontbuf = resolve_frontbuf(dev, IPC_GET_ARG1(*icall), iid);
-	if (frontbuf == NULL)
-		return;
-	
-	if ((dev->claimed) && (dev->active_vp)) {
-		fbvp_t *vp = dev->active_vp;
-		screenbuffer_t *screenbuf = (screenbuffer_t *) frontbuf->data;
-		
-		if (fbsrv_vp_update_scroll(dev, vp, screenbuf)) {
-			async_answer_0(iid, EOK);
-			return;
-		}
-		
-		for (sysarg_t y = 0; y < vp->rows; y++) {
-			for (sysarg_t x = 0; x < vp->cols; x++) {
-				charfield_t *front_field =
-				    screenbuffer_field_at(screenbuf, x, y);
-				charfield_t *back_field =
-				    screenbuffer_field_at(vp->backbuf, x, y);
-				bool update = false;
-				
-				if ((front_field->flags & CHAR_FLAG_DIRTY) == CHAR_FLAG_DIRTY) {
-					if (front_field->ch != back_field->ch) {
-						back_field->ch = front_field->ch;
-						update = true;
-					}
-					
-					if (!attrs_same(front_field->attrs, back_field->attrs)) {
-						back_field->attrs = front_field->attrs;
-						update = true;
-					}
-					
-					front_field->flags &= ~CHAR_FLAG_DIRTY;
-				}
-				
-				if (update)
-					dev->ops.vp_char_update(dev, vp, x, y);
-			}
-		}
-		
-		async_answer_0(iid, EOK);
-	} else
-		async_answer_0(iid, ENOENT);
-}
-
-static void fbsrv_vp_damage(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	assert(dev->ops.vp_char_update);
-	
-	frontbuf_t *frontbuf = resolve_frontbuf(dev, IPC_GET_ARG1(*icall), iid);
-	if (frontbuf == NULL)
-		return;
-	
-	if ((dev->claimed) && (dev->active_vp)) {
-		fbvp_t *vp = dev->active_vp;
-		screenbuffer_t *screenbuf = (screenbuffer_t *) frontbuf->data;
-		
-		if (fbsrv_vp_update_scroll(dev, vp, screenbuf)) {
-			async_answer_0(iid, EOK);
-			return;
-		}
-		
-		sysarg_t col = IPC_GET_ARG2(*icall);
-		sysarg_t row = IPC_GET_ARG3(*icall);
-		
-		sysarg_t cols = IPC_GET_ARG4(*icall);
-		sysarg_t rows = IPC_GET_ARG5(*icall);
-		
-		for (sysarg_t y = 0; y < rows; y++) {
-			for (sysarg_t x = 0; x < cols; x++) {
-				charfield_t *front_field =
-				    screenbuffer_field_at(screenbuf, col + x, row + y);
-				charfield_t *back_field =
-				    screenbuffer_field_at(vp->backbuf, col + x, row + y);
-				bool update = false;
-				
-				if (front_field->ch != back_field->ch) {
-					back_field->ch = front_field->ch;
-					update = true;
-				}
-				
-				if (!attrs_same(front_field->attrs, back_field->attrs)) {
-					back_field->attrs = front_field->attrs;
-					update = true;
-				}
-				
-				front_field->flags &= ~CHAR_FLAG_DIRTY;
-				
-				if (update)
-					dev->ops.vp_char_update(dev, vp, col + x, row + y);
-			}
-		}
-		
-		async_answer_0(iid, EOK);
-	} else
-		async_answer_0(iid, ENOENT);
-}
-
-static void fbsrv_vp_imagemap_damage(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	imagemap_t *imagemap = resolve_imagemap(dev, IPC_GET_ARG1(*icall), iid);
-	if (imagemap == NULL)
-		return;
-	
-	if ((dev->claimed) && (dev->ops.vp_imgmap_damage)) {
-		if (dev->active_vp) {
-			dev->ops.vp_imgmap_damage(dev, dev->active_vp,
-			    (imgmap_t *) imagemap->data,
-			    IPC_GET_ARG2(*icall), IPC_GET_ARG3(*icall),
-			    IPC_GET_ARG4(*icall), IPC_GET_ARG5(*icall));
-			async_answer_0(iid, EOK);
-		} else
-			async_answer_0(iid, ENOENT);
-	} else
-		async_answer_0(iid, ENOTSUP);
-}
-
-static void fbsrv_vp_sequence_start(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	sequence_t *sequence = resolve_sequence(dev, IPC_GET_ARG1(*icall), iid);
-	if (sequence == NULL)
-		return;
-	
-	if (dev->active_vp) {
-		/* Check if the sequence is not already started */
-		list_foreach(dev->active_vp->sequences, link) {
-			sequence_vp_t *seq_vp =
-			    list_get_instance(link, sequence_vp_t, link);
-			
-			if (seq_vp->seq == sequence) {
-				async_answer_0(iid, EEXISTS);
-				return;
-			}
-		}
-		
-		sequence_vp_t *seq_vp =
-		    (sequence_vp_t *) malloc(sizeof(sequence_vp_t));
-		
-		if (seq_vp != NULL) {
-			link_initialize(&seq_vp->link);
-			seq_vp->seq = sequence;
-			seq_vp->current = 0;
-			
-			list_append(&seq_vp->link, &dev->active_vp->sequences);
-			async_answer_0(iid, EOK);
-		} else
-			async_answer_0(iid, ENOMEM);
-	} else
-		async_answer_0(iid, ENOENT);
-}
-
-static void fbsrv_vp_sequence_stop(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall)
-{
-	sequence_t *sequence = resolve_sequence(dev, IPC_GET_ARG1(*icall), iid);
-	if (sequence == NULL)
-		return;
-	
-	if (dev->active_vp) {
-		list_foreach(dev->active_vp->sequences, link) {
-			sequence_vp_t *seq_vp =
-			    list_get_instance(link, sequence_vp_t, link);
-			
-			if (seq_vp->seq == sequence) {
-				list_remove(&seq_vp->link);
-				free(seq_vp);
-				
-				async_answer_0(iid, EOK);
-				return;
-			}
-		}
-		
-		async_answer_0(iid, ENOENT);
-	} else
-		async_answer_0(iid, ENOENT);
-}
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	fbdev_t *dev = NULL;
-	service_id_t dsid = (service_id_t) IPC_GET_ARG1(*icall);
-	
-	list_foreach(fbdevs, link) {
-		fbdev_t *fbdev = list_get_instance(link, fbdev_t, link);
-		if (fbdev->dsid == dsid) {
-			dev = fbdev;
-			break;
-		}
-	}
-	
-	if (dev == NULL) {
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	if (atomic_get(&dev->refcnt) > 0) {
-		async_answer_0(iid, ELIMIT);
-		return;
-	}
-	
-	/*
-	 * Accept the connection
-	 */
-	
-	atomic_inc(&dev->refcnt);
-	dev->claimed = true;
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid =
-		    async_get_call_timeout(&call, TICK_INTERVAL);
-		
-		if (!callid) {
-			fbsrv_vp_cursor_flash(dev);
-			fbsrv_sequences_update(dev);
-			continue;
-		}
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			dev->claimed = false;
-			atomic_dec(&dev->refcnt);
-			async_answer_0(callid, EOK);
-			break;
-		}
-		
-		switch (IPC_GET_IMETHOD(call)) {
-			
-			/* Screen methods */
-			
-			case FB_GET_RESOLUTION:
-				fbsrv_get_resolution(dev, callid, &call);
-				break;
-			case FB_YIELD:
-				fbsrv_yield(dev, callid, &call);
-				break;
-			case FB_CLAIM:
-				fbsrv_claim(dev, callid, &call);
-				break;
-			case FB_POINTER_UPDATE:
-				fbsrv_pointer_update(dev, callid, &call);
-				break;
-			
-			/* Object methods */
-			
-			case FB_VP_CREATE:
-				fbsrv_vp_create(dev, callid, &call);
-				break;
-			case FB_VP_DESTROY:
-				fbsrv_vp_destroy(dev, callid, &call);
-				break;
-			case FB_FRONTBUF_CREATE:
-				fbsrv_frontbuf_create(dev, callid, &call);
-				break;
-			case FB_FRONTBUF_DESTROY:
-				fbsrv_frontbuf_destroy(dev, callid, &call);
-				break;
-			case FB_IMAGEMAP_CREATE:
-				fbsrv_imagemap_create(dev, callid, &call);
-				break;
-			case FB_IMAGEMAP_DESTROY:
-				fbsrv_imagemap_destroy(dev, callid, &call);
-				break;
-			case FB_SEQUENCE_CREATE:
-				fbsrv_sequence_create(dev, callid, &call);
-				break;
-			case FB_SEQUENCE_DESTROY:
-				fbsrv_sequence_destroy(dev, callid, &call);
-				break;
-			case FB_SEQUENCE_ADD_IMAGEMAP:
-				fbsrv_sequence_add_imagemap(dev, callid, &call);
-				break;
-			
-			/* Viewport stateful methods */
-			
-			case FB_VP_FOCUS:
-				fbsrv_vp_focus(dev, callid, &call);
-				break;
-			case FB_VP_CLEAR:
-				fbsrv_vp_clear(dev, callid, &call);
-				break;
-			case FB_VP_GET_DIMENSIONS:
-				fbsrv_vp_get_dimensions(dev, callid, &call);
-				break;
-			case FB_VP_GET_CAPS:
-				fbsrv_vp_get_caps(dev, callid, &call);
-				break;
-			
-			/* Style methods (viewport specific) */
-			
-			case FB_VP_CURSOR_UPDATE:
-				fbsrv_vp_cursor_update(dev, callid, &call);
-				break;
-			case FB_VP_SET_STYLE:
-				fbsrv_vp_set_style(dev, callid, &call);
-				break;
-			case FB_VP_SET_COLOR:
-				fbsrv_vp_set_color(dev, callid, &call);
-				break;
-			case FB_VP_SET_RGB_COLOR:
-				fbsrv_vp_set_rgb_color(dev, callid, &call);
-				break;
-			
-			/* Text output methods (viewport specific) */
-			
-			case FB_VP_PUTCHAR:
-				fbsrv_vp_putchar(dev, callid, &call);
-				break;
-			case FB_VP_UPDATE:
-				fbsrv_vp_update(dev, callid, &call);
-				break;
-			case FB_VP_DAMAGE:
-				fbsrv_vp_damage(dev, callid, &call);
-				break;
-			
-			/* Image map methods (viewport specific) */
-			
-			case FB_VP_IMAGEMAP_DAMAGE:
-				fbsrv_vp_imagemap_damage(dev, callid, &call);
-				break;
-			
-			/* Sequence methods (viewport specific) */
-			
-			case FB_VP_SEQUENCE_START:
-				fbsrv_vp_sequence_start(dev, callid, &call);
-				break;
-			case FB_VP_SEQUENCE_STOP:
-				fbsrv_vp_sequence_stop(dev, callid, &call);
-				break;
-			
-			default:
-				async_answer_0(callid, EINVAL);
-		}
-	}
-}
-
-int main(int argc, char *argv[])
-{
-	printf("%s: HelenOS framebuffer service\n", NAME);
-	
-	/* Register server */
-	async_set_client_connection(client_connection);
-	int rc = loc_server_register(NAME);
-	if (rc != EOK) {
-		printf("%s: Unable to register driver\n", NAME);
-		return rc;
-	}
-	
-	ega_init();
-	kchar_init();
-	kfb_init();
-	niagara_init();
-	ski_init();
-	
-	printf("%s: Accepting connections\n", NAME);
-	task_retval(0);
-	async_manager();
-	
-	/* Never reached */
-	return 0;
-}
Index: pace/srv/hid/fb/fb.h
===================================================================
--- uspace/srv/hid/fb/fb.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,152 +1,0 @@
-/*
- * Copyright (c) 2011 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.
- */
-
-#ifndef FB_FB_H_
-#define FB_FB_H_
-
-#include <sys/types.h>
-#include <bool.h>
-#include <loc.h>
-#include <io/console.h>
-#include <io/style.h>
-#include <io/color.h>
-#include <fb.h>
-#include <screenbuffer.h>
-#include <imgmap.h>
-
-struct fbdev;
-struct fbvp;
-
-typedef struct {
-	int (* yield)(struct fbdev *dev);
-	int (* claim)(struct fbdev *dev);
-	void (* pointer_update)(struct fbdev *dev, sysarg_t x, sysarg_t y,
-	    bool visible);
-	
-	int (* get_resolution)(struct fbdev *dev, sysarg_t *width,
-	    sysarg_t *height);
-	void (* font_metrics)(struct fbdev *dev, sysarg_t width,
-	    sysarg_t height, sysarg_t *cols, sysarg_t *rows);
-	
-	int (* vp_create)(struct fbdev *dev, struct fbvp *vp);
-	void (* vp_destroy)(struct fbdev *dev, struct fbvp *vp);
-	
-	void (* vp_clear)(struct fbdev *dev, struct fbvp *vp);
-	console_caps_t (* vp_get_caps)(struct fbdev *dev, struct fbvp *vp);
-	
-	void (* vp_cursor_update)(struct fbdev *dev, struct fbvp *vp,
-	    sysarg_t prev_col, sysarg_t prev_row, sysarg_t col, sysarg_t row,
-	    bool visible);
-	void (* vp_cursor_flash)(struct fbdev *dev, struct fbvp *vp,
-	    sysarg_t col, sysarg_t row);
-	
-	void (* vp_char_update)(struct fbdev *dev, struct fbvp *vp, sysarg_t col,
-	    sysarg_t row);
-	
-	void (* vp_imgmap_damage)(struct fbdev *dev, struct fbvp *vp,
-	    imgmap_t *imgmap, sysarg_t col, sysarg_t row, sysarg_t cols,
-	    sysarg_t rows);
-} fbdev_ops_t;
-
-typedef struct fbdev {
-	link_t link;
-	
-	atomic_t refcnt;
-	bool claimed;
-	
-	sysarg_t index;
-	service_id_t dsid;
-	struct fbvp *active_vp;
-	
-	list_t vps;
-	list_t frontbufs;
-	list_t imagemaps;
-	list_t sequences;
-	
-	fbdev_ops_t ops;
-	void *data;
-} fbdev_t;
-
-typedef struct fbvp {
-	link_t link;
-	
-	sysarg_t x;
-	sysarg_t y;
-	
-	sysarg_t width;
-	sysarg_t height;
-	
-	sysarg_t cols;
-	sysarg_t rows;
-	
-	char_attrs_t attrs;
-	list_t sequences;
-	
-	screenbuffer_t *backbuf;
-	sysarg_t top_row;
-	
-	bool cursor_active;
-	bool cursor_flash;
-	
-	void *data;
-} fbvp_t;
-
-typedef struct {
-	link_t link;
-	
-	size_t size;
-	unsigned int flags;
-	void *data;
-} frontbuf_t;
-
-typedef struct {
-	link_t link;
-	link_t seq_link;
-	
-	size_t size;
-	unsigned int flags;
-	void *data;
-} imagemap_t;
-
-typedef struct {
-	link_t link;
-	
-	list_t imagemaps;
-	size_t count;
-} sequence_t;
-
-typedef struct {
-	link_t link;
-	
-	sequence_t *seq;
-	size_t current;
-} sequence_vp_t;
-
-extern fbdev_t *fbdev_register(fbdev_ops_t *, void *);
-
-#endif
Index: pace/srv/hid/fb/gfx/font-8x16.c
===================================================================
--- uspace/srv/hid/fb/gfx/font-8x16.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,3272 +1,0 @@
-/*
- * Copyright (c) 2000 Dmitry Bolkhovityanov
- * Copyright (c) 2009 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 genarch
- * @{
- */
-/** @file
- */
-
-#include <sys/types.h>
-#include "font-8x16.h"
-
-/** Convert character to font glyph index
- *
- * The font does not cover all Unicode characters.
- * This function converts the character to an appropriate
- * glyph in the font or returns an index to the question
- * mark glyph if no specific glyph exists.
- *
- */
-uint16_t fb_font_glyph(const wchar_t ch)
-{
-	if (ch == 0x0000)
-		return 0;
-	
-	if ((ch >= 0x0020) && (ch <= 0x007f))
-		return (ch - 32);
-	
-	if ((ch >= 0x00a0) && (ch <= 0x021f))
-		return (ch - 64);
-	
-	if ((ch >= 0x0222) && (ch <= 0x0233))
-		return (ch - 66);
-	
-	if ((ch >= 0x0250) && (ch <= 0x02ad))
-		return (ch - 94);
-	
-	if ((ch >= 0x02b0) && (ch <= 0x02cf))
-		return (ch - 96);
-	
-	if ((ch >= 0x02d8) && (ch <= 0x02dd))
-		return (ch - 104);
-	
-	if (ch == 0x02ee)
-		return 630;
-	
-	if ((ch >= 0x0300) && (ch <= 0x0301))
-		return (ch - 137);
-	
-	if (ch == 0x0303)
-		return 633;
-	
-	if (ch == 0x0309)
-		return 634;
-	
-	if ((ch >= 0x0312) && (ch <= 0x0314))
-		return (ch - 151);
-	
-	if (ch == 0x0323)
-		return 638;
-	
-	if ((ch >= 0x0340) && (ch <= 0x0341))
-		return (ch - 193);
-	
-	if ((ch >= 0x0374) && (ch <= 0x0375))
-		return (ch - 243);
-	
-	if (ch == 0x037a)
-		return 643;
-	
-	if (ch == 0x037e)
-		return 644;
-	
-	if ((ch >= 0x0384) && (ch <= 0x038a))
-		return (ch - 255);
-	
-	if (ch == 0x038c)
-		return 652;
-	
-	if ((ch >= 0x038e) && (ch <= 0x03a1))
-		return (ch - 257);
-	
-	if ((ch >= 0x03a3) && (ch <= 0x03ce))
-		return (ch - 258);
-	
-	if ((ch >= 0x03d0) && (ch <= 0x03d7))
-		return (ch - 259);
-	
-	if ((ch >= 0x03da) && (ch <= 0x03f3))
-		return (ch - 261);
-	
-	if ((ch >= 0x0400) && (ch <= 0x0486))
-		return (ch - 273);
-	
-	if ((ch >= 0x0488) && (ch <= 0x04ce))
-		return (ch - 274);
-	
-	if ((ch >= 0x04d0) && (ch <= 0x04f5))
-		return (ch - 275);
-	
-	if ((ch >= 0x04f8) && (ch <= 0x04f9))
-		return (ch - 277);
-	
-	if ((ch >= 0x0500) && (ch <= 0x050f))
-		return (ch - 283);
-	
-	if ((ch >= 0x0530) && (ch <= 0x0556))
-		return (ch - 315);
-	
-	if ((ch >= 0x0559) && (ch <= 0x055f))
-		return (ch - 317);
-	
-	if ((ch >= 0x0561) && (ch <= 0x0587))
-		return (ch - 318);
-	
-	if ((ch >= 0x0589) && (ch <= 0x058a))
-		return (ch - 319);
-	
-	if ((ch >= 0x0591) && (ch <= 0x05a1))
-		return (ch - 325);
-	
-	if ((ch >= 0x05a3) && (ch <= 0x05b9))
-		return (ch - 326);
-	
-	if ((ch >= 0x05bb) && (ch <= 0x05c4))
-		return (ch - 327);
-	
-	if ((ch >= 0x05d0) && (ch <= 0x05ea))
-		return (ch - 338);
-	
-	if ((ch >= 0x05f0) && (ch <= 0x05f4))
-		return (ch - 343);
-	
-	if (ch == 0x060c)
-		return 1182;
-	
-	if (ch == 0x061b)
-		return 1183;
-	
-	if (ch == 0x061f)
-		return 1184;
-	
-	if ((ch >= 0x0621) && (ch <= 0x063a))
-		return (ch - 384);
-	
-	if ((ch >= 0x0640) && (ch <= 0x0655))
-		return (ch - 389);
-	
-	if ((ch >= 0x0660) && (ch <= 0x066d))
-		return (ch - 399);
-	
-	if ((ch >= 0x0670) && (ch <= 0x06ed))
-		return (ch - 401);
-	
-	if ((ch >= 0x06f0) && (ch <= 0x06fe))
-		return (ch - 403);
-	
-	if (ch == 0x10d3)
-		return 1388;
-	
-	if (ch == 0x10d7)
-		return 1389;
-	
-	if (ch == 0x10da)
-		return 1390;
-	
-	if (ch == 0x10dd)
-		return 1391;
-	
-	if (ch == 0x10e6)
-		return 1392;
-	
-	if ((ch >= 0x1e00) && (ch <= 0x1e9b))
-		return (ch - 6287);
-	
-	if ((ch >= 0x1ea0) && (ch <= 0x1ef9))
-		return (ch - 6291);
-	
-	if ((ch >= 0x1f00) && (ch <= 0x1f07))
-		return (ch - 6297);
-	
-	if ((ch >= 0x2000) && (ch <= 0x2027))
-		return (ch - 6545);
-	
-	if ((ch >= 0x2030) && (ch <= 0x2046))
-		return (ch - 6553);
-	
-	if ((ch >= 0x2048) && (ch <= 0x204d))
-		return (ch - 6554);
-	
-	if (ch == 0x2070)
-		return 1716;
-	
-	if ((ch >= 0x2074) && (ch <= 0x208f))
-		return (ch - 6591);
-	
-	if ((ch >= 0x20a0) && (ch <= 0x20af))
-		return (ch - 6607);
-	
-	if ((ch >= 0x2100) && (ch <= 0x213a))
-		return (ch - 6687);
-	
-	if ((ch >= 0x2153) && (ch <= 0x2183))
-		return (ch - 6711);
-	
-	if ((ch >= 0x2190) && (ch <= 0x21f3))
-		return (ch - 6723);
-	
-	if ((ch >= 0x2200) && (ch <= 0x22f1))
-		return (ch - 6735);
-	
-	if (ch == 0x2300)
-		return 2211;
-	
-	if (ch == 0x2302)
-		return 2212;
-	
-	if ((ch >= 0x2308) && (ch <= 0x230b))
-		return (ch - 6755);
-	
-	if (ch == 0x2310)
-		return 2217;
-	
-	if (ch == 0x2318)
-		return 2218;
-	
-	if ((ch >= 0x231a) && (ch <= 0x231b))
-		return (ch - 6767);
-	
-	if ((ch >= 0x2320) && (ch <= 0x2321))
-		return (ch - 6771);
-	
-	if ((ch >= 0x2329) && (ch <= 0x232a))
-		return (ch - 6778);
-	
-	if ((ch >= 0x239b) && (ch <= 0x23bd))
-		return (ch - 6890);
-	
-	if (ch == 0x23ce)
-		return 2260;
-	
-	if ((ch >= 0x2409) && (ch <= 0x240d))
-		return (ch - 6964);
-	
-	if ((ch >= 0x2423) && (ch <= 0x2424))
-		return (ch - 6985);
-	
-	if (ch == 0x2426)
-		return 2268;
-	
-	if ((ch >= 0x2500) && (ch <= 0x2595))
-		return (ch - 7203);
-	
-	if ((ch >= 0x25a0) && (ch <= 0x25f7))
-		return (ch - 7213);
-	
-	if ((ch >= 0x2600) && (ch <= 0x2602))
-		return (ch - 7221);
-	
-	if ((ch >= 0x2605) && (ch <= 0x260d))
-		return (ch - 7223);
-	
-	if ((ch >= 0x2610) && (ch <= 0x2613))
-		return (ch - 7225);
-	
-	if (ch == 0x2620)
-		return 2523;
-	
-	if (ch == 0x2622)
-		return 2524;
-	
-	if (ch == 0x2626)
-		return 2525;
-	
-	if ((ch >= 0x2628) && (ch <= 0x262b))
-		return (ch - 7242);
-	
-	if ((ch >= 0x262e) && (ch <= 0x2637))
-		return (ch - 7244);
-	
-	if ((ch >= 0x2639) && (ch <= 0x2653))
-		return (ch - 7245);
-	
-	if ((ch >= 0x2660) && (ch <= 0x2667))
-		return (ch - 7257);
-	
-	if ((ch >= 0x2669) && (ch <= 0x266f))
-		return (ch - 7258);
-	
-	if ((ch >= 0xfb00) && (ch <= 0xfb05))
-		return (ch - 61674);
-	
-	if ((ch >= 0xfb50) && (ch <= 0xfbb1))
-		return (ch - 61748);
-	
-	if ((ch >= 0xfbd3) && (ch <= 0xfbe9))
-		return (ch - 61781);
-	
-	if ((ch >= 0xfbfc) && (ch <= 0xfbff))
-		return (ch - 61799);
-	
-	if ((ch >= 0xfc5b) && (ch <= 0xfc63))
-		return (ch - 61890);
-	
-	if (ch == 0xfc90)
-		return 2722;
-	
-	if ((ch >= 0xfcf2) && (ch <= 0xfcf4))
-		return (ch - 62031);
-	
-	if ((ch >= 0xfd3c) && (ch <= 0xfd3f))
-		return (ch - 62102);
-	
-	if (ch == 0xfdf2)
-		return 2730;
-	
-	if ((ch >= 0xfe50) && (ch <= 0xfe52))
-		return (ch - 62373);
-	
-	if ((ch >= 0xfe54) && (ch <= 0xfe66))
-		return (ch - 62374);
-	
-	if ((ch >= 0xfe68) && (ch <= 0xfe6b))
-		return (ch - 62375);
-	
-	if ((ch >= 0xfe70) && (ch <= 0xfe72))
-		return (ch - 62379);
-	
-	if (ch == 0xfe74)
-		return 2760;
-	
-	if ((ch >= 0xfe76) && (ch <= 0xfefc))
-		return (ch - 62381);
-	
-	if (ch == 0xfeff)
-		return 2896;
-	
-	return 2898;
-}
-
-uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES] = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x30, 0x30, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00},
-	{0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x42, 0x99, 0xa5, 0xa1, 0xa1, 0xa5, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x44, 0xba, 0xb2, 0xaa, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0xd8, 0x30, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf6, 0xc0, 0xc0, 0xc0, 0x00},
-	{0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x38, 0x00},
-	{0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00},
-	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00},
-	{0x00, 0xe0, 0x30, 0x62, 0x36, 0xec, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x30, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x38, 0x6c, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x0c, 0x38, 0x00},
-	{0x30, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x44, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x18, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x3c, 0x42, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7a, 0xc4, 0xce, 0xce, 0xd6, 0xd6, 0xe6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x44, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf0, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x66, 0x66, 0xec, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
-	{0x00, 0x00, 0x60, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x76, 0x1c, 0x3c, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xc4, 0xce, 0xd6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x00, 0x7c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x0c, 0x18, 0x0e, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x0c, 0x18, 0x0e, 0x00},
-	{0x0c, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x44, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x3e, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x7c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x18, 0x30, 0x1c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
-	{0x6c, 0x38, 0x10, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x44, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
-	{0x6c, 0x38, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
-	{0x18, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x18, 0x18, 0x30},
-	{0x00, 0x18, 0x30, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
-	{0x10, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x44, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0xff, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0xf8, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x7e, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7e, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x66, 0x3c, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x3c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x30, 0x1c, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x30, 0x1c, 0x00},
-	{0x18, 0x18, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf7, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7b, 0x7b, 0xee, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x00, 0xee, 0x66, 0x66, 0x66, 0x66, 0x66, 0xf6, 0x06, 0x66, 0x3c, 0x00},
-	{0x08, 0x1c, 0x22, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x04, 0x0e, 0x1b, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
-	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x30},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x30},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x30, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x30},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x30},
-	{0x6c, 0x38, 0x10, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x66, 0x66, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0x30, 0x30, 0x30, 0x36, 0x36, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x78, 0xe0, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x1e, 0x78, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x18, 0x18, 0x30},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x18, 0x18, 0x30},
-	{0x6c, 0x38, 0x10, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x60, 0x60, 0xc0, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x06, 0x06, 0x1c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x1c, 0x00},
-	{0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x66, 0xcc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0xcc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6e, 0xd8, 0xd8, 0xd8, 0xde, 0xd8, 0xd8, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xd6, 0xd6, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x30},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x18, 0x18, 0x30},
-	{0x6c, 0x38, 0x10, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
-	{0x6c, 0x38, 0x10, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x0c, 0x38, 0x00},
-	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x18, 0x0c, 0x38, 0x00},
-	{0x6c, 0x38, 0x10, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0x10, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x76, 0xdc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x78, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0x78, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x38, 0x6c, 0x38, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x6c, 0x38, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x66, 0xcc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x30, 0x60, 0x38, 0x00},
-	{0x10, 0x38, 0x44, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x44, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0xf8, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0xb3, 0xb3, 0x33, 0x3e, 0x33, 0x33, 0x33, 0x33, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x64, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x62, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xe6, 0xe6, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0xe0, 0xe0, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x06, 0x06, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x03, 0x3e, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x03, 0x7e, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xb6, 0xb3, 0x33, 0x33, 0x33, 0x33, 0x33, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x4c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0x4c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x18, 0xcc, 0x78, 0x00},
-	{0x00, 0x00, 0xfe, 0xcc, 0x8c, 0x2c, 0x3c, 0x2c, 0x0c, 0x8c, 0xcc, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x06, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc2, 0xc0, 0x78, 0xc0, 0xc0, 0xc2, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x00},
-	{0x00, 0x00, 0x1c, 0x36, 0x32, 0x30, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x00},
-	{0x00, 0x03, 0x3e, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x38, 0x6c, 0x38, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xf3, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe6, 0x6d, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc8, 0x38, 0x70, 0xd0, 0x38, 0x38, 0x6c, 0x64, 0xc6, 0xc2, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0xec, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x76, 0x7e, 0x7e, 0x6e, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0xc0, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x03, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x03, 0x03, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x73, 0xdf, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x03, 0x03, 0x03, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0xdf, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x03, 0x03, 0x03, 0x00},
-	{0x00, 0x00, 0x7e, 0xb3, 0xb3, 0x33, 0x3e, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
-	{0x00, 0x00, 0xf0, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x78, 0x6c, 0x6c, 0xe6, 0x06, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x38, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x0c, 0x38, 0x60, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0x62, 0x30, 0x18, 0x18, 0x30, 0x62, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0xd8, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00},
-	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x0c, 0x6c, 0x38, 0x00},
-	{0x00, 0x00, 0x7e, 0xfe, 0x9a, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1c, 0x36, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00},
-	{0x03, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x03, 0x03, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xee, 0x6c, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x63, 0xb3, 0xb3, 0x33, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x06, 0x0d, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0xf0, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x7e, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0xfc, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x7c, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc0, 0x60, 0x30, 0x18, 0x7c, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x60, 0x30, 0x78, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x7c, 0xc0, 0xc6, 0x7c, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x7e, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x60, 0x60, 0x78, 0x0c, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x60, 0x78, 0x0c, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x18, 0x4c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x70, 0x60, 0x60, 0xf0, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x1b, 0x0e, 0x04, 0xf7, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf5, 0xda, 0xd8, 0xdf, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3d, 0x1a, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0x6f, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xcb, 0xf6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf3, 0x63, 0x60, 0x67, 0x63, 0x63, 0x63, 0x67, 0x6f, 0xff, 0x03, 0x1b, 0x0e, 0x00},
-	{0x00, 0x00, 0xe3, 0x63, 0x60, 0x67, 0x63, 0x63, 0x63, 0x63, 0x63, 0xf3, 0x03, 0x33, 0x1e, 0x00},
-	{0x00, 0x00, 0xdb, 0xdb, 0xfb, 0xfb, 0xfb, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xdb, 0xdb, 0xf8, 0xff, 0xfb, 0xfb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x33, 0x1e, 0x00},
-	{0x00, 0x00, 0x03, 0x03, 0x00, 0xb7, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x33, 0x1e, 0x00},
-	{0x6c, 0x38, 0x10, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x7c, 0x00, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x78, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x10, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x30, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x28, 0x10, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x78, 0x30, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x20, 0x10, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x30, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x7c, 0x00, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x7c, 0x00, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x7c, 0x30, 0x30, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x7c, 0x00, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x7c, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xdf, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x3e, 0xcc, 0x78, 0x00},
-	{0x6c, 0x38, 0x10, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
-	{0x6c, 0x38, 0x10, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
-	{0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
-	{0x6c, 0x38, 0x10, 0xfe, 0x0c, 0x18, 0x30, 0x7c, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00},
-	{0x00, 0x1b, 0x0e, 0x04, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
-	{0x00, 0x00, 0xf7, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xdc, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf0, 0xd8, 0xd8, 0xdf, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0x6f, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
-	{0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xdb, 0xfb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x70, 0x60, 0x60, 0x60, 0x60, 0xe0, 0x00},
-	{0x60, 0x30, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x38, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x38, 0x6c, 0x38, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x7a, 0xc4, 0xce, 0xce, 0xd6, 0xe6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7a, 0xc4, 0xce, 0xd6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00},
-	{0xcc, 0x66, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0x66, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x38, 0x6c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0xcc, 0x66, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0x66, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x38, 0x6c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0xcc, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x3c, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0xcc, 0x66, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0x66, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0xcc, 0x66, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0x66, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x38, 0x6c, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0xcc, 0x66, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0x66, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x18, 0x18, 0x30},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x18, 0x18, 0x30},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x30},
-	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x18, 0x18, 0x30},
-	{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x1c, 0x74, 0x06, 0x06, 0x06, 0x06, 0x1c, 0xf0, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0e, 0x3c, 0x06, 0x06, 0x1c, 0xf0, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x24, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xfc, 0x06, 0x0c, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc0, 0xfc, 0x06, 0x0c, 0x00, 0x00},
-	{0x30, 0x30, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x18, 0x0c, 0x38, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
-	{0x7c, 0x00, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x7c, 0x00, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x7c, 0x00, 0x72, 0x9c, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x7c, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x7c, 0x00, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x7c, 0x00, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x5c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xdc, 0xe6, 0x7c, 0x80, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0d, 0x06, 0x00},
-	{0x00, 0x00, 0x06, 0x0d, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x6c, 0x8e, 0x16, 0x26, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xcd, 0x0d, 0x38, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xdc, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x06, 0x06, 0x1f, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
-	{0x00, 0x00, 0x00, 0x06, 0x0d, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x46, 0x6c, 0x2c, 0x2c, 0x38, 0x18, 0x18, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x64, 0x28, 0x38, 0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xdc, 0x6c, 0x0c, 0x0c, 0x0e, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x06, 0x06, 0x1c, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x7b, 0xde, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x78, 0x58, 0x3e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x7f, 0x63, 0x66, 0x6c, 0x7e, 0x63, 0xf3, 0x03, 0x33, 0x1e, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6e, 0x06, 0x06, 0x06, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x06, 0x06, 0x1c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0xc0, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x03, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xd8, 0xd8, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xdc, 0x6c, 0x0c, 0x0d, 0x06, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0x60, 0x60, 0x6c, 0x38, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x66, 0x6c, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xfc, 0xc0, 0xd8, 0x70, 0x00},
-	{0x00, 0x00, 0x0e, 0x1b, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x98, 0xd8, 0x70, 0x00},
-	{0x00, 0x00, 0x0e, 0x1b, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x98, 0xd8, 0x70, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0xd8, 0x70, 0x00},
-	{0x00, 0x00, 0x70, 0xd8, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x3b, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3e, 0x60, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x06, 0x06, 0x03, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xcb, 0xfe, 0x10, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x7e, 0xc7, 0x7c, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0x70, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x76, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x03, 0x7e, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x0c, 0x00, 0x1c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7e, 0xcc, 0x78, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xcc, 0x6c, 0x3c, 0x3c, 0x6c, 0xcc, 0x0c, 0x0c, 0x0e, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x06, 0x0d, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x1c, 0x18, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0x70, 0x30, 0xfc, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0x6f, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xdb, 0xdb, 0xde, 0xde, 0xdb, 0x6b, 0x03, 0x1b, 0x0e, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xdb, 0xdd, 0x6f, 0x04, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x20, 0x60, 0x60, 0xf6, 0x6d, 0x6c, 0x66, 0x63, 0x6b, 0x36, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x26, 0x6d, 0x6c, 0xfc, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x3c, 0x0c, 0x2c, 0x18, 0x00},
-	{0x00, 0x00, 0x20, 0x60, 0x60, 0xf6, 0x6d, 0x6c, 0x6c, 0x6e, 0x6d, 0x36, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0xd8, 0xc0, 0xfe, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x03, 0x0e, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6d, 0x6c, 0x66, 0x63, 0x6b, 0xf6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6f, 0x6b, 0x63, 0x66, 0x6c, 0x6d, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xd6, 0x7c, 0x6c, 0x28, 0xc6, 0xd6, 0x7c, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0xc0, 0xc0, 0xf0, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0xc0, 0xf0, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xb0, 0xd8, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x18, 0x18, 0xd8, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x18, 0x18, 0xd8, 0x68, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0xd8, 0xd8, 0xf0, 0xd8, 0xd8, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc6, 0xd6, 0x7c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xd8, 0xd8, 0x78, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x30, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0xd8, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0xd8, 0xc0, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x70, 0xc0, 0x70, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0x70, 0x18, 0x70, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x20, 0x20, 0x70, 0x70, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0xd8, 0xd8, 0x70, 0x70, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x1c, 0x00},
-	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x6c, 0x6c, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x34, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00},
-	{0xc0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x30, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x60, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x34, 0x18, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0xc0, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0xc0, 0x3e, 0x32, 0x30, 0x34, 0x3c, 0x34, 0x30, 0x30, 0x32, 0x3e, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0xc0, 0x33, 0x33, 0x33, 0x33, 0x3f, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0xc0, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0xc0, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0xc0, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0xc0, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x36, 0x36, 0x77, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0x82, 0x44, 0x7c, 0x44, 0x00, 0x82, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0x62, 0x30, 0x18, 0x18, 0x30, 0x62, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x92, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00},
-	{0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x6c, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x6c, 0x60, 0x60, 0x60, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x46, 0x6c, 0x2c, 0x2c, 0x38, 0x18, 0x18, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x30, 0x18, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x46, 0x7c, 0x18, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0x20, 0x30, 0x10, 0x38, 0x38, 0x6c, 0x64, 0xc6, 0xc2, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf6, 0xc0, 0xc0, 0xc0, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x66, 0x6c, 0x3c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x3c, 0x30, 0x60, 0x3c, 0x60, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x46, 0x2c, 0x2c, 0x18, 0x30, 0x68, 0x68, 0xc4, 0xc2, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x6c, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x36, 0x1e, 0xc6, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc2, 0x65, 0x24, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0xc0, 0x21, 0x32, 0x12, 0x1c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0xc2, 0x65, 0x24, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xa6, 0x2c, 0x38, 0x68, 0xca, 0xc4, 0x0c, 0x18, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x3c, 0x06, 0x06, 0x1c, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x32, 0x30, 0x30, 0x3c, 0x34, 0x30, 0x30, 0x30, 0x30, 0x00},
-	{0x00, 0x60, 0x30, 0x30, 0x60, 0x63, 0xff, 0xc6, 0x06, 0x0c, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x60, 0x60, 0xfe, 0xfe, 0x0c, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xac, 0x26, 0x26, 0x0b, 0x0b, 0x1b, 0x1b, 0x1b, 0x1b, 0x03, 0x02, 0x04, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x28, 0x4c, 0x14, 0x24, 0x06, 0x02, 0x02, 0x00},
-	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6d, 0x03, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6d, 0x03, 0x7e, 0x00, 0x00},
-	{0x00, 0x00, 0x76, 0xd6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x06, 0x76, 0x9c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0x7c, 0xd6, 0x66, 0x06, 0x06, 0x66, 0xbc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x3c, 0x60, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x26, 0x1c, 0x70, 0xc0, 0xc2, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0x68, 0x38, 0x30, 0x38, 0x38, 0x4c, 0x4c, 0x86, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xba, 0x30, 0x38, 0x28, 0x4c, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0xc0, 0xcc, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xdc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x18, 0x7e, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x1c, 0x18, 0x7e, 0x58, 0x18, 0x18, 0x18, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xa6, 0x2c, 0x38, 0x68, 0xca, 0xc4, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0xc0, 0x60, 0x3c, 0x06, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
-	{0x30, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xb2, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x03, 0x06, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xf8, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xd8, 0xd8, 0xd8, 0xde, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xd8, 0xfe, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xb2, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x18, 0x00, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x38, 0x10, 0x10, 0x00},
-	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfe, 0xc6, 0x82, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0xc6, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfe, 0x06, 0x02, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xff, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0xb0, 0xb0, 0x30, 0x3c, 0x36, 0x36, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x3e, 0x06, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x9c, 0xb6, 0xb6, 0xb6, 0xf6, 0xb6, 0xb6, 0xb6, 0xb6, 0x9c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0xcc, 0xcc, 0xcc, 0x7c, 0x6c, 0x6c, 0x6c, 0x6c, 0xce, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x06, 0x7c, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfe, 0xc6, 0x82, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfe, 0x06, 0x02, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xff, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb0, 0x30, 0x3c, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3e, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xb6, 0xb6, 0xf6, 0xb6, 0xb6, 0x9c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xcc, 0xcc, 0x7c, 0x6c, 0x6c, 0xce, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0xf8, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x06, 0x06, 0x1c, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xf8, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd8, 0xd8, 0xde, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xfe, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0xf8, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x30, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x38, 0x10, 0x10, 0x00},
-	{0x00, 0x00, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0xfc, 0xb4, 0x30, 0x3c, 0x36, 0x36, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x30, 0xfc, 0xb4, 0x30, 0x3c, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xce, 0xdb, 0xd9, 0xd8, 0xfe, 0xd8, 0xd8, 0xd9, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xdb, 0xd8, 0xfe, 0xd8, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0x6c, 0xfe, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x6c, 0x7c, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x88, 0x8c, 0x9c, 0x96, 0xf6, 0xb6, 0xbf, 0xab, 0xeb, 0xeb, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x8c, 0x9c, 0xf6, 0xbe, 0xab, 0xeb, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0x6c, 0x6c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x6c, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0xa3, 0xb2, 0x96, 0xfc, 0x9c, 0xbe, 0xaa, 0xab, 0xeb, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xa3, 0x96, 0xfe, 0xab, 0xab, 0xeb, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x10, 0x7c, 0xc6, 0x06, 0x06, 0x7c, 0x06, 0x06, 0x06, 0x7c, 0xc0, 0x7c, 0x00, 0x00},
-	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0x86, 0x06, 0x7c, 0x06, 0x06, 0x7c, 0xc0, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x96, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0x10, 0x96, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc2, 0xc6, 0xc6, 0xc4, 0xcc, 0x6c, 0x68, 0x78, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x64, 0x6c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0xcc, 0x66, 0x00, 0xc2, 0xc6, 0xc4, 0xc4, 0x6c, 0x68, 0x78, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0x66, 0x00, 0xc2, 0xc6, 0x64, 0x6c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0xd8, 0xd8, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6f, 0x03, 0x06, 0x1c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6f, 0x03, 0x06, 0x1c, 0x00},
-	{0x00, 0x10, 0x7c, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x7c, 0xd6, 0xc6, 0xc6, 0xc6, 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x00},
-	{0x04, 0x7c, 0x40, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x04, 0x7c, 0x40, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x7c, 0x54, 0x00, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0x54, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x3c, 0x0c, 0x0c, 0x0c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0x78, 0x18, 0x18, 0x00, 0x00},
-	{0x00, 0x00, 0x06, 0x06, 0x3c, 0x0f, 0x18, 0x18, 0xf0, 0x3c, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x04, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x40, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x04, 0x7c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x18, 0x66, 0x00, 0xc3, 0x00, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x50, 0x46, 0x00, 0x82, 0x41, 0x00, 0x62, 0x0a, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0xc6, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x6e, 0x64, 0x7a, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x6e, 0x64, 0x7a, 0x60, 0x60, 0xf0, 0x00},
-	{0x02, 0x06, 0xfe, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x02, 0x06, 0xfe, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0xf8, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0xf8, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xf6, 0x06, 0x16, 0x0c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x78, 0x6c, 0x66, 0xf6, 0x06, 0x16, 0x0c, 0x00},
-	{0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
-	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xdc, 0xf8, 0xdc, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xdc, 0xf8, 0xdc, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe6, 0x66, 0xf6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0xf0, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf3, 0xb3, 0xb3, 0x36, 0x3c, 0x3c, 0x36, 0x33, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0xb6, 0xbc, 0x3c, 0x36, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0xdf, 0xdb, 0xd9, 0xd8, 0xf8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xdb, 0xd9, 0xf8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0xd8, 0xd8, 0xd8, 0xde, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x0b, 0x06, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xfe, 0xdb, 0xdb, 0xdb, 0x03, 0x0b, 0x06, 0x00},
-	{0x00, 0x00, 0x7c, 0xc2, 0xcc, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xcc, 0x7a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc2, 0xcc, 0xd6, 0xd6, 0xcc, 0x7a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x0c, 0x38, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x0c, 0x04, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x0c, 0x04, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x3c, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0xf6, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7f, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7f, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0x7e, 0x16, 0x16, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0x7e, 0x16, 0x16, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x33, 0xb3, 0xb3, 0x7f, 0x30, 0x30, 0x30, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xb3, 0x7f, 0x30, 0x30, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x33, 0xb3, 0xb3, 0x7f, 0x30, 0x30, 0x30, 0x33, 0x1e, 0x0c, 0x18, 0x0e, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xb3, 0x7f, 0x30, 0x30, 0x33, 0x1e, 0x0c, 0x18, 0x0e, 0x00},
-	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x06, 0x16, 0x0c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x06, 0x16, 0x0c, 0x00},
-	{0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x06, 0x16, 0x0c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x06, 0x16, 0x0c, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0e, 0x0c, 0x08, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0e, 0x0c, 0x08, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
-	{0x6c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x06, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x86, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00},
-	{0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x3e, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x3e, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x66, 0xcc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0xcc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x7c, 0xcd, 0xcd, 0xcd, 0xcd, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcd, 0xcd, 0xcd, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xcc, 0x8c, 0x0c, 0x38, 0x0d, 0x0d, 0x0d, 0x0d, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x0c, 0x39, 0x0d, 0x0d, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x06, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0xcd, 0xcd, 0xcd, 0xcd, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xfd, 0xcd, 0xcd, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xce, 0xc6, 0xc6, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x1b, 0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5a, 0x18, 0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x64, 0x94, 0xba, 0x52, 0x4c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x7b, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x7f, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x7e, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x0c, 0xd8, 0xfe, 0xc3, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x06, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xcf, 0xd6, 0xd6, 0xd6, 0xd6, 0xcc, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x7f, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x06, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0xc0, 0xf6, 0xd6, 0xd6, 0xd6, 0xd6, 0xcc, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0x7f, 0x24, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0xf0, 0x3c, 0x0e, 0x04, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x6c, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0c, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x30, 0x60, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcf, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x7c, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x60, 0x60, 0x60, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x6c, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x16, 0x16, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x76, 0x1e, 0x0e, 0x0c, 0xd8, 0xfe, 0xc3, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x30, 0x18, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x63, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xfe, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0xd0, 0xd0, 0xd0, 0x7c, 0x16, 0x16, 0x16, 0xd6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x30, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x06, 0x3c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x1c, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7f, 0x0c, 0x0c, 0x0c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x0c, 0x0c, 0x0c, 0x00},
-	{0x00, 0x00, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x0f, 0x00},
-	{0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x0c, 0x18, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x7e, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xcf, 0xd6, 0xd6, 0xcc, 0xc0, 0xc0, 0xc0, 0x00},
-	{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x7f, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3e, 0x00},
-	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xf6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xca, 0xc0, 0xc0, 0xc0, 0x00},
-	{0x00, 0x00, 0x60, 0x38, 0x0c, 0x7f, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x00},
-	{0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x1c, 0x0c, 0x18, 0x3c, 0x64, 0x66, 0x62, 0x63, 0x3d, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0c, 0x0c, 0x0f, 0x00},
-	{0x00, 0x00, 0x0e, 0x18, 0x30, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0f, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x3e, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x3e, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7e, 0x06, 0x06, 0x06, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x76, 0x1c, 0x18, 0x30, 0x60, 0x3e, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x0f, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0x10, 0xdc, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x76, 0x10, 0x10, 0x10, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xfe, 0x60, 0x60, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0xd0, 0xd0, 0x7c, 0x16, 0x16, 0x16, 0x16, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
-	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xcc, 0xcc, 0xcc, 0xcc, 0x77, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x6c},
-	{0x18, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x38, 0x10, 0x38, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x60, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x0c, 0x00},
-	{0x10, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x74, 0xd6, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0xc0, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x03, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x18, 0x30, 0x00},
-	{0x0c, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x03, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x1b, 0x36, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x44, 0xaa, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x0a, 0x0c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x40, 0x50, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x3c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x18, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x60, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x6c, 0xd8, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x08, 0x30},
-	{0x60, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x40, 0xa0, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0x10, 0x10},
-	{0x18, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x06, 0x03, 0x00},
-	{0x48, 0xa8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x33, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x06, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x60, 0x66, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x18, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18},
-	{0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x18, 0x03, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x66, 0x76, 0xdc, 0xcc, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x0c, 0x0c, 0x1c, 0x36, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xcc, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xde, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xee, 0x66, 0x66, 0x66, 0x66, 0x66, 0x2c, 0xf8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x4c, 0xcc, 0xcc, 0xec, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x46, 0xc6, 0xc6, 0xe6, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xee, 0x66, 0x66, 0x6c, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x70, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xee, 0x66, 0x66, 0x34, 0x18, 0x0c, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x66, 0x64, 0x6c, 0x6e, 0x60, 0x60, 0x60, 0x60, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xf6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x66, 0x66, 0xc6, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x20, 0x1e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x02, 0x3c, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x20, 0x1c, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x18, 0x20, 0x1c, 0x20, 0x00, 0x00},
-	{0x00, 0x30, 0x40, 0x38, 0x40, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x28, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x88, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x20, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
-	{0x00, 0x40, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x40, 0x30, 0x4e, 0x49, 0x39, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x24, 0x00},
-	{0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x12, 0xca, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00},
-	{0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x14, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00},
-	{0x0a, 0x2a, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x01, 0x7e, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x10, 0x0c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x10, 0x0c, 0x10},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x20, 0x70, 0x70, 0x38, 0x18, 0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x44, 0xfc, 0xf8, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x4a, 0xfe, 0xf4, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x20, 0x40, 0x30, 0x10, 0x20, 0x42, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x38, 0x2c, 0x44, 0x42, 0x82, 0x82, 0xfe, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x80, 0xf8, 0x78, 0x08, 0x08, 0x08, 0x0c, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x82, 0xc6, 0xc6, 0x6c, 0x28, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0x10, 0x38, 0x28, 0x6c, 0xc6, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0xf8, 0x88, 0xf8, 0x78, 0x08, 0x0c, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x91, 0x92, 0x64, 0x08, 0x10, 0x26, 0x49, 0x89, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x18, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0xfe, 0x7c, 0x38, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x06, 0x29, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x06, 0x28, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x06, 0x28, 0x5e, 0x00, 0x00, 0x00},
-	{0x00, 0x07, 0x08, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x03, 0x04, 0x03, 0x14, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x03, 0x04, 0x03, 0x04, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x23, 0x54, 0x33, 0x24, 0x40, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x03, 0x04, 0x03, 0x04, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0x81, 0x7e, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x00, 0x08, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00},
-	{0x00, 0x14, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00},
-	{0x06, 0x08, 0x06, 0x08, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x08, 0x00, 0x08, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x94, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x88, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x08, 0x00, 0x14, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x94, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x20, 0x38, 0x28, 0x70, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x20, 0x38, 0x28, 0x70, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x00, 0x14, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x14, 0x00, 0x08, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x14, 0x00, 0x14, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x08, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x1c, 0x6a, 0x04, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x14, 0x08, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x12, 0x04, 0x18, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x14, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x15, 0x88, 0x88, 0x8a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x88, 0x90, 0x65, 0x00, 0x02, 0x00, 0x00, 0x00},
-	{0x00, 0x04, 0x00, 0x0a, 0x00, 0x01, 0x15, 0x88, 0x88, 0x90, 0x65, 0x00, 0x02, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x90, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x00, 0x2a, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x20, 0x00, 0x50, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x00},
-	{0x0a, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
-	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
-	{0x00, 0x01, 0x02, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x18, 0x20, 0x40, 0x3e, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x01, 0x02, 0x05, 0x0b, 0x48, 0x84, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x00, 0x29, 0x01, 0x19, 0x21, 0x19, 0xa1, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x09, 0x12, 0x05, 0x0b, 0x48, 0x84, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0xa4, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x44, 0x09, 0xa2, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x14, 0x08, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x02, 0x2a, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x14, 0x00, 0x08, 0x00},
-	{0x00, 0x08, 0x00, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x04, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x08, 0x14, 0x08, 0x00, 0x00},
-	{0x08, 0x00, 0x14, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0x3c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x38, 0x40, 0x38, 0x40, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x40, 0x38, 0x40, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x12, 0x2c, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x3c, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x28, 0x18, 0x10, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x08, 0x08, 0x08, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x20, 0x47, 0x88, 0x08, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x50, 0x20, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x08, 0x00, 0x08},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x14, 0x00, 0x08},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x80, 0x60, 0x80, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x40, 0x40, 0x43, 0x55, 0x7e, 0x80, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x2a, 0x20, 0x26, 0x2a, 0x7c, 0x80, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x0e, 0x1c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x14, 0x14, 0x08, 0x14, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x2c, 0x10, 0x28, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x15, 0x8a, 0x90, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x5a, 0xa5, 0x66, 0x5b, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x5a, 0x66, 0xa5, 0x5a, 0x00},
-	{0x00, 0x00, 0x18, 0x66, 0x42, 0x42, 0x81, 0x99, 0x99, 0x81, 0x42, 0x42, 0x66, 0x18, 0x00, 0x00},
-	{0x08, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x26, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x0c, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x8a, 0x90, 0x60},
-	{0x32, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x0c, 0x04, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x30, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x28, 0x54, 0xaa, 0x92, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x82, 0xfe, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x14, 0x08},
-	{0x08, 0x14, 0x22, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x10, 0x10, 0x10},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x20, 0x70, 0x70, 0x38, 0x18, 0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x44, 0xfc, 0xf8, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x4a, 0xfe, 0xf4, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x4e, 0xf0, 0xfe, 0x7c, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x38, 0x2c, 0x44, 0x42, 0x82, 0x92, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x3c, 0x60, 0x7e, 0x3c, 0x30, 0x60, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x82, 0xc6, 0xc6, 0x6c, 0x28, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0x10, 0x38, 0x28, 0x6c, 0xc6, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0xf8, 0x88, 0xf8, 0x78, 0x08, 0x0c, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x88, 0x88, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x40, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x88, 0x80, 0x41, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x20, 0x1e, 0x20, 0x00, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x3c, 0x40, 0x54, 0x54, 0x54, 0x54, 0x40, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x92, 0x92, 0x4c, 0x30, 0x4c, 0x02, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0xaa, 0xaa, 0xaa, 0x82, 0x82, 0x40, 0x30, 0x4c, 0x02, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x82, 0x82, 0x44, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x82, 0x82, 0x40, 0x30, 0x4c, 0x02, 0x00},
-	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x38, 0x6c, 0x38},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x38, 0x6c, 0x38},
-	{0x18, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x0c, 0xec, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x7c, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x0c, 0x38, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
-	{0x30, 0x30, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x60, 0x0c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x30, 0x18, 0x70, 0x00},
-	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x30, 0x18, 0x70, 0x00},
-	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x10, 0x38, 0x6c, 0x00},
-	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x10, 0x38, 0x6c, 0x00},
-	{0x60, 0x30, 0x00, 0x7c, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x30, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x7c, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x10, 0x38, 0x6c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x10, 0x38, 0x6c, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x76, 0xdc, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x76, 0xdc, 0x00},
-	{0x6c, 0x38, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x18, 0x0c, 0x38, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
-	{0x18, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x30, 0x00, 0x38, 0x6c, 0x64, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x7c, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
-	{0x30, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x0c, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
-	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x60, 0x30, 0xe0, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x30, 0x18, 0x70, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x6c, 0x38, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x6c, 0x38, 0x00},
-	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x76, 0xdc, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x76, 0xdc, 0x00},
-	{0x0c, 0x18, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x0c, 0xec, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x7c, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x7c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x7e, 0x00, 0x00},
-	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x10, 0x38, 0x6c, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x10, 0x38, 0x6c, 0x00},
-	{0x0c, 0x18, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x30, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x30, 0x30, 0x00},
-	{0x30, 0x30, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x10, 0x38, 0x6c, 0x00},
-	{0x0c, 0x18, 0x72, 0x9c, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x00, 0x72, 0x9c, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x30, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x30, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
-	{0x18, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
-	{0x18, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x7c, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x7c, 0x00, 0x00},
-	{0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
-	{0x60, 0x6c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0x70, 0x1c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x60, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x44, 0x38, 0x10, 0x7c, 0xc6, 0xc6, 0x70, 0x1c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x30, 0x44, 0x38, 0x10, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
-	{0x18, 0x18, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x06, 0x16, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x7e, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x7e, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x10, 0x38, 0x6c, 0x00},
-	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x08, 0x1c, 0x36, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x6c, 0x6c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x6c, 0x6c, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x76, 0xdc, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x76, 0xdc, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x10, 0x38, 0x6c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x10, 0x38, 0x6c, 0x00},
-	{0x0c, 0x18, 0x72, 0x9c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x76, 0xdc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0xcc, 0xcc, 0x00, 0xfc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x18, 0x18, 0x00},
-	{0x60, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x30, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x30, 0x30, 0x00},
-	{0x30, 0x30, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x10, 0x38, 0x44, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00},
-	{0x6c, 0x6c, 0x00, 0x10, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x00, 0x18, 0x0c, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x30, 0x00, 0x38, 0x6c, 0x64, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
-	{0x38, 0x0c, 0x18, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x0c, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x03, 0x16, 0x38, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x03, 0x16, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0xc0, 0x68, 0x1c, 0x36, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0xc0, 0x68, 0x1c, 0x36, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x0e, 0x13, 0x3a, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x10, 0x28, 0x54, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x10, 0x38, 0x44, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
-	{0x0c, 0x18, 0x44, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x18, 0x44, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x30, 0x44, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x30, 0x44, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x08, 0x54, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x08, 0x54, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x72, 0x9c, 0x44, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x72, 0x9c, 0x44, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x6c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
-	{0x38, 0x0c, 0x18, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x23, 0x76, 0x88, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x03, 0x26, 0x70, 0xd8, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0xc4, 0x6e, 0x11, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0xc0, 0x64, 0x0e, 0x1b, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x10, 0x38, 0x44, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x10, 0x38, 0x44, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x44, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
-	{0x38, 0x0c, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
-	{0x38, 0x0c, 0x18, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x23, 0x76, 0x88, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x03, 0x26, 0x70, 0xd8, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0xc4, 0x6e, 0x11, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0xc0, 0x64, 0x0e, 0x1b, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0e, 0x13, 0x3a, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x10, 0x28, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x76, 0xdc, 0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
-	{0x18, 0x33, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1b, 0x33, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x33, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x63, 0x33, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x70, 0x1b, 0x33, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0x1b, 0x33, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x68, 0xb3, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x68, 0xb3, 0x03, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x03, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x03, 0x03, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
-	{0x38, 0x0c, 0x18, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0x18, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x33, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1b, 0x33, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x33, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x63, 0x33, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x70, 0x1b, 0x33, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0x1b, 0x33, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x68, 0xb3, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x68, 0xb3, 0x03, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x03, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x30, 0x30, 0x00},
-	{0x00, 0x00, 0x03, 0x03, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
-	{0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x0c, 0x18, 0xf6, 0x06, 0x00},
-	{0x38, 0x0c, 0x18, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x38, 0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x3a, 0x5c, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
-	{0x00, 0x18, 0x18, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x30, 0x30, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x60, 0x6c, 0xc6, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0xc0, 0xcc, 0x66, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x60, 0x66, 0xcc, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0xc0, 0xc6, 0x6c, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x34, 0x58, 0x0c, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x34, 0x58, 0x30, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0xfe, 0x00, 0xa4, 0xaa, 0xea, 0xea, 0xa6, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0xa4, 0xea, 0xaa, 0xaa, 0xa6, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0xea, 0x8a, 0xce, 0x8e, 0xea, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0xea, 0x8e, 0xca, 0x8a, 0xea, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0xca, 0x2e, 0x4a, 0x2a, 0xca, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0xaa, 0xae, 0xea, 0x2a, 0x2a, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0x6a, 0x8e, 0xca, 0xaa, 0x4a, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0x38, 0x20, 0x30, 0x20, 0x20, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0x30, 0x28, 0x30, 0x20, 0x20, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0xea, 0x4a, 0x4e, 0x4a, 0x4a, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0x28, 0x28, 0x38, 0x28, 0x28, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0xea, 0x2a, 0x4e, 0x8e, 0xee, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0xea, 0x2a, 0x4e, 0x8e, 0xee, 0x00, 0xa2, 0xa2, 0xe2, 0xea, 0xa4, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0xea, 0x2a, 0x4e, 0x8e, 0xee, 0x00, 0x08, 0x08, 0x08, 0x28, 0x10, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0x80, 0x80, 0x80, 0xf0, 0x28, 0x30, 0x28, 0x0a, 0x0e, 0x0e, 0x0a, 0x00, 0xfe, 0x00},
-	{0xfe, 0x00, 0xc0, 0xa0, 0xc0, 0xa0, 0x20, 0x20, 0x38, 0x0a, 0x0e, 0x0e, 0x0a, 0x00, 0xfe, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x9c, 0xd2, 0xbc, 0x92, 0x9c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xfe, 0x00},
-	{0x00, 0x18, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00},
-	{0x00, 0x30, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x66, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00},
-	{0x00, 0xcc, 0xcc, 0xcc, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x38, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc0, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc0, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x6b, 0x6b, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xdb, 0xdb, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xdb, 0xdb, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x92, 0x44, 0x28, 0x92, 0x28, 0x44, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0xc3, 0xdb, 0x1b, 0x1e, 0x1c, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x7c, 0x00, 0x00},
-	{0x7c, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x38, 0x6c, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x38, 0x28, 0x00, 0x00, 0x44, 0xee, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7b, 0xcf, 0xcf, 0x1b, 0x33, 0x33, 0x33, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xde, 0xf3, 0xf3, 0xc6, 0xcc, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x06, 0x06, 0x0c, 0x0c, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xdb, 0xdb, 0xdb, 0xde, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x3e, 0x72, 0xf2, 0xf2, 0xf2, 0x72, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x9c, 0x9e, 0x9e, 0x9e, 0x9c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x18, 0x38, 0x78, 0xd8, 0xfc, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0xf8, 0xc0, 0xf0, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x78, 0xc0, 0xf0, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0xf8, 0xd8, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0xd8, 0x70, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0xd8, 0xd8, 0x78, 0x18, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x60, 0x30, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xb0, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0xd8, 0xfc, 0x18, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xc0, 0xf0, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xc0, 0xf0, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd8, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x70, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0xd8, 0x78, 0x18, 0xf0, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcf, 0xcc, 0xcc, 0x7f, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x04, 0x7c, 0xce, 0xc8, 0xc8, 0xd0, 0xd0, 0xd0, 0xe0, 0xe6, 0x7c, 0x40, 0x40, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xd6, 0xd8, 0xd8, 0xd8, 0xde, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0xc0, 0xc0, 0xc0, 0xf0, 0xcd, 0xce, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x60, 0xf8, 0x60, 0xf8, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x02, 0xec, 0xd6, 0xde, 0xd6, 0xd6, 0xf6, 0xd6, 0x40, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x66, 0x76, 0xff, 0x76, 0x6e, 0xff, 0x6e, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xf8, 0xe0, 0xf3, 0xd6, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x81, 0x81, 0x81, 0x5a, 0xff, 0x5a, 0xff, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xf2, 0x8a, 0xaa, 0xaa, 0xaa, 0xaa, 0xa2, 0xbc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x3e, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x7c, 0x00, 0x00},
-	{0x00, 0x00, 0x1c, 0x36, 0x60, 0xfc, 0x60, 0xf8, 0x60, 0x60, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0xfe, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x1e, 0x78, 0x1e, 0x78, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x7c, 0xb6, 0x36, 0x33, 0x33, 0x33, 0x63, 0x66, 0xf6, 0xdc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0xd0, 0xd2, 0xd6, 0x7c, 0x18, 0x30, 0x6e, 0xd8, 0x98, 0x18, 0x0e, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0xd0, 0xd2, 0xd6, 0x7c, 0x18, 0x30, 0x6e, 0xd8, 0x8c, 0x06, 0x1c, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x62, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x62, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x4e, 0xb9, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x18, 0x7c, 0xda, 0xd8, 0xd8, 0xda, 0x7c, 0x19, 0x3f, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0xc0, 0xc2, 0xc6, 0x7c, 0x18, 0x30, 0x6e, 0xdb, 0x9b, 0x1b, 0x0e, 0x00, 0x00, 0x00},
-	{0x00, 0x70, 0xc0, 0xc2, 0xc6, 0x7c, 0x18, 0x30, 0x7b, 0xdb, 0x9b, 0x1b, 0x0d, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc2, 0xc0, 0x78, 0xc0, 0xc0, 0xc2, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xcc, 0x86, 0x26, 0x3e, 0x26, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7f, 0xb9, 0x58, 0x1a, 0x1e, 0x1a, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x66, 0x46, 0x87, 0x8c, 0x8c, 0x7c, 0x98, 0x98, 0x70, 0x00},
-	{0x00, 0x00, 0x52, 0xb5, 0x15, 0x16, 0x2c, 0x34, 0x68, 0xa9, 0xaa, 0x4c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x48, 0xb0, 0x80, 0x48, 0x7c, 0x66, 0x26, 0x26, 0xa6, 0x46, 0x06, 0x34, 0x48, 0x00},
-	{0x00, 0x00, 0xe2, 0xa2, 0xa2, 0xa2, 0xbe, 0xa2, 0xa2, 0xa2, 0xa2, 0xe2, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x36, 0x3b, 0x3b, 0x33, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x1e, 0x18, 0x76, 0x3b, 0x3b, 0x33, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x33, 0x4e, 0x06, 0x06, 0x0c, 0x0c, 0x1f, 0x6c, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x71, 0x8e, 0x04, 0x0c, 0x06, 0x03, 0x63, 0xc3, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x46, 0x49, 0x39, 0x1e, 0x18, 0x30, 0x70, 0xb1, 0xba, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0e, 0x19, 0x31, 0x32, 0x64, 0x68, 0x70, 0xe1, 0x66, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xd8, 0xff, 0xd8, 0xde, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe2, 0xa2, 0xb2, 0xb2, 0xaa, 0xaa, 0xa6, 0xa6, 0xa2, 0xe2, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xcc, 0xcf, 0xed, 0xff, 0xfc, 0xdf, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x42, 0xb9, 0xa5, 0xa5, 0xb9, 0xa1, 0xa1, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x40, 0x8e, 0x93, 0xa3, 0x63, 0x4b, 0x6a, 0xa4, 0xb0, 0xb0, 0x60, 0x00},
-	{0x00, 0x00, 0xfc, 0xa2, 0xa2, 0xa2, 0xa2, 0xbc, 0xa0, 0xa0, 0xa0, 0xe0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xaa, 0xa6, 0x7e, 0x01, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3e, 0x4d, 0x4d, 0x19, 0x1e, 0x1c, 0x34, 0x34, 0xb5, 0x62, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x58, 0xa6, 0xa3, 0x6c, 0xb8, 0x26, 0x26, 0x26, 0xa7, 0xc2, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0xa2, 0xa2, 0xa2, 0xa2, 0xbc, 0xb0, 0xa8, 0xa4, 0xe2, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x6d, 0x67, 0x66, 0xee, 0x08, 0x00, 0x00, 0x00},
-	{0x30, 0x0c, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xd8, 0xdc, 0xdc, 0xe6, 0xe6, 0x20, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x71, 0xdb, 0x35, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x52, 0x5a, 0x52, 0x5f, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf1, 0x5b, 0x55, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x18, 0xce, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xe6, 0x6c, 0x38, 0x50, 0x40, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x0a, 0x14, 0x14, 0x28, 0x28, 0x50, 0x50, 0xa0, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x9c, 0x30, 0xfe, 0x0c, 0x18, 0x38, 0x0c, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00},
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xee, 0x6c, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x26, 0x03, 0x13, 0x0c, 0x13, 0x03, 0x03, 0x66, 0x98, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
-	{0x38, 0x6c, 0x38, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x2d, 0x2d, 0x1a, 0x1e, 0x1b, 0x31, 0x31, 0xb2, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x14, 0x6b, 0xc8, 0xcc, 0xc6, 0xc6, 0xcc, 0xc0, 0x63, 0x1c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xe7, 0xff, 0xe0, 0x67, 0x3e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x44, 0xf8, 0xc0, 0xc8, 0x70, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x4c, 0x52, 0x3c, 0x10, 0x3c, 0x60, 0xc0, 0xc3, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x73, 0xce, 0x18, 0x3a, 0x5c, 0x18, 0x30, 0x30, 0xb0, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x2c, 0x3c, 0x2c, 0x8c, 0xcc, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x12, 0x12, 0x12, 0x16, 0x36, 0x3e, 0x3a, 0x5a, 0x52, 0x91, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x46, 0xc6, 0xc4, 0xc8, 0x70, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x42, 0xc6, 0xe7, 0x7a, 0x38, 0x5c, 0xce, 0xe7, 0x63, 0xe2, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x80, 0xfc, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x7e, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x40, 0x78, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x7e, 0xf2, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x80, 0xfe, 0x7e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x38, 0x00, 0x78, 0x38, 0x38, 0x38, 0x38, 0x38, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xff, 0x83, 0x86, 0x82, 0xfe, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x1c, 0x06, 0x1c, 0x00, 0x00},
-	{0x00, 0xe0, 0x30, 0x62, 0xc6, 0xfc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x1c, 0x06, 0x1c, 0x00, 0x00},
-	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00},
-	{0x00, 0xe0, 0x30, 0x62, 0xc6, 0xfc, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00},
-	{0x00, 0xe0, 0x30, 0x62, 0x36, 0xec, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00},
-	{0x00, 0x30, 0x70, 0xb2, 0xf6, 0x3c, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00},
-	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0xb0, 0x3c, 0x36, 0x1c, 0x00, 0x00},
-	{0x00, 0xf0, 0xc0, 0xe2, 0x36, 0xec, 0x18, 0x30, 0x60, 0xdc, 0xb0, 0x3c, 0x36, 0x1c, 0x00, 0x00},
-	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00},
-	{0x00, 0xe0, 0x30, 0x62, 0x36, 0xec, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00},
-	{0x00, 0xf0, 0x80, 0xe2, 0x36, 0xec, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00},
-	{0x00, 0xf0, 0x30, 0x62, 0x66, 0x6c, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00},
-	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0xce, 0xc4, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x73, 0x23, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x65, 0x65, 0x65, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xce, 0xce, 0xce, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0x73, 0x73, 0x73, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x95, 0x95, 0x95, 0x65, 0x65, 0x65, 0x95, 0x95, 0x95, 0x95, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xdb, 0xdb, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0xc0, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0xc4, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x03, 0x03, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x23, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x05, 0x05, 0x00, 0x95, 0x95, 0x95, 0x95, 0x95, 0x65, 0x65, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x15, 0x15, 0x00, 0xb5, 0xb5, 0xb5, 0xb5, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0xc0, 0x00, 0xdb, 0xdb, 0xce, 0xce, 0xce, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x03, 0x03, 0x00, 0xdb, 0xdb, 0x73, 0x73, 0x73, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x05, 0x05, 0x00, 0x95, 0x95, 0x65, 0x65, 0x95, 0x95, 0x95, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x5a, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0xcc, 0xe6, 0xd6, 0xd6, 0xd6, 0xd6, 0xe6, 0xcc, 0xf8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x5a, 0x99, 0xbd, 0xdb, 0xdb, 0xbd, 0x99, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x06, 0x06, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xf0, 0xe0, 0xb0, 0x18, 0x0c, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x0f, 0x07, 0x0d, 0x18, 0x30, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x0d, 0x07, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x0c, 0x18, 0xb0, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x62, 0xff, 0x64, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x26, 0xff, 0x46, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xce, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x73, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xff, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x36, 0xff, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x66, 0xfc, 0x66, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x3f, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x63, 0xff, 0x63, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xc6, 0xff, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x06, 0x33, 0x63, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0xc6, 0x7f, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x06, 0x3b, 0x6b, 0xfe, 0x68, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x60, 0xdc, 0xd6, 0x7f, 0x16, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x5a, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x6e, 0xff, 0x76, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x30, 0x60, 0x63, 0xff, 0xc6, 0x16, 0x1c, 0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x66, 0x36, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0xcc, 0xd8, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x36, 0x66, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xd8, 0xcc, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x36, 0x66, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x1e, 0x33, 0x33, 0x33, 0x30, 0xfc, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x0c, 0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0x00, 0xf0, 0xe0, 0xb0, 0x18, 0x0c, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x98, 0xb0, 0xff, 0xb0, 0x98, 0x19, 0x0d, 0xff, 0x0d, 0x19, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x1e, 0x1c, 0x16, 0x03, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x78, 0x38, 0x68, 0xc0, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x1c, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x06, 0xff, 0x06, 0x0c, 0x30, 0x60, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x24, 0x2e, 0x3f, 0x24, 0x24, 0x24, 0x24, 0xfc, 0x74, 0x24, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x60, 0xff, 0x60, 0x30, 0x0c, 0x06, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x24, 0x7e, 0xff, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0xff, 0x7e, 0x24, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xff, 0x00, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xff, 0x00, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x7f, 0xc4, 0x7f, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x7e, 0xcb, 0x7e, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xfe, 0x23, 0xfe, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x7f, 0xc0, 0x7f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x7c, 0xee, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0x03, 0xfe, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x7e, 0xc3, 0x7e, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x7c, 0xee, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xf0, 0xe0, 0xb0, 0xd8, 0xec, 0xb6, 0x1b, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x0f, 0x07, 0x0d, 0x1b, 0x37, 0x6d, 0xd8, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x20, 0x30, 0xd8, 0x6d, 0x37, 0x1b, 0x0d, 0x07, 0x0f, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x04, 0x0c, 0x1b, 0xb6, 0xec, 0xd8, 0xb0, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x3f, 0x60, 0xff, 0x60, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0xfc, 0x06, 0xff, 0x06, 0xfc, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x6a, 0xff, 0x65, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xa6, 0xff, 0x56, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x3c, 0x18, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x3c, 0x18, 0x3c, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xd5, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x3c, 0x66, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xab, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xb0, 0xff, 0xb0, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0d, 0xff, 0x0d, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x3f, 0x41, 0x81, 0x41, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x44, 0x44, 0x44, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0xfc, 0x82, 0x81, 0x82, 0xfc, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc6, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x7c, 0x00, 0x7c, 0x44, 0x7c, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x44, 0xc6, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x28, 0x7c, 0xc6, 0x44, 0x44, 0x44, 0xc6, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x38, 0x54, 0xd6, 0x54, 0x54, 0x54, 0xd6, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x28, 0x54, 0xee, 0x44, 0xc6, 0x44, 0x44, 0x44, 0x44, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x28, 0x54, 0xee, 0x44, 0xc6, 0x44, 0x44, 0xc6, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xe8, 0xbc, 0x82, 0x81, 0x82, 0xbc, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0x80, 0xbc, 0xb8, 0xac, 0x86, 0x83, 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x01, 0x81, 0xc1, 0x61, 0x35, 0x1d, 0x3d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x44, 0xc6, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0xfe, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x06, 0x06, 0x3e, 0x66, 0xc6, 0xc6, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x7e, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0xfe, 0x16, 0x16, 0x16, 0x7e, 0x16, 0x26, 0x26, 0x26, 0xfe, 0x40, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x03, 0x3e, 0x66, 0xcf, 0xdb, 0xdb, 0xf3, 0x66, 0x7c, 0xc0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x3e, 0x60, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x3e, 0x64, 0xc8, 0xc8, 0xfe, 0xc8, 0xd0, 0x70, 0x3e, 0x20, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x3e, 0x60, 0xc0, 0xfe, 0xc0, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xf8, 0x0c, 0x06, 0x06, 0xfe, 0x06, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0xf8, 0x1c, 0x16, 0x26, 0xfe, 0x26, 0x26, 0x4c, 0xf8, 0x40, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x0c, 0x06, 0xfe, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe7, 0x00, 0x00},
-	{0x00, 0x00, 0xe7, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0xc1, 0x60, 0x30, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xff, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0x00, 0x00, 0x00},
-	{0x00, 0xc0, 0xc0, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x7e, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x03, 0x03, 0x06, 0x06, 0x06, 0x0c, 0xcc, 0x6c, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe3, 0x33, 0x66, 0x36, 0xe6, 0x0c, 0xcc, 0x6c, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x33, 0x73, 0xb6, 0xf6, 0x36, 0x0c, 0xcc, 0x6c, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdb, 0xdb, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x16, 0x0c, 0x1c, 0x34, 0x62, 0xff, 0x02, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x1a, 0x1c, 0x38, 0x58, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6e, 0x7c, 0xec, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x1a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00},
-	{0x33, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00},
-	{0x2a, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0xa8, 0x00, 0x00},
-	{0x0c, 0x1a, 0x18, 0x18, 0x3c, 0x5a, 0x99, 0x99, 0x5a, 0x3c, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00},
-	{0x33, 0x66, 0x66, 0x66, 0x7e, 0xe7, 0xe7, 0xe7, 0xe7, 0x7e, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00},
-	{0x2a, 0x54, 0x54, 0x54, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x54, 0x54, 0x54, 0xa8, 0x00, 0x00},
-	{0x18, 0x34, 0x30, 0x30, 0x38, 0x35, 0x33, 0x37, 0x30, 0x30, 0x30, 0x30, 0xb0, 0x60, 0x00, 0x00},
-	{0x0c, 0x1a, 0x18, 0x18, 0x3c, 0x5a, 0xfa, 0x5a, 0x5a, 0x3c, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00},
-	{0x0c, 0x1a, 0x18, 0x18, 0x3c, 0x5a, 0x5f, 0x5a, 0x5a, 0x3c, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0xfc, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x7e, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x76, 0xdc, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0xdb, 0xdb, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0xdb, 0xdb, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x1c, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x76, 0xdc, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x08, 0x08, 0x76, 0xdc, 0x10, 0xfe, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x08, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x08, 0x76, 0xdc, 0x10, 0xfe, 0x20, 0xfe, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x08, 0x08, 0x76, 0xdc, 0x10, 0x76, 0xdc, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x00, 0x00, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0x60, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x06, 0x06, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf, 0x00, 0x00, 0xdf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x03, 0xfb, 0x00, 0x00, 0xfb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x28, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x28, 0x10, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x38, 0x44, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x44, 0x28, 0x10, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x10, 0x7c, 0x28, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x10, 0x28, 0x44, 0x7c, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x26, 0x7c, 0xb4, 0x6c, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x68, 0x54, 0x54, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x30, 0x08, 0x10, 0x00, 0x10, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x04, 0x08, 0x7e, 0x08, 0x10, 0x7e, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x08, 0xfe, 0x08, 0x10, 0xfe, 0x10, 0x20, 0xfe, 0x20, 0x40, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x08, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x08, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x1b, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x1b, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x66, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x66, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0xce, 0x7c, 0x10, 0x7c, 0xe6, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x04, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0xe0, 0x38, 0x2e, 0x38, 0xe0, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x04, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0xe0, 0x38, 0x2e, 0x38, 0xe0, 0x40, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x04, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0x76, 0xdc, 0x20, 0x20, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0xe0, 0x38, 0x2e, 0x38, 0xe0, 0x40, 0x76, 0xdc, 0x80, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x0e, 0x38, 0xe8, 0x38, 0x1e, 0xf0, 0x38, 0x2e, 0x38, 0xe0, 0x20, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0xe8, 0x38, 0x0e, 0x38, 0xf0, 0x1e, 0x38, 0xe0, 0x38, 0x2e, 0x20, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0xf2, 0x1c, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x9e, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x06, 0x0c, 0x38, 0xe8, 0x38, 0x1c, 0x16, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0xd0, 0x70, 0x38, 0x2e, 0x38, 0x60, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x04, 0x7e, 0xc8, 0xc8, 0xd0, 0xd0, 0x7e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x08, 0xfc, 0x16, 0x16, 0x26, 0x26, 0xfc, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x7e, 0xc8, 0xc8, 0xd0, 0xd0, 0x7e, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0xfc, 0x16, 0x16, 0x26, 0x26, 0xfc, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0x7e, 0x08, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x82, 0x92, 0xa2, 0xfa, 0xa2, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0xba, 0xba, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0xba, 0x92, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x54, 0x92, 0xfe, 0x92, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0xfe, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0xaa, 0x92, 0xaa, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x8a, 0x92, 0xa2, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x92, 0xba, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x92, 0xaa, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x54, 0xd6, 0xba, 0xd6, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0xba, 0x82, 0xba, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0xba, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x92, 0x92, 0xfe, 0x92, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0xfe, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xaa, 0x92, 0xaa, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x92, 0xba, 0x92, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x7e, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xd8, 0xdf, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xa8, 0xa8, 0xa8, 0xa8, 0xaf, 0xa8, 0xa8, 0xa8, 0xa8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xdf, 0xd8, 0xdf, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc0, 0xc2, 0xc4, 0xc4, 0xff, 0xc8, 0xc8, 0xd0, 0xc0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc0, 0xc4, 0xc4, 0xff, 0xc8, 0xff, 0xd0, 0xd0, 0xc0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xd8, 0xd9, 0xda, 0xda, 0xdf, 0xda, 0xda, 0xdc, 0xd8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xd8, 0xd9, 0xda, 0xdf, 0xda, 0xdf, 0xda, 0xdc, 0xd8, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x0c, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x60, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x06, 0x1e, 0x76, 0xc6, 0x76, 0x1e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc0, 0xf0, 0xdc, 0xc6, 0xdc, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x06, 0x1e, 0x76, 0xc6, 0x76, 0x1e, 0x06, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0xf0, 0xdc, 0xc6, 0xdc, 0xf0, 0xc0, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xbf, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0xc6, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xf0, 0xc8, 0xc4, 0xc4, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0b, 0x13, 0x23, 0x43, 0x83, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x38, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x92, 0x44, 0x28, 0x92, 0x28, 0x44, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x82, 0xc6, 0xaa, 0x92, 0xaa, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x82, 0xc4, 0xa8, 0x90, 0xa8, 0xc4, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x82, 0x46, 0x2a, 0x12, 0x2a, 0x46, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x3e, 0x60, 0xce, 0xd8, 0xd8, 0xce, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xf8, 0x0c, 0xe6, 0x36, 0x36, 0xe6, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x38, 0x44, 0x92, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x10, 0x38, 0x54, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x64, 0xce, 0x64, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x4c, 0xe6, 0x4c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x15, 0x2a, 0x54, 0xa8, 0x54, 0x2a, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xa8, 0x54, 0x2a, 0x15, 0x2a, 0x54, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0xfe, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x00},
-	{0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0xfe, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf2, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x80, 0xc0, 0x70, 0x9e, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0a, 0x0e, 0x1c, 0xf0, 0x1c, 0x16, 0xf2, 0x1c, 0x26, 0x22, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x88, 0xc8, 0x70, 0x1e, 0x70, 0xd0, 0x9e, 0x70, 0xe0, 0xa0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0xfe, 0xc8, 0xc8, 0xd0, 0xd0, 0xfe, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0xfe, 0x16, 0x16, 0x26, 0x26, 0xfe, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x08, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x0e, 0x1e, 0x76, 0xd6, 0x76, 0x1e, 0x26, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0xc8, 0xf0, 0xdc, 0xd6, 0xdc, 0xf0, 0xe0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x0e, 0x1e, 0x76, 0xd6, 0x76, 0x1e, 0x26, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0xc8, 0xf0, 0xdc, 0xd6, 0xdc, 0xf0, 0xe0, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x3d, 0x66, 0xc7, 0xcb, 0xd3, 0xe3, 0x66, 0xbc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x42, 0xa5, 0x7e, 0x24, 0x24, 0x7e, 0xa5, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x38, 0x38, 0x54, 0x8a, 0xf6, 0x82, 0x54, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0xfe, 0xfe, 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x00, 0x00},
-	{0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00},
-	{0x00, 0x03, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
-	{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
-	{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x03, 0x00, 0x00},
-	{0x00, 0xc0, 0x60, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
-	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
-	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x30, 0x30, 0x60, 0xc0, 0x00, 0x00},
-	{0x00, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
-	{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
-	{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3f, 0x00, 0x00},
-	{0x00, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
-	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
-	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xfc, 0x00, 0x00},
-	{0x00, 0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0},
-	{0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07},
-	{0x00, 0x00, 0xff, 0xc1, 0xc0, 0x60, 0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x60, 0x60, 0x60, 0x60, 0xc0, 0xc1, 0xff, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xff, 0x00, 0xff, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x78, 0x78, 0x38, 0x38, 0x18, 0x18, 0x00, 0x00},
-	{0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
-	{0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03},
-	{0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x07, 0x05, 0x05, 0x05, 0x05, 0x25, 0x79, 0xc2, 0x7c, 0x20, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xd8, 0xd8, 0xf8, 0xd8, 0xd8, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0, 0x0f, 0x0c, 0x0e, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xd8, 0xd8, 0xf8, 0x70, 0x20, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xf0, 0xc0, 0xe0, 0xc0, 0xc0, 0x0f, 0x0c, 0x0e, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0xc0, 0xc0, 0xc0, 0x70, 0x1e, 0x1b, 0x1e, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x98, 0xd8, 0xf8, 0xd8, 0xd8, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7c, 0xfe, 0xc6, 0xc6, 0x60, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xfc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0e, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x70, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x70, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x0e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80},
-	{0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01},
-	{0x81, 0x81, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x42, 0x42, 0x81, 0x81},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
-	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-	{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-	{0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-	{0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe},
-	{0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc},
-	{0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8},
-	{0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0},
-	{0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0},
-	{0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
-	{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80},
-	{0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f},
-	{0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44},
-	{0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa},
-	{0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77},
-	{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
-	{0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0x82, 0xba, 0xba, 0xba, 0xba, 0xba, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0x82, 0xfe, 0x82, 0xfe, 0x82, 0xfe, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0xaa, 0xfe, 0xaa, 0xfe, 0xaa, 0xfe, 0xaa, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0x8a, 0xc6, 0xa2, 0x92, 0x8a, 0xc6, 0xa2, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0xa2, 0xc6, 0x8a, 0x92, 0xa2, 0xc6, 0x8a, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0xaa, 0xc6, 0xaa, 0x92, 0xaa, 0xc6, 0xaa, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x44, 0x44, 0x44, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x84, 0x84, 0xfc, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x44, 0x44, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x80, 0xc0, 0xa0, 0x90, 0x88, 0x84, 0x88, 0x90, 0xa0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, 0x78, 0x70, 0x40, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, 0x48, 0x70, 0x40, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x98, 0x86, 0x98, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x02, 0x06, 0x0a, 0x12, 0x22, 0x42, 0x22, 0x12, 0x0a, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x38, 0x78, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x38, 0x48, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x32, 0xc2, 0x32, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x82, 0x82, 0x44, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x28, 0x44, 0x54, 0xba, 0xba, 0x54, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x42, 0x99, 0xbd, 0xbd, 0xbd, 0xbd, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x28, 0x28, 0x44, 0x82, 0x82, 0x44, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x14, 0x40, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x42, 0x99, 0xa5, 0xa5, 0xa5, 0xa5, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x72, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0x72, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x4e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x4e, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x4e, 0x8f, 0x8f, 0x8f, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x4e, 0x8f, 0x8f, 0x8f, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x70, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x70, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-	{0xff, 0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0xbd, 0xc3, 0xff, 0xff, 0xff, 0xff},
-	{0xff, 0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0xbd, 0xc3, 0xff, 0xff, 0xff, 0xff},
-	{0x00, 0x00, 0x30, 0x40, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0c, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x0f, 0x1f, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f, 0xff, 0xff},
-	{0x80, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfc, 0xfe, 0xfe, 0xff, 0xff},
-	{0xff, 0xff, 0xfe, 0xfe, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, 0xe0, 0xe0, 0xc0, 0xc0, 0x80, 0x80},
-	{0xff, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x07, 0x03, 0x03, 0x01, 0x01},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0xff, 0xfd, 0xf9, 0xf1, 0xf1, 0xe1, 0xc1, 0x81, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0x81, 0x83, 0x87, 0x8f, 0x8f, 0x9f, 0xbf, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xff, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x10, 0x28, 0x28, 0x44, 0x44, 0x92, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x74, 0x74, 0xf2, 0xf2, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x5c, 0x5c, 0x9e, 0x9e, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0x92, 0x92, 0x92, 0xf2, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0xf2, 0x92, 0x92, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x9e, 0x92, 0x92, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xfe, 0x92, 0x92, 0x92, 0x9e, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x4a, 0x89, 0x89, 0x89, 0xf9, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0xf9, 0x89, 0x89, 0x89, 0x4a, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x9f, 0x91, 0x91, 0x91, 0x52, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x52, 0x91, 0x91, 0x91, 0x9f, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x10, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x30, 0x7c, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x38, 0x7c, 0xfe, 0x10, 0x10, 0x10, 0x10, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0xfe, 0x7c, 0x38, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x10, 0x28, 0xee, 0x44, 0x54, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x34, 0x1c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcd, 0xc7, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x92, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0xa5, 0xa5, 0x42, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x42, 0xa5, 0xa5, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x18, 0x30, 0x70, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x86, 0x8a, 0xba, 0x92, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0xee, 0xba, 0xba, 0xee, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x82, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x7c, 0x82, 0xaa, 0x82, 0x44, 0x7c, 0x44, 0x38, 0x00, 0x44, 0xc6, 0x38, 0xc6, 0x44, 0x00},
-	{0x00, 0x00, 0x00, 0x38, 0x44, 0xee, 0xfe, 0x92, 0xba, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x7e, 0x18, 0x18, 0xff, 0x18, 0x1e, 0x78, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x7e, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x38, 0x10, 0x10, 0x92, 0xfe, 0x92, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x72, 0xe0, 0xc4, 0xdf, 0xce, 0xca, 0xe0, 0x72, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x54, 0x28, 0x54, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x5a, 0x99, 0x99, 0x99, 0xbd, 0xff, 0xdb, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x85, 0xb1, 0xf9, 0xff, 0xdf, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0x81, 0x99, 0xa5, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xa5, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xdb, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x10, 0x54, 0x28, 0xc6, 0x28, 0x54, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x78, 0x14, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x14, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x28, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x28, 0x1e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x06, 0x0e, 0x1a, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x03, 0x03, 0x7b, 0xcf, 0xcf, 0xcf, 0x0f, 0x1b, 0x33, 0xff, 0x03, 0x03, 0x03, 0x00, 0x00},
-	{0x00, 0x00, 0x60, 0xf0, 0x60, 0x6e, 0x73, 0x63, 0x63, 0x66, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xd6, 0x54, 0x54, 0x7c, 0x54, 0x54, 0xd6, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x3c, 0xdb, 0xdb, 0xdb, 0xdb, 0x7e, 0x3c, 0x18, 0x3c, 0x18, 0x18, 0x00, 0x00},
-	{0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xf8, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x42, 0xa5, 0xa5, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0xc3, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00},
-	{0x00, 0x00, 0xc3, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7e, 0xc3, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7e, 0xdb, 0xd8, 0x70, 0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1e, 0x33, 0x33, 0x33, 0x33, 0x1b, 0x7b, 0xdb, 0xdb, 0x73, 0x03, 0x01, 0x00, 0x00},
-	{0x00, 0x00, 0x94, 0x7c, 0x55, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x06, 0x0b, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x24, 0xe7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x94, 0x7c, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x04, 0x03, 0x00, 0x00},
-	{0x00, 0x00, 0x1f, 0x07, 0x8f, 0xdb, 0x73, 0x70, 0xd8, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x90, 0x50, 0x70, 0x68, 0x48, 0x48, 0x4e, 0x49, 0x09, 0x0e, 0x10, 0x20, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x2a, 0x7e, 0xaa, 0x00, 0x00, 0x2a, 0x7e, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc3, 0x66, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x82, 0x82, 0x82, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x44, 0x82, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x81, 0x81, 0x66, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x18, 0x24, 0x3c, 0xe7, 0xa5, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x30, 0x3c, 0x3e, 0x32, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0x7f, 0x6f, 0x63, 0x63, 0x63, 0x63, 0xe3, 0xe7, 0xc7, 0x06, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x63, 0xe7, 0xe7, 0xc6, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xcc, 0xde, 0xe6, 0xc4, 0xd8, 0xe0, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x40, 0x40, 0x44, 0x5c, 0x74, 0x44, 0x44, 0x5c, 0x74, 0x44, 0x04, 0x04, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x04, 0x46, 0x5c, 0x74, 0xc4, 0x46, 0x5c, 0x74, 0xc4, 0x40, 0x40, 0x00, 0x00},
-	{0x00, 0x00, 0x3b, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3c, 0x6e, 0x66, 0x60, 0xfe, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x3e, 0x6e, 0x66, 0x66, 0xfe, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6e, 0xdb, 0xdb, 0xd8, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x6f, 0xdb, 0xdb, 0xdb, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xff, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x38, 0x6c, 0x6c, 0x6f, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0xf6, 0x00, 0x00, 0x00, 0x00},
-	{0x06, 0x29, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x06, 0x29, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x00, 0x14, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x89, 0x86, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0a, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0a, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x89, 0x86, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x14, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x14, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x88, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x88, 0x80, 0x88, 0x40, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x94, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x94, 0x80, 0x40, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x94, 0x80, 0x88, 0x40, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x94, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x94, 0x80, 0x94, 0x40, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x28, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x28, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x00, 0x28, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x00, 0x28, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x20, 0x38, 0x28, 0x70, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x20, 0x38, 0x28, 0x70, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x01, 0x02, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x01, 0x02, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x06, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x06, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x09, 0x12, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x30, 0x46, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x30, 0x46, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00},
-	{0x04, 0x09, 0x12, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00},
-	{0x0c, 0x30, 0x46, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00},
-	{0x0c, 0x30, 0x46, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0xa4, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0xa4, 0x09, 0x12, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0xa2, 0x0c, 0x13, 0x0c, 0x10, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0xa2, 0x0c, 0x13, 0x0c, 0x10, 0x10, 0x08, 0x04, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x00, 0x01, 0x41, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x38, 0x40, 0x38, 0x40, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x70, 0x80, 0x70, 0x80, 0x10, 0x68, 0x88, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xf0, 0x10, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xf7, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x70, 0x80, 0x70, 0x80, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x1c, 0x20, 0x1c, 0x20, 0x00, 0x00, 0x07, 0x18, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x00, 0x29, 0x01, 0x19, 0x21, 0x19, 0xa1, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x00, 0x2a, 0x02, 0x32, 0x42, 0x32, 0xc6, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x40, 0x00, 0xa3, 0x0c, 0x10, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x40, 0x00, 0xa3, 0x0c, 0x10, 0x10, 0x08, 0x04, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x28, 0x18, 0x10, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x28, 0x18, 0x10, 0x20, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
-	{0x08, 0x08, 0x08, 0x08, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
-	{0x23, 0x54, 0x33, 0x24, 0x40, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x3c, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x3c, 0x18, 0x60, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x10, 0x00, 0x10},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x10, 0x00, 0x10},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
-	{0x20, 0x20, 0x20, 0x20, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x10, 0x10, 0x10, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x10, 0x10, 0x10, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x24, 0x98, 0x60, 0xc2, 0x12, 0x92, 0x9c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x02, 0x92, 0x9c, 0x60, 0x0e, 0x70, 0x0e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x60, 0x04, 0x54, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x28, 0x10, 0x60, 0x04, 0x54, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x04, 0x54, 0x58, 0x20, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x10, 0x04, 0x54, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00},
-	{0x0e, 0xf0, 0x02, 0x92, 0x9c, 0x60, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x24, 0x18, 0x60, 0x02, 0x92, 0x9c, 0x60, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x02, 0x12, 0x9c, 0x60, 0x0e, 0x70, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x28, 0x50, 0x28, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x14, 0x28, 0x14, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x08, 0x10, 0x54, 0x38, 0x54, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x20, 0x10, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x2a, 0x14, 0x00, 0x21, 0x69, 0xa9, 0x69, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x08, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x20, 0x10, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x04, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x7c, 0x28, 0x7c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x10, 0x2a, 0x24, 0x1a, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x38, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x54, 0x30, 0x18, 0x54, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x08, 0x08, 0x10, 0x10, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x54, 0x58, 0x40, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x06, 0x18, 0x60, 0x06, 0x18, 0x60, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x12, 0xca, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00},
-	{0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x06, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x08, 0x14, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x24, 0x14, 0x18, 0x60, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x06, 0x18, 0x60, 0x00, 0x00},
-	{0x0a, 0x2a, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x02, 0x12, 0x92, 0x9c, 0x60, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x20, 0x1e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x02, 0x3c, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x01, 0x3e, 0x40, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x20, 0x1c, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x10, 0x0e, 0x10, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x0c, 0x10, 0x0e, 0x10, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x0c, 0x10, 0x0e, 0x10, 0x00, 0x00},
-	{0x00, 0x30, 0x40, 0x38, 0x40, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x30, 0x40, 0x38, 0x40, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00},
-	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x28, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x50, 0x00, 0x10, 0x10, 0x68, 0x88, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x14, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x14, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x14, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x14, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x88, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x88, 0x80, 0x40, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x80, 0x80, 0x40, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x20, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x20, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x80, 0x80, 0x40, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x15, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0x2a, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0x22, 0x41, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x10, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x40, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
-	{0x00, 0x08, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0x22, 0x41, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
-	{0x00, 0x00, 0x10, 0x00, 0x00, 0x0e, 0x10, 0x10, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x89, 0x86, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x0a, 0x00, 0x00, 0x06, 0x09, 0x49, 0x87, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x32, 0x42, 0x32, 0x42, 0x02, 0x86, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x06, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x06, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3c, 0x4b, 0x4a, 0x44, 0x40, 0x40, 0x40, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x32, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x08, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x41, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x10, 0x10, 0x68, 0x88, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x40, 0x30, 0x4e, 0x49, 0x39, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x24, 0x28, 0xf3, 0x24, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x24, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x24, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
-	{0x68, 0x90, 0x02, 0x22, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x68, 0x90, 0x02, 0x32, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x60, 0x80, 0x72, 0xa2, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x40, 0x3a, 0x52, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x42, 0x22, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x18, 0x20, 0x1c, 0x20, 0x00},
-	{0x00, 0x00, 0x22, 0x12, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x18, 0x20, 0x1c, 0x20, 0x00},
-	{0x00, 0x00, 0x42, 0x22, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0x00, 0x00, 0x22, 0x12, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-	{0xf1, 0x35, 0x55, 0x8a, 0xe0, 0x06, 0x95, 0xd6, 0xb5, 0x97, 0x00, 0xee, 0x8a, 0xee, 0x28, 0xe8},
-	{0x00, 0x38, 0x7c, 0x7c, 0xc6, 0x92, 0xf2, 0xe6, 0xfe, 0xe6, 0x7c, 0x7c, 0x38, 0x00, 0x00, 0x00},
-	
-	/* Special glyph for unknown character */
-	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}
-};
-
-/** @}
- */
Index: pace/srv/hid/fb/gfx/font-8x16.h
===================================================================
--- uspace/srv/hid/fb/gfx/font-8x16.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2005 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 genarch
- * @{
- */
-/** @file
- */
-
-#ifndef FONT_8X16_H_
-#define FONT_8X16_H_
-
-#include <sys/types.h>
-
-#define FONT_GLYPHS     2899
-#define FONT_WIDTH      8
-#define FONT_SCANLINES  16
-
-extern uint16_t fb_font_glyph(const wchar_t);
-extern uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES];
-
-#endif
-
-/** @}
- */
Index: pace/srv/hid/fb/port/ega.c
===================================================================
--- uspace/srv/hid/fb/port/ega.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,315 +1,0 @@
-/*
- * Copyright (c) 2011 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.
- */
-
-/** @file
- */
-
-#include <sys/types.h>
-#include <errno.h>
-#include <sysinfo.h>
-#include <task.h>
-#include <ddi.h>
-#include <libarch/ddi.h>
-#include <as.h>
-#include <malloc.h>
-#include <align.h>
-#include <screenbuffer.h>
-#include "../fb.h"
-#include "ega.h"
-
-#define EGA_IO_BASE  ((ioport8_t *) 0x3d4)
-#define EGA_IO_SIZE  2
-
-#define FB_POS(x, y)  (((y) * ega.width + (x)) << 1)
-
-typedef struct {
-	sysarg_t width;
-	sysarg_t height;
-	
-	size_t size;
-	uint8_t *addr;
-	
-	uint8_t style_normal;
-	uint8_t style_inverted;
-	
-	uint8_t *backbuf;
-} ega_t;
-
-static ega_t ega;
-
-static uint8_t attrs_attr(char_attrs_t attrs)
-{
-	uint8_t attr = 0;
-	
-	switch (attrs.type) {
-	case CHAR_ATTR_STYLE:
-		switch (attrs.val.style) {
-		case STYLE_NORMAL:
-			attr = ega.style_normal;
-			break;
-		case STYLE_EMPHASIS:
-			attr = (ega.style_normal | 0x04);
-			break;
-		case STYLE_INVERTED:
-			attr = ega.style_inverted;
-			break;
-		case STYLE_SELECTED:
-			attr = (ega.style_inverted | 0x40);
-			break;
-		}
-		break;
-	case CHAR_ATTR_INDEX:
-		attr = ((attrs.val.index.bgcolor & 7) << 4) |
-		    (attrs.val.index.fgcolor & 7);
-		
-		if (attrs.val.index.attr & CATTR_BRIGHT)
-			attr |= 0x08;
-		
-		break;
-	case CHAR_ATTR_RGB:
-		attr = (attrs.val.rgb.bgcolor < attrs.val.rgb.fgcolor) ?
-		    ega.style_inverted : ega.style_normal;
-		break;
-	}
-	
-	return attr;
-}
-
-/** Draw the character at the specified position in viewport.
- *
- * @param vp     Viewport.
- * @param col    Screen position relative to viewport.
- * @param row    Screen position relative to viewport.
- *
- */
-static void draw_vp_char(fbvp_t *vp, sysarg_t col, sysarg_t row)
-{
-	sysarg_t x = vp->x + col;
-	sysarg_t y = vp->y + row;
-	
-	charfield_t *field = screenbuffer_field_at(vp->backbuf, col, row);
-	
-	uint8_t glyph;
-	
-	if (ascii_check(field->ch))
-		glyph = field->ch;
-	else
-		glyph = '?';
-	
-	uint8_t attr = attrs_attr(field->attrs);
-	
-	ega.addr[FB_POS(x, y)] = glyph;
-	ega.addr[FB_POS(x, y) + 1] = attr;
-}
-
-static int ega_yield(fbdev_t *dev)
-{
-	if (ega.backbuf == NULL) {
-		ega.backbuf = malloc(ega.size);
-		if (ega.backbuf == NULL)
-			return ENOMEM;
-	}
-	
-	memcpy(ega.backbuf, ega.addr, ega.size);
-	return EOK;
-}
-
-static int ega_claim(fbdev_t *dev)
-{
-	if (ega.backbuf == NULL)
-		return ENOENT;
-	
-	memcpy(ega.addr, ega.backbuf, ega.size);
-	return EOK;
-}
-
-static int ega_get_resolution(fbdev_t *dev, sysarg_t *width, sysarg_t *height)
-{
-	*width = ega.width;
-	*height = ega.height;
-	return EOK;
-}
-
-static void ega_font_metrics(fbdev_t *dev, sysarg_t width, sysarg_t height,
-    sysarg_t *cols, sysarg_t *rows)
-{
-	*cols = width;
-	*rows = height;
-}
-
-static int ega_vp_create(fbdev_t *dev, fbvp_t *vp)
-{
-	vp->attrs.type = CHAR_ATTR_STYLE;
-	vp->attrs.val.style = STYLE_NORMAL;
-	vp->data = NULL;
-	
-	return EOK;
-}
-
-static void ega_vp_destroy(fbdev_t *dev, fbvp_t *vp)
-{
-	/* No-op */
-}
-
-static void ega_vp_clear(fbdev_t *dev, fbvp_t *vp)
-{
-	for (sysarg_t row = 0; row < vp->rows; row++) {
-		for (sysarg_t col = 0; col < vp->cols; col++) {
-			charfield_t *field =
-			    screenbuffer_field_at(vp->backbuf, col, row);
-			
-			field->ch = 0;
-			field->attrs = vp->attrs;
-			
-			draw_vp_char(vp, col, row);
-		}
-	}
-}
-
-static console_caps_t ega_vp_get_caps(fbdev_t *dev, fbvp_t *vp)
-{
-	return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED);
-}
-
-static void ega_vp_cursor_update(fbdev_t *dev, fbvp_t *vp, sysarg_t prev_col,
-    sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
-{
-	/* Cursor position */
-	uint16_t cursor = row * ega.width + col;
-	
-	pio_write_8(EGA_IO_BASE, 0x0e);
-	pio_write_8(EGA_IO_BASE + 1, (cursor >> 8) & 0xff);
-	pio_write_8(EGA_IO_BASE, 0x0f);
-	pio_write_8(EGA_IO_BASE + 1, cursor & 0xff);
-	
-	/* Cursor visibility */
-	pio_write_8(EGA_IO_BASE, 0x0a);
-	uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
-	
-	pio_write_8(EGA_IO_BASE, 0x0a);
-	
-	if (visible)
-		pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5)));
-	else
-		pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5));
-}
-
-static void ega_vp_char_update(fbdev_t *dev, fbvp_t *vp, sysarg_t col,
-    sysarg_t row)
-{
-	draw_vp_char(vp, col, row);
-}
-
-static fbdev_ops_t ega_ops = {
-	.yield = ega_yield,
-	.claim = ega_claim,
-	.get_resolution = ega_get_resolution,
-	.font_metrics = ega_font_metrics,
-	.vp_create = ega_vp_create,
-	.vp_destroy = ega_vp_destroy,
-	.vp_clear = ega_vp_clear,
-	.vp_get_caps = ega_vp_get_caps,
-	.vp_cursor_update = ega_vp_cursor_update,
-	.vp_char_update = ega_vp_char_update
-};
-
-int ega_init(void)
-{
-	sysarg_t present;
-	int rc = sysinfo_get_value("fb", &present);
-	if (rc != EOK)
-		present = false;
-	
-	if (!present)
-		return ENOENT;
-	
-	sysarg_t kind;
-	rc = sysinfo_get_value("fb.kind", &kind);
-	if (rc != EOK)
-		kind = (sysarg_t) -1;
-	
-	if (kind != 2)
-		return EINVAL;
-	
-	sysarg_t paddr;
-	rc = sysinfo_get_value("fb.address.physical", &paddr);
-	if (rc != EOK)
-		return rc;
-	
-	sysarg_t width;
-	rc = sysinfo_get_value("fb.width", &width);
-	if (rc != EOK)
-		return rc;
-	
-	sysarg_t height;
-	rc = sysinfo_get_value("fb.height", &height);
-	if (rc != EOK)
-		return rc;
-	
-	rc = iospace_enable(task_get_id(), (void *) EGA_IO_BASE, EGA_IO_SIZE);
-	if (rc != EOK)
-		return rc;
-	
-	ega.width = width;
-	ega.height = height;
-	
-	ega.size = (width * height) << 1;
-	
-	rc = physmem_map((void *) paddr,
-	    ALIGN_UP(ega.size, PAGE_SIZE) >> PAGE_WIDTH,
-	    AS_AREA_READ | AS_AREA_WRITE, (void *) &ega.addr);
-	if (rc != EOK)
-		return rc;
-	
-	sysarg_t blinking;
-	rc = sysinfo_get_value("fb.blinking", &blinking);
-	if (rc != EOK)
-		blinking = false;
-	
-	ega.style_normal = 0xf0;
-	ega.style_inverted = 0x0f;
-	
-	if (blinking) {
-		ega.style_normal &= 0x77;
-		ega.style_inverted &= 0x77;
-	}
-	
-	ega.backbuf = NULL;
-	
-	fbdev_t *dev = fbdev_register(&ega_ops, (void *) &ega);
-	if (dev == NULL) {
-		as_area_destroy(ega.addr);
-		return EINVAL;
-	}
-	
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/fb/port/ega.h
===================================================================
--- uspace/srv/hid/fb/port/ega.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,40 +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.
- */
-
-/** @file
- */
-
-#ifndef FB_PORT_EGA_H_
-#define FB_PORT_EGA_H_
-
-extern int ega_init(void);
-
-#endif
-
-/** @}
- */
Index: pace/srv/hid/fb/port/kchar.c
===================================================================
--- uspace/srv/hid/fb/port/kchar.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,95 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * Copyright (c) 2008 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.
- */
-
-/** @file
- */
-
-#include <sys/types.h>
-#include <errno.h>
-#include <sysinfo.h>
-#include <ddi.h>
-#include <as.h>
-#include <align.h>
-#include "../ctl/serial.h"
-#include "kchar.h"
-
-typedef struct {
-	uint8_t *addr;
-} kchar_t;
-
-static kchar_t kchar;
-
-static void kchar_putchar(wchar_t ch)
-{
-	if (ascii_check(ch))
-		*kchar.addr = ch;
-	else
-		*kchar.addr = '?';
-}
-
-static void kchar_control_puts(const char *str)
-{
-	while (*str)
-		*kchar.addr = *(str++);
-}
-
-int kchar_init(void)
-{
-	sysarg_t present;
-	int rc = sysinfo_get_value("fb", &present);
-	if (rc != EOK)
-		present = false;
-	
-	if (!present)
-		return ENOENT;
-	
-	sysarg_t kind;
-	rc = sysinfo_get_value("fb.kind", &kind);
-	if (rc != EOK)
-		kind = (sysarg_t) -1;
-	
-	if (kind != 3)
-		return EINVAL;
-	
-	sysarg_t paddr;
-	rc = sysinfo_get_value("fb.address.physical", &paddr);
-	if (rc != EOK)
-		return rc;
-	
-	rc = physmem_map((void *) paddr,
-	    ALIGN_UP(1, PAGE_SIZE) >> PAGE_WIDTH,
-	    AS_AREA_READ | AS_AREA_WRITE, (void *) &kchar.addr);
-	if (rc != EOK)
-		return rc;
-	
-	return serial_init(kchar_putchar, kchar_control_puts);
-}
-
-/** @}
- */
Index: pace/srv/hid/fb/port/kchar.h
===================================================================
--- uspace/srv/hid/fb/port/kchar.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,41 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * Copyright (c) 2008 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.
- */
-
-/** @file
- */
-
-#ifndef FB_PORT_KCHAR_H_
-#define FB_PORT_KCHAR_H_
-
-extern int kchar_init(void);
-
-#endif
-
-/** @}
- */
Index: pace/srv/hid/fb/port/kfb.c
===================================================================
--- uspace/srv/hid/fb/port/kfb.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,787 +1,0 @@
-/*
- * Copyright (c) 2008 Martin Decky
- * Copyright (c) 2006 Jakub Vana
- * 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.
- */
-
-/** @file
- */
-
-#include <abi/fb/visuals.h>
-#include <sys/types.h>
-#include <inttypes.h>
-#include <screenbuffer.h>
-#include <imgmap.h>
-#include <errno.h>
-#include <bool.h>
-#include <sysinfo.h>
-#include <ddi.h>
-#include <malloc.h>
-#include <mem.h>
-#include <as.h>
-#include <align.h>
-#include "../gfx/font-8x16.h"
-#include "../fb.h"
-#include "kfb.h"
-
-#define DEFAULT_BGCOLOR  0xffffff
-#define DEFAULT_FGCOLOR  0x000000
-
-#define FB_POS(x, y)  ((y) * kfb.scanline + (x) * kfb.pixel_bytes)
-
-#define COL2X(col)  ((col) * FONT_WIDTH)
-#define ROW2Y(row)  ((row) * FONT_SCANLINES)
-#define X2COL(x)    ((x) / FONT_WIDTH)
-#define Y2ROW(y)    ((y) / FONT_SCANLINES)
-
-#define GLYPH_POS(glyph, y, inverted) \
-	(((glyph) + (inverted) * FONT_GLYPHS) * (kfb.glyph_bytes) + (y) * (kfb.glyph_scanline))
-
-#define POINTER_WIDTH   11
-#define POINTER_HEIGHT  18
-
-static uint8_t pointer[] = {
-	0x01, 0x00, 0x03, 0x00, 0x05, 0x00, 0x09, 0x00, 0x11, 0x00, 0x21, 0x00,
-	0x41, 0x00, 0x81, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x04, 0x01, 0x03,
-	0x81, 0x00, 0x89, 0x00, 0x15, 0x01, 0x23, 0x01, 0x21, 0x01, 0xc0, 0x00
-};
-
-static uint8_t pointer_mask[] = {
-	0x01, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x3f, 0x00,
-	0x7f, 0x00, 0xff, 0x00, 0xff, 0x01, 0xff, 0x03, 0xff, 0x07, 0xff, 0x03,
-	0xff, 0x00, 0xff, 0x00, 0xf7, 0x01, 0xe3, 0x01, 0xe1, 0x01, 0xc0, 0x00
-};
-
-/** Function to draw a character. */
-typedef void (*draw_char_t)(sysarg_t, sysarg_t, bool, wchar_t, pixel_t,
-    pixel_t);
-
-typedef struct {
-	sysarg_t width;
-	sysarg_t height;
-	size_t offset;
-	size_t scanline;
-	visual_t visual;
-	
-	size_t size;
-	uint8_t *addr;
-	
-	pixel2visual_t pixel2visual;
-	visual2pixel_t visual2pixel;
-	visual_mask_t visual_mask;
-	size_t pixel_bytes;
-	
-	sysarg_t pointer_x;
-	sysarg_t pointer_y;
-	bool pointer_visible;
-	imgmap_t *pointer_imgmap;
-	
-	/*
-	 * Pre-rendered mask for rendering
-	 * glyphs. Specific for the framebuffer
-	 * visual.
-	 */
-	
-	size_t glyph_scanline;
-	size_t glyph_bytes;
-	uint8_t *glyphs;
-	
-	uint8_t *backbuf;
-} kfb_t;
-
-typedef struct {
-	/**
-	 * Character drawing function for this viewport.
-	 * Different viewports might use different drawing
-	 * functions depending on whether their scanlines
-	 * are aligned on a word boundary.
-	 */
-	draw_char_t draw_char;
-} kfb_vp_t;
-
-static kfb_t kfb;
-
-static pixel_t color_table[16] = {
-	[COLOR_BLACK]       = 0x000000,
-	[COLOR_BLUE]        = 0x0000f0,
-	[COLOR_GREEN]       = 0x00f000,
-	[COLOR_CYAN]        = 0x00f0f0,
-	[COLOR_RED]         = 0xf00000,
-	[COLOR_MAGENTA]     = 0xf000f0,
-	[COLOR_YELLOW]      = 0xf0f000,
-	[COLOR_WHITE]       = 0xf0f0f0,
-	
-	[COLOR_BLACK + 8]   = 0x000000,
-	[COLOR_BLUE + 8]    = 0x0000ff,
-	[COLOR_GREEN + 8]   = 0x00ff00,
-	[COLOR_CYAN + 8]    = 0x00ffff,
-	[COLOR_RED + 8]     = 0xff0000,
-	[COLOR_MAGENTA + 8] = 0xff00ff,
-	[COLOR_YELLOW + 8]  = 0xffff00,
-	[COLOR_WHITE + 8]   = 0xffffff,
-};
-
-static void put_pixel(sysarg_t x, sysarg_t y, pixel_t pixel)
-{
-	if ((x >= kfb.width) || (y >= kfb.height))
-		return;
-	
-	kfb.pixel2visual(kfb.addr + FB_POS(x, y), pixel);
-}
-
-static pixel_t get_pixel(sysarg_t x, sysarg_t y)
-{
-	if ((x >= kfb.width) || (y >= kfb.height))
-		return 0;
-	
-	return kfb.visual2pixel(kfb.addr + FB_POS(x, y));
-}
-
-static void pointer_show(void)
-{
-	if (kfb.pointer_visible) {
-		for (sysarg_t y = 0; y < POINTER_HEIGHT; y++) {
-			for (sysarg_t x = 0; x < POINTER_WIDTH; x++) {
-				sysarg_t dx = kfb.pointer_x + x;
-				sysarg_t dy = kfb.pointer_y + y;
-				
-				pixel_t pixel = get_pixel(dx, dy);
-				imgmap_put_pixel(kfb.pointer_imgmap, x, y, pixel);
-				
-				size_t offset = y * ((POINTER_WIDTH - 1) / 8 + 1) + x / 8;
-				bool visible = pointer_mask[offset] & (1 << (x % 8));
-				
-				if (visible) {
-					pixel = (pointer[offset] & (1 << (x % 8))) ?
-					    0x000000 : 0xffffff;
-					put_pixel(dx, dy, pixel);
-				}
-			}
-		}
-	}
-}
-
-static void pointer_hide(void)
-{
-	if (kfb.pointer_visible) {
-		for (sysarg_t y = 0; y < POINTER_HEIGHT; y++) {
-			for (sysarg_t x = 0; x < POINTER_WIDTH; x++) {
-				sysarg_t dx = kfb.pointer_x + x;
-				sysarg_t dy = kfb.pointer_y + y;
-				
-				pixel_t pixel =
-				    imgmap_get_pixel(kfb.pointer_imgmap, x, y);
-				put_pixel(dx, dy, pixel);
-			}
-		}
-	}
-}
-
-/** Draw a filled rectangle.
- *
- */
-static void draw_filled_rect(sysarg_t x1, sysarg_t y1, sysarg_t x2, sysarg_t y2,
-    pixel_t color)
-{
-	if ((y1 >= y2) || (x1 >= x2))
-		return;
-	
-	uint8_t cbuf[4];
-	kfb.pixel2visual(cbuf, color);
-	
-	for (sysarg_t y = y1; y < y2; y++) {
-		uint8_t *dst = kfb.addr + FB_POS(x1, y);
-		
-		for (sysarg_t x = x1; x < x2; x++) {
-			memcpy(dst, cbuf, kfb.pixel_bytes);
-			dst += kfb.pixel_bytes;
-		}
-	}
-}
-
-static void vp_put_pixel(fbvp_t *vp, sysarg_t x, sysarg_t y, pixel_t pixel)
-{
-	put_pixel(vp->x + x, vp->y + y, pixel);
-}
-
-static void attrs_rgb(char_attrs_t attrs, pixel_t *bgcolor, pixel_t *fgcolor)
-{
-	switch (attrs.type) {
-	case CHAR_ATTR_STYLE:
-		switch (attrs.val.style) {
-		case STYLE_NORMAL:
-			*bgcolor = color_table[COLOR_WHITE];
-			*fgcolor = color_table[COLOR_BLACK];
-			break;
-		case STYLE_EMPHASIS:
-			*bgcolor = color_table[COLOR_WHITE];
-			*fgcolor = color_table[COLOR_RED];
-			break;
-		case STYLE_INVERTED:
-			*bgcolor = color_table[COLOR_BLACK];
-			*fgcolor = color_table[COLOR_WHITE];
-			break;
-		case STYLE_SELECTED:
-			*bgcolor = color_table[COLOR_RED];
-			*fgcolor = color_table[COLOR_WHITE];
-			break;
-		}
-		break;
-	case CHAR_ATTR_INDEX:
-		*bgcolor = color_table[(attrs.val.index.bgcolor & 7) |
-		    ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
-		*fgcolor = color_table[(attrs.val.index.fgcolor & 7) |
-		    ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
-		break;
-	case CHAR_ATTR_RGB:
-		*bgcolor = attrs.val.rgb.bgcolor;
-		*fgcolor = attrs.val.rgb.fgcolor;
-		break;
-	}
-}
-
-/** Draw a character, takes advantage of alignment.
- *
- * This version can only be used if the following conditions are met:
- *
- *   - word size is divisible by pixel_bytes
- *   - cell scanline size is divisible by word size
- *   - cell scanlines are word-aligned
- *
- * It makes use of the pre-rendered mask to process (possibly) several
- * pixels at once (word size / pixel_bytes pixels at a time are processed)
- * making it very fast. Most notably this version is not applicable at 24 bits
- * per pixel.
- *
- * @param x        X coordinate of top-left corner on screen.
- * @param y        Y coordinate of top-left corner on screen.
- * @param inverted Draw inverted character.
- * @param ch       Character to draw.
- * @param bgcolor  Background color.
- * @param fbgcolor Foreground color.
- *
- */
-static void draw_char_aligned(sysarg_t x, sysarg_t y, bool inverted, wchar_t ch,
-    pixel_t bgcolor, pixel_t fgcolor)
-{
-	size_t word_size = sizeof(unsigned long);
-	
-	/*
-	 * Prepare a pair of words, one filled with foreground-color
-	 * pattern and the other filled with background-color pattern.
-	 */
-	unsigned long fg_buf;
-	unsigned long bg_buf;
-	
-	for (size_t i = 0; i < word_size / kfb.pixel_bytes; i++) {
-		kfb.pixel2visual(&((uint8_t *) &bg_buf)[i * kfb.pixel_bytes],
-		    bgcolor);
-		kfb.pixel2visual(&((uint8_t *) &fg_buf)[i * kfb.pixel_bytes],
-		    fgcolor);
-	}
-	
-	/* Pointer to the current position in the mask. */
-	unsigned long *maskp =
-	    (unsigned long *) &kfb.glyphs[GLYPH_POS(
-	    fb_font_glyph(ch), 0, inverted)];
-	
-	/* Pointer to the current position on the screen. */
-	unsigned long *dst =
-	    (unsigned long *) &kfb.addr[FB_POS(x, y)];
-	
-	/* Width of the character cell in words. */
-	size_t ww = FONT_WIDTH * kfb.pixel_bytes / word_size;
-	
-	/* Offset to add when moving to another screen scanline. */
-	size_t d_add = kfb.scanline - FONT_WIDTH * kfb.pixel_bytes;
-	
-	for (size_t yd = 0; yd < FONT_SCANLINES; yd++) {
-		/*
-		 * Now process the cell scanline, combining foreground
-		 * and background color patters using the pre-rendered mask.
-		 */
-		for (size_t i = 0; i < ww; i++) {
-			unsigned long mask = *maskp++;
-			*dst++ = (fg_buf & mask) | (bg_buf & ~mask);
-		}
-		
-		/* Move to the beginning of the next scanline of the cell. */
-		dst = (unsigned long *) ((uint8_t *) dst + d_add);
-	}
-}
-
-/** Draw a character, fallback version.
- *
- * This version does not make use of the pre-rendered mask, it uses
- * the font bitmap directly. It works always, but it is slower.
- *
- * @param x        X coordinate of top-left corner on screen.
- * @param y        Y coordinate of top-left corner on screen.
- * @param inverted Draw inverted character.
- * @param ch       Character to draw.
- * @param bgcolor  Background color.
- * @param fgcolor  Foreground color.
- *
- */
-static void draw_char_fallback(sysarg_t x, sysarg_t y, bool inverted,
-    wchar_t ch, pixel_t bgcolor, pixel_t fgcolor)
-{
-	/* Character glyph */
-	uint16_t glyph = fb_font_glyph(ch);
-	
-	/* Pre-render the foreground and background color pixels. */
-	uint8_t fg_buf[4];
-	uint8_t bg_buf[4];
-	
-	if (inverted) {
-		kfb.pixel2visual(bg_buf, fgcolor);
-		kfb.pixel2visual(fg_buf, bgcolor);
-	} else {
-		kfb.pixel2visual(bg_buf, bgcolor);
-		kfb.pixel2visual(fg_buf, fgcolor);
-	}
-	
-	/* Pointer to the current position on the screen. */
-	uint8_t *dst = (uint8_t *) &kfb.addr[FB_POS(x, y)];
-	
-	/* Offset to add when moving to another screen scanline. */
-	size_t d_add = kfb.scanline - FONT_WIDTH * kfb.pixel_bytes;
-	
-	for (size_t yd = 0; yd < FONT_SCANLINES; yd++) {
-		/* Byte containing bits of the glyph scanline. */
-		uint8_t byte = fb_font[glyph][yd];
-		
-		for (size_t i = 0; i < FONT_WIDTH; i++) {
-			/* Choose color based on the current bit. */
-			uint8_t *src = (byte & 0x80) ? fg_buf : bg_buf;
-			
-			/* Copy the pixel. */
-			for (size_t j = 0; j < kfb.pixel_bytes; j++)
-				*dst++ = *src++;
-			
-			/* Move to the next bit. */
-			byte <<= 1;
-		}
-		
-		/* Move to the beginning of the next scanline of the cell. */
-		dst += d_add;
-	}
-}
-
-/** Draw the character at the specified position in viewport.
- *
- * @param vp     Viewport.
- * @param col    Screen position relative to viewport.
- * @param row    Screen position relative to viewport.
- *
- */
-static void draw_vp_char(fbvp_t *vp, sysarg_t col, sysarg_t row)
-{
-	kfb_vp_t *kfb_vp = (kfb_vp_t *) vp->data;
-	
-	sysarg_t x = vp->x + COL2X(col);
-	sysarg_t y = vp->y + ROW2Y(row);
-	
-	charfield_t *field = screenbuffer_field_at(vp->backbuf, col, row);
-	
-	pixel_t bgcolor = 0;
-	pixel_t fgcolor = 0;
-	attrs_rgb(field->attrs, &bgcolor, &fgcolor);
-	
-	bool inverted = (vp->cursor_flash) &&
-	    screenbuffer_cursor_at(vp->backbuf, col, row);
-	
-	(*kfb_vp->draw_char)(x, y, inverted, field->ch, bgcolor, fgcolor);
-}
-
-static int kfb_yield(fbdev_t *dev)
-{
-	if (kfb.backbuf == NULL) {
-		kfb.backbuf =
-		    malloc(kfb.width * kfb.height * kfb.pixel_bytes);
-		if (kfb.backbuf == NULL)
-			return ENOMEM;
-	}
-	
-	for (sysarg_t y = 0; y < kfb.height; y++)
-		memcpy(kfb.backbuf + y * kfb.width * kfb.pixel_bytes,
-		    kfb.addr + FB_POS(0, y), kfb.width * kfb.pixel_bytes);
-	
-	return EOK;
-}
-
-static int kfb_claim(fbdev_t *dev)
-{
-	if (kfb.backbuf == NULL)
-		return ENOENT;
-	
-	for (sysarg_t y = 0; y < kfb.height; y++)
-		memcpy(kfb.addr + FB_POS(0, y),
-		    kfb.backbuf + y * kfb.width * kfb.pixel_bytes,
-		    kfb.width * kfb.pixel_bytes);
-	
-	return EOK;
-}
-
-static void kfb_pointer_update(struct fbdev *dev, sysarg_t x, sysarg_t y,
-    bool visible)
-{
-	pointer_hide();
-	
-	kfb.pointer_x = x;
-	kfb.pointer_y = y;
-	kfb.pointer_visible = visible;
-	
-	pointer_show();
-}
-
-static int kfb_get_resolution(fbdev_t *dev, sysarg_t *width, sysarg_t *height)
-{
-	*width = kfb.width;
-	*height = kfb.height;
-	return EOK;
-}
-
-static void kfb_font_metrics(fbdev_t *dev, sysarg_t width, sysarg_t height,
-    sysarg_t *cols, sysarg_t *rows)
-{
-	*cols = X2COL(width);
-	*rows = Y2ROW(height);
-}
-
-static int kfb_vp_create(fbdev_t *dev, fbvp_t *vp)
-{
-	kfb_vp_t *kfb_vp = malloc(sizeof(kfb_vp_t));
-	if (kfb_vp == NULL)
-		return ENOMEM;
-	
-	/*
-	 * Conditions necessary to select aligned glyph
-	 * drawing variants:
-	 *  - word size is divisible by number of bytes per pixel
-	 *  - cell scanline size is divisible by word size
-	 *  - cell scanlines are word-aligned
-	 *
-	 */
-	size_t word_size = sizeof(unsigned long);
-	
-	if (((word_size % kfb.pixel_bytes) == 0)
-	    && ((FONT_WIDTH * kfb.pixel_bytes) % word_size == 0)
-	    && ((vp->x * kfb.pixel_bytes) % word_size == 0)
-	    && (kfb.scanline % word_size == 0))
-		kfb_vp->draw_char = draw_char_aligned;
-	else
-		kfb_vp->draw_char = draw_char_fallback;
-	
-	vp->attrs.type = CHAR_ATTR_RGB;
-	vp->attrs.val.rgb.bgcolor = DEFAULT_BGCOLOR;
-	vp->attrs.val.rgb.fgcolor = DEFAULT_FGCOLOR;
-	vp->data = (void *) kfb_vp;
-	
-	return EOK;
-}
-
-static void kfb_vp_destroy(fbdev_t *dev, fbvp_t *vp)
-{
-	free(vp->data);
-}
-
-static void kfb_vp_clear(fbdev_t *dev, fbvp_t *vp)
-{
-	pointer_hide();
-	
-	for (sysarg_t row = 0; row < vp->rows; row++) {
-		for (sysarg_t col = 0; col < vp->cols; col++) {
-			charfield_t *field =
-			    screenbuffer_field_at(vp->backbuf, col, row);
-			
-			field->ch = 0;
-			field->attrs = vp->attrs;
-		}
-	}
-	
-	pixel_t bgcolor = 0;
-	pixel_t fgcolor = 0;
-	attrs_rgb(vp->attrs, &bgcolor, &fgcolor);
-	
-	draw_filled_rect(vp->x, vp->y, vp->x + vp->width,
-	    vp->y + vp->height, bgcolor);
-	
-	pointer_show();
-}
-
-static console_caps_t kfb_vp_get_caps(fbdev_t *dev, fbvp_t *vp)
-{
-	return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB);
-}
-
-static void kfb_vp_cursor_update(fbdev_t *dev, fbvp_t *vp, sysarg_t prev_col,
-    sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
-{
-	pointer_hide();
-	draw_vp_char(vp, prev_col, prev_row);
-	draw_vp_char(vp, col, row);
-	pointer_show();
-}
-
-static void kfb_vp_cursor_flash(fbdev_t *dev, fbvp_t *vp, sysarg_t col,
-    sysarg_t row)
-{
-	pointer_hide();
-	draw_vp_char(vp, col, row);
-	pointer_show();
-}
-
-static void kfb_vp_char_update(fbdev_t *dev, fbvp_t *vp, sysarg_t col,
-    sysarg_t row)
-{
-	pointer_hide();
-	draw_vp_char(vp, col, row);
-	pointer_show();
-}
-
-static void kfb_vp_imgmap_damage(fbdev_t *dev, fbvp_t *vp, imgmap_t *imgmap,
-    sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height)
-{
-	pointer_hide();
-	
-	for (sysarg_t y = 0; y < height; y++) {
-		for (sysarg_t x = 0; x < width; x++) {
-			pixel_t pixel = imgmap_get_pixel(imgmap, x0 + x, y0 + y);
-			vp_put_pixel(vp, x0 + x, y0 + y, pixel);
-		}
-	}
-	
-	pointer_show();
-}
-
-static fbdev_ops_t kfb_ops = {
-	.yield = kfb_yield,
-	.claim = kfb_claim,
-	.pointer_update = kfb_pointer_update,
-	.get_resolution = kfb_get_resolution,
-	.font_metrics = kfb_font_metrics,
-	.vp_create = kfb_vp_create,
-	.vp_destroy = kfb_vp_destroy,
-	.vp_clear = kfb_vp_clear,
-	.vp_get_caps = kfb_vp_get_caps,
-	.vp_cursor_update = kfb_vp_cursor_update,
-	.vp_cursor_flash = kfb_vp_cursor_flash,
-	.vp_char_update = kfb_vp_char_update,
-	.vp_imgmap_damage = kfb_vp_imgmap_damage
-};
-
-/** Render glyphs
- *
- * Convert glyphs from device independent font
- * description to current visual representation.
- *
- */
-static void render_glyphs(size_t sz)
-{
-	memset(kfb.glyphs, 0, sz);
-	
-	for (unsigned int glyph = 0; glyph < FONT_GLYPHS; glyph++) {
-		for (unsigned int y = 0; y < FONT_SCANLINES; y++) {
-			for (unsigned int x = 0; x < FONT_WIDTH; x++) {
-				kfb.visual_mask(
-				    &kfb.glyphs[GLYPH_POS(glyph, y, false) + x * kfb.pixel_bytes],
-				    (fb_font[glyph][y] & (1 << (7 - x))) ? true : false);
-				kfb.visual_mask(
-				    &kfb.glyphs[GLYPH_POS(glyph, y, true) + x * kfb.pixel_bytes],
-				    (fb_font[glyph][y] & (1 << (7 - x))) ? false : true);
-			}
-		}
-	}
-}
-
-int kfb_init(void)
-{
-	sysarg_t present;
-	int rc = sysinfo_get_value("fb", &present);
-	if (rc != EOK)
-		present = false;
-	
-	if (!present)
-		return ENOENT;
-	
-	sysarg_t kind;
-	rc = sysinfo_get_value("fb.kind", &kind);
-	if (rc != EOK)
-		kind = (sysarg_t) -1;
-	
-	if (kind != 1)
-		return EINVAL;
-	
-	sysarg_t paddr;
-	rc = sysinfo_get_value("fb.address.physical", &paddr);
-	if (rc != EOK)
-		return rc;
-	
-	sysarg_t offset;
-	rc = sysinfo_get_value("fb.offset", &offset);
-	if (rc != EOK)
-		offset = 0;
-	
-	sysarg_t width;
-	rc = sysinfo_get_value("fb.width", &width);
-	if (rc != EOK)
-		return rc;
-	
-	sysarg_t height;
-	rc = sysinfo_get_value("fb.height", &height);
-	if (rc != EOK)
-		return rc;
-	
-	sysarg_t scanline;
-	rc = sysinfo_get_value("fb.scanline", &scanline);
-	if (rc != EOK)
-		return rc;
-	
-	sysarg_t visual;
-	rc = sysinfo_get_value("fb.visual", &visual);
-	if (rc != EOK)
-		return rc;
-	
-	kfb.width = width;
-	kfb.height = height;
-	kfb.offset = offset;
-	kfb.scanline = scanline;
-	kfb.visual = visual;
-	
-	switch (visual) {
-	case VISUAL_INDIRECT_8:
-		kfb.pixel2visual = pixel2bgr_323;
-		kfb.visual2pixel = bgr_323_2pixel;
-		kfb.visual_mask = visual_mask_323;
-		kfb.pixel_bytes = 1;
-		break;
-	case VISUAL_RGB_5_5_5_LE:
-		kfb.pixel2visual = pixel2rgb_555_le;
-		kfb.visual2pixel = rgb_555_le_2pixel;
-		kfb.visual_mask = visual_mask_555;
-		kfb.pixel_bytes = 2;
-		break;
-	case VISUAL_RGB_5_5_5_BE:
-		kfb.pixel2visual = pixel2rgb_555_be;
-		kfb.visual2pixel = rgb_555_be_2pixel;
-		kfb.visual_mask = visual_mask_555;
-		kfb.pixel_bytes = 2;
-		break;
-	case VISUAL_RGB_5_6_5_LE:
-		kfb.pixel2visual = pixel2rgb_565_le;
-		kfb.visual2pixel = rgb_565_le_2pixel;
-		kfb.visual_mask = visual_mask_565;
-		kfb.pixel_bytes = 2;
-		break;
-	case VISUAL_RGB_5_6_5_BE:
-		kfb.pixel2visual = pixel2rgb_565_be;
-		kfb.visual2pixel = rgb_565_be_2pixel;
-		kfb.visual_mask = visual_mask_565;
-		kfb.pixel_bytes = 2;
-		break;
-	case VISUAL_RGB_8_8_8:
-		kfb.pixel2visual = pixel2rgb_888;
-		kfb.visual2pixel = rgb_888_2pixel;
-		kfb.visual_mask = visual_mask_888;
-		kfb.pixel_bytes = 3;
-		break;
-	case VISUAL_BGR_8_8_8:
-		kfb.pixel2visual = pixel2bgr_888;
-		kfb.visual2pixel = bgr_888_2pixel;
-		kfb.visual_mask = visual_mask_888;
-		kfb.pixel_bytes = 3;
-		break;
-	case VISUAL_RGB_8_8_8_0:
-		kfb.pixel2visual = pixel2rgb_8880;
-		kfb.visual2pixel = rgb_8880_2pixel;
-		kfb.visual_mask = visual_mask_8880;
-		kfb.pixel_bytes = 4;
-		break;
-	case VISUAL_RGB_0_8_8_8:
-		kfb.pixel2visual = pixel2rgb_0888;
-		kfb.visual2pixel = rgb_0888_2pixel;
-		kfb.visual_mask = visual_mask_0888;
-		kfb.pixel_bytes = 4;
-		break;
-	case VISUAL_BGR_0_8_8_8:
-		kfb.pixel2visual = pixel2bgr_0888;
-		kfb.visual2pixel = bgr_0888_2pixel;
-		kfb.visual_mask = visual_mask_0888;
-		kfb.pixel_bytes = 4;
-		break;
-	case VISUAL_BGR_8_8_8_0:
-		kfb.pixel2visual = pixel2bgr_8880;
-		kfb.visual2pixel = bgr_8880_2pixel;
-		kfb.visual_mask = visual_mask_8880;
-		kfb.pixel_bytes = 4;
-		break;
-	default:
-		return EINVAL;
-	}
-	
-	kfb.glyph_scanline = FONT_WIDTH * kfb.pixel_bytes;
-	kfb.glyph_bytes = kfb.glyph_scanline * FONT_SCANLINES;
-	
-	size_t sz = 2 * FONT_GLYPHS * kfb.glyph_bytes;
-	kfb.glyphs = (uint8_t *) malloc(sz);
-	if (kfb.glyphs == NULL)
-		return EINVAL;
-	
-	render_glyphs(sz);
-	
-	kfb.size = scanline * height;
-	
-	rc = physmem_map((void *) paddr + offset,
-	    ALIGN_UP(kfb.size, PAGE_SIZE) >> PAGE_WIDTH,
-	    AS_AREA_READ | AS_AREA_WRITE, (void *) &kfb.addr);
-	if (rc != EOK) {
-		free(kfb.glyphs);
-		return rc;
-	}
-	
-	kfb.pointer_x = 0;
-	kfb.pointer_y = 0;
-	kfb.pointer_visible = false;
-	kfb.pointer_imgmap = imgmap_create(POINTER_WIDTH, POINTER_HEIGHT,
-	    VISUAL_RGB_0_8_8_8, IMGMAP_FLAG_NONE);
-	
-	kfb.backbuf = NULL;
-	
-	fbdev_t *dev = fbdev_register(&kfb_ops, (void *) &kfb);
-	if (dev == NULL) {
-		free(kfb.glyphs);
-		as_area_destroy(kfb.addr);
-		return EINVAL;
-	}
-	
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/fb/port/kfb.h
===================================================================
--- uspace/srv/hid/fb/port/kfb.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,44 +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 fb
- * @ingroup fbs
- * @{
- */
-/** @file
- */
-
-#ifndef FB_PORT_KFB_H_
-#define FB_PORT_KFB_H_
-
-extern int kfb_init(void);
-
-#endif
-
-/** @}
- */
Index: pace/srv/hid/fb/port/niagara.c
===================================================================
--- uspace/srv/hid/fb/port/niagara.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,114 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * Copyright (c) 2008 Martin Decky
- * Copyright (c) 2008 Pavel Rimsky
- * 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.
- */
-
-/** @file
- */
-
-#include <sys/types.h>
-#include <errno.h>
-#include <sysinfo.h>
-#include <ddi.h>
-#include <as.h>
-#include <align.h>
-#include "../ctl/serial.h"
-#include "niagara.h"
-
-#define OUTPUT_FIFO_SIZE  ((PAGE_SIZE) - 2 * sizeof(uint64_t))
-
-typedef volatile struct {
-	uint64_t read_ptr;
-	uint64_t write_ptr;
-	char data[OUTPUT_FIFO_SIZE];
-} __attribute__((packed)) output_fifo_t;
-
-typedef struct {
-	output_fifo_t *fifo;
-} niagara_t;
-
-static niagara_t niagara;
-
-static void niagara_putc(const char c)
-{
-	while (niagara.fifo->write_ptr ==
-	    (niagara.fifo->read_ptr + OUTPUT_FIFO_SIZE - 1)
-	    % OUTPUT_FIFO_SIZE);
-	
-	niagara.fifo->data[niagara.fifo->write_ptr] = c;
-	niagara.fifo->write_ptr =
-	    ((niagara.fifo->write_ptr) + 1) % OUTPUT_FIFO_SIZE;
-}
-
-static void niagara_putchar(wchar_t ch)
-{
-	if (ascii_check(ch))
-		niagara_putc(ch);
-	else
-		niagara_putc('?');
-}
-
-static void niagara_control_puts(const char *str)
-{
-	while (*str)
-		niagara_putc(*(str++));
-}
-
-int niagara_init(void)
-{
-	sysarg_t present;
-	int rc = sysinfo_get_value("fb", &present);
-	if (rc != EOK)
-		present = false;
-	
-	if (!present)
-		return ENOENT;
-	
-	sysarg_t kind;
-	rc = sysinfo_get_value("fb.kind", &kind);
-	if (rc != EOK)
-		kind = (sysarg_t) -1;
-	
-	if (kind != 5)
-		return EINVAL;
-	
-	sysarg_t paddr;
-	rc = sysinfo_get_value("niagara.outbuf.address", &paddr);
-	if (rc != EOK)
-		return rc;
-	
-	rc = physmem_map((void *) paddr, 1,
-	    AS_AREA_READ | AS_AREA_WRITE, (void *) &niagara.fifo);
-	if (rc != EOK)
-		return rc;
-	
-	return serial_init(niagara_putchar, niagara_control_puts);
-}
-
-/** @}
- */
Index: pace/srv/hid/fb/port/niagara.h
===================================================================
--- uspace/srv/hid/fb/port/niagara.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,41 +1,0 @@
-/*
- * Copyright (c) 2008 Pavel Rimsky
- * 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.
- */
-
-/** @file
- */
-
-#ifndef FB_PORT_NIAGARA_H_
-#define FB_PORT_NIAGARA_H_
-
-extern int niagara_init(void);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/fb/port/ski.c
===================================================================
--- uspace/srv/hid/fb/port/ski.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,111 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * Copyright (c) 2008 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.
- */
-
-/** @file
- */
-
-#include <sys/types.h>
-#include <errno.h>
-#include <sysinfo.h>
-#include "../ctl/serial.h"
-#include "ski.h"
-
-#ifdef UARCH_ia64
-
-#define SKI_PUTCHAR  31
-
-/** Display character on ski debug console
- *
- * Use SSC (Simulator System Call) to
- * display character on debug console.
- *
- * @param c Character to be printed.
- *
- */
-static void ski_putc(const char c)
-{
-	asm volatile (
-		"mov r15 = %0\n"
-		"mov r32 = %1\n"   /* r32 is in0 */
-		"break 0x80000\n"  /* modifies r8 */
-		:
-		: "i" (SKI_PUTCHAR), "r" (c)
-		: "r15", "in0", "r8"
-	);
-	
-	if (c == '\n')
-		ski_putc('\r');
-}
-
-static void ski_putchar(wchar_t ch)
-{
-	if ((ch >= 0) && (ch < 128))
-		ski_putc(ch);
-	else
-		ski_putc('?');
-}
-
-static void ski_control_puts(const char *str)
-{
-	while (*str)
-		ski_putc(*(str++));
-}
-
-int ski_init(void)
-{
-	sysarg_t present;
-	int rc = sysinfo_get_value("fb", &present);
-	if (rc != EOK)
-		present = false;
-	
-	if (!present)
-		return ENOENT;
-	
-	sysarg_t kind;
-	rc = sysinfo_get_value("fb.kind", &kind);
-	if (rc != EOK)
-		kind = (sysarg_t) -1;
-	
-	if (kind != 6)
-		return EINVAL;
-	
-	return serial_init(ski_putchar, ski_control_puts);
-}
-
-#else /* UARCH_ia64 */
-
-int ski_init(void)
-{
-	return ENOENT;
-}
-
-#endif
-
-/** @}
- */
Index: pace/srv/hid/fb/port/ski.h
===================================================================
--- uspace/srv/hid/fb/port/ski.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,40 +1,0 @@
-/*
- * Copyright (c) 2008 Jiri Svoboda
- * 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.
- */
-
-/** @file
- */
-
-#ifndef FB_PORT_SKI_H_
-#define FB_PORT_SKI_H_
-
-extern int ski_init(void);
-
-#endif
-
-/** @}
- */
Index: pace/srv/hid/fb/proto/vt100.c
===================================================================
--- uspace/srv/hid/fb/proto/vt100.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,264 +1,0 @@
-/*
- * Copyright (c) 2011 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.
- */
-
-/** @file
- */
-
-#include <sys/types.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <io/color.h>
-#include <malloc.h>
-#include <errno.h>
-#include "vt100.h"
-
-#define MAX_CONTROL  20
-
-#define BACKBUF_POS(state, x, y)  ((y) * ((state)->width) + (x))
-
-struct vt100_state {
-	vt100_putchar_t putchar;
-	vt100_control_puts_t control_puts;
-	
-	sysarg_t width;
-	sysarg_t height;
-	
-	sysarg_t cur_col;
-	sysarg_t cur_row;
-	
-	char_attrs_t cur_attrs;
-	
-	charfield_t backbuf[];
-};
-
-typedef enum {
-	CI_BLACK   = 0,
-	CI_RED     = 1,
-	CI_GREEN   = 2,
-	CI_BROWN   = 3,
-	CI_BLUE    = 4,
-	CI_MAGENTA = 5,
-	CI_CYAN    = 6,
-	CI_WHITE   = 7
-} sgr_color_index_t;
-
-typedef enum {
-	SGR_RESET       = 0,
-	SGR_BOLD        = 1,
-	SGR_UNDERLINE   = 4,
-	SGR_BLINK       = 5,
-	SGR_REVERSE     = 7,
-	SGR_FGCOLOR     = 30,
-	SGR_BGCOLOR     = 40
-} sgr_command_t;
-
-static sgr_color_index_t color_map[] = {
-	[COLOR_BLACK]   = CI_BLACK,
-	[COLOR_BLUE]    = CI_RED,
-	[COLOR_GREEN]   = CI_GREEN,
-	[COLOR_CYAN]    = CI_CYAN,
-	[COLOR_RED]     = CI_RED,
-	[COLOR_MAGENTA] = CI_MAGENTA,
-	[COLOR_YELLOW]  = CI_BROWN,
-	[COLOR_WHITE]   = CI_WHITE
-};
-
-/** ECMA-48 Set Graphics Rendition. */
-static void vt100_sgr(vt100_state_t *state, unsigned int mode)
-{
-	char control[MAX_CONTROL];
-	
-	snprintf(control, MAX_CONTROL, "\033[%um", mode);
-	state->control_puts(control);
-}
-
-static void vt100_set_pos(vt100_state_t *state, sysarg_t col, sysarg_t row)
-{
-	char control[MAX_CONTROL];
-	
-	snprintf(control, MAX_CONTROL, "\033[%" PRIun ";%" PRIun "f",
-	    row + 1, col + 1);
-	state->control_puts(control);
-}
-
-static void vt100_set_sgr(vt100_state_t *state, char_attrs_t attrs)
-{
-	switch (attrs.type) {
-	case CHAR_ATTR_STYLE:
-		switch (attrs.val.style) {
-		case STYLE_NORMAL:
-			vt100_sgr(state, SGR_RESET);
-			vt100_sgr(state, SGR_BGCOLOR + CI_WHITE);
-			vt100_sgr(state, SGR_FGCOLOR + CI_BLACK);
-			break;
-		case STYLE_EMPHASIS:
-			vt100_sgr(state, SGR_RESET);
-			vt100_sgr(state, SGR_BGCOLOR + CI_WHITE);
-			vt100_sgr(state, SGR_FGCOLOR + CI_RED);
-			vt100_sgr(state, SGR_BOLD);
-			break;
-		case STYLE_INVERTED:
-			vt100_sgr(state, SGR_RESET);
-			vt100_sgr(state, SGR_BGCOLOR + CI_BLACK);
-			vt100_sgr(state, SGR_FGCOLOR + CI_WHITE);
-			break;
-		case STYLE_SELECTED:
-			vt100_sgr(state, SGR_RESET);
-			vt100_sgr(state, SGR_BGCOLOR + CI_RED);
-			vt100_sgr(state, SGR_FGCOLOR + CI_WHITE);
-			break;
-		}
-		break;
-	case CHAR_ATTR_INDEX:
-		vt100_sgr(state, SGR_RESET);
-		vt100_sgr(state, SGR_BGCOLOR + color_map[attrs.val.index.bgcolor & 7]);
-		vt100_sgr(state, SGR_FGCOLOR + color_map[attrs.val.index.fgcolor & 7]);
-		
-		if (attrs.val.index.attr & CATTR_BRIGHT)
-			vt100_sgr(state, SGR_BOLD);
-		
-		break;
-	case CHAR_ATTR_RGB:
-		vt100_sgr(state, SGR_RESET);
-		
-		if (attrs.val.rgb.bgcolor <= attrs.val.rgb.fgcolor)
-			vt100_sgr(state, SGR_REVERSE);
-		
-		break;
-	}
-}
-
-vt100_state_t *vt100_state_create(sysarg_t width, sysarg_t height,
-    vt100_putchar_t putchar_fn, vt100_control_puts_t control_puts_fn)
-{
-	size_t sz = width * height * sizeof(charfield_t);
-	
-	vt100_state_t *state =
-	    malloc(sizeof(vt100_state_t) + sz);
-	if (state == NULL)
-		return NULL;
-	
-	state->putchar = putchar_fn;
-	state->control_puts = control_puts_fn;
-	
-	state->width = width;
-	state->height = height;
-	
-	state->cur_col = (sysarg_t) -1;
-	state->cur_row = (sysarg_t) -1;
-	
-	state->cur_attrs.type = CHAR_ATTR_STYLE;
-	state->cur_attrs.val.style = STYLE_NORMAL;
-	
-	memset(state->backbuf, 0, sz);
-	
-	/* Initialize graphic rendition attributes */
-	vt100_sgr(state, SGR_RESET);
-	vt100_sgr(state, SGR_FGCOLOR + CI_BLACK);
-	vt100_sgr(state, SGR_BGCOLOR + CI_WHITE);
-	state->control_puts("\033[2J");
-	
-	return state;
-}
-
-void vt100_get_resolution(vt100_state_t *state, sysarg_t *width,
-    sysarg_t *height)
-{
-	*width = state->width;
-	*height = state->height;
-}
-
-int vt100_yield(vt100_state_t *state)
-{
-	return EOK;
-}
-
-int vt100_claim(vt100_state_t *state)
-{
-	for (sysarg_t row = 0; row < state->height; row++) {
-		vt100_set_pos(state, 0, row);
-		for (sysarg_t col = 0; col < state->width; col++) {
-			charfield_t *field = state->backbuf +
-			    BACKBUF_POS(state, col, row);
-			vt100_set_sgr(state, field->attrs);
-			state->putchar(field->ch);
-		}
-	}
-	
-	vt100_set_pos(state, state->cur_col, state->cur_row);
-	vt100_set_sgr(state, state->cur_attrs);
-	
-	return EOK;
-}
-
-void vt100_putchar(vt100_state_t *state, wchar_t ch)
-{
-	charfield_t *field = state->backbuf +
-	    BACKBUF_POS(state, state->cur_col, state->cur_row);
-	field->ch = ch;
-	field->attrs = state->cur_attrs;
-	
-	state->putchar(ch);
-	state->cur_col++;
-	
-	if (state->cur_col >= state->width) {
-		state->cur_row += state->cur_col / state->width;
-		state->cur_col %= state->width;
-	}
-}
-
-void vt100_set_attr(vt100_state_t *state, char_attrs_t attrs)
-{
-	if (!attrs_same(state->cur_attrs, attrs)) {
-		vt100_set_sgr(state, attrs);
-		state->cur_attrs = attrs;
-	}
-}
-
-void vt100_goto(vt100_state_t *state, sysarg_t col, sysarg_t row)
-{
-	if ((col >= state->width) || (row >= state->height))
-		return;
-	
-	if ((col != state->cur_col) || (row != state->cur_row)) {
-		vt100_set_pos(state, col, row);
-		state->cur_col = col;
-		state->cur_row = row;
-	}
-}
-
-void vt100_cursor_visibility(vt100_state_t *state, bool visible)
-{
-	if (visible)
-		state->control_puts("\033[?25h");
-	else
-		state->control_puts("\033[?25l");
-}
-
-/** @}
- */
Index: pace/srv/hid/fb/proto/vt100.h
===================================================================
--- uspace/srv/hid/fb/proto/vt100.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,60 +1,0 @@
-/*
- * Copyright (c) 2011 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.
- */
-
-/** @file
- */
-
-#ifndef FB_PROTO_VT100_H_
-#define FB_PROTO_VT100_H_
-
-#include <sys/types.h>
-#include <screenbuffer.h>
-
-typedef void (* vt100_putchar_t)(wchar_t ch);
-typedef void (* vt100_control_puts_t)(const char *str);
-
-/** Forward declaration */
-struct vt100_state;
-typedef struct vt100_state vt100_state_t;
-
-extern vt100_state_t *vt100_state_create(sysarg_t, sysarg_t, vt100_putchar_t,
-    vt100_control_puts_t);
-extern void vt100_get_resolution(vt100_state_t *, sysarg_t *, sysarg_t *);
-extern int vt100_yield(vt100_state_t *);
-extern int vt100_claim(vt100_state_t *);
-
-extern void vt100_putchar(vt100_state_t *, wchar_t);
-
-extern void vt100_set_attr(vt100_state_t *, char_attrs_t);
-extern void vt100_goto(vt100_state_t *, sysarg_t, sysarg_t);
-extern void vt100_cursor_visibility(vt100_state_t *, bool);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/hid/input/Makefile
===================================================================
--- uspace/srv/hid/input/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -29,12 +29,7 @@
 
 USPACE_PREFIX = ../../..
-EXTRA_CFLAGS = -Iinclude
 BINARY = input
 
 SOURCES = \
-	generic/gsp.c \
-	generic/input.c \
-	generic/layout.c \
-	generic/stroke.c \
 	layout/cz.c \
 	layout/us_qwerty.c \
@@ -56,5 +51,9 @@
 	ctl/pc.c \
 	ctl/stty.c \
-	ctl/sun.c
+	ctl/sun.c \
+	gsp.c \
+	input.c \
+	layout.c \
+	stroke.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/input/ctl/apple.c
===================================================================
--- uspace/srv/hid/input/ctl/apple.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/ctl/apple.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,9 +36,9 @@
  */
 
-#include <kbd.h>
 #include <io/console.h>
 #include <io/keycode.h>
-#include <kbd_ctl.h>
-#include <kbd_port.h>
+#include "../kbd.h"
+#include "../kbd_ctl.h"
+#include "../kbd_port.h"
 
 static void apple_ctl_parse(sysarg_t);
Index: uspace/srv/hid/input/ctl/gxe_fb.c
===================================================================
--- uspace/srv/hid/input/ctl/gxe_fb.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/ctl/gxe_fb.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,14 +33,14 @@
 /**
  * @file
- * @brief	GXEmul framebuffer-mode keyboard controller driver.
+ * @brief GXEmul framebuffer-mode keyboard controller driver.
  */
 
-#include <kbd.h>
 #include <io/console.h>
 #include <io/keycode.h>
-#include <kbd_ctl.h>
-#include <kbd_port.h>
-#include <gsp.h>
-#include <stroke.h>
+#include "../stroke.h"
+#include "../gsp.h"
+#include "../kbd.h"
+#include "../kbd_port.h"
+#include "../kbd_ctl.h"
 
 static void gxe_fb_ctl_parse(sysarg_t);
Index: uspace/srv/hid/input/ctl/kbdev.c
===================================================================
--- uspace/srv/hid/input/ctl/kbdev.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/ctl/kbdev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,16 +40,16 @@
 #include <errno.h>
 #include <fcntl.h>
-#include <gsp.h>
 #include <io/console.h>
 #include <io/keycode.h>
 #include <ipc/kbdev.h>
-#include <input.h>
-#include <kbd.h>
-#include <kbd_ctl.h>
-#include <kbd_port.h>
 #include <loc.h>
 #include <stdlib.h>
 #include <vfs/vfs_sess.h>
 #include <sys/typefmt.h>
+#include "../gsp.h"
+#include "../input.h"
+#include "../kbd.h"
+#include "../kbd_ctl.h"
+#include "../kbd_port.h"
 
 static int kbdev_ctl_init(kbd_dev_t *);
Index: uspace/srv/hid/input/ctl/pc.c
===================================================================
--- uspace/srv/hid/input/ctl/pc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/ctl/pc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,10 +36,10 @@
  */
 
-#include <kbd.h>
 #include <io/console.h>
 #include <io/keycode.h>
-#include <kbd_ctl.h>
-#include <kbd_port.h>
-#include <gsp.h>
+#include "../gsp.h"
+#include "../kbd.h"
+#include "../kbd_port.h"
+#include "../kbd_ctl.h"
 
 static void pc_ctl_parse(sysarg_t);
Index: uspace/srv/hid/input/ctl/stty.c
===================================================================
--- uspace/srv/hid/input/ctl/stty.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/ctl/stty.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,10 +38,10 @@
  */
 
-#include <kbd.h>
 #include <io/keycode.h>
-#include <kbd_ctl.h>
-#include <kbd_port.h>
-#include <gsp.h>
-#include <stroke.h>
+#include "../stroke.h"
+#include "../gsp.h"
+#include "../kbd.h"
+#include "../kbd_port.h"
+#include "../kbd_ctl.h"
 
 static void stty_ctl_parse(sysarg_t);
Index: uspace/srv/hid/input/ctl/sun.c
===================================================================
--- uspace/srv/hid/input/ctl/sun.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/ctl/sun.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,9 +37,9 @@
  */
 
-#include <kbd.h>
 #include <io/console.h>
 #include <io/keycode.h>
-#include <kbd_ctl.h>
-#include <kbd_port.h>
+#include "../kbd.h"
+#include "../kbd_port.h"
+#include "../kbd_ctl.h"
 
 static void sun_ctl_parse(sysarg_t);
Index: pace/srv/hid/input/generic/gsp.c
===================================================================
--- uspace/srv/hid/input/generic/gsp.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,291 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * 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 kbdgen generic
- * @ingroup  input
- * @{
- */ 
-/** @file
- * @brief	Generic scancode parser.
- *
- * The scancode parser is a simple finite state machine. It is described
- * using sequences of input symbols (scancodes) and the corresponding output
- * value (mods, key pair). When the parser recognizes a sequence,
- * it outputs the value and restarts. If a transition is undefined,
- * the parser restarts, too.
- *
- * Apart from precise values, GSP_DEFAULT allows to catch general cases.
- * I.e. if we knew that after 0x1b 0x4f there always follow two more
- * scancodes, we can define (0x1b, 0x4f, GSP_DEFAULT, GSP_DEFAULT, GSP_END)
- * with null output. This will force the parser to read the entire sequence,
- * not leaving garbage on the input if it does not recognize the specific
- * sequence.
- */
-
-#include <gsp.h>
-#include <adt/hash_table.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define TRANS_TABLE_CHAINS 256
-
-/*
- * Hash table operations for the transition function.
- */
-
-static hash_index_t trans_op_hash(unsigned long key[]);
-static int trans_op_compare(unsigned long key[], hash_count_t keys,
-    link_t *item);
-static void trans_op_remove_callback(link_t *item);
-
-static hash_table_operations_t trans_ops = {
-	.hash = trans_op_hash,
-	.compare = trans_op_compare,
-	.remove_callback = trans_op_remove_callback
-};
-
-static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input);
-static void trans_insert(gsp_t *p, gsp_trans_t *t);
-static gsp_trans_t *trans_new(void);
-
-/** Initialise scancode parser. */
-void gsp_init(gsp_t *p)
-{
-	p->states = 1;
-	hash_table_create(&p->trans, TRANS_TABLE_CHAINS, 2, &trans_ops);
-}
-
-/** Insert a series of definitions into the parser.
- *
- * @param p	The parser.
- * @param defs	Definition list. Each definition starts with two output values
- *		(mods, key) and continues with a sequence of input values
- *		terminated with GSP_END. The definition list is terminated
- *		with two zeroes (0, 0) for output values.
- */
-int gsp_insert_defs(gsp_t *p, const int *defs)
-{
-	unsigned mods, key;
-	const int *dp;
-	int rc;
-
-	dp = defs;
-
-	while (1) {
-		/* Read the output values. */
-		mods = *dp++;
-		key = *dp++;
-		if (key == 0) break;
-
-		/* Insert one sequence. */
-		rc = gsp_insert_seq(p, dp, mods, key);
-		if (rc != 0)
-			return rc;
-
-		/* Skip to the next definition. */
-		while (*dp != GSP_END)
-			++dp;
-		++dp;
-	}
-
-	return 0;
-}
-
-/** Insert one sequence into the parser.
- *
- * @param p	The parser.
- * @param seq	Sequence of input values terminated with GSP_END.
- * @param mods	Corresponsing output value.
- * @param key	Corresponsing output value.
- */
-int gsp_insert_seq(gsp_t *p, const int *seq, unsigned mods, unsigned key)
-{
-	int state;
-	gsp_trans_t *t;
-
-	state = 0;
-	t = NULL;
-
-	/* Input sequence must be non-empty. */
-	if (*seq == GSP_END)
-		return -1;
-
-	while (*(seq + 1) != GSP_END) {
-		t = trans_lookup(p, state, *seq);
-		if (t == NULL) {
-			/* Create new state. */
-			t = trans_new();
-			t->old_state = state;
-			t->input = *seq;
-			t->new_state = p->states++;
-
-			t->out_mods = 0;
-			t->out_key = 0;
-
-			trans_insert(p, t);
-		}
-		state = t->new_state;
-		++seq;
-	}
-
-	/* Process the last transition. */
-	t = trans_lookup(p, state, *seq);
-	if (t != NULL) {
-		exit(1);
-		return -1;	/* Conflicting definition. */
-	}
-
-	t = trans_new();
-	t->old_state = state;
-	t->input = *seq;
-	t->new_state = 0;
-
-	t->out_mods = mods;
-	t->out_key = key;
-
-	trans_insert(p, t);
-
-	return 0;
-}
-
-/** Compute one parser step.
- *
- * Computes the next state and output values for a given state and input.
- * This handles everything including restarts and default branches.
- *
- * @param p		The parser.
- * @param state		Old state.
- * @param input		Input symbol (scancode).
- * @param mods		Output value (modifier).
- * @param key		Output value (key).
- * @return		New state.
- */
-int gsp_step(gsp_t *p, int state, int input, unsigned *mods, unsigned *key)
-{
-	gsp_trans_t *t;
-
-	t = trans_lookup(p, state, input);
-	if (t == NULL) {
-		t = trans_lookup(p, state, GSP_DEFAULT);
-	}
-
-	if (t == NULL) {
-		printf("gsp_step: not found, state=%d, input=0x%x\n",
-		    state, input);
-		*mods = 0;
-		*key = 0;
-		return 0;
-	}
-
-	*mods = t->out_mods;
-	*key = t->out_key;
-
-	return t->new_state;
-}
-
-/** Transition function lookup.
- *
- * Returns the value of the transition function for the given state
- * and input. Note that the transition must be specified precisely,
- * to obtain the default branch use input = GSP_DEFAULT.
- *
- * @param p		Parser.
- * @param state		Current state.
- * @param input		Input value.
- * @return		The transition or @c NULL if not defined.
- */
-static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input)
-{
-	link_t *item;
-	unsigned long key[2];
-
-	key[0] = state;
-	key[1] = input;
-
-	item = hash_table_find(&p->trans, key);
-	if (item == NULL) return NULL;
-
-	return hash_table_get_instance(item, gsp_trans_t, link);
-}
-
-/** Define a new transition.
- *
- * @param p	The parser.
- * @param t	Transition with all fields defined.
- */
-static void trans_insert(gsp_t *p, gsp_trans_t *t)
-{
-	unsigned long key[2];
-
-	key[0] = t->old_state;
-	key[1] = t->input;
-
-	hash_table_insert(&p->trans, key, &t->link);
-}
-
-/** Allocate transition structure. */
-static gsp_trans_t *trans_new(void)
-{
-	gsp_trans_t *t;
-
-	t = malloc(sizeof(gsp_trans_t));
-	if (t == NULL) {
-		printf("Memory allocation failed.\n");
-		exit(1);
-	}
-
-	return t;
-}
-
-/*
- * Transition function hash table operations.
- */
-
-static hash_index_t trans_op_hash(unsigned long key[])
-{
-	return (key[0] * 17 + key[1]) % TRANS_TABLE_CHAINS;
-}
-
-static int trans_op_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
-{
-	gsp_trans_t *t;
-
-	t = hash_table_get_instance(item, gsp_trans_t, link);
-	return ((key[0] == (unsigned long) t->old_state)
-	    && (key[1] == (unsigned long) t->input));
-}
-
-static void trans_op_remove_callback(link_t *item)
-{
-}
-
-/**
- * @}
- */ 
Index: pace/srv/hid/input/generic/input.c
===================================================================
--- uspace/srv/hid/input/generic/input.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,691 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * Copyright (c) 2011 Jiri Svoboda
- * 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 inputgen generic
- * @brief HelenOS input server.
- * @ingroup input
- * @{
- */
-/** @file
- */
-
-#include <adt/list.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <ipc/services.h>
-#include <ipc/input.h>
-#include <sysinfo.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ns.h>
-#include <async.h>
-#include <errno.h>
-#include <adt/fifo.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <loc.h>
-#include <input.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <kbd_ctl.h>
-#include <mouse_proto.h>
-#include <layout.h>
-#include <mouse.h>
-
-#define NUM_LAYOUTS  3
-
-static layout_ops_t *layout[NUM_LAYOUTS] = {
-	&us_qwerty_ops,
-	&us_dvorak_ops,
-	&cz_ops
-};
-
-static void kbd_devs_yield(void);
-static void kbd_devs_reclaim(void);
-
-async_sess_t *client_sess = NULL;
-
-/** List of keyboard devices */
-static list_t kbd_devs;
-
-/** List of mouse devices */
-static list_t mouse_devs;
-
-bool irc_service = false;
-async_sess_t *irc_sess = NULL;
-
-static FIBRIL_MUTEX_INITIALIZE(discovery_lock);
-
-void kbd_push_data(kbd_dev_t *kdev, sysarg_t data)
-{
-	(*kdev->ctl_ops->parse)(data);
-}
-
-void mouse_push_data(mouse_dev_t *mdev, sysarg_t data)
-{
-	(*mdev->proto_ops->parse)(data);
-}
-
-void kbd_push_event(kbd_dev_t *kdev, int type, unsigned int key)
-{
-	kbd_event_t ev;
-	unsigned int mod_mask;
-	
-	switch (key) {
-	case KC_LCTRL: mod_mask = KM_LCTRL; break;
-	case KC_RCTRL: mod_mask = KM_RCTRL; break;
-	case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
-	case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
-	case KC_LALT: mod_mask = KM_LALT; break;
-	case KC_RALT: mod_mask = KM_RALT; break;
-	default: mod_mask = 0; break;
-	}
-	
-	if (mod_mask != 0) {
-		if (type == KEY_PRESS)
-			kdev->mods = kdev->mods | mod_mask;
-		else
-			kdev->mods = kdev->mods & ~mod_mask;
-	}
-	
-	switch (key) {
-	case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
-	case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
-	case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
-	default: mod_mask = 0; break;
-	}
-	
-	if (mod_mask != 0) {
-		if (type == KEY_PRESS) {
-			/*
-			 * Only change lock state on transition from released
-			 * to pressed. This prevents autorepeat from messing
-			 * up the lock state.
-			 */
-			kdev->mods = kdev->mods ^ (mod_mask & ~kdev->lock_keys);
-			kdev->lock_keys = kdev->lock_keys | mod_mask;
-			
-			/* Update keyboard lock indicator lights. */
-			(*kdev->ctl_ops->set_ind)(kdev, kdev->mods);
-		} else {
-			kdev->lock_keys = kdev->lock_keys & ~mod_mask;
-		}
-	}
-	
-	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
-	    key == KC_F1) {
-		layout_destroy(kdev->active_layout);
-		kdev->active_layout = layout_create(layout[0]);
-		return;
-	}
-	
-	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
-	    key == KC_F2) {
-		layout_destroy(kdev->active_layout);
-		kdev->active_layout = layout_create(layout[1]);
-		return;
-	}
-	
-	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
-	    key == KC_F3) {
-		layout_destroy(kdev->active_layout);
-		kdev->active_layout = layout_create(layout[2]);
-		return;
-	}
-	
-	ev.type = type;
-	ev.key = key;
-	ev.mods = kdev->mods;
-	
-	ev.c = layout_parse_ev(kdev->active_layout, &ev);
-	
-	async_exch_t *exch = async_exchange_begin(client_sess);
-	async_msg_4(exch, INPUT_EVENT_KEY, ev.type, ev.key, ev.mods, ev.c);
-	async_exchange_end(exch);
-}
-
-/** Mouse pointer has moved. */
-void mouse_push_event_move(mouse_dev_t *mdev, int dx, int dy, int dz)
-{
-	async_exch_t *exch = async_exchange_begin(client_sess);
-	if (dx || dy)
-		async_msg_2(exch, INPUT_EVENT_MOVE, dx, dy);
-	if (dz) {
-		// TODO: Implement proper wheel support
-		keycode_t code = dz > 0 ? KC_UP : KC_DOWN;
-		for (int i = 0; i < 3; ++i) {
-			async_msg_4(exch, INPUT_EVENT_KEY, KEY_PRESS, code, 0, 0);
-		}
-		async_msg_4(exch, INPUT_EVENT_KEY, KEY_RELEASE, code, 0, 0);
-	}
-	async_exchange_end(exch);
-}
-
-/** Mouse button has been pressed. */
-void mouse_push_event_button(mouse_dev_t *mdev, int bnum, int press)
-{
-	async_exch_t *exch = async_exchange_begin(client_sess);
-	async_msg_2(exch, INPUT_EVENT_BUTTON, bnum, press);
-	async_exchange_end(exch);
-}
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			if (client_sess != NULL) {
-				async_hangup(client_sess);
-				client_sess = NULL;
-			}
-			
-			async_answer_0(callid, EOK);
-			return;
-		}
-		
-		async_sess_t *sess =
-		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
-		if (sess != NULL) {
-			if (client_sess == NULL) {
-				client_sess = sess;
-				async_answer_0(callid, EOK);
-			} else
-				async_answer_0(callid, ELIMIT);
-		} else {
-			switch (IPC_GET_IMETHOD(call)) {
-			case INPUT_YIELD:
-				kbd_devs_yield();
-				async_answer_0(callid, EOK);
-				break;
-			case INPUT_RECLAIM:
-				kbd_devs_reclaim();
-				async_answer_0(callid, EOK);
-				break;
-			default:
-				async_answer_0(callid, EINVAL);
-			}
-		}
-	}
-}
-
-static kbd_dev_t *kbd_dev_new(void)
-{
-	kbd_dev_t *kdev = calloc(1, sizeof(kbd_dev_t));
-	if (kdev == NULL) {
-		printf("%s: Error allocating keyboard device. "
-		    "Out of memory.\n", NAME);
-		return NULL;
-	}
-	
-	link_initialize(&kdev->kbd_devs);
-	
-	kdev->mods = KM_NUM_LOCK;
-	kdev->lock_keys = 0;
-	kdev->active_layout = layout_create(layout[0]);
-	
-	return kdev;
-}
-
-static mouse_dev_t *mouse_dev_new(void)
-{
-	mouse_dev_t *mdev = calloc(1, sizeof(mouse_dev_t));
-	if (mdev == NULL) {
-		printf("%s: Error allocating keyboard device. "
-		    "Out of memory.\n", NAME);
-		return NULL;
-	}
-	
-	link_initialize(&mdev->mouse_devs);
-	
-	return mdev;
-}
-
-/** Add new legacy keyboard device. */
-static void kbd_add_dev(kbd_port_ops_t *port, kbd_ctl_ops_t *ctl)
-{
-	kbd_dev_t *kdev = kbd_dev_new();
-	if (kdev == NULL)
-		return;
-	
-	kdev->port_ops = port;
-	kdev->ctl_ops = ctl;
-	kdev->svc_id = 0;
-	
-	/* Initialize port driver. */
-	if ((*kdev->port_ops->init)(kdev) != 0)
-		goto fail;
-	
-	/* Initialize controller driver. */
-	if ((*kdev->ctl_ops->init)(kdev) != 0) {
-		/* XXX Uninit port */
-		goto fail;
-	}
-	
-	list_append(&kdev->kbd_devs, &kbd_devs);
-	return;
-	
-fail:
-	free(kdev);
-}
-
-/** Add new legacy mouse device. */
-static void mouse_add_dev(mouse_port_ops_t *port, mouse_proto_ops_t *proto)
-{
-	mouse_dev_t *mdev = mouse_dev_new();
-	if (mdev == NULL)
-		return;
-	
-	mdev->port_ops = port;
-	mdev->proto_ops = proto;
-	mdev->svc_id = 0;
-	
-	/* Initialize port driver. */
-	if ((*mdev->port_ops->init)(mdev) != 0)
-		goto fail;
-	
-	/* Initialize protocol driver. */
-	if ((*mdev->proto_ops->init)(mdev) != 0) {
-		/* XXX Uninit port */
-		goto fail;
-	}
-	
-	list_append(&mdev->mouse_devs, &mouse_devs);
-	return;
-	
-fail:
-	free(mdev);
-}
-
-/** Add new kbdev device.
- *
- * @param service_id	Service ID of the keyboard device
- *
- */
-static int kbd_add_kbdev(service_id_t service_id, kbd_dev_t **kdevp)
-{
-	kbd_dev_t *kdev = kbd_dev_new();
-	if (kdev == NULL)
-		return -1;
-	
-	kdev->svc_id = service_id;
-	kdev->port_ops = NULL;
-	kdev->ctl_ops = &kbdev_ctl;
-	
-	int rc = loc_service_get_name(service_id, &kdev->svc_name);
-	if (rc != EOK) {
-		kdev->svc_name = NULL;
-		goto fail;
-	}
-	
-	/* Initialize controller driver. */
-	if ((*kdev->ctl_ops->init)(kdev) != 0) {
-		goto fail;
-	}
-	
-	list_append(&kdev->kbd_devs, &kbd_devs);
-	*kdevp = kdev;
-	return EOK;
-	
-fail:
-	if (kdev->svc_name != NULL)
-		free(kdev->svc_name);
-	free(kdev);
-	return -1;
-}
-
-/** Add new mousedev device.
- *
- * @param service_id	Service ID of the mouse device
- *
- */
-static int mouse_add_mousedev(service_id_t service_id, mouse_dev_t **mdevp)
-{
-	mouse_dev_t *mdev = mouse_dev_new();
-	if (mdev == NULL)
-		return -1;
-	
-	mdev->svc_id = service_id;
-	mdev->port_ops = NULL;
-	mdev->proto_ops = &mousedev_proto;
-	
-	int rc = loc_service_get_name(service_id, &mdev->svc_name);
-	if (rc != EOK) {
-		mdev->svc_name = NULL;
-		goto fail;
-	}
-	
-	/* Initialize controller driver. */
-	if ((*mdev->proto_ops->init)(mdev) != 0) {
-		goto fail;
-	}
-	
-	list_append(&mdev->mouse_devs, &mouse_devs);
-	*mdevp = mdev;
-	return EOK;
-	
-fail:
-	free(mdev);
-	return -1;
-}
-
-/** Add legacy drivers/devices. */
-static void kbd_add_legacy_devs(void)
-{
-	/*
-	 * Need to add these drivers based on config unless we can probe
-	 * them automatically.
-	 */
-#if defined(UARCH_arm32) && defined(MACHINE_gta02)
-	kbd_add_dev(&chardev_port, &stty_ctl);
-#endif
-#if defined(UARCH_arm32) && defined(MACHINE_testarm) && defined(CONFIG_FB)
-	kbd_add_dev(&gxemul_port, &gxe_fb_ctl);
-#endif
-#if defined(UARCH_arm32) && defined(MACHINE_testarm) && !defined(CONFIG_FB)
-	kbd_add_dev(&gxemul_port, &stty_ctl);
-#endif
-#if defined(UARCH_arm32) && defined(MACHINE_integratorcp)
-	kbd_add_dev(&pl050_port, &pc_ctl);
-#endif
-#if defined(MACHINE_ski)
-	kbd_add_dev(&ski_port, &stty_ctl);
-#endif
-#if defined(MACHINE_msim)
-	kbd_add_dev(&msim_port, &stty_ctl);
-#endif
-#if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)
-	kbd_add_dev(&gxemul_port, &gxe_fb_ctl);
-#endif
-#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul) && !defined(CONFIG_FB)
-	kbd_add_dev(&gxemul_port, &stty_ctl);
-#endif
-#if defined(UARCH_ppc32)
-	kbd_add_dev(&adb_port, &apple_ctl);
-#endif
-#if defined(UARCH_sparc64) && defined(PROCESSOR_sun4v)
-	kbd_add_dev(&niagara_port, &stty_ctl);
-#endif
-#if defined(UARCH_sparc64) && defined(MACHINE_generic)
-	kbd_add_dev(&ns16550_port, &sun_ctl);
-#endif
-	/* Silence warning on abs32le about kbd_add_dev() being unused */
-	(void) kbd_add_dev;
-}
-
-/** Add legacy drivers/devices. */
-static void mouse_add_legacy_devs(void)
-{
-	/*
-	 * Need to add these drivers based on config unless we can probe
-	 * them automatically.
-	 */
-#if defined(UARCH_ppc32)
-	mouse_add_dev(&adb_mouse_port, &adb_proto);
-#endif
-	/* Silence warning on abs32le about mouse_add_dev() being unused */
-	(void) mouse_add_dev;
-}
-
-static void kbd_devs_yield(void)
-{
-	/* For each keyboard device */
-	list_foreach(kbd_devs, kdev_link) {
-		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
-		    kbd_devs);
-		
-		/* Yield port */
-		if (kdev->port_ops != NULL)
-			(*kdev->port_ops->yield)();
-	}
-}
-
-static void kbd_devs_reclaim(void)
-{
-	/* For each keyboard device */
-	list_foreach(kbd_devs, kdev_link) {
-		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
-		    kbd_devs);
-		
-		/* Reclaim port */
-		if (kdev->port_ops != NULL)
-			(*kdev->port_ops->reclaim)();
-	}
-}
-
-static int dev_check_new_kbdevs(void)
-{
-	category_id_t keyboard_cat;
-	service_id_t *svcs;
-	size_t count, i;
-	bool already_known;
-	int rc;
-	
-	rc = loc_category_get_id("keyboard", &keyboard_cat, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		printf("%s: Failed resolving category 'keyboard'.\n", NAME);
-		return ENOENT;
-	}
-	
-	/*
-	 * Check for new keyboard devices
-	 */
-	rc = loc_category_get_svcs(keyboard_cat, &svcs, &count);
-	if (rc != EOK) {
-		printf("%s: Failed getting list of keyboard devices.\n",
-		    NAME);
-		return EIO;
-	}
-
-	for (i = 0; i < count; i++) {
-		already_known = false;
-		
-		/* Determine whether we already know this device. */
-		list_foreach(kbd_devs, kdev_link) {
-			kbd_dev_t *kdev = list_get_instance(kdev_link,
-			    kbd_dev_t, kbd_devs);
-			if (kdev->svc_id == svcs[i]) {
-				already_known = true;
-				break;
-			}
-		}
-		
-		if (!already_known) {
-			kbd_dev_t *kdev;
-			if (kbd_add_kbdev(svcs[i], &kdev) == EOK) {
-				printf("%s: Connected keyboard device '%s'\n",
-				    NAME, kdev->svc_name);
-			}
-		}
-	}
-	
-	free(svcs);
-	
-	/* XXX Handle device removal */
-	
-	return EOK;
-}
-
-static int dev_check_new_mousedevs(void)
-{
-	category_id_t mouse_cat;
-	service_id_t *svcs;
-	size_t count, i;
-	bool already_known;
-	int rc;
-	
-	rc = loc_category_get_id("mouse", &mouse_cat, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		printf("%s: Failed resolving category 'mouse'.\n", NAME);
-		return ENOENT;
-	}
-	
-	/*
-	 * Check for new mouse devices
-	 */
-	rc = loc_category_get_svcs(mouse_cat, &svcs, &count);
-	if (rc != EOK) {
-		printf("%s: Failed getting list of mouse devices.\n",
-		    NAME);
-		return EIO;
-	}
-	
-	for (i = 0; i < count; i++) {
-		already_known = false;
-		
-		/* Determine whether we already know this device. */
-		list_foreach(mouse_devs, mdev_link) {
-			mouse_dev_t *mdev = list_get_instance(mdev_link,
-			    mouse_dev_t, mouse_devs);
-			if (mdev->svc_id == svcs[i]) {
-				already_known = true;
-				break;
-			}
-		}
-		
-		if (!already_known) {
-			mouse_dev_t *mdev;
-			if (mouse_add_mousedev(svcs[i], &mdev) == EOK) {
-				printf("%s: Connected mouse device '%s'\n",
-				    NAME, mdev->svc_name);
-			}
-		}
-	}
-	
-	free(svcs);
-	
-	/* XXX Handle device removal */
-	
-	return EOK;
-}
-
-static int dev_check_new(void)
-{
-	int rc;
-	
-	fibril_mutex_lock(&discovery_lock);
-	
-	rc = dev_check_new_kbdevs();
-	if (rc != EOK) {
-		fibril_mutex_unlock(&discovery_lock);
-		return rc;
-	}
-	
-	rc = dev_check_new_mousedevs();
-	if (rc != EOK) {
-		fibril_mutex_unlock(&discovery_lock);
-		return rc;
-	}
-	
-	fibril_mutex_unlock(&discovery_lock);
-	
-	return EOK;
-}
-
-static void cat_change_cb(void)
-{
-	dev_check_new();
-}
-
-/** Start listening for new devices. */
-static int input_start_dev_discovery(void)
-{
-	int rc;
-
-	rc = loc_register_cat_change_cb(cat_change_cb);
-	if (rc != EOK) {
-		printf("%s: Failed registering callback for device discovery. "
-		    "(%d)\n", NAME, rc);
-		return rc;
-	}
-
-	return dev_check_new();
-}
-
-int main(int argc, char **argv)
-{
-	printf("%s: HelenOS input service\n", NAME);
-	
-	sysarg_t obio;
-	
-	list_initialize(&kbd_devs);
-	list_initialize(&mouse_devs);
-	
-	if ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio))
-		irc_service = true;
-	
-	if (irc_service) {
-		while (irc_sess == NULL)
-			irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
-			    SERVICE_IRC, 0, 0);
-	}
-	
-	/* Add legacy keyboard devices. */
-	kbd_add_legacy_devs();
-	
-	/* Add legacy mouse devices. */
-	mouse_add_legacy_devs();
-	
-	/* Register driver */
-	async_set_client_connection(client_connection);
-	int rc = loc_server_register(NAME);
-	if (rc != EOK) {
-		printf("%s: Unable to register server\n", NAME);
-		return rc;
-	}
-	
-	char kbd[LOC_NAME_MAXLEN + 1];
-	snprintf(kbd, LOC_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
-	
-	service_id_t service_id;
-	rc = loc_service_register(kbd, &service_id);
-	if (rc != EOK) {
-		printf("%s: Unable to register service %s\n", NAME, kbd);
-		return rc;
-	}
-	
-	/* Start looking for new input devices */
-	input_start_dev_discovery();
-	
-	printf("%s: Accepting connections\n", NAME);
-	async_manager();
-	
-	/* Not reached. */
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/input/generic/layout.c
===================================================================
--- uspace/srv/hid/input/generic/layout.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,78 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * 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 inputgen generic
- * @brief Keyboard layouts
- * @ingroup input
- * @{
- */
-/** @file
- */
-
-#include <errno.h>
-#include <input.h>
-#include <layout.h>
-#include <stdlib.h>
-
-/** Create a new layout instance. */
-layout_t *layout_create(layout_ops_t *ops)
-{
-	layout_t *layout;
-
-	layout = calloc(1, sizeof(layout_t));
-	if (layout == NULL) {
-		printf("%s: Out of memory.\n", NAME);
-		return NULL;
-	}
-
-	layout->ops = ops;
-	if ((*ops->create)(layout) != EOK) {
-		free(layout);
-		return NULL;
-	}
-
-	return layout;
-}
-
-/** Destroy layout instance. */
-void layout_destroy(layout_t *layout)
-{
-	(*layout->ops->destroy)(layout);
-	free(layout);
-}
-
-/** Parse keyboard event. */
-wchar_t layout_parse_ev(layout_t *layout, kbd_event_t *ev)
-{
-	return (*layout->ops->parse_ev)(layout, ev);
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/input/generic/stroke.c
===================================================================
--- uspace/srv/hid/input/generic/stroke.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,85 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * 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 input
- * @{
- */
-/**
- * @file
- * @brief Stroke simulator.
- *
- * When simulating a keyboard using a serial TTY we need to convert the
- * recognized strokes (such as Shift-A) to sequences of key presses and
- * releases (such as 'press Shift, press A, release A, release Shift').
- *
- */
-
-#include <stroke.h>
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-
-/** Correspondence between modifers and the modifier keycodes. */
-static unsigned int mods_keys[][2] = {
-	{ KM_LSHIFT, KC_LSHIFT },
-	{ 0, 0 }
-};
-
-/** Simulate keystroke using sequences of key presses and releases. */
-void stroke_sim(kbd_dev_t *kdev, unsigned mod, unsigned key)
-{
-	int i;
-
-	/* Simulate modifier presses. */
-	i = 0;
-	while (mods_keys[i][0] != 0) {
-		if (mod & mods_keys[i][0]) {
-			kbd_push_event(kdev, KEY_PRESS, mods_keys[i][1]);
-		}
-		++i;
-	}
-
-	/* Simulate key press and release. */
-	if (key != 0) {
-		kbd_push_event(kdev, KEY_PRESS, key);
-		kbd_push_event(kdev, KEY_RELEASE, key);
-	}
-
-	/* Simulate modifier releases. */
-	i = 0;
-	while (mods_keys[i][0] != 0) {
-		if (mod & mods_keys[i][0]) {
-			kbd_push_event(kdev, KEY_RELEASE, mods_keys[i][1]);
-		}
-		++i;
-	}
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/input/gsp.c
===================================================================
--- uspace/srv/hid/input/gsp.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/gsp.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * 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 kbdgen generic
+ * @ingroup  input
+ * @{
+ */
+/** @file
+ * @brief Generic scancode parser.
+ *
+ * The scancode parser is a simple finite state machine. It is described
+ * using sequences of input symbols (scancodes) and the corresponding output
+ * value (mods, key pair). When the parser recognizes a sequence,
+ * it outputs the value and restarts. If a transition is undefined,
+ * the parser restarts, too.
+ *
+ * Apart from precise values, GSP_DEFAULT allows to catch general cases.
+ * I.e. if we knew that after 0x1b 0x4f there always follow two more
+ * scancodes, we can define (0x1b, 0x4f, GSP_DEFAULT, GSP_DEFAULT, GSP_END)
+ * with null output. This will force the parser to read the entire sequence,
+ * not leaving garbage on the input if it does not recognize the specific
+ * sequence.
+ */
+
+#include <adt/hash_table.h>
+#include <adt/hash.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "gsp.h"
+
+/*
+ * Transition function hash table operations.
+ */
+typedef struct {
+	int old_state;
+	int input;
+} trans_key_t;
+
+static size_t trans_key_hash(void *key)
+{
+	trans_key_t *trans_key = (trans_key_t *)key;
+	return hash_combine(trans_key->input, trans_key->old_state);
+}
+
+static size_t trans_hash(const ht_link_t *item)
+{
+	gsp_trans_t *t = hash_table_get_inst(item, gsp_trans_t, link);
+	return hash_combine(t->input, t->old_state);
+}
+
+static bool trans_key_equal(void *key, const ht_link_t *item)
+{
+	trans_key_t *trans_key = (trans_key_t *)key;
+	gsp_trans_t *t = hash_table_get_inst(item, gsp_trans_t, link);
+	
+	return trans_key->input == t->input && trans_key->old_state == t->old_state;
+}
+
+static hash_table_ops_t trans_ops = {
+	.hash = trans_hash,
+	.key_hash = trans_key_hash,
+	.key_equal = trans_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
+};
+
+
+static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input);
+static void trans_insert(gsp_t *p, gsp_trans_t *t);
+static gsp_trans_t *trans_new(void);
+
+/** Initialize scancode parser. */
+void gsp_init(gsp_t *p)
+{
+	p->states = 1;
+	hash_table_create(&p->trans, 0, 0, &trans_ops);
+}
+
+/** Insert a series of definitions into the parser.
+ *
+ * @param p	The parser.
+ * @param defs	Definition list. Each definition starts with two output values
+ *		(mods, key) and continues with a sequence of input values
+ *		terminated with GSP_END. The definition list is terminated
+ *		with two zeroes (0, 0) for output values.
+ */
+int gsp_insert_defs(gsp_t *p, const int *defs)
+{
+	unsigned mods, key;
+	const int *dp;
+	int rc;
+
+	dp = defs;
+
+	while (1) {
+		/* Read the output values. */
+		mods = *dp++;
+		key = *dp++;
+		if (key == 0) break;
+
+		/* Insert one sequence. */
+		rc = gsp_insert_seq(p, dp, mods, key);
+		if (rc != 0)
+			return rc;
+
+		/* Skip to the next definition. */
+		while (*dp != GSP_END)
+			++dp;
+		++dp;
+	}
+
+	return 0;
+}
+
+/** Insert one sequence into the parser.
+ *
+ * @param p	The parser.
+ * @param seq	Sequence of input values terminated with GSP_END.
+ * @param mods	Corresponsing output value.
+ * @param key	Corresponsing output value.
+ */
+int gsp_insert_seq(gsp_t *p, const int *seq, unsigned mods, unsigned key)
+{
+	int state;
+	gsp_trans_t *t;
+
+	state = 0;
+	t = NULL;
+
+	/* Input sequence must be non-empty. */
+	if (*seq == GSP_END)
+		return -1;
+
+	while (*(seq + 1) != GSP_END) {
+		t = trans_lookup(p, state, *seq);
+		if (t == NULL) {
+			/* Create new state. */
+			t = trans_new();
+			t->old_state = state;
+			t->input = *seq;
+			t->new_state = p->states++;
+
+			t->out_mods = 0;
+			t->out_key = 0;
+
+			trans_insert(p, t);
+		}
+		state = t->new_state;
+		++seq;
+	}
+
+	/* Process the last transition. */
+	t = trans_lookup(p, state, *seq);
+	if (t != NULL) {
+		exit(1);
+		return -1;	/* Conflicting definition. */
+	}
+
+	t = trans_new();
+	t->old_state = state;
+	t->input = *seq;
+	t->new_state = 0;
+
+	t->out_mods = mods;
+	t->out_key = key;
+
+	trans_insert(p, t);
+
+	return 0;
+}
+
+/** Compute one parser step.
+ *
+ * Computes the next state and output values for a given state and input.
+ * This handles everything including restarts and default branches.
+ *
+ * @param p		The parser.
+ * @param state		Old state.
+ * @param input		Input symbol (scancode).
+ * @param mods		Output value (modifier).
+ * @param key		Output value (key).
+ * @return		New state.
+ */
+int gsp_step(gsp_t *p, int state, int input, unsigned *mods, unsigned *key)
+{
+	gsp_trans_t *t;
+
+	t = trans_lookup(p, state, input);
+	if (t == NULL) {
+		t = trans_lookup(p, state, GSP_DEFAULT);
+	}
+
+	if (t == NULL) {
+		printf("gsp_step: not found, state=%d, input=0x%x\n",
+		    state, input);
+		*mods = 0;
+		*key = 0;
+		return 0;
+	}
+
+	*mods = t->out_mods;
+	*key = t->out_key;
+
+	return t->new_state;
+}
+
+/** Transition function lookup.
+ *
+ * Returns the value of the transition function for the given state
+ * and input. Note that the transition must be specified precisely,
+ * to obtain the default branch use input = GSP_DEFAULT.
+ *
+ * @param p		Parser.
+ * @param state		Current state.
+ * @param input		Input value.
+ * @return		The transition or @c NULL if not defined.
+ */
+static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input)
+{
+	ht_link_t *item;
+	
+	trans_key_t key = {
+		.input = input,
+		.old_state = state
+	};
+
+	item = hash_table_find(&p->trans, &key);
+	if (item == NULL) return NULL;
+
+	return hash_table_get_inst(item, gsp_trans_t, link);
+}
+
+/** Define a new transition.
+ *
+ * @param p	The parser.
+ * @param t	Transition with all fields defined.
+ */
+static void trans_insert(gsp_t *p, gsp_trans_t *t)
+{
+	hash_table_insert(&p->trans, &t->link);
+}
+
+/** Allocate transition structure. */
+static gsp_trans_t *trans_new(void)
+{
+	gsp_trans_t *t;
+
+	t = malloc(sizeof(gsp_trans_t));
+	if (t == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return t;
+}
+
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/gsp.h
===================================================================
--- uspace/srv/hid/input/gsp.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/gsp.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * 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 inputgen generic
+ * @brief	Generic scancode parser.
+ * @ingroup  input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_GSP_H_
+#define KBD_GSP_H_
+
+#include <adt/hash_table.h>
+
+enum {
+	GSP_END		= -1,	/**< Terminates a sequence. */
+	GSP_DEFAULT	= -2	/**< Wildcard, catches unhandled cases. */
+};
+
+/** Scancode parser description */
+typedef struct {
+	/** Transition table, (state, input) -> (state, output) */
+	hash_table_t trans;
+
+	/** Number of states */
+	int states;
+} gsp_t;
+
+/** Scancode parser transition. */
+typedef struct {
+	ht_link_t link;		/**< Link to hash table in @c gsp_t */ 
+
+	/* Preconditions */
+
+	int old_state;		/**< State before transition */
+	int input;		/**< Input symbol (scancode) */
+
+	/* Effects */
+
+	int new_state;		/**< State after transition */
+
+	/* Output emitted during transition */
+
+	unsigned out_mods;	/**< Modifier to emit */
+	unsigned out_key;	/**< Keycode to emit */
+} gsp_trans_t;
+
+extern void gsp_init(gsp_t *);
+extern int gsp_insert_defs(gsp_t *, const int *);
+extern int gsp_insert_seq(gsp_t *, const int *, unsigned, unsigned);
+extern int gsp_step(gsp_t *, int, int, unsigned *, unsigned *);
+
+#endif
+
+/**
+ * @}
+ */ 
Index: pace/srv/hid/input/include/gsp.h
===================================================================
--- uspace/srv/hid/input/include/gsp.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,84 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * 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 inputgen generic
- * @brief	Generic scancode parser.
- * @ingroup  input
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_GSP_H_
-#define KBD_GSP_H_
-
-#include <adt/hash_table.h>
-
-enum {
-	GSP_END		= -1,	/**< Terminates a sequence. */
-	GSP_DEFAULT	= -2	/**< Wildcard, catches unhandled cases. */
-};
-
-/** Scancode parser description */
-typedef struct {
-	/** Transition table, (state, input) -> (state, output) */
-	hash_table_t trans;
-
-	/** Number of states */
-	int states;
-} gsp_t;
-
-/** Scancode parser transition. */
-typedef struct {
-	link_t link;		/**< Link to hash table in @c gsp_t */ 
-
-	/* Preconditions */
-
-	int old_state;		/**< State before transition */
-	int input;		/**< Input symbol (scancode) */
-
-	/* Effects */
-
-	int new_state;		/**< State after transition */
-
-	/* Output emitted during transition */
-
-	unsigned out_mods;	/**< Modifier to emit */
-	unsigned out_key;	/**< Keycode to emit */
-} gsp_trans_t;
-
-extern void gsp_init(gsp_t *);
-extern int gsp_insert_defs(gsp_t *, const int *);
-extern int gsp_insert_seq(gsp_t *, const int *, unsigned, unsigned);
-extern int gsp_step(gsp_t *, int, int, unsigned *, unsigned *);
-
-#endif
-
-/**
- * @}
- */ 
Index: pace/srv/hid/input/include/input.h
===================================================================
--- uspace/srv/hid/input/include/input.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * Copyright (c) 2011 Jiri Svoboda
- * 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 inputgen generic
- * @brief HelenOS input server.
- * @ingroup input
- * @{
- */
-/** @file
- */
-
-#ifndef INPUT_H_
-#define INPUT_H_
-
-#include <bool.h>
-#include <async.h>
-
-#define NAME       "input"
-#define NAMESPACE  "hid"
-
-extern bool irc_service;
-extern async_sess_t *irc_sess;
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/input/include/kbd.h
===================================================================
--- uspace/srv/hid/input/include/kbd.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,84 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * Copyright (c) 2011 Jiri Svoboda
- * 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 inputgen generic
- * @brief HelenOS input server.
- * @ingroup input
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_KBD_H_
-#define KBD_KBD_H_
-
-#include <adt/list.h>
-#include <ipc/loc.h>
-
-struct kbd_port_ops;
-struct kbd_ctl_ops;
-struct layout;
-
-typedef struct kbd_dev {
-	/** Link to kbd_devs list */
-	link_t kbd_devs;
-
-	/** Service ID (only for kbdev devices) */
-	service_id_t svc_id;
-
-	/** Device service name (only for kbdev devices) */
-	char *svc_name;
-
-	/** Port ops */
-	struct kbd_port_ops *port_ops;
-
-	/** Ctl ops */
-	struct kbd_ctl_ops *ctl_ops;
-
-	/** Controller-private data */
-	void *ctl_private;
-
-	/** Currently active modifiers. */
-	unsigned mods;
-
-	/** Currently pressed lock keys. We track these to tackle autorepeat. */
-	unsigned lock_keys;
-
-	/** Active keyboard layout */
-	struct layout *active_layout;
-} kbd_dev_t;
-
-extern void kbd_push_data(kbd_dev_t *, sysarg_t);
-extern void kbd_push_event(kbd_dev_t *, int, unsigned int);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/input/include/kbd_ctl.h
===================================================================
--- uspace/srv/hid/input/include/kbd_ctl.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,61 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * 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 inputgen generic
- * @brief Keyboard controller driver interface.
- * @ingroup input
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_CTL_H_
-#define KBD_CTL_H_
-
-#include <kbd_port.h>
-
-struct kbd_dev;
-
-typedef struct kbd_ctl_ops {
-	void (*parse)(sysarg_t);
-	int (*init)(struct kbd_dev *);
-	void (*set_ind)(struct kbd_dev *, unsigned int);
-} kbd_ctl_ops_t;
-
-extern kbd_ctl_ops_t apple_ctl;
-extern kbd_ctl_ops_t gxe_fb_ctl;
-extern kbd_ctl_ops_t kbdev_ctl;
-extern kbd_ctl_ops_t pc_ctl;
-extern kbd_ctl_ops_t stty_ctl;
-extern kbd_ctl_ops_t sun_ctl;
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/input/include/kbd_port.h
===================================================================
--- uspace/srv/hid/input/include/kbd_port.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,64 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * 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 inputgen generic
- * @brief Keyboard port driver interface.
- * @ingroup input
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_PORT_H_
-#define KBD_PORT_H_
-
-#include <sys/types.h>
-
-struct kbd_dev;
-
-typedef struct kbd_port_ops {
-	int (*init)(struct kbd_dev *);
-	void (*yield)(void);
-	void (*reclaim)(void);
-	void (*write)(uint8_t);
-} kbd_port_ops_t;
-
-extern kbd_port_ops_t adb_port;
-extern kbd_port_ops_t chardev_port;
-extern kbd_port_ops_t gxemul_port;
-extern kbd_port_ops_t msim_port;
-extern kbd_port_ops_t niagara_port;
-extern kbd_port_ops_t ns16550_port;
-extern kbd_port_ops_t pl050_port;
-extern kbd_port_ops_t ski_port;
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/input/include/layout.h
===================================================================
--- uspace/srv/hid/input/include/layout.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,71 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * 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 inputgen generic
- * @brief Keyboard layout interface.
- * @ingroup input
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_LAYOUT_H_
-#define KBD_LAYOUT_H_
-
-#include <sys/types.h>
-#include <io/console.h>
-
-/** Layout instance state */
-typedef struct layout {
-	/** Ops structure */
-	struct layout_ops *ops;
-
-	/* Layout-private data */
-	void *layout_priv;
-} layout_t;
-
-/** Layout ops */
-typedef struct layout_ops {
-	int (*create)(layout_t *);
-	void (*destroy)(layout_t *);
-	wchar_t (*parse_ev)(layout_t *, kbd_event_t *);
-} layout_ops_t;
-
-extern layout_ops_t us_qwerty_ops;
-extern layout_ops_t us_dvorak_ops;
-extern layout_ops_t cz_ops;
-
-extern layout_t *layout_create(layout_ops_t *);
-extern void layout_destroy(layout_t *);
-extern wchar_t layout_parse_ev(layout_t *, kbd_event_t *);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/input/include/mouse.h
===================================================================
--- uspace/srv/hid/input/include/mouse.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,71 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * 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 inputgen generic
- * @brief Mouse device handling.
- * @ingroup input
- * @{
- */
-/** @file
- */
-
-#ifndef MOUSE_H_
-#define MOUSE_H_
-
-#include <adt/list.h>
-#include <ipc/loc.h>
-
-struct mouse_port_ops;
-struct mouse_proto_ops;
-
-typedef struct mouse_dev {
-	/** Link to mouse_devs list */
-	link_t mouse_devs;
-	
-	/** Service ID (only for mousedev devices) */
-	service_id_t svc_id;
-	
-	/** Device service name (only for mousedev devices) */
-	char *svc_name;
-	
-	/** Port ops */
-	struct mouse_port_ops *port_ops;
-	
-	/** Protocol ops */
-	struct mouse_proto_ops *proto_ops;
-} mouse_dev_t;
-
-extern void mouse_push_data(mouse_dev_t *, sysarg_t);
-extern void mouse_push_event_move(mouse_dev_t *, int, int, int);
-extern void mouse_push_event_button(mouse_dev_t *, int, int);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/input/include/mouse_port.h
===================================================================
--- uspace/srv/hid/input/include/mouse_port.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/*
- * Copyright (c) 2011 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 inputgen generic
- * @brief Mouse port driver interface.
- * @ingroup input
- * @{
- */
-/** @file
- */
-
-#ifndef MOUSE_PORT_H_
-#define MOUSE_PORT_H_
-
-#include <sys/types.h>
-
-struct mouse_dev;
-
-typedef struct mouse_port_ops {
-	int (*init)(struct mouse_dev *);
-	void (*yield)(void);
-	void (*reclaim)(void);
-	void (*write)(uint8_t);
-} mouse_port_ops_t;
-
-extern mouse_port_ops_t adb_mouse_port;
-extern mouse_port_ops_t chardev_mouse_port;
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/input/include/mouse_proto.h
===================================================================
--- uspace/srv/hid/input/include/mouse_proto.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,56 +1,0 @@
-/*
- * Copyright (c) 2011 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 inputgen generic
- * @brief Mouse protocol driver interface.
- * @ingroup input
- * @{
- */
-/** @file
- */
-
-#ifndef MOUSE_PROTO_H_
-#define MOUSE_PROTO_H_
-
-#include <mouse_port.h>
-
-struct mouse_dev;
-
-typedef struct mouse_proto_ops {
-	void (*parse)(sysarg_t);
-	int (*init)(struct mouse_dev *);
-} mouse_proto_ops_t;
-
-extern mouse_proto_ops_t adb_proto;
-extern mouse_proto_ops_t mousedev_proto;
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/input/include/stroke.h
===================================================================
--- uspace/srv/hid/input/include/stroke.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,49 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * 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 inputgen generic
- * @brief	Generic scancode parser.
- * @ingroup  input
- * @{
- */ 
-/** @file
- */
-
-#ifndef KBD_STROKE_H_
-#define KBD_STROKE_H_
-
-#include <kbd.h>
-
-extern void stroke_sim(kbd_dev_t *, unsigned, unsigned);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: uspace/srv/hid/input/input.c
===================================================================
--- uspace/srv/hid/input/input.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/input.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,710 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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 inputgen generic
+ * @brief HelenOS input server.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#include <adt/list.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <ipc/services.h>
+#include <ipc/input.h>
+#include <sysinfo.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ns.h>
+#include <async.h>
+#include <errno.h>
+#include <adt/fifo.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <loc.h>
+#include "layout.h"
+#include "kbd.h"
+#include "kbd_port.h"
+#include "kbd_ctl.h"
+#include "mouse.h"
+#include "mouse_proto.h"
+#include "input.h"
+
+#define NUM_LAYOUTS  3
+
+static layout_ops_t *layout[NUM_LAYOUTS] = {
+	&us_qwerty_ops,
+	&us_dvorak_ops,
+	&cz_ops
+};
+
+static void kbd_devs_yield(void);
+static void kbd_devs_reclaim(void);
+
+async_sess_t *client_sess = NULL;
+
+/** List of keyboard devices */
+static list_t kbd_devs;
+
+/** List of mouse devices */
+static list_t mouse_devs;
+
+bool irc_service = false;
+async_sess_t *irc_sess = NULL;
+
+static FIBRIL_MUTEX_INITIALIZE(discovery_lock);
+
+void kbd_push_data(kbd_dev_t *kdev, sysarg_t data)
+{
+	(*kdev->ctl_ops->parse)(data);
+}
+
+void mouse_push_data(mouse_dev_t *mdev, sysarg_t data)
+{
+	(*mdev->proto_ops->parse)(data);
+}
+
+void kbd_push_event(kbd_dev_t *kdev, int type, unsigned int key)
+{
+	kbd_event_t ev;
+	unsigned int mod_mask;
+	
+	switch (key) {
+	case KC_LCTRL: mod_mask = KM_LCTRL; break;
+	case KC_RCTRL: mod_mask = KM_RCTRL; break;
+	case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
+	case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
+	case KC_LALT: mod_mask = KM_LALT; break;
+	case KC_RALT: mod_mask = KM_RALT; break;
+	default: mod_mask = 0; break;
+	}
+	
+	if (mod_mask != 0) {
+		if (type == KEY_PRESS)
+			kdev->mods = kdev->mods | mod_mask;
+		else
+			kdev->mods = kdev->mods & ~mod_mask;
+	}
+	
+	switch (key) {
+	case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
+	case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
+	case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
+	default: mod_mask = 0; break;
+	}
+	
+	if (mod_mask != 0) {
+		if (type == KEY_PRESS) {
+			/*
+			 * Only change lock state on transition from released
+			 * to pressed. This prevents autorepeat from messing
+			 * up the lock state.
+			 */
+			kdev->mods = kdev->mods ^ (mod_mask & ~kdev->lock_keys);
+			kdev->lock_keys = kdev->lock_keys | mod_mask;
+			
+			/* Update keyboard lock indicator lights. */
+			(*kdev->ctl_ops->set_ind)(kdev, kdev->mods);
+		} else {
+			kdev->lock_keys = kdev->lock_keys & ~mod_mask;
+		}
+	}
+	
+	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
+	    key == KC_F1) {
+		layout_destroy(kdev->active_layout);
+		kdev->active_layout = layout_create(layout[0]);
+		return;
+	}
+	
+	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
+	    key == KC_F2) {
+		layout_destroy(kdev->active_layout);
+		kdev->active_layout = layout_create(layout[1]);
+		return;
+	}
+	
+	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
+	    key == KC_F3) {
+		layout_destroy(kdev->active_layout);
+		kdev->active_layout = layout_create(layout[2]);
+		return;
+	}
+	
+	ev.type = type;
+	ev.key = key;
+	ev.mods = kdev->mods;
+	
+	ev.c = layout_parse_ev(kdev->active_layout, &ev);
+	
+	async_exch_t *exch = async_exchange_begin(client_sess);
+	async_msg_4(exch, INPUT_EVENT_KEY, ev.type, ev.key, ev.mods, ev.c);
+	async_exchange_end(exch);
+}
+
+/** Mouse pointer has moved. */
+void mouse_push_event_move(mouse_dev_t *mdev, int dx, int dy, int dz)
+{
+	async_exch_t *exch = async_exchange_begin(client_sess);
+	if (dx || dy)
+		async_msg_2(exch, INPUT_EVENT_MOVE, dx, dy);
+	if (dz) {
+		// TODO: Implement proper wheel support
+		keycode_t code = dz > 0 ? KC_UP : KC_DOWN;
+		for (int i = 0; i < 3; ++i) {
+			async_msg_4(exch, INPUT_EVENT_KEY, KEY_PRESS, code, 0, 0);
+		}
+		async_msg_4(exch, INPUT_EVENT_KEY, KEY_RELEASE, code, 0, 0);
+	}
+	async_exchange_end(exch);
+}
+
+/** Mouse pointer has moved in absolute mode. */
+void mouse_push_event_abs_move(mouse_dev_t *mdev, unsigned int x, unsigned int y,
+    unsigned int max_x, unsigned int max_y)
+{
+	if (max_x && max_y) {
+		async_exch_t *exch = async_exchange_begin(client_sess);
+		async_msg_4(exch, INPUT_EVENT_ABS_MOVE, x, y, max_x, max_y);
+		async_exchange_end(exch);
+	}
+}
+
+/** Mouse button has been pressed. */
+void mouse_push_event_button(mouse_dev_t *mdev, int bnum, int press)
+{
+	async_exch_t *exch = async_exchange_begin(client_sess);
+	async_msg_2(exch, INPUT_EVENT_BUTTON, bnum, press);
+	async_exchange_end(exch);
+}
+
+static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	async_answer_0(iid, EOK);
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			if (client_sess != NULL) {
+				async_hangup(client_sess);
+				client_sess = NULL;
+			}
+			
+			async_answer_0(callid, EOK);
+			return;
+		}
+		
+		async_sess_t *sess =
+		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
+		if (sess != NULL) {
+			if (client_sess == NULL) {
+				client_sess = sess;
+				async_answer_0(callid, EOK);
+			} else
+				async_answer_0(callid, ELIMIT);
+		} else {
+			switch (IPC_GET_IMETHOD(call)) {
+			case INPUT_YIELD:
+				kbd_devs_yield();
+				async_answer_0(callid, EOK);
+				break;
+			case INPUT_RECLAIM:
+				kbd_devs_reclaim();
+				async_answer_0(callid, EOK);
+				break;
+			default:
+				async_answer_0(callid, EINVAL);
+			}
+		}
+	}
+}
+
+static kbd_dev_t *kbd_dev_new(void)
+{
+	kbd_dev_t *kdev = calloc(1, sizeof(kbd_dev_t));
+	if (kdev == NULL) {
+		printf("%s: Error allocating keyboard device. "
+		    "Out of memory.\n", NAME);
+		return NULL;
+	}
+	
+	link_initialize(&kdev->kbd_devs);
+	
+	kdev->mods = KM_NUM_LOCK;
+	kdev->lock_keys = 0;
+	kdev->active_layout = layout_create(layout[0]);
+	
+	return kdev;
+}
+
+static mouse_dev_t *mouse_dev_new(void)
+{
+	mouse_dev_t *mdev = calloc(1, sizeof(mouse_dev_t));
+	if (mdev == NULL) {
+		printf("%s: Error allocating keyboard device. "
+		    "Out of memory.\n", NAME);
+		return NULL;
+	}
+	
+	link_initialize(&mdev->mouse_devs);
+	
+	return mdev;
+}
+
+/** Add new legacy keyboard device. */
+static void kbd_add_dev(kbd_port_ops_t *port, kbd_ctl_ops_t *ctl)
+{
+	kbd_dev_t *kdev = kbd_dev_new();
+	if (kdev == NULL)
+		return;
+	
+	kdev->port_ops = port;
+	kdev->ctl_ops = ctl;
+	kdev->svc_id = 0;
+	
+	/* Initialize port driver. */
+	if ((*kdev->port_ops->init)(kdev) != 0)
+		goto fail;
+	
+	/* Initialize controller driver. */
+	if ((*kdev->ctl_ops->init)(kdev) != 0) {
+		/* XXX Uninit port */
+		goto fail;
+	}
+	
+	list_append(&kdev->kbd_devs, &kbd_devs);
+	return;
+	
+fail:
+	free(kdev);
+}
+
+/** Add new legacy mouse device. */
+static void mouse_add_dev(mouse_port_ops_t *port, mouse_proto_ops_t *proto)
+{
+	mouse_dev_t *mdev = mouse_dev_new();
+	if (mdev == NULL)
+		return;
+	
+	mdev->port_ops = port;
+	mdev->proto_ops = proto;
+	mdev->svc_id = 0;
+	
+	/* Initialize port driver. */
+	if ((*mdev->port_ops->init)(mdev) != 0)
+		goto fail;
+	
+	/* Initialize protocol driver. */
+	if ((*mdev->proto_ops->init)(mdev) != 0) {
+		/* XXX Uninit port */
+		goto fail;
+	}
+	
+	list_append(&mdev->mouse_devs, &mouse_devs);
+	return;
+	
+fail:
+	free(mdev);
+}
+
+/** Add new kbdev device.
+ *
+ * @param service_id	Service ID of the keyboard device
+ *
+ */
+static int kbd_add_kbdev(service_id_t service_id, kbd_dev_t **kdevp)
+{
+	kbd_dev_t *kdev = kbd_dev_new();
+	if (kdev == NULL)
+		return -1;
+	
+	kdev->svc_id = service_id;
+	kdev->port_ops = NULL;
+	kdev->ctl_ops = &kbdev_ctl;
+	
+	int rc = loc_service_get_name(service_id, &kdev->svc_name);
+	if (rc != EOK) {
+		kdev->svc_name = NULL;
+		goto fail;
+	}
+	
+	/* Initialize controller driver. */
+	if ((*kdev->ctl_ops->init)(kdev) != 0) {
+		goto fail;
+	}
+	
+	list_append(&kdev->kbd_devs, &kbd_devs);
+	*kdevp = kdev;
+	return EOK;
+	
+fail:
+	if (kdev->svc_name != NULL)
+		free(kdev->svc_name);
+	free(kdev);
+	return -1;
+}
+
+/** Add new mousedev device.
+ *
+ * @param service_id	Service ID of the mouse device
+ *
+ */
+static int mouse_add_mousedev(service_id_t service_id, mouse_dev_t **mdevp)
+{
+	mouse_dev_t *mdev = mouse_dev_new();
+	if (mdev == NULL)
+		return -1;
+	
+	mdev->svc_id = service_id;
+	mdev->port_ops = NULL;
+	mdev->proto_ops = &mousedev_proto;
+	
+	int rc = loc_service_get_name(service_id, &mdev->svc_name);
+	if (rc != EOK) {
+		mdev->svc_name = NULL;
+		goto fail;
+	}
+	
+	/* Initialize controller driver. */
+	if ((*mdev->proto_ops->init)(mdev) != 0) {
+		goto fail;
+	}
+	
+	list_append(&mdev->mouse_devs, &mouse_devs);
+	*mdevp = mdev;
+	return EOK;
+	
+fail:
+	free(mdev);
+	return -1;
+}
+
+/** Add legacy drivers/devices. */
+static void kbd_add_legacy_devs(void)
+{
+	/*
+	 * Need to add these drivers based on config unless we can probe
+	 * them automatically.
+	 */
+#if defined(UARCH_arm32) && defined(MACHINE_gta02)
+	kbd_add_dev(&chardev_port, &stty_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_testarm) && defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &gxe_fb_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_testarm) && !defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &stty_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_integratorcp)
+	kbd_add_dev(&pl050_port, &pc_ctl);
+#endif
+#if defined(MACHINE_ski)
+	kbd_add_dev(&ski_port, &stty_ctl);
+#endif
+#if defined(MACHINE_msim)
+	kbd_add_dev(&msim_port, &stty_ctl);
+#endif
+#if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &gxe_fb_ctl);
+#endif
+#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul) && !defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &stty_ctl);
+#endif
+#if defined(UARCH_ppc32)
+	kbd_add_dev(&adb_port, &apple_ctl);
+#endif
+#if defined(UARCH_sparc64) && defined(PROCESSOR_sun4v)
+	kbd_add_dev(&niagara_port, &stty_ctl);
+#endif
+#if defined(UARCH_sparc64) && defined(MACHINE_generic)
+	kbd_add_dev(&ns16550_port, &sun_ctl);
+#endif
+	/* Silence warning on abs32le about kbd_add_dev() being unused */
+	(void) kbd_add_dev;
+}
+
+/** Add legacy drivers/devices. */
+static void mouse_add_legacy_devs(void)
+{
+	/*
+	 * Need to add these drivers based on config unless we can probe
+	 * them automatically.
+	 */
+#if defined(UARCH_ppc32)
+	mouse_add_dev(&adb_mouse_port, &adb_proto);
+#endif
+	/* Silence warning on abs32le about mouse_add_dev() being unused */
+	(void) mouse_add_dev;
+}
+
+static void kbd_devs_yield(void)
+{
+	/* For each keyboard device */
+	list_foreach(kbd_devs, kdev_link) {
+		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
+		    kbd_devs);
+		
+		/* Yield port */
+		if (kdev->port_ops != NULL)
+			(*kdev->port_ops->yield)();
+	}
+}
+
+static void kbd_devs_reclaim(void)
+{
+	/* For each keyboard device */
+	list_foreach(kbd_devs, kdev_link) {
+		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
+		    kbd_devs);
+		
+		/* Reclaim port */
+		if (kdev->port_ops != NULL)
+			(*kdev->port_ops->reclaim)();
+	}
+}
+
+static int dev_check_new_kbdevs(void)
+{
+	category_id_t keyboard_cat;
+	service_id_t *svcs;
+	size_t count, i;
+	bool already_known;
+	int rc;
+	
+	rc = loc_category_get_id("keyboard", &keyboard_cat, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		printf("%s: Failed resolving category 'keyboard'.\n", NAME);
+		return ENOENT;
+	}
+	
+	/*
+	 * Check for new keyboard devices
+	 */
+	rc = loc_category_get_svcs(keyboard_cat, &svcs, &count);
+	if (rc != EOK) {
+		printf("%s: Failed getting list of keyboard devices.\n",
+		    NAME);
+		return EIO;
+	}
+
+	for (i = 0; i < count; i++) {
+		already_known = false;
+		
+		/* Determine whether we already know this device. */
+		list_foreach(kbd_devs, kdev_link) {
+			kbd_dev_t *kdev = list_get_instance(kdev_link,
+			    kbd_dev_t, kbd_devs);
+			if (kdev->svc_id == svcs[i]) {
+				already_known = true;
+				break;
+			}
+		}
+		
+		if (!already_known) {
+			kbd_dev_t *kdev;
+			if (kbd_add_kbdev(svcs[i], &kdev) == EOK) {
+				printf("%s: Connected keyboard device '%s'\n",
+				    NAME, kdev->svc_name);
+			}
+		}
+	}
+	
+	free(svcs);
+	
+	/* XXX Handle device removal */
+	
+	return EOK;
+}
+
+static int dev_check_new_mousedevs(void)
+{
+	category_id_t mouse_cat;
+	service_id_t *svcs;
+	size_t count, i;
+	bool already_known;
+	int rc;
+	
+	rc = loc_category_get_id("mouse", &mouse_cat, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		printf("%s: Failed resolving category 'mouse'.\n", NAME);
+		return ENOENT;
+	}
+	
+	/*
+	 * Check for new mouse devices
+	 */
+	rc = loc_category_get_svcs(mouse_cat, &svcs, &count);
+	if (rc != EOK) {
+		printf("%s: Failed getting list of mouse devices.\n",
+		    NAME);
+		return EIO;
+	}
+	
+	for (i = 0; i < count; i++) {
+		already_known = false;
+		
+		/* Determine whether we already know this device. */
+		list_foreach(mouse_devs, mdev_link) {
+			mouse_dev_t *mdev = list_get_instance(mdev_link,
+			    mouse_dev_t, mouse_devs);
+			if (mdev->svc_id == svcs[i]) {
+				already_known = true;
+				break;
+			}
+		}
+		
+		if (!already_known) {
+			mouse_dev_t *mdev;
+			if (mouse_add_mousedev(svcs[i], &mdev) == EOK) {
+				printf("%s: Connected mouse device '%s'\n",
+				    NAME, mdev->svc_name);
+			}
+		}
+	}
+	
+	free(svcs);
+	
+	/* XXX Handle device removal */
+	
+	return EOK;
+}
+
+static int dev_check_new(void)
+{
+	int rc;
+	
+	fibril_mutex_lock(&discovery_lock);
+	
+	rc = dev_check_new_kbdevs();
+	if (rc != EOK) {
+		fibril_mutex_unlock(&discovery_lock);
+		return rc;
+	}
+	
+	rc = dev_check_new_mousedevs();
+	if (rc != EOK) {
+		fibril_mutex_unlock(&discovery_lock);
+		return rc;
+	}
+	
+	fibril_mutex_unlock(&discovery_lock);
+	
+	return EOK;
+}
+
+static void cat_change_cb(void)
+{
+	dev_check_new();
+}
+
+/** Start listening for new devices. */
+static int input_start_dev_discovery(void)
+{
+	int rc;
+
+	rc = loc_register_cat_change_cb(cat_change_cb);
+	if (rc != EOK) {
+		printf("%s: Failed registering callback for device discovery. "
+		    "(%d)\n", NAME, rc);
+		return rc;
+	}
+
+	return dev_check_new();
+}
+
+static void usage(char *name)
+{
+	printf("Usage: %s <service_name>\n", name);
+}
+
+int main(int argc, char **argv)
+{
+	if (argc < 2) {
+		usage(argv[0]);
+		return 1;
+	}
+	
+	printf("%s: HelenOS input service\n", NAME);
+	
+	sysarg_t obio;
+	
+	list_initialize(&kbd_devs);
+	list_initialize(&mouse_devs);
+	
+	if ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio))
+		irc_service = true;
+	
+	if (irc_service) {
+		while (irc_sess == NULL)
+			irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+			    SERVICE_IRC, 0, 0);
+	}
+	
+	/* Add legacy keyboard devices. */
+	kbd_add_legacy_devs();
+	
+	/* Add legacy mouse devices. */
+	mouse_add_legacy_devs();
+	
+	/* Register driver */
+	async_set_client_connection(client_connection);
+	int rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		printf("%s: Unable to register server\n", NAME);
+		return rc;
+	}
+	
+	service_id_t service_id;
+	rc = loc_service_register(argv[1], &service_id);
+	if (rc != EOK) {
+		printf("%s: Unable to register service %s\n", NAME, argv[1]);
+		return rc;
+	}
+	
+	/* Start looking for new input devices */
+	input_start_dev_discovery();
+	
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
+	async_manager();
+	
+	/* Not reached. */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/input.h
===================================================================
--- uspace/srv/hid/input/input.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/input.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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 inputgen generic
+ * @brief HelenOS input server.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef INPUT_H_
+#define INPUT_H_
+
+#include <bool.h>
+#include <async.h>
+
+#define NAME  "input"
+
+extern bool irc_service;
+extern async_sess_t *irc_sess;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/kbd.h
===================================================================
--- uspace/srv/hid/input/kbd.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/kbd.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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 inputgen generic
+ * @brief HelenOS input server.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_KBD_H_
+#define KBD_KBD_H_
+
+#include <adt/list.h>
+#include <ipc/loc.h>
+
+struct kbd_port_ops;
+struct kbd_ctl_ops;
+struct layout;
+
+typedef struct kbd_dev {
+	/** Link to kbd_devs list */
+	link_t kbd_devs;
+
+	/** Service ID (only for kbdev devices) */
+	service_id_t svc_id;
+
+	/** Device service name (only for kbdev devices) */
+	char *svc_name;
+
+	/** Port ops */
+	struct kbd_port_ops *port_ops;
+
+	/** Ctl ops */
+	struct kbd_ctl_ops *ctl_ops;
+
+	/** Controller-private data */
+	void *ctl_private;
+
+	/** Currently active modifiers. */
+	unsigned mods;
+
+	/** Currently pressed lock keys. We track these to tackle autorepeat. */
+	unsigned lock_keys;
+
+	/** Active keyboard layout */
+	struct layout *active_layout;
+} kbd_dev_t;
+
+extern void kbd_push_data(kbd_dev_t *, sysarg_t);
+extern void kbd_push_event(kbd_dev_t *, int, unsigned int);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/kbd_ctl.h
===================================================================
--- uspace/srv/hid/input/kbd_ctl.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/kbd_ctl.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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 inputgen generic
+ * @brief Keyboard controller driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_CTL_H_
+#define KBD_CTL_H_
+
+#include "kbd_port.h"
+
+struct kbd_dev;
+
+typedef struct kbd_ctl_ops {
+	void (*parse)(sysarg_t);
+	int (*init)(struct kbd_dev *);
+	void (*set_ind)(struct kbd_dev *, unsigned int);
+} kbd_ctl_ops_t;
+
+extern kbd_ctl_ops_t apple_ctl;
+extern kbd_ctl_ops_t gxe_fb_ctl;
+extern kbd_ctl_ops_t kbdev_ctl;
+extern kbd_ctl_ops_t pc_ctl;
+extern kbd_ctl_ops_t stty_ctl;
+extern kbd_ctl_ops_t sun_ctl;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/kbd_port.h
===================================================================
--- uspace/srv/hid/input/kbd_port.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/kbd_port.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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 inputgen generic
+ * @brief Keyboard port driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_PORT_H_
+#define KBD_PORT_H_
+
+#include <sys/types.h>
+
+struct kbd_dev;
+
+typedef struct kbd_port_ops {
+	int (*init)(struct kbd_dev *);
+	void (*yield)(void);
+	void (*reclaim)(void);
+	void (*write)(uint8_t);
+} kbd_port_ops_t;
+
+extern kbd_port_ops_t adb_port;
+extern kbd_port_ops_t chardev_port;
+extern kbd_port_ops_t gxemul_port;
+extern kbd_port_ops_t msim_port;
+extern kbd_port_ops_t niagara_port;
+extern kbd_port_ops_t ns16550_port;
+extern kbd_port_ops_t pl050_port;
+extern kbd_port_ops_t ski_port;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/layout.c
===================================================================
--- uspace/srv/hid/input/layout.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/layout.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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 inputgen generic
+ * @brief Keyboard layouts
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include "input.h"
+#include "layout.h"
+
+/** Create a new layout instance. */
+layout_t *layout_create(layout_ops_t *ops)
+{
+	layout_t *layout;
+
+	layout = calloc(1, sizeof(layout_t));
+	if (layout == NULL) {
+		printf("%s: Out of memory.\n", NAME);
+		return NULL;
+	}
+
+	layout->ops = ops;
+	if ((*ops->create)(layout) != EOK) {
+		free(layout);
+		return NULL;
+	}
+
+	return layout;
+}
+
+/** Destroy layout instance. */
+void layout_destroy(layout_t *layout)
+{
+	(*layout->ops->destroy)(layout);
+	free(layout);
+}
+
+/** Parse keyboard event. */
+wchar_t layout_parse_ev(layout_t *layout, kbd_event_t *ev)
+{
+	return (*layout->ops->parse_ev)(layout, ev);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/layout.h
===================================================================
--- uspace/srv/hid/input/layout.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/layout.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * 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 inputgen generic
+ * @brief Keyboard layout interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_LAYOUT_H_
+#define KBD_LAYOUT_H_
+
+#include <sys/types.h>
+#include <io/console.h>
+
+/** Layout instance state */
+typedef struct layout {
+	/** Ops structure */
+	struct layout_ops *ops;
+
+	/* Layout-private data */
+	void *layout_priv;
+} layout_t;
+
+/** Layout ops */
+typedef struct layout_ops {
+	int (*create)(layout_t *);
+	void (*destroy)(layout_t *);
+	wchar_t (*parse_ev)(layout_t *, kbd_event_t *);
+} layout_ops_t;
+
+extern layout_ops_t us_qwerty_ops;
+extern layout_ops_t us_dvorak_ops;
+extern layout_ops_t cz_ops;
+
+extern layout_t *layout_create(layout_ops_t *);
+extern void layout_destroy(layout_t *);
+extern wchar_t layout_parse_ev(layout_t *, kbd_event_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/layout/cz.c
===================================================================
--- uspace/srv/hid/input/layout/cz.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/layout/cz.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,10 +33,10 @@
 
 #include <errno.h>
-#include <input.h>
 #include <io/console.h>
 #include <io/keycode.h>
 #include <bool.h>
-#include <layout.h>
 #include <stdlib.h>
+#include "../input.h"
+#include "../layout.h"
 
 static int cz_create(layout_t *);
Index: uspace/srv/hid/input/layout/us_dvorak.c
===================================================================
--- uspace/srv/hid/input/layout/us_dvorak.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/layout/us_dvorak.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -33,8 +33,8 @@
 
 #include <errno.h>
-#include <kbd.h>
 #include <io/console.h>
 #include <io/keycode.h>
-#include <layout.h>
+#include "../layout.h"
+#include "../kbd.h"
 
 static int us_dvorak_create(layout_t *);
Index: uspace/srv/hid/input/layout/us_qwerty.c
===================================================================
--- uspace/srv/hid/input/layout/us_qwerty.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/layout/us_qwerty.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -28,13 +28,13 @@
 
 /** @addtogroup input
- * @brief	US QWERTY layout.
+ * @brief US QWERTY layout.
  * @{
  */
 
 #include <errno.h>
-#include <kbd.h>
 #include <io/console.h>
 #include <io/keycode.h>
-#include <layout.h>
+#include "../layout.h"
+#include "../kbd.h"
 
 static int us_qwerty_create(layout_t *);
Index: uspace/srv/hid/input/mouse.h
===================================================================
--- uspace/srv/hid/input/mouse.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/mouse.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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 inputgen generic
+ * @brief Mouse device handling.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef MOUSE_H_
+#define MOUSE_H_
+
+#include <adt/list.h>
+#include <ipc/loc.h>
+
+struct mouse_port_ops;
+struct mouse_proto_ops;
+
+typedef struct mouse_dev {
+	/** Link to mouse_devs list */
+	link_t mouse_devs;
+	
+	/** Service ID (only for mousedev devices) */
+	service_id_t svc_id;
+	
+	/** Device service name (only for mousedev devices) */
+	char *svc_name;
+	
+	/** Port ops */
+	struct mouse_port_ops *port_ops;
+	
+	/** Protocol ops */
+	struct mouse_proto_ops *proto_ops;
+} mouse_dev_t;
+
+extern void mouse_push_data(mouse_dev_t *, sysarg_t);
+extern void mouse_push_event_move(mouse_dev_t *, int, int, int);
+extern void mouse_push_event_abs_move(mouse_dev_t *, unsigned int, unsigned int,
+    unsigned int, unsigned int);
+extern void mouse_push_event_button(mouse_dev_t *, int, int);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/mouse_port.h
===================================================================
--- uspace/srv/hid/input/mouse_port.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/mouse_port.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 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 inputgen generic
+ * @brief Mouse port driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef MOUSE_PORT_H_
+#define MOUSE_PORT_H_
+
+#include <sys/types.h>
+
+struct mouse_dev;
+
+typedef struct mouse_port_ops {
+	int (*init)(struct mouse_dev *);
+	void (*yield)(void);
+	void (*reclaim)(void);
+	void (*write)(uint8_t);
+} mouse_port_ops_t;
+
+extern mouse_port_ops_t adb_mouse_port;
+extern mouse_port_ops_t chardev_mouse_port;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/mouse_proto.h
===================================================================
--- uspace/srv/hid/input/mouse_proto.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/mouse_proto.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011 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 inputgen generic
+ * @brief Mouse protocol driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef MOUSE_PROTO_H_
+#define MOUSE_PROTO_H_
+
+#include "mouse_port.h"
+
+struct mouse_dev;
+
+typedef struct mouse_proto_ops {
+	void (*parse)(sysarg_t);
+	int (*init)(struct mouse_dev *);
+} mouse_proto_ops_t;
+
+extern mouse_proto_ops_t adb_proto;
+extern mouse_proto_ops_t mousedev_proto;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/adb.c
===================================================================
--- uspace/srv/hid/input/port/adb.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/port/adb.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,11 +37,11 @@
 #include <ipc/adb.h>
 #include <async.h>
-#include <input.h>
-#include <kbd_port.h>
-#include <kbd.h>
 #include <vfs/vfs.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <loc.h>
+#include "../input.h"
+#include "../kbd_port.h"
+#include "../kbd.h"
 
 static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg);
Index: uspace/srv/hid/input/port/adb_mouse.c
===================================================================
--- uspace/srv/hid/input/port/adb_mouse.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/port/adb_mouse.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,10 +37,10 @@
 #include <ipc/adb.h>
 #include <async.h>
-#include <input.h>
-#include <mouse_port.h>
-#include <mouse.h>
 #include <errno.h>
 #include <loc.h>
 #include <stdio.h>
+#include "../mouse.h"
+#include "../mouse_port.h"
+#include "../input.h"
 
 static mouse_dev_t *mouse_dev;
Index: uspace/srv/hid/input/port/chardev.c
===================================================================
--- uspace/srv/hid/input/port/chardev.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/port/chardev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,10 +37,10 @@
 #include <ipc/char.h>
 #include <async.h>
-#include <input.h>
-#include <kbd_port.h>
-#include <kbd.h>
 #include <loc.h>
 #include <errno.h>
 #include <stdio.h>
+#include "../input.h"
+#include "../kbd_port.h"
+#include "../kbd.h"
 
 static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg);
Index: uspace/srv/hid/input/port/gxemul.c
===================================================================
--- uspace/srv/hid/input/port/gxemul.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/port/gxemul.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -31,15 +31,15 @@
  * @{
  * @ingroup  kbd
- */ 
+ */
 /** @file
- * @brief	GXEmul keyboard port driver.
+ * @brief GXEmul keyboard port driver.
  */
 
 #include <async.h>
 #include <sysinfo.h>
-#include <kbd_port.h>
-#include <kbd.h>
 #include <ddi.h>
 #include <errno.h>
+#include "../kbd_port.h"
+#include "../kbd.h"
 
 static int gxemul_port_init(kbd_dev_t *);
Index: uspace/srv/hid/input/port/msim.c
===================================================================
--- uspace/srv/hid/input/port/msim.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/port/msim.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -38,8 +38,8 @@
 #include <async.h>
 #include <sysinfo.h>
-#include <kbd_port.h>
-#include <kbd.h>
 #include <ddi.h>
 #include <errno.h>
+#include "../kbd_port.h"
+#include "../kbd.h"
 
 static int msim_port_init(kbd_dev_t *);
Index: uspace/srv/hid/input/port/niagara.c
===================================================================
--- uspace/srv/hid/input/port/niagara.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/port/niagara.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -31,7 +31,7 @@
  * @ingroup  kbd
  * @{
- */ 
+ */
 /** @file
- * @brief	Niagara console keyboard port driver.
+ * @brief Niagara console keyboard port driver.
  */
 
@@ -39,6 +39,4 @@
 #include <ddi.h>
 #include <async.h>
-#include <kbd.h>
-#include <kbd_port.h>
 #include <sysinfo.h>
 #include <stdio.h>
@@ -46,4 +44,6 @@
 #include <bool.h>
 #include <errno.h>
+#include "../kbd_port.h"
+#include "../kbd.h"
 
 static int niagara_port_init(kbd_dev_t *);
Index: uspace/srv/hid/input/port/ns16550.c
===================================================================
--- uspace/srv/hid/input/port/ns16550.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/port/ns16550.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -39,9 +39,9 @@
 #include <async.h>
 #include <sysinfo.h>
-#include <input.h>
-#include <kbd.h>
-#include <kbd_port.h>
 #include <ddi.h>
 #include <errno.h>
+#include "../input.h"
+#include "../kbd_port.h"
+#include "../kbd.h"
 
 static int ns16550_port_init(kbd_dev_t *);
@@ -84,5 +84,5 @@
 	},
 	{
-		.cmd = CMD_BTEST,
+		.cmd = CMD_AND,
 		.value = LSR_DATA_READY,
 		.srcarg = 1,
Index: uspace/srv/hid/input/port/pl050.c
===================================================================
--- uspace/srv/hid/input/port/pl050.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/port/pl050.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,9 +41,9 @@
 #include <unistd.h>
 #include <sysinfo.h>
-#include <kbd_port.h>
-#include <kbd.h>
 #include <ddi.h>
 #include <stdio.h>
 #include <errno.h>
+#include "../kbd_port.h"
+#include "../kbd.h"
 
 static int pl050_port_init(kbd_dev_t *);
@@ -80,5 +80,5 @@
 	},
 	{
-		.cmd = CMD_BTEST,
+		.cmd = CMD_AND,
 		.value = PL050_STAT_RXFULL,
 		.srcarg = 1,
Index: uspace/srv/hid/input/port/ski.c
===================================================================
--- uspace/srv/hid/input/port/ski.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/port/ski.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -31,17 +31,16 @@
  * @ingroup  kbd
  * @{
- */ 
+ */
 /** @file
- * @brief	Ski console keyboard port driver.
+ * @brief Ski console keyboard port driver.
  */
-
 
 #include <stdlib.h>
 #include <unistd.h>
-#include <kbd.h>
-#include <kbd_port.h>
 #include <sys/types.h>
 #include <thread.h>
 #include <bool.h>
+#include "../kbd_port.h"
+#include "../kbd.h"
 
 static int ski_port_init(kbd_dev_t *);
Index: uspace/srv/hid/input/proto/adb.c
===================================================================
--- uspace/srv/hid/input/proto/adb.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/proto/adb.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -37,7 +37,7 @@
 
 #include <bool.h>
-#include <mouse.h>
-#include <mouse_port.h>
-#include <mouse_proto.h>
+#include "../mouse.h"
+#include "../mouse_port.h"
+#include "../mouse_proto.h"
 
 static mouse_dev_t *mouse_dev;
Index: uspace/srv/hid/input/proto/mousedev.c
===================================================================
--- uspace/srv/hid/input/proto/mousedev.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/input/proto/mousedev.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -43,10 +43,10 @@
 #include <errno.h>
 #include <ipc/mouseev.h>
-#include <input.h>
 #include <loc.h>
-#include <mouse.h>
-#include <mouse_port.h>
-#include <mouse_proto.h>
 #include <sys/typefmt.h>
+#include "../mouse.h"
+#include "../mouse_port.h"
+#include "../mouse_proto.h"
+#include "../input.h"
 
 /** Mousedev softstate */
@@ -94,4 +94,10 @@
 			    IPC_GET_ARG1(call), IPC_GET_ARG2(call),
 			    IPC_GET_ARG3(call));
+			retval = EOK;
+			break;
+		case MOUSEEV_ABS_MOVE_EVENT:
+			mouse_push_event_abs_move(mousedev->mouse_dev,
+				IPC_GET_ARG1(call), IPC_GET_ARG2(call),
+				IPC_GET_ARG3(call), IPC_GET_ARG4(call));
 			retval = EOK;
 			break;
Index: uspace/srv/hid/input/stroke.c
===================================================================
--- uspace/srv/hid/input/stroke.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/stroke.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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 input
+ * @{
+ */
+/**
+ * @file
+ * @brief Stroke simulator.
+ *
+ * When simulating a keyboard using a serial TTY we need to convert the
+ * recognized strokes (such as Shift-A) to sequences of key presses and
+ * releases (such as 'press Shift, press A, release A, release Shift').
+ *
+ */
+
+#include <io/console.h>
+#include <io/keycode.h>
+#include "stroke.h"
+#include "kbd.h"
+
+/** Correspondence between modifers and the modifier keycodes. */
+static unsigned int mods_keys[][2] = {
+	{ KM_LSHIFT, KC_LSHIFT },
+	{ 0, 0 }
+};
+
+/** Simulate keystroke using sequences of key presses and releases. */
+void stroke_sim(kbd_dev_t *kdev, unsigned mod, unsigned key)
+{
+	int i;
+
+	/* Simulate modifier presses. */
+	i = 0;
+	while (mods_keys[i][0] != 0) {
+		if (mod & mods_keys[i][0]) {
+			kbd_push_event(kdev, KEY_PRESS, mods_keys[i][1]);
+		}
+		++i;
+	}
+
+	/* Simulate key press and release. */
+	if (key != 0) {
+		kbd_push_event(kdev, KEY_PRESS, key);
+		kbd_push_event(kdev, KEY_RELEASE, key);
+	}
+
+	/* Simulate modifier releases. */
+	i = 0;
+	while (mods_keys[i][0] != 0) {
+		if (mod & mods_keys[i][0]) {
+			kbd_push_event(kdev, KEY_RELEASE, mods_keys[i][1]);
+		}
+		++i;
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/stroke.h
===================================================================
--- uspace/srv/hid/input/stroke.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/input/stroke.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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 inputgen generic
+ * @brief Generic scancode parser.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_STROKE_H_
+#define KBD_STROKE_H_
+
+#include "kbd.h"
+
+extern void stroke_sim(kbd_dev_t *, unsigned, unsigned);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/isdv4_tablet/Makefile
===================================================================
--- uspace/srv/hid/isdv4_tablet/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/isdv4_tablet/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2012 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.
+#
+
+USPACE_PREFIX = ../../..
+#LIBS = 
+#EXTRA_CFLAGS = 
+BINARY = isdv4_tablet
+
+SOURCES = \
+	main.c \
+	isdv4.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/isdv4_tablet/isdv4.c
===================================================================
--- uspace/srv/hid/isdv4_tablet/isdv4.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/isdv4_tablet/isdv4.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include <device/char_dev.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <mem.h>
+
+#include "isdv4.h"
+
+#define BUF_SIZE 64
+
+#define START_OF_PACKET 128
+#define CONTROL_PACKET 64
+#define TOUCH_EVENT 16
+#define FINGER1 1
+#define FINGER2 2
+#define TIP 1
+#define BUTTON1 2
+#define BUTTON2 4
+#define PROXIMITY 32
+
+#define CMD_START '1'
+#define CMD_STOP '0'
+#define CMD_QUERY_STYLUS '*'
+#define CMD_QUERY_TOUCH '%'
+
+/* packet_consumer_fn(uint8_t *packet, size_t size, isdv4_state_t *state,
+   void *data)
+   return true if reading of packets should continue */
+typedef bool (*packet_consumer_fn)(uint8_t *, size_t, isdv4_state_t *);
+
+static void isdv4_event_init(isdv4_event_t *event)
+{
+	memset(event, 0, sizeof(isdv4_event_t));
+}
+
+/**
+ * Parse event packet and emit events
+ * @return true if reading of packets should continue
+ */
+static bool parse_event(uint8_t *packet, size_t size, isdv4_state_t *state)
+{
+	if (size < 1)
+		return false;
+
+	bool control_packet = ((packet[0] & CONTROL_PACKET) > 0);
+	if (control_packet)
+		return true;
+
+	/* This is an event initiated by the device */
+	isdv4_event_t event;
+	isdv4_event_init(&event);
+
+	if (packet[0] & TOUCH_EVENT) {
+		if (size != 5)
+			return true;
+
+		/* This is a touch event */
+		bool finger1 = (packet[0] & FINGER1) > 0;
+		event.x = ((packet[1] & 127) << 7) | (packet[2] & 127);
+		event.y = ((packet[3] & 127) << 7) | (packet[4] & 127);
+		event.source = TOUCH;
+
+		if (!state->stylus_in_proximity) {
+			if (!finger1 && state->finger1_pressed) {
+				state->finger1_pressed = false;
+
+				event.type = RELEASE;
+				event.button = 1;
+				state->emit_event_fn(&event);
+			}
+			else if (finger1 && !state->finger1_pressed) {
+				state->finger1_pressed = true;
+
+				event.type = PRESS;
+				event.button = 1;
+				state->emit_event_fn(&event);
+			}
+			else {
+				event.type = MOVE;
+				event.button = 1;
+				state->emit_event_fn(&event);
+			}
+		}
+	}
+	else {
+		if (size != 9)
+			return true;
+
+		/* This is a stylus event */
+		bool tip = packet[0] & TIP;
+		bool button1 = packet[0] & BUTTON1;
+		bool button2 = packet[0] & BUTTON2;
+		bool proximity = packet[0] & PROXIMITY;
+		event.x = ((packet[1] & 127) << 7) | (packet[2] & 124) | ((packet[6] >> 5) & 3);
+		event.y = ((packet[3] & 127) << 7) | (packet[4] & 124) | ((packet[6] >> 3) & 3);
+		event.pressure = (packet[5] & 127) | ((packet[6] & 7) << 7);
+
+		if (proximity && !state->stylus_in_proximity) {
+			/* Stylus came into proximity */
+			state->stylus_in_proximity = true;
+			state->stylus_is_eraser = !tip && button2;
+			event.source = (state->stylus_is_eraser ? STYLUS_ERASER : STYLUS_TIP);
+			event.type = PROXIMITY_IN;
+			state->emit_event_fn(&event);
+		}
+		else if (!proximity && state->stylus_in_proximity) {
+			/* Stylus came out of proximity */
+			state->stylus_in_proximity = false;
+			event.source = (state->stylus_is_eraser ? STYLUS_ERASER : STYLUS_TIP);
+			event.type = PROXIMITY_OUT;
+			state->emit_event_fn(&event);
+		}
+		else {
+			/* Proximity state didn't change, but we need to check if it is still eraser */
+			if (state->stylus_is_eraser && !button2) {
+				event.type = PROXIMITY_OUT;
+				event.source = STYLUS_ERASER;
+				state->emit_event_fn(&event);
+				event.type = PROXIMITY_IN;
+				event.source = STYLUS_TIP;
+				state->emit_event_fn(&event);
+				state->stylus_is_eraser = false;
+			}
+			else if (!state->stylus_is_eraser && !tip && button2) {
+				event.type = PROXIMITY_OUT;
+				event.source = STYLUS_TIP;
+				state->emit_event_fn(&event);
+				event.type = PROXIMITY_IN;
+				event.source = STYLUS_ERASER;
+				state->emit_event_fn(&event);
+				state->stylus_is_eraser = true;
+			}
+		}
+
+		if (!state->stylus_is_eraser) {
+			if (tip && !state->tip_pressed) {
+				state->tip_pressed = true;
+				event.type = PRESS;
+				event.source = STYLUS_TIP;
+				event.button = 1;
+				state->emit_event_fn(&event);
+			}
+			else if (!tip && state->tip_pressed) {
+				state->tip_pressed = false;
+				event.type = RELEASE;
+				event.source = STYLUS_TIP;
+				event.button = 1;
+				state->emit_event_fn(&event);
+			}
+			if (button1 && !state->button1_pressed) {
+				state->button1_pressed = true;
+				event.type = PRESS;
+				event.source = STYLUS_TIP;
+				event.button = 2;
+				state->emit_event_fn(&event);
+			}
+			else if (!button1 && state->button1_pressed) {
+				state->button1_pressed = false;
+				event.type = RELEASE;
+				event.source = STYLUS_TIP;
+				event.button = 2;
+				state->emit_event_fn(&event);
+			}
+			if (button2 && !state->button2_pressed) {
+				state->button2_pressed = true;
+				event.type = PRESS;
+				event.source = STYLUS_TIP;
+				event.button = 3;
+				state->emit_event_fn(&event);
+			}
+			else if (!button2 && state->button2_pressed) {
+				state->button2_pressed = false;
+				event.type = RELEASE;
+				event.source = STYLUS_TIP;
+				event.button = 3;
+				state->emit_event_fn(&event);
+			}
+			event.type = MOVE;
+			event.source = STYLUS_TIP;
+			event.button = 0;
+			state->emit_event_fn(&event);
+		}
+		else {
+			if (tip && !state->tip_pressed) {
+				state->tip_pressed = true;
+				event.type = PRESS;
+				event.source = STYLUS_ERASER;
+				event.button = 1;
+				state->emit_event_fn(&event);
+			}
+			else if (!tip && state->tip_pressed) {
+				state->tip_pressed = false;
+				event.type = RELEASE;
+				event.source = STYLUS_ERASER;
+				event.button = 1;
+				state->emit_event_fn(&event);
+			}
+			event.type = MOVE;
+			event.source = STYLUS_ERASER;
+			event.button = 0;
+			state->emit_event_fn(&event);
+		}
+	}
+
+	return true;
+}
+
+static bool parse_response_stylus(uint8_t *packet, size_t size,
+    isdv4_state_t *state)
+{
+	if (size < 1)
+		return false;
+
+	bool control_packet = ((packet[0] & CONTROL_PACKET) > 0);
+	if (!control_packet)
+		return true;
+
+	if (size != 11)
+		return false;
+
+	state->stylus_max_x = ((packet[1] & 127) << 7) | (packet[2] & 124) |
+	    ((packet[6] >> 5) & 3);
+	state->stylus_max_y = ((packet[3] & 127) << 7) | (packet[4] & 124) |
+	    ((packet[6] >> 3) & 3);
+	state->stylus_max_pressure = (packet[5] & 63) | ((packet[6] & 7) << 7);
+	state->stylus_max_xtilt = packet[8] & 127;
+	state->stylus_max_ytilt = packet[7] & 127;
+	state->stylus_tilt_supported = (state->stylus_max_xtilt &&
+	    state->stylus_max_ytilt);
+
+	return false;
+}
+
+static bool parse_response_touch(uint8_t *packet, size_t size,
+    isdv4_state_t *state)
+{
+	if (size < 1)
+		return false;
+
+	bool control_packet = ((packet[0] & CONTROL_PACKET) > 0);
+	if (!control_packet)
+		return true;
+
+	if (size != 11)
+		return false;
+
+	state->touch_type = (packet[0] & 63);
+
+	unsigned int touch_resolution = packet[1] & 127;
+	state->touch_max_x = ((packet[2] >> 5) & 3) | ((packet[3] & 127) << 7) |
+	    (packet[4] & 124);
+	state->touch_max_y = ((packet[2] >> 3) & 3) | ((packet[5] & 127) << 7) |
+	    (packet[6] & 124);
+	
+	if (touch_resolution == 0)
+		touch_resolution = 10;
+
+	if (state->touch_max_x == 0 || state->touch_max_y == 0) {
+		state->touch_max_x = (1 << touch_resolution);
+		state->touch_max_y = (1 << touch_resolution);
+	}
+
+	return false;
+}
+
+static int read_packets(isdv4_state_t *state, packet_consumer_fn consumer)
+{
+	bool reading = true;
+	while (reading) {
+		ssize_t read = char_dev_read(state->sess, state->buf + state->buf_end,
+		    state->buf_size - state->buf_end);
+		if (read < 0)
+			return EIO;
+		state->buf_end += read;
+
+		size_t i = 0;
+
+		/* Skip data until a start of packet is found */
+		while (i < state->buf_end && (state->buf[i] & START_OF_PACKET) == 0) i++;
+
+		size_t start = i;
+		size_t end = i;
+		size_t processed_end = i;
+
+		/* Process packets one by one */
+		while (reading && i < state->buf_end) {
+			/* Determine the packet length */
+			size_t packet_remaining;
+			if (state->buf[i] & CONTROL_PACKET) {
+				packet_remaining = 11;
+			}
+			else if (state->buf[i] & TOUCH_EVENT) {
+				packet_remaining = 5;
+			}
+			else {
+				packet_remaining = 9;
+			}
+
+			/* Find the end of the packet */
+			i++; /* We need to skip the first byte with START_OF_PACKET set */
+			packet_remaining--; 
+			while (packet_remaining > 0 && i < state->buf_end &&
+			    (state->buf[i] & START_OF_PACKET) == 0) {
+				i++;
+				packet_remaining--;
+			}
+			end = i;
+
+			/* If we have whole packet, process it */
+			if (end > start && packet_remaining == 0) {
+				reading = consumer(state->buf + start, end - start, state);
+				start = end;
+				processed_end = end;
+			}
+		}
+
+		if (processed_end == 0 && state->buf_end == state->buf_size) {
+			/* Packet too large, throw it away */
+			state->buf_end = 0;
+		}
+
+		/* Shift the buffer contents to the left */
+		size_t unprocessed_len = state->buf_end - processed_end;
+		memcpy(state->buf, state->buf + processed_end, unprocessed_len);
+		state->buf_end = unprocessed_len;
+	}
+	return EOK;
+}
+static bool write_command(async_sess_t *sess, uint8_t command)
+{
+	return char_dev_write(sess, &command, 1) == 1;
+}
+
+int isdv4_init(isdv4_state_t *state, async_sess_t *sess,
+    isdv4_event_fn event_fn)
+{
+	memset(state, 0, sizeof(isdv4_state_t));
+	state->sess = sess;
+	state->buf = malloc(BUF_SIZE);
+	if (state->buf == NULL)
+		return ENOMEM;
+	state->buf_size = BUF_SIZE;
+	state->emit_event_fn = event_fn;
+	return EOK;
+}
+
+int isdv4_init_tablet(isdv4_state_t *state)
+{
+	if (!write_command(state->sess, CMD_STOP))
+		return EIO;
+
+	usleep(250000); /* 250 ms */
+
+	// FIXME: Read all possible garbage before sending commands
+	if (!write_command(state->sess, CMD_QUERY_STYLUS))
+		return EIO;
+
+	int rc = read_packets(state, parse_response_stylus);
+	if (rc != EOK)
+		return rc;
+
+	if (!write_command(state->sess, CMD_QUERY_TOUCH))
+		return EIO;
+
+	rc = read_packets(state, parse_response_touch);
+	if (rc != EOK)
+		return rc;
+
+	if (!write_command(state->sess, CMD_START))
+		return EIO;
+
+	return EOK;
+}
+
+int isdv4_read_events(isdv4_state_t *state)
+{
+	return read_packets(state, parse_event);
+}
+
+void isdv4_fini(isdv4_state_t *state)
+{
+	free(state->buf);
+}
Index: uspace/srv/hid/isdv4_tablet/isdv4.h
===================================================================
--- uspace/srv/hid/isdv4_tablet/isdv4.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/isdv4_tablet/isdv4.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#ifndef __ISDV4_H__
+#define __ISDV4_H__
+
+typedef struct isdv4_event isdv4_event_t;
+
+typedef void (*isdv4_event_fn)(const isdv4_event_t *);
+
+typedef struct {
+	/* Stylus information */
+	unsigned int stylus_max_x;
+	unsigned int stylus_max_y;
+	unsigned int stylus_max_pressure;
+	unsigned int stylus_max_xtilt;
+	unsigned int stylus_max_ytilt;
+	bool stylus_tilt_supported;
+
+	/* Touch information */
+	unsigned int touch_type;
+	unsigned int touch_max_x;
+	unsigned int touch_max_y;
+
+	/* Event state */
+	bool stylus_in_proximity;
+	bool stylus_is_eraser;
+	bool tip_pressed; /* Reported as stylus button 1 */
+	bool button1_pressed; /* Reported as stylus button 2 */
+	bool button2_pressed; /* Reported as stylus button 3 */
+	bool finger1_pressed; /* Reported as touch button 1 */
+
+	/* Session to the serial device */
+	async_sess_t *sess;
+
+	/* Receive buffer state */
+	uint8_t *buf;
+	size_t buf_size;
+	size_t buf_end;
+
+	/* Callbacks */
+	isdv4_event_fn emit_event_fn;
+} isdv4_state_t;
+
+typedef enum {
+	UNKNOWN, PRESS, RELEASE, PROXIMITY_IN, PROXIMITY_OUT, MOVE
+} isdv4_event_type_t;
+
+typedef enum {
+	STYLUS_TIP, STYLUS_ERASER, TOUCH
+} isdv4_source_type_t;
+
+typedef struct isdv4_event {
+	isdv4_event_type_t type;
+	isdv4_source_type_t source;
+	unsigned int x;
+	unsigned int y;
+	unsigned int pressure;
+	unsigned int button;
+} isdv4_event_t;
+
+extern int isdv4_init(isdv4_state_t *, async_sess_t *, isdv4_event_fn);
+extern int isdv4_init_tablet(isdv4_state_t *);
+extern int isdv4_read_events(isdv4_state_t *state);
+extern void isdv4_fini(isdv4_state_t *);
+
+#endif
Index: uspace/srv/hid/isdv4_tablet/main.c
===================================================================
--- uspace/srv/hid/isdv4_tablet/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/isdv4_tablet/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include <device/char_dev.h>
+#include <errno.h>
+#include <ipc/serial_ctl.h>
+#include <loc.h>
+#include <stdio.h>
+#include <fibril_synch.h>
+#include <abi/ipc/methods.h>
+#include <ipc/mouseev.h>
+#include <inttypes.h>
+
+#include "isdv4.h"
+
+#define NAME "isdv4_tablet"
+
+static async_sess_t *client_sess = NULL;
+static fibril_mutex_t client_mutex;
+static isdv4_state_t state;
+
+static void syntax_print(void)
+{
+	fprintf(stderr, "Usage: %s [--baud=<baud>] [--print-events] [device_service]\n", NAME);
+}
+
+static int read_fibril(void *unused)
+{
+	int rc = isdv4_read_events(&state);
+	if (rc != EOK) {
+		fprintf(stderr, "Failed reading events");
+		return rc;
+	}
+
+	isdv4_fini(&state);
+	return EOK;
+}
+
+static void mouse_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	async_answer_0(iid, EOK);
+	
+	async_sess_t *sess =
+	    async_callback_receive(EXCHANGE_SERIALIZE);
+	fibril_mutex_lock(&client_mutex);
+		if (client_sess == NULL) {
+			client_sess = sess;
+		}
+	fibril_mutex_unlock(&client_mutex);
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
+		async_answer_0(callid, ENOTSUP);
+	}
+}
+
+static void emit_event(const isdv4_event_t *event)
+{
+	fibril_mutex_lock(&client_mutex);
+	async_sess_t *sess = client_sess;
+	fibril_mutex_unlock(&client_mutex);
+	
+	if (!sess) return;
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (exch) {
+		unsigned int max_x = state.stylus_max_x;
+		unsigned int max_y = state.stylus_max_y;
+		if (event->source == TOUCH) {
+			max_x = state.touch_max_x;
+			max_y = state.touch_max_y;
+		}
+		async_msg_4(exch, MOUSEEV_ABS_MOVE_EVENT, event->x, event->y,
+				    max_x, max_y);
+		if (event->type == PRESS || event->type == RELEASE) {
+			async_msg_2(exch, MOUSEEV_BUTTON_EVENT, event->button,
+				    event->type == PRESS);
+		}
+	}
+	async_exchange_end(exch);
+}
+
+static void print_and_emit_event(const isdv4_event_t *event)
+{
+	const char *type = NULL;
+	switch (event->type) {
+		case PRESS:
+			type = "PRESS";
+			break;
+		case RELEASE:
+			type = "RELEASE";
+			break;
+		case PROXIMITY_IN:
+			type = "PROXIMITY IN";
+			break;
+		case PROXIMITY_OUT:
+			type = "PROXIMITY OUT";
+			break;
+		case MOVE:
+			type = "MOVE";
+			break;
+		default:
+			type = "UNKNOWN";
+			break;
+	}
+
+	const char *source = NULL;
+	switch (event->source) {
+		case STYLUS_TIP:
+			source = "stylus tip";
+			break;
+		case STYLUS_ERASER:
+			source = "stylus eraser";
+			break;
+		case TOUCH:
+			source = "touch";
+			break;
+	}
+
+	printf("%s %s %u %u %u %u\n", type, source, event->x, event->y,
+	    event->pressure, event->button);
+	
+	emit_event(event);
+}
+
+static const char *touch_type(unsigned int data_id)
+{
+	switch (data_id) {
+		case 0:
+			return "resistive+stylus";
+		case 1:
+			return "capacitive+stylus";
+		case 2:
+			return "resistive";
+		case 3:
+		case 4:
+			return "capacitive";
+		case 5:
+			return "penabled";
+	}
+	return "unknown";
+}
+
+int main(int argc, char **argv)
+{
+	sysarg_t baud = 38400;
+	service_id_t svc_id;
+	char *serial_port_name = NULL;
+
+	int arg = 1;
+	int rc;
+
+	isdv4_event_fn event_fn = emit_event;
+
+	if (argc > arg && str_test_prefix(argv[arg], "--baud=")) {
+		size_t arg_offset = str_lsize(argv[arg], 7);
+		char* arg_str = argv[arg] + arg_offset;
+		if (str_length(arg_str) == 0) {
+			fprintf(stderr, "--baud requires an argument\n");
+			syntax_print();
+			return 1;
+		}
+		char *endptr;
+		baud = strtol(arg_str, &endptr, 10);
+		if (*endptr != '\0') {
+			fprintf(stderr, "Invalid value for baud\n");
+			syntax_print();
+			return 1;
+		}
+		arg++;
+	}
+
+	if (argc > arg && str_cmp(argv[arg], "--print-events") == 0) {
+		event_fn = print_and_emit_event;
+		arg++;
+	}
+
+	if (argc > arg) {
+		serial_port_name = argv[arg];
+		rc = loc_service_get_id(serial_port_name, &svc_id, 0);
+		if (rc != EOK) {
+			fprintf(stderr, "Cannot find device service %s\n",
+			    argv[arg]);
+			return 1;
+		}
+		arg++;
+	}
+	else {
+		category_id_t serial_cat_id;
+
+		rc = loc_category_get_id("serial", &serial_cat_id, 0);
+		if (rc != EOK) {
+			fprintf(stderr, "Failed getting id of category "
+			    "'serial'\n");
+			return 1;
+		}
+
+		service_id_t *svc_ids;
+		size_t svc_count;
+
+		rc = loc_category_get_svcs(serial_cat_id, &svc_ids, &svc_count);		if (rc != EOK) {
+			fprintf(stderr, "Failed getting list of services\n");
+			return 1;
+		}
+
+		if (svc_count == 0) {
+			fprintf(stderr, "No service in category 'serial'\n");
+			free(svc_ids);
+			return 1;
+		}
+
+		svc_id = svc_ids[0];
+
+		rc = loc_service_get_name(svc_id, &serial_port_name);
+		if (rc != EOK) {
+			fprintf(stderr, "Failed getting name of serial service\n");
+			return 1;
+		}
+
+		free(svc_ids);
+	}
+
+	if (argc > arg) {
+		fprintf(stderr, "Too many arguments\n");
+		syntax_print();
+		return 1;
+	}
+
+	fibril_mutex_initialize(&client_mutex);
+
+	printf(NAME ": Using serial port %s\n", serial_port_name);
+
+	async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE, svc_id,
+	    IPC_FLAG_BLOCKING);
+	if (!sess) {
+		fprintf(stderr, "Failed connecting to service\n");
+	}
+
+	async_exch_t *exch = async_exchange_begin(sess);
+	rc = async_req_4_0(exch, SERIAL_SET_COM_PROPS, baud,
+	    SERIAL_NO_PARITY, 8, 1);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		fprintf(stderr, "Failed setting serial properties\n");
+		return 2;
+	}
+
+	rc = isdv4_init(&state, sess, event_fn);
+	if (rc != EOK) {
+		fprintf(stderr, "Failed initializing isdv4 state");
+		return 2;
+	}
+
+	rc = isdv4_init_tablet(&state);
+	if (rc != EOK) {
+		fprintf(stderr, "Failed initializing tablet");
+		return 2;
+	}
+
+	printf("Tablet information:\n");
+	printf(" Stylus: %ux%u pressure: %u tilt: ", state.stylus_max_x,
+	    state.stylus_max_y, state.stylus_max_pressure);
+	if (state.stylus_tilt_supported) {
+		printf("%ux%u\n", state.stylus_max_xtilt, state.stylus_max_ytilt);
+	}
+	else {
+		printf("not supported\n");
+	}
+	printf(" Touch: %ux%u type: %s\n", state.touch_max_x, state.touch_max_y,
+		touch_type(state.touch_type));
+	
+	fid_t fibril = fibril_create(read_fibril, NULL);
+	/* From this on, state is to be used only by read_fibril */
+	fibril_add_ready(fibril);
+
+	async_set_client_connection(mouse_connection);
+	rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		printf("%s: Unable to register driver.\n", NAME);
+		return rc;
+	}
+
+	service_id_t service_id;
+	char *service_name;
+	rc = asprintf(&service_name, "mouse/isdv4-%" PRIun, svc_id);
+	if (rc < 0) {
+		printf(NAME ": Unable to create service name\n");
+		return rc;
+	}
+
+	rc = loc_service_register(service_name, &service_id);
+	if (rc != EOK) {
+		printf(NAME ": Unable to register service %s.\n", service_name);
+		return rc;
+	}
+
+	category_id_t mouse_category;
+	rc = loc_category_get_id("mouse", &mouse_category, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		printf(NAME ": Unable to get mouse category id.\n");
+	}
+	else {
+		rc = loc_service_add_to_cat(service_id, mouse_category);
+		if (rc != EOK) {
+			printf(NAME ": Unable to add device to mouse category.\n");
+		}
+	}
+
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
Index: uspace/srv/hid/output/Makefile
===================================================================
--- uspace/srv/hid/output/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,42 @@
+#
+# 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 = output
+
+SOURCES = \
+	ctl/serial.c \
+	port/ega.c \
+	port/kchar.c \
+	port/niagara.c \
+	port/ski.c \
+	proto/vt100.c \
+	output.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/output/ctl/serial.c
===================================================================
--- uspace/srv/hid/output/ctl/serial.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/ctl/serial.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2008 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 console
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <io/chargrid.h>
+#include "../output.h"
+#include "../proto/vt100.h"
+#include "serial.h"
+
+#define SERIAL_COLS  80
+#define SERIAL_ROWS  24
+
+/** Draw the character at the specified position.
+ *
+ * @param state VT100 protocol state.
+ * @param field Character field.
+ * @param col   Horizontal screen position.
+ * @param row   Vertical screen position.
+ *
+ */
+static void draw_char(vt100_state_t *state, charfield_t *field,
+    sysarg_t col, sysarg_t row)
+{
+	vt100_goto(state, col, row);
+	vt100_set_attr(state, field->attrs);
+	vt100_putchar(state, field->ch);
+}
+
+static int serial_yield(outdev_t *dev)
+{
+	vt100_state_t *state = (vt100_state_t *) dev->data;
+	
+	return vt100_yield(state);
+}
+
+static int serial_claim(outdev_t *dev)
+{
+	vt100_state_t *state = (vt100_state_t *) dev->data;
+	
+	return vt100_claim(state);
+}
+
+static void serial_get_dimensions(outdev_t *dev, sysarg_t *cols,
+    sysarg_t *rows)
+{
+	vt100_state_t *state = (vt100_state_t *) dev->data;
+	
+	vt100_get_dimensions(state, cols, rows);
+}
+
+static console_caps_t serial_get_caps(outdev_t *dev)
+{
+	return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED);
+}
+
+static void serial_cursor_update(outdev_t *dev, sysarg_t prev_col,
+    sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
+{
+	vt100_state_t *state = (vt100_state_t *) dev->data;
+	
+	vt100_goto(state, col, row);
+	vt100_cursor_visibility(state, visible);
+}
+
+static void serial_char_update(outdev_t *dev, sysarg_t col, sysarg_t row)
+{
+	vt100_state_t *state = (vt100_state_t *) dev->data;
+	charfield_t *field =
+	    chargrid_charfield_at(dev->backbuf, col, row);
+	
+	draw_char(state, field, col, row);
+}
+
+static outdev_ops_t serial_ops = {
+	.yield = serial_yield,
+	.claim = serial_claim,
+	.get_dimensions = serial_get_dimensions,
+	.get_caps = serial_get_caps,
+	.cursor_update = serial_cursor_update,
+	.char_update = serial_char_update
+};
+
+int serial_init(vt100_putchar_t putchar_fn,
+    vt100_control_puts_t control_puts_fn)
+{
+	vt100_state_t *state =
+	    vt100_state_create(SERIAL_COLS, SERIAL_ROWS, putchar_fn,
+	    control_puts_fn);
+	if (state == NULL)
+		return ENOMEM;
+	
+	outdev_t *dev = outdev_register(&serial_ops, state);
+	if (dev == NULL) {
+		vt100_state_destroy(state);
+		return ENOMEM;
+	}
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/hid/output/ctl/serial.h
===================================================================
--- uspace/srv/hid/output/ctl/serial.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/ctl/serial.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2008 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.
+ */
+
+/** @file
+ */
+
+#ifndef OUTPUT_CTL_SERIAL_H_
+#define OUTPUT_CTL_SERIAL_H_
+
+#include "../proto/vt100.h"
+
+extern int serial_init(vt100_putchar_t, vt100_control_puts_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/output/gfx/font-8x16.c
===================================================================
--- uspace/srv/hid/output/gfx/font-8x16.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/gfx/font-8x16.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,3272 @@
+/*
+ * Copyright (c) 2000 Dmitry Bolkhovityanov
+ * Copyright (c) 2009 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 genarch
+ * @{
+ */
+/** @file
+ */
+
+#include <sys/types.h>
+#include "font-8x16.h"
+
+/** Convert character to font glyph index
+ *
+ * The font does not cover all Unicode characters.
+ * This function converts the character to an appropriate
+ * glyph in the font or returns an index to the question
+ * mark glyph if no specific glyph exists.
+ *
+ */
+uint16_t fb_font_glyph(const wchar_t ch)
+{
+	if (ch == 0x0000)
+		return 0;
+	
+	if ((ch >= 0x0020) && (ch <= 0x007f))
+		return (ch - 32);
+	
+	if ((ch >= 0x00a0) && (ch <= 0x021f))
+		return (ch - 64);
+	
+	if ((ch >= 0x0222) && (ch <= 0x0233))
+		return (ch - 66);
+	
+	if ((ch >= 0x0250) && (ch <= 0x02ad))
+		return (ch - 94);
+	
+	if ((ch >= 0x02b0) && (ch <= 0x02cf))
+		return (ch - 96);
+	
+	if ((ch >= 0x02d8) && (ch <= 0x02dd))
+		return (ch - 104);
+	
+	if (ch == 0x02ee)
+		return 630;
+	
+	if ((ch >= 0x0300) && (ch <= 0x0301))
+		return (ch - 137);
+	
+	if (ch == 0x0303)
+		return 633;
+	
+	if (ch == 0x0309)
+		return 634;
+	
+	if ((ch >= 0x0312) && (ch <= 0x0314))
+		return (ch - 151);
+	
+	if (ch == 0x0323)
+		return 638;
+	
+	if ((ch >= 0x0340) && (ch <= 0x0341))
+		return (ch - 193);
+	
+	if ((ch >= 0x0374) && (ch <= 0x0375))
+		return (ch - 243);
+	
+	if (ch == 0x037a)
+		return 643;
+	
+	if (ch == 0x037e)
+		return 644;
+	
+	if ((ch >= 0x0384) && (ch <= 0x038a))
+		return (ch - 255);
+	
+	if (ch == 0x038c)
+		return 652;
+	
+	if ((ch >= 0x038e) && (ch <= 0x03a1))
+		return (ch - 257);
+	
+	if ((ch >= 0x03a3) && (ch <= 0x03ce))
+		return (ch - 258);
+	
+	if ((ch >= 0x03d0) && (ch <= 0x03d7))
+		return (ch - 259);
+	
+	if ((ch >= 0x03da) && (ch <= 0x03f3))
+		return (ch - 261);
+	
+	if ((ch >= 0x0400) && (ch <= 0x0486))
+		return (ch - 273);
+	
+	if ((ch >= 0x0488) && (ch <= 0x04ce))
+		return (ch - 274);
+	
+	if ((ch >= 0x04d0) && (ch <= 0x04f5))
+		return (ch - 275);
+	
+	if ((ch >= 0x04f8) && (ch <= 0x04f9))
+		return (ch - 277);
+	
+	if ((ch >= 0x0500) && (ch <= 0x050f))
+		return (ch - 283);
+	
+	if ((ch >= 0x0530) && (ch <= 0x0556))
+		return (ch - 315);
+	
+	if ((ch >= 0x0559) && (ch <= 0x055f))
+		return (ch - 317);
+	
+	if ((ch >= 0x0561) && (ch <= 0x0587))
+		return (ch - 318);
+	
+	if ((ch >= 0x0589) && (ch <= 0x058a))
+		return (ch - 319);
+	
+	if ((ch >= 0x0591) && (ch <= 0x05a1))
+		return (ch - 325);
+	
+	if ((ch >= 0x05a3) && (ch <= 0x05b9))
+		return (ch - 326);
+	
+	if ((ch >= 0x05bb) && (ch <= 0x05c4))
+		return (ch - 327);
+	
+	if ((ch >= 0x05d0) && (ch <= 0x05ea))
+		return (ch - 338);
+	
+	if ((ch >= 0x05f0) && (ch <= 0x05f4))
+		return (ch - 343);
+	
+	if (ch == 0x060c)
+		return 1182;
+	
+	if (ch == 0x061b)
+		return 1183;
+	
+	if (ch == 0x061f)
+		return 1184;
+	
+	if ((ch >= 0x0621) && (ch <= 0x063a))
+		return (ch - 384);
+	
+	if ((ch >= 0x0640) && (ch <= 0x0655))
+		return (ch - 389);
+	
+	if ((ch >= 0x0660) && (ch <= 0x066d))
+		return (ch - 399);
+	
+	if ((ch >= 0x0670) && (ch <= 0x06ed))
+		return (ch - 401);
+	
+	if ((ch >= 0x06f0) && (ch <= 0x06fe))
+		return (ch - 403);
+	
+	if (ch == 0x10d3)
+		return 1388;
+	
+	if (ch == 0x10d7)
+		return 1389;
+	
+	if (ch == 0x10da)
+		return 1390;
+	
+	if (ch == 0x10dd)
+		return 1391;
+	
+	if (ch == 0x10e6)
+		return 1392;
+	
+	if ((ch >= 0x1e00) && (ch <= 0x1e9b))
+		return (ch - 6287);
+	
+	if ((ch >= 0x1ea0) && (ch <= 0x1ef9))
+		return (ch - 6291);
+	
+	if ((ch >= 0x1f00) && (ch <= 0x1f07))
+		return (ch - 6297);
+	
+	if ((ch >= 0x2000) && (ch <= 0x2027))
+		return (ch - 6545);
+	
+	if ((ch >= 0x2030) && (ch <= 0x2046))
+		return (ch - 6553);
+	
+	if ((ch >= 0x2048) && (ch <= 0x204d))
+		return (ch - 6554);
+	
+	if (ch == 0x2070)
+		return 1716;
+	
+	if ((ch >= 0x2074) && (ch <= 0x208f))
+		return (ch - 6591);
+	
+	if ((ch >= 0x20a0) && (ch <= 0x20af))
+		return (ch - 6607);
+	
+	if ((ch >= 0x2100) && (ch <= 0x213a))
+		return (ch - 6687);
+	
+	if ((ch >= 0x2153) && (ch <= 0x2183))
+		return (ch - 6711);
+	
+	if ((ch >= 0x2190) && (ch <= 0x21f3))
+		return (ch - 6723);
+	
+	if ((ch >= 0x2200) && (ch <= 0x22f1))
+		return (ch - 6735);
+	
+	if (ch == 0x2300)
+		return 2211;
+	
+	if (ch == 0x2302)
+		return 2212;
+	
+	if ((ch >= 0x2308) && (ch <= 0x230b))
+		return (ch - 6755);
+	
+	if (ch == 0x2310)
+		return 2217;
+	
+	if (ch == 0x2318)
+		return 2218;
+	
+	if ((ch >= 0x231a) && (ch <= 0x231b))
+		return (ch - 6767);
+	
+	if ((ch >= 0x2320) && (ch <= 0x2321))
+		return (ch - 6771);
+	
+	if ((ch >= 0x2329) && (ch <= 0x232a))
+		return (ch - 6778);
+	
+	if ((ch >= 0x239b) && (ch <= 0x23bd))
+		return (ch - 6890);
+	
+	if (ch == 0x23ce)
+		return 2260;
+	
+	if ((ch >= 0x2409) && (ch <= 0x240d))
+		return (ch - 6964);
+	
+	if ((ch >= 0x2423) && (ch <= 0x2424))
+		return (ch - 6985);
+	
+	if (ch == 0x2426)
+		return 2268;
+	
+	if ((ch >= 0x2500) && (ch <= 0x2595))
+		return (ch - 7203);
+	
+	if ((ch >= 0x25a0) && (ch <= 0x25f7))
+		return (ch - 7213);
+	
+	if ((ch >= 0x2600) && (ch <= 0x2602))
+		return (ch - 7221);
+	
+	if ((ch >= 0x2605) && (ch <= 0x260d))
+		return (ch - 7223);
+	
+	if ((ch >= 0x2610) && (ch <= 0x2613))
+		return (ch - 7225);
+	
+	if (ch == 0x2620)
+		return 2523;
+	
+	if (ch == 0x2622)
+		return 2524;
+	
+	if (ch == 0x2626)
+		return 2525;
+	
+	if ((ch >= 0x2628) && (ch <= 0x262b))
+		return (ch - 7242);
+	
+	if ((ch >= 0x262e) && (ch <= 0x2637))
+		return (ch - 7244);
+	
+	if ((ch >= 0x2639) && (ch <= 0x2653))
+		return (ch - 7245);
+	
+	if ((ch >= 0x2660) && (ch <= 0x2667))
+		return (ch - 7257);
+	
+	if ((ch >= 0x2669) && (ch <= 0x266f))
+		return (ch - 7258);
+	
+	if ((ch >= 0xfb00) && (ch <= 0xfb05))
+		return (ch - 61674);
+	
+	if ((ch >= 0xfb50) && (ch <= 0xfbb1))
+		return (ch - 61748);
+	
+	if ((ch >= 0xfbd3) && (ch <= 0xfbe9))
+		return (ch - 61781);
+	
+	if ((ch >= 0xfbfc) && (ch <= 0xfbff))
+		return (ch - 61799);
+	
+	if ((ch >= 0xfc5b) && (ch <= 0xfc63))
+		return (ch - 61890);
+	
+	if (ch == 0xfc90)
+		return 2722;
+	
+	if ((ch >= 0xfcf2) && (ch <= 0xfcf4))
+		return (ch - 62031);
+	
+	if ((ch >= 0xfd3c) && (ch <= 0xfd3f))
+		return (ch - 62102);
+	
+	if (ch == 0xfdf2)
+		return 2730;
+	
+	if ((ch >= 0xfe50) && (ch <= 0xfe52))
+		return (ch - 62373);
+	
+	if ((ch >= 0xfe54) && (ch <= 0xfe66))
+		return (ch - 62374);
+	
+	if ((ch >= 0xfe68) && (ch <= 0xfe6b))
+		return (ch - 62375);
+	
+	if ((ch >= 0xfe70) && (ch <= 0xfe72))
+		return (ch - 62379);
+	
+	if (ch == 0xfe74)
+		return 2760;
+	
+	if ((ch >= 0xfe76) && (ch <= 0xfefc))
+		return (ch - 62381);
+	
+	if (ch == 0xfeff)
+		return 2896;
+	
+	return 2898;
+}
+
+uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES] = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x30, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00},
+	{0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x99, 0xa5, 0xa1, 0xa1, 0xa5, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x44, 0xba, 0xb2, 0xaa, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd8, 0x30, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf6, 0xc0, 0xc0, 0xc0, 0x00},
+	{0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00},
+	{0x00, 0xe0, 0x30, 0x62, 0x36, 0xec, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x0c, 0x38, 0x00},
+	{0x30, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x18, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x3c, 0x42, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7a, 0xc4, 0xce, 0xce, 0xd6, 0xd6, 0xe6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x66, 0x66, 0xec, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0x1c, 0x3c, 0x06, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xc4, 0xce, 0xd6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x7c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x0c, 0x18, 0x0e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x0c, 0x18, 0x0e, 0x00},
+	{0x0c, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x3e, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x18, 0x30, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x6c, 0x38, 0x10, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x6c, 0x38, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x18, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x18, 0x30, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x10, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0xff, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0xf8, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7e, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7e, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x3c, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x3c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x30, 0x1c, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x30, 0x1c, 0x00},
+	{0x18, 0x18, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf7, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7b, 0x7b, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x00, 0xee, 0x66, 0x66, 0x66, 0x66, 0x66, 0xf6, 0x06, 0x66, 0x3c, 0x00},
+	{0x08, 0x1c, 0x22, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x04, 0x0e, 0x1b, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x30, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x30},
+	{0x6c, 0x38, 0x10, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x66, 0x66, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0x30, 0x30, 0x30, 0x36, 0x36, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x78, 0xe0, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x1e, 0x78, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x18, 0x18, 0x30},
+	{0x6c, 0x38, 0x10, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x60, 0x60, 0xc0, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0xcc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0xcc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6e, 0xd8, 0xd8, 0xd8, 0xde, 0xd8, 0xd8, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xd6, 0xd6, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x18, 0x18, 0x30},
+	{0x6c, 0x38, 0x10, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x6c, 0x38, 0x10, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x18, 0x0c, 0x38, 0x00},
+	{0x6c, 0x38, 0x10, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x10, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0xfc, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x78, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x78, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x38, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x38, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0xcc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x30, 0x60, 0x38, 0x00},
+	{0x10, 0x38, 0x44, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0xf8, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0xb3, 0xb3, 0x33, 0x3e, 0x33, 0x33, 0x33, 0x33, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x64, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x62, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xe6, 0xe6, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0xe0, 0xe0, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x06, 0x06, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x03, 0x3e, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x03, 0x7e, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0xf6, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xb6, 0xb3, 0x33, 0x33, 0x33, 0x33, 0x33, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x4c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0x4c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x18, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0xfe, 0xcc, 0x8c, 0x2c, 0x3c, 0x2c, 0x0c, 0x8c, 0xcc, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x06, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc2, 0xc0, 0x78, 0xc0, 0xc0, 0xc2, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xc0, 0x00},
+	{0x00, 0x00, 0x1c, 0x36, 0x32, 0x30, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x00},
+	{0x00, 0x03, 0x3e, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x38, 0x6c, 0x38, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xf3, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x6d, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc8, 0x38, 0x70, 0xd0, 0x38, 0x38, 0x6c, 0x64, 0xc6, 0xc2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0xec, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x76, 0x7e, 0x7e, 0x6e, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0xc0, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x73, 0xdf, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x03, 0x03, 0x03, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0xdf, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x03, 0x03, 0x03, 0x00},
+	{0x00, 0x00, 0x7e, 0xb3, 0xb3, 0x33, 0x3e, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x78, 0x6c, 0x6c, 0xe6, 0x06, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x38, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x0c, 0x38, 0x60, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x62, 0x30, 0x18, 0x18, 0x30, 0x62, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd8, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x0c, 0x6c, 0x38, 0x00},
+	{0x00, 0x00, 0x7e, 0xfe, 0x9a, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x36, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00},
+	{0x03, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xee, 0x6c, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x63, 0xb3, 0xb3, 0x33, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x06, 0x0d, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0xf0, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x7e, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0xfc, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x7c, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc0, 0x60, 0x30, 0x18, 0x7c, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x60, 0x30, 0x78, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x7c, 0xc0, 0xc6, 0x7c, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x7e, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x60, 0x60, 0x78, 0x0c, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x60, 0x78, 0x0c, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x18, 0x4c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x70, 0x60, 0x60, 0xf0, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x1b, 0x0e, 0x04, 0xf7, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf5, 0xda, 0xd8, 0xdf, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3d, 0x1a, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0x6f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xcb, 0xf6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf3, 0x63, 0x60, 0x67, 0x63, 0x63, 0x63, 0x67, 0x6f, 0xff, 0x03, 0x1b, 0x0e, 0x00},
+	{0x00, 0x00, 0xe3, 0x63, 0x60, 0x67, 0x63, 0x63, 0x63, 0x63, 0x63, 0xf3, 0x03, 0x33, 0x1e, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xfb, 0xfb, 0xfb, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xf8, 0xff, 0xfb, 0xfb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x33, 0x1e, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x00, 0xb7, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x33, 0x1e, 0x00},
+	{0x6c, 0x38, 0x10, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x00, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x78, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x10, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x30, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x28, 0x10, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x78, 0x30, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x10, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x00, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x30, 0x30, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xdf, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x3e, 0xcc, 0x78, 0x00},
+	{0x6c, 0x38, 0x10, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x6c, 0x38, 0x10, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x6c, 0x38, 0x10, 0xfe, 0x0c, 0x18, 0x30, 0x7c, 0x06, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00},
+	{0x00, 0x1b, 0x0e, 0x04, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
+	{0x00, 0x00, 0xf7, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xdc, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0xd8, 0xd8, 0xdf, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0xf7, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0x6f, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xdb, 0xfb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x70, 0x60, 0x60, 0x60, 0x60, 0xe0, 0x00},
+	{0x60, 0x30, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x38, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x38, 0x6c, 0x38, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x7a, 0xc4, 0xce, 0xce, 0xd6, 0xe6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7a, 0xc4, 0xce, 0xd6, 0xe6, 0x46, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x3c, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x18, 0x18, 0x30},
+	{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x1c, 0x74, 0x06, 0x06, 0x06, 0x06, 0x1c, 0xf0, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0e, 0x3c, 0x06, 0x06, 0x1c, 0xf0, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc0, 0xfc, 0x06, 0x0c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc0, 0xfc, 0x06, 0x0c, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x7c, 0x00, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x00, 0x72, 0x9c, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x00, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x5c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xdc, 0xe6, 0x7c, 0x80, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0d, 0x06, 0x00},
+	{0x00, 0x00, 0x06, 0x0d, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x6c, 0x8e, 0x16, 0x26, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xcd, 0x0d, 0x38, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xdc, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x06, 0x06, 0x1f, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
+	{0x00, 0x00, 0x00, 0x06, 0x0d, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x46, 0x6c, 0x2c, 0x2c, 0x38, 0x18, 0x18, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x64, 0x28, 0x38, 0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xdc, 0x6c, 0x0c, 0x0c, 0x0e, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x7b, 0xde, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x78, 0x58, 0x3e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x7f, 0x63, 0x66, 0x6c, 0x7e, 0x63, 0xf3, 0x03, 0x33, 0x1e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6e, 0x06, 0x06, 0x06, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0xc0, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x03, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xd8, 0xd8, 0xde, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xdc, 0x6c, 0x0c, 0x0d, 0x06, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0x60, 0x60, 0x6c, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x66, 0x6c, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xfc, 0xc0, 0xd8, 0x70, 0x00},
+	{0x00, 0x00, 0x0e, 0x1b, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x98, 0xd8, 0x70, 0x00},
+	{0x00, 0x00, 0x0e, 0x1b, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x98, 0xd8, 0x70, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0xd8, 0x70, 0x00},
+	{0x00, 0x00, 0x70, 0xd8, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x3b, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3e, 0x60, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x06, 0x06, 0x03, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xcb, 0xfe, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x7e, 0xc7, 0x7c, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0x70, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x76, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x03, 0x7e, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x0c, 0x00, 0x1c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7e, 0xcc, 0x78, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xcc, 0x6c, 0x3c, 0x3c, 0x6c, 0xcc, 0x0c, 0x0c, 0x0e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x06, 0x0d, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x1c, 0x18, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0x70, 0x30, 0xfc, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xda, 0xdc, 0x6f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xdb, 0xdb, 0xde, 0xde, 0xdb, 0x6b, 0x03, 0x1b, 0x0e, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x7f, 0xd9, 0xda, 0xda, 0xdb, 0xdd, 0x6f, 0x04, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x60, 0x60, 0xf6, 0x6d, 0x6c, 0x66, 0x63, 0x6b, 0x36, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x26, 0x6d, 0x6c, 0xfc, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x3c, 0x0c, 0x2c, 0x18, 0x00},
+	{0x00, 0x00, 0x20, 0x60, 0x60, 0xf6, 0x6d, 0x6c, 0x6c, 0x6e, 0x6d, 0x36, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd8, 0xc0, 0xfe, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x03, 0x0e, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6d, 0x6c, 0x66, 0x63, 0x6b, 0xf6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6f, 0x6b, 0x63, 0x66, 0x6c, 0x6d, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xd6, 0x7c, 0x6c, 0x28, 0xc6, 0xd6, 0x7c, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xf0, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xc0, 0xf0, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xb0, 0xd8, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x18, 0xd8, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x18, 0xd8, 0x68, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xd8, 0xd8, 0xf0, 0xd8, 0xd8, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc6, 0xd6, 0x7c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xd8, 0xd8, 0x78, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd8, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd8, 0xc0, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x70, 0xc0, 0x70, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0x70, 0x18, 0x70, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x20, 0x20, 0x70, 0x70, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xd8, 0xd8, 0x70, 0x70, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x1c, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x6c, 0x6c, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x34, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00},
+	{0xc0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x34, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x3e, 0x32, 0x30, 0x34, 0x3c, 0x34, 0x30, 0x30, 0x32, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x33, 0x33, 0x33, 0x33, 0x3f, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x36, 0x36, 0x77, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x82, 0x44, 0x7c, 0x44, 0x00, 0x82, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x62, 0x30, 0x18, 0x18, 0x30, 0x62, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x92, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x6c, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x6c, 0x60, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x46, 0x6c, 0x2c, 0x2c, 0x38, 0x18, 0x18, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x30, 0x18, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x46, 0x7c, 0x18, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0x20, 0x30, 0x10, 0x38, 0x38, 0x6c, 0x64, 0xc6, 0xc2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf6, 0xc0, 0xc0, 0xc0, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x66, 0x6c, 0x3c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x3c, 0x30, 0x60, 0x3c, 0x60, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x46, 0x2c, 0x2c, 0x18, 0x30, 0x68, 0x68, 0xc4, 0xc2, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xcc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x6c, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x36, 0x1e, 0xc6, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc2, 0x65, 0x24, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x21, 0x32, 0x12, 0x1c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc2, 0x65, 0x24, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xa6, 0x2c, 0x38, 0x68, 0xca, 0xc4, 0x0c, 0x18, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x3c, 0x06, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x7c, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x32, 0x30, 0x30, 0x3c, 0x34, 0x30, 0x30, 0x30, 0x30, 0x00},
+	{0x00, 0x60, 0x30, 0x30, 0x60, 0x63, 0xff, 0xc6, 0x06, 0x0c, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x60, 0x60, 0xfe, 0xfe, 0x0c, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xac, 0x26, 0x26, 0x0b, 0x0b, 0x1b, 0x1b, 0x1b, 0x1b, 0x03, 0x02, 0x04, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x28, 0x4c, 0x14, 0x24, 0x06, 0x02, 0x02, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6d, 0x03, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6d, 0x03, 0x7e, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xd6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x06, 0x76, 0x9c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x7c, 0xd6, 0x66, 0x06, 0x06, 0x66, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x06, 0x3c, 0x60, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x26, 0x1c, 0x70, 0xc0, 0xc2, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0x68, 0x38, 0x30, 0x38, 0x38, 0x4c, 0x4c, 0x86, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xba, 0x30, 0x38, 0x28, 0x4c, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0xc0, 0xcc, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xdc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x7e, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x1c, 0x18, 0x7e, 0x58, 0x18, 0x18, 0x18, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xa6, 0x2c, 0x38, 0x68, 0xca, 0xc4, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0xc0, 0x60, 0x3c, 0x06, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
+	{0x30, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xb2, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x03, 0x06, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xf8, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xd8, 0xd8, 0xd8, 0xde, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xd8, 0xfe, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xb2, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x18, 0x00, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x38, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfe, 0xc6, 0x82, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0xc6, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfe, 0x06, 0x02, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xff, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0xb0, 0xb0, 0x30, 0x3c, 0x36, 0x36, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x3e, 0x06, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x9c, 0xb6, 0xb6, 0xb6, 0xf6, 0xb6, 0xb6, 0xb6, 0xb6, 0x9c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0xcc, 0xcc, 0xcc, 0x7c, 0x6c, 0x6c, 0x6c, 0x6c, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x7c, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfe, 0xc6, 0x82, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfe, 0x06, 0x02, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xff, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb0, 0x30, 0x3c, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3e, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xb6, 0xb6, 0xf6, 0xb6, 0xb6, 0x9c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xcc, 0xcc, 0x7c, 0x6c, 0x6c, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0xf8, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x06, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xf8, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xd8, 0xd8, 0xde, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xfe, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0xf8, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x38, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0xfc, 0xb4, 0x30, 0x3c, 0x36, 0x36, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x30, 0xfc, 0xb4, 0x30, 0x3c, 0x36, 0x36, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xce, 0xdb, 0xd9, 0xd8, 0xfe, 0xd8, 0xd8, 0xd9, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xdb, 0xd8, 0xfe, 0xd8, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0x6c, 0xfe, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x6c, 0x7c, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x88, 0x8c, 0x9c, 0x96, 0xf6, 0xb6, 0xbf, 0xab, 0xeb, 0xeb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x8c, 0x9c, 0xf6, 0xbe, 0xab, 0xeb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x6c, 0x6c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x6c, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0xa3, 0xb2, 0x96, 0xfc, 0x9c, 0xbe, 0xaa, 0xab, 0xeb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xa3, 0x96, 0xfe, 0xab, 0xab, 0xeb, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x10, 0x7c, 0xc6, 0x06, 0x06, 0x7c, 0x06, 0x06, 0x06, 0x7c, 0xc0, 0x7c, 0x00, 0x00},
+	{0x00, 0x6c, 0x38, 0x10, 0x00, 0x7c, 0x86, 0x06, 0x7c, 0x06, 0x06, 0x7c, 0xc0, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x96, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x10, 0x96, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc2, 0xc6, 0xc6, 0xc4, 0xcc, 0x6c, 0x68, 0x78, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x64, 0x6c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0x66, 0x00, 0xc2, 0xc6, 0xc4, 0xc4, 0x6c, 0x68, 0x78, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0x66, 0x00, 0xc2, 0xc6, 0x64, 0x6c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd8, 0xd8, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6f, 0x03, 0x06, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x6f, 0x03, 0x06, 0x1c, 0x00},
+	{0x00, 0x10, 0x7c, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x7c, 0xd6, 0xc6, 0xc6, 0xc6, 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x00},
+	{0x04, 0x7c, 0x40, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x04, 0x7c, 0x40, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x7c, 0x54, 0x00, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0x54, 0x00, 0x6c, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x60, 0x3c, 0x0c, 0x0c, 0x0c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0x78, 0x18, 0x18, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x06, 0x3c, 0x0f, 0x18, 0x18, 0xf0, 0x3c, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x04, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x40, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x04, 0x7c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x66, 0x00, 0xc3, 0x00, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x50, 0x46, 0x00, 0x82, 0x41, 0x00, 0x62, 0x0a, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0xc6, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x6e, 0x64, 0x7a, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x6e, 0x64, 0x7a, 0x60, 0x60, 0xf0, 0x00},
+	{0x02, 0x06, 0xfe, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x02, 0x06, 0xfe, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0xf8, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0xf8, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xf6, 0x06, 0x16, 0x0c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x78, 0x6c, 0x66, 0xf6, 0x06, 0x16, 0x0c, 0x00},
+	{0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x30, 0x60, 0x38, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xdc, 0xf8, 0xdc, 0xd6, 0xd6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xdc, 0xf8, 0xdc, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0xf6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0xf0, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf3, 0xb3, 0xb3, 0x36, 0x3c, 0x3c, 0x36, 0x33, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0xb6, 0xbc, 0x3c, 0x36, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xdf, 0xdb, 0xd9, 0xd8, 0xf8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xdb, 0xd9, 0xf8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0xd8, 0xd8, 0xd8, 0xde, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x03, 0x0b, 0x06, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xfe, 0xdb, 0xdb, 0xdb, 0x03, 0x0b, 0x06, 0x00},
+	{0x00, 0x00, 0x7c, 0xc2, 0xcc, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xcc, 0x7a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc2, 0xcc, 0xd6, 0xd6, 0xcc, 0x7a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x0c, 0x04, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x0c, 0x04, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x3c, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xf6, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7f, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7f, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0x7e, 0x16, 0x16, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0x7e, 0x16, 0x16, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x33, 0xb3, 0xb3, 0x7f, 0x30, 0x30, 0x30, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xb3, 0x7f, 0x30, 0x30, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x33, 0xb3, 0xb3, 0x7f, 0x30, 0x30, 0x30, 0x33, 0x1e, 0x0c, 0x18, 0x0e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xb3, 0x7f, 0x30, 0x30, 0x33, 0x1e, 0x0c, 0x18, 0x0e, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x06, 0x16, 0x0c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x06, 0x16, 0x0c, 0x00},
+	{0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x06, 0x16, 0x0c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x06, 0x16, 0x0c, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0e, 0x0c, 0x08, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0e, 0x0c, 0x08, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc7, 0x03, 0x01, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x06, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0xfe, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0x38, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xd6, 0xd6, 0xd6, 0x7c, 0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x86, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x0c, 0x18, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00},
+	{0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xce, 0xde, 0xfe, 0xf6, 0xe6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x3e, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0xc6, 0x06, 0x3e, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x66, 0xcc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0xcc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc3, 0xc3, 0xc3, 0xf3, 0xdb, 0xdb, 0xf3, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x7c, 0xcd, 0xcd, 0xcd, 0xcd, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcd, 0xcd, 0xcd, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0x8c, 0x0c, 0x38, 0x0d, 0x0d, 0x0d, 0x0d, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0x0c, 0x39, 0x0d, 0x0d, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0x86, 0x06, 0x3c, 0x06, 0x06, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0xcd, 0xcd, 0xcd, 0xcd, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xfd, 0xcd, 0xcd, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xce, 0xc6, 0xc6, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x1b, 0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5a, 0x18, 0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x64, 0x94, 0xba, 0x52, 0x4c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x7b, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x7f, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x7e, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x0c, 0xd8, 0xfe, 0xc3, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x06, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xcf, 0xd6, 0xd6, 0xd6, 0xd6, 0xcc, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x7f, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7c, 0x06, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xf6, 0xd6, 0xd6, 0xd6, 0xd6, 0xcc, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0x7f, 0x24, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0xf0, 0x3c, 0x0e, 0x04, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x6c, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0c, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x30, 0x60, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcf, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x7c, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x60, 0x60, 0x60, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x06, 0x06, 0x06, 0x6c, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x16, 0x16, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x76, 0x1e, 0x0e, 0x0c, 0xd8, 0xfe, 0xc3, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x30, 0x18, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x63, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xfe, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd0, 0xd0, 0xd0, 0x7c, 0x16, 0x16, 0x16, 0xd6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x06, 0x3c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x1c, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x6a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7f, 0x0c, 0x0c, 0x0c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x0c, 0x0c, 0x0c, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x0f, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x0c, 0x18, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x7e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xcf, 0xd6, 0xd6, 0xcc, 0xc0, 0xc0, 0xc0, 0x00},
+	{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x7f, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3e, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xf6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xca, 0xc0, 0xc0, 0xc0, 0x00},
+	{0x00, 0x00, 0x60, 0x38, 0x0c, 0x7f, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x1c, 0x0c, 0x18, 0x3c, 0x64, 0x66, 0x62, 0x63, 0x3d, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0c, 0x0c, 0x0f, 0x00},
+	{0x00, 0x00, 0x0e, 0x18, 0x30, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0f, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x3e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x3e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x7e, 0x06, 0x06, 0x06, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x76, 0x1c, 0x18, 0x30, 0x60, 0x3e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcf, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x0f, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x10, 0xdc, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0x76, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xfe, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xd0, 0xd0, 0x7c, 0x16, 0x16, 0x16, 0x16, 0xd6, 0x7c, 0x10, 0x10, 0x10, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xcc, 0xcc, 0xcc, 0xcc, 0x77, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x6c},
+	{0x18, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x38, 0x10, 0x38, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x60, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x0c, 0x00},
+	{0x10, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x74, 0xd6, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xc0, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x03, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x18, 0x30, 0x00},
+	{0x0c, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1b, 0x36, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x44, 0xaa, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x0a, 0x0c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0x50, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x3c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x6c, 0xd8, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x08, 0x30},
+	{0x60, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0xa0, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0x10, 0x10},
+	{0x18, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x06, 0x03, 0x00},
+	{0x48, 0xa8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x33, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x06, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x60, 0x66, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18},
+	{0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x18, 0x03, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x66, 0x76, 0xdc, 0xcc, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x0c, 0x0c, 0x1c, 0x36, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xcc, 0xd6, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0xc6, 0xc6, 0xc6, 0xc6, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xee, 0x66, 0x66, 0x66, 0x66, 0x66, 0x2c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x4c, 0xcc, 0xcc, 0xec, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x46, 0xc6, 0xc6, 0xe6, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xee, 0x66, 0x66, 0x6c, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x70, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xee, 0x66, 0x66, 0x34, 0x18, 0x0c, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x66, 0x64, 0x6c, 0x6e, 0x60, 0x60, 0x60, 0x60, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xf6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x66, 0x66, 0xc6, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x20, 0x1e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x02, 0x3c, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x20, 0x1c, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x18, 0x20, 0x1c, 0x20, 0x00, 0x00},
+	{0x00, 0x30, 0x40, 0x38, 0x40, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x28, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x88, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x20, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x40, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x40, 0x30, 0x4e, 0x49, 0x39, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x24, 0x00},
+	{0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x12, 0xca, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00},
+	{0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x14, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00},
+	{0x0a, 0x2a, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x01, 0x7e, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x10, 0x0c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x10, 0x0c, 0x10},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x70, 0x70, 0x38, 0x18, 0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x44, 0xfc, 0xf8, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x4a, 0xfe, 0xf4, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x20, 0x40, 0x30, 0x10, 0x20, 0x42, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x2c, 0x44, 0x42, 0x82, 0x82, 0xfe, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xf8, 0x78, 0x08, 0x08, 0x08, 0x0c, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x82, 0xc6, 0xc6, 0x6c, 0x28, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x10, 0x38, 0x28, 0x6c, 0xc6, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xf8, 0x88, 0xf8, 0x78, 0x08, 0x0c, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x91, 0x92, 0x64, 0x08, 0x10, 0x26, 0x49, 0x89, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x18, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0xfe, 0x7c, 0x38, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x06, 0x29, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x06, 0x28, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x06, 0x28, 0x5e, 0x00, 0x00, 0x00},
+	{0x00, 0x07, 0x08, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x04, 0x03, 0x14, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x04, 0x03, 0x04, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x23, 0x54, 0x33, 0x24, 0x40, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x04, 0x03, 0x04, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0x81, 0x7e, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x08, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00},
+	{0x06, 0x08, 0x06, 0x08, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x08, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x94, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x88, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x94, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x20, 0x38, 0x28, 0x70, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x38, 0x28, 0x70, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x00, 0x08, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x00, 0x14, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x08, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x1c, 0x6a, 0x04, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x14, 0x08, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x12, 0x04, 0x18, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x15, 0x88, 0x88, 0x8a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x88, 0x90, 0x65, 0x00, 0x02, 0x00, 0x00, 0x00},
+	{0x00, 0x04, 0x00, 0x0a, 0x00, 0x01, 0x15, 0x88, 0x88, 0x90, 0x65, 0x00, 0x02, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x90, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x2a, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x00, 0x50, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x00},
+	{0x0a, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x00, 0x01, 0x02, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x20, 0x40, 0x3e, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x01, 0x02, 0x05, 0x0b, 0x48, 0x84, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x00, 0x29, 0x01, 0x19, 0x21, 0x19, 0xa1, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x05, 0x0b, 0x48, 0x84, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xa4, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x44, 0x09, 0xa2, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x08, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x02, 0x2a, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x14, 0x00, 0x08, 0x00},
+	{0x00, 0x08, 0x00, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x04, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x08, 0x14, 0x08, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0x3c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x38, 0x40, 0x38, 0x40, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x40, 0x38, 0x40, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x12, 0x2c, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x3c, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x28, 0x18, 0x10, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x08, 0x08, 0x08, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x20, 0x47, 0x88, 0x08, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x50, 0x20, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x08, 0x00, 0x08},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x14, 0x00, 0x08},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x80, 0x60, 0x80, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0x40, 0x43, 0x55, 0x7e, 0x80, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x2a, 0x20, 0x26, 0x2a, 0x7c, 0x80, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0e, 0x1c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x14, 0x08, 0x14, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x2c, 0x10, 0x28, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x15, 0x8a, 0x90, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x5a, 0xa5, 0x66, 0x5b, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x5a, 0x66, 0xa5, 0x5a, 0x00},
+	{0x00, 0x00, 0x18, 0x66, 0x42, 0x42, 0x81, 0x99, 0x99, 0x81, 0x42, 0x42, 0x66, 0x18, 0x00, 0x00},
+	{0x08, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x26, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0c, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x8a, 0x90, 0x60},
+	{0x32, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x0c, 0x04, 0x08, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x30, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x28, 0x54, 0xaa, 0x92, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x82, 0xfe, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x14, 0x08},
+	{0x08, 0x14, 0x22, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x10, 0x10, 0x10},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x70, 0x70, 0x38, 0x18, 0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x44, 0xfc, 0xf8, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x4a, 0xfe, 0xf4, 0x60, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x4e, 0xf0, 0xfe, 0x7c, 0x30, 0x30, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x38, 0x2c, 0x44, 0x42, 0x82, 0x92, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x60, 0x7e, 0x3c, 0x30, 0x60, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x82, 0xc6, 0xc6, 0x6c, 0x28, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x10, 0x38, 0x28, 0x6c, 0xc6, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xf8, 0x88, 0xf8, 0x78, 0x08, 0x0c, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x88, 0x88, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x40, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x88, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x20, 0x1e, 0x20, 0x00, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x3c, 0x40, 0x54, 0x54, 0x54, 0x54, 0x40, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x92, 0x92, 0x4c, 0x30, 0x4c, 0x02, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0xaa, 0xaa, 0xaa, 0x82, 0x82, 0x40, 0x30, 0x4c, 0x02, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x82, 0x82, 0x44, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x92, 0x92, 0x82, 0x82, 0x40, 0x30, 0x4c, 0x02, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x38, 0x6c, 0x38},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x38, 0x6c, 0x38},
+	{0x18, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x0c, 0xec, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x7c, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x30, 0x30, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x60, 0x0c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x30, 0x18, 0x70, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x30, 0x18, 0x70, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x10, 0x38, 0x6c, 0x00},
+	{0x60, 0x30, 0x00, 0x7c, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x7c, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x76, 0xdc, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x76, 0xdc, 0x00},
+	{0x6c, 0x38, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x18, 0x0c, 0x38, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x0c, 0x38, 0x00},
+	{0x18, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0x38, 0x6c, 0x64, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00},
+	{0x30, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0c, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x60, 0x30, 0xe0, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x30, 0x18, 0x70, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x6c, 0x38, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x6c, 0x38, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x76, 0xdc, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x76, 0xdc, 0x00},
+	{0x0c, 0x18, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x0c, 0xec, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x7c, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x7c, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x7e, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x10, 0x38, 0x6c, 0x00},
+	{0x0c, 0x18, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x30, 0x30, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x10, 0x38, 0x6c, 0x00},
+	{0x0c, 0x18, 0x72, 0x9c, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x00, 0x72, 0x9c, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+	{0x18, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00},
+	{0x18, 0x18, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x7c, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x7c, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x60, 0x6c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0x70, 0x1c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x60, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x44, 0x38, 0x10, 0x7c, 0xc6, 0xc6, 0x70, 0x1c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x44, 0x38, 0x10, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x18, 0x18, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x06, 0x16, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x7e, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x7e, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x08, 0x1c, 0x36, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x6c, 0x6c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x6c, 0x6c, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x76, 0xdc, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x76, 0xdc, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x10, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x10, 0x38, 0x6c, 0x00},
+	{0x0c, 0x18, 0x72, 0x9c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x76, 0xdc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x00, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0xcc, 0xcc, 0x00, 0xfc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x18, 0x18, 0x00},
+	{0x60, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x30, 0x30, 0x00},
+	{0x30, 0x30, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x10, 0x38, 0x44, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0x00, 0x00},
+	{0x6c, 0x6c, 0x00, 0x10, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x6c, 0x38, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x18, 0x0c, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x30, 0x00, 0x38, 0x6c, 0x64, 0x60, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
+	{0x38, 0x0c, 0x18, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x0c, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x16, 0x38, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x16, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0xc0, 0x68, 0x1c, 0x36, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0xc0, 0x68, 0x1c, 0x36, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x13, 0x3a, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x10, 0x28, 0x54, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x10, 0x38, 0x44, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x6c, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
+	{0x0c, 0x18, 0x44, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x18, 0x44, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x44, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x30, 0x44, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x08, 0x54, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x08, 0x54, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x72, 0x9c, 0x44, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x72, 0x9c, 0x44, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x6c, 0x38, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x38, 0x0c, 0x18, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x23, 0x76, 0x88, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x26, 0x70, 0xd8, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0xc4, 0x6e, 0x11, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0xc0, 0x64, 0x0e, 0x1b, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x10, 0x38, 0x44, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x10, 0x38, 0x44, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x38, 0x0c, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x38, 0x0c, 0x18, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x0c, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x23, 0x76, 0x88, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x26, 0x70, 0xd8, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0xc4, 0x6e, 0x11, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0xc0, 0x64, 0x0e, 0x1b, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x13, 0x3a, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x13, 0x3a, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x10, 0x28, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x76, 0xdc, 0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x38, 0x44, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x18, 0x33, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1b, 0x33, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x33, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x63, 0x33, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x70, 0x1b, 0x33, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0x1b, 0x33, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x68, 0xb3, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x68, 0xb3, 0x03, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x03, 0x7a, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x06, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
+	{0x38, 0x0c, 0x18, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0x18, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x33, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1b, 0x33, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x33, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x63, 0x33, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x70, 0x1b, 0x33, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0x1b, 0x33, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x68, 0xb3, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x68, 0xb3, 0x03, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x03, 0x03, 0xce, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x30, 0x30, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x06, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x00},
+	{0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x18, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x0c, 0x18, 0xf6, 0x06, 0x00},
+	{0x38, 0x0c, 0x18, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x38, 0x0c, 0x18, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x3a, 0x5c, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x76, 0xdc, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00},
+	{0x00, 0x18, 0x18, 0x30, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x30, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x60, 0x6c, 0xc6, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xcc, 0x66, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x60, 0x66, 0xcc, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xc6, 0x6c, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x34, 0x58, 0x0c, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x34, 0x58, 0x30, 0x18, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0xfe, 0x00, 0xa4, 0xaa, 0xea, 0xea, 0xa6, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xa4, 0xea, 0xaa, 0xaa, 0xa6, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xea, 0x8a, 0xce, 0x8e, 0xea, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xea, 0x8e, 0xca, 0x8a, 0xea, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xca, 0x2e, 0x4a, 0x2a, 0xca, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xaa, 0xae, 0xea, 0x2a, 0x2a, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0x6a, 0x8e, 0xca, 0xaa, 0x4a, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0x38, 0x20, 0x30, 0x20, 0x20, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0x30, 0x28, 0x30, 0x20, 0x20, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xea, 0x4a, 0x4e, 0x4a, 0x4a, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0x28, 0x28, 0x38, 0x28, 0x28, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xea, 0x2a, 0x4e, 0x8e, 0xee, 0x00, 0x6c, 0x8a, 0x4c, 0x28, 0xc8, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xea, 0x2a, 0x4e, 0x8e, 0xee, 0x00, 0xa2, 0xa2, 0xe2, 0xea, 0xa4, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xea, 0x2a, 0x4e, 0x8e, 0xee, 0x00, 0x08, 0x08, 0x08, 0x28, 0x10, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0x80, 0x80, 0x80, 0xf0, 0x28, 0x30, 0x28, 0x0a, 0x0e, 0x0e, 0x0a, 0x00, 0xfe, 0x00},
+	{0xfe, 0x00, 0xc0, 0xa0, 0xc0, 0xa0, 0x20, 0x20, 0x38, 0x0a, 0x0e, 0x0e, 0x0a, 0x00, 0xfe, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x9c, 0xd2, 0xbc, 0x92, 0x9c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xfe, 0x00},
+	{0x00, 0x18, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00},
+	{0x00, 0x30, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x66, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00},
+	{0x00, 0xcc, 0xcc, 0xcc, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x38, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x6b, 0x6b, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x92, 0x44, 0x28, 0x92, 0x28, 0x44, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0xc3, 0xdb, 0x1b, 0x1e, 0x1c, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x7c, 0x00, 0x00},
+	{0x7c, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x38, 0x6c, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x38, 0x28, 0x00, 0x00, 0x44, 0xee, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7b, 0xcf, 0xcf, 0x1b, 0x33, 0x33, 0x33, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xde, 0xf3, 0xf3, 0xc6, 0xcc, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x06, 0x06, 0x0c, 0x0c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xdb, 0xdb, 0xdb, 0xde, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x3e, 0x72, 0xf2, 0xf2, 0xf2, 0x72, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x9c, 0x9e, 0x9e, 0x9e, 0x9c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x18, 0x38, 0x78, 0xd8, 0xfc, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xf8, 0xc0, 0xf0, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x78, 0xc0, 0xf0, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xf8, 0xd8, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd8, 0x70, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd8, 0xd8, 0x78, 0x18, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x60, 0x30, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xb0, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0xd8, 0xfc, 0x18, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xc0, 0xf0, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xc0, 0xf0, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xd8, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x70, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0xd8, 0x78, 0x18, 0xf0, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcf, 0xcc, 0xcc, 0x7f, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x04, 0x7c, 0xce, 0xc8, 0xc8, 0xd0, 0xd0, 0xd0, 0xe0, 0xe6, 0x7c, 0x40, 0x40, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xd6, 0xd8, 0xd8, 0xd8, 0xde, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0xc0, 0xc0, 0xc0, 0xf0, 0xcd, 0xce, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x60, 0xf8, 0x60, 0xf8, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x02, 0xec, 0xd6, 0xde, 0xd6, 0xd6, 0xf6, 0xd6, 0x40, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x66, 0x76, 0xff, 0x76, 0x6e, 0xff, 0x6e, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xf8, 0xe0, 0xf3, 0xd6, 0xdb, 0xce, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x81, 0x81, 0x81, 0x5a, 0xff, 0x5a, 0xff, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xf2, 0x8a, 0xaa, 0xaa, 0xaa, 0xaa, 0xa2, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x3e, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x7c, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x36, 0x60, 0xfc, 0x60, 0xf8, 0x60, 0x60, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0xfe, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x1e, 0x78, 0x1e, 0x78, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x7c, 0xb6, 0x36, 0x33, 0x33, 0x33, 0x63, 0x66, 0xf6, 0xdc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd0, 0xd2, 0xd6, 0x7c, 0x18, 0x30, 0x6e, 0xd8, 0x98, 0x18, 0x0e, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xd0, 0xd2, 0xd6, 0x7c, 0x18, 0x30, 0x6e, 0xd8, 0x8c, 0x06, 0x1c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x62, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x62, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x4e, 0xb9, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x7c, 0xda, 0xd8, 0xd8, 0xda, 0x7c, 0x19, 0x3f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xc0, 0xc2, 0xc6, 0x7c, 0x18, 0x30, 0x6e, 0xdb, 0x9b, 0x1b, 0x0e, 0x00, 0x00, 0x00},
+	{0x00, 0x70, 0xc0, 0xc2, 0xc6, 0x7c, 0x18, 0x30, 0x7b, 0xdb, 0x9b, 0x1b, 0x0d, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc2, 0xc0, 0x78, 0xc0, 0xc0, 0xc2, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0x86, 0x26, 0x3e, 0x26, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7f, 0xb9, 0x58, 0x1a, 0x1e, 0x1a, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x66, 0x46, 0x87, 0x8c, 0x8c, 0x7c, 0x98, 0x98, 0x70, 0x00},
+	{0x00, 0x00, 0x52, 0xb5, 0x15, 0x16, 0x2c, 0x34, 0x68, 0xa9, 0xaa, 0x4c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x48, 0xb0, 0x80, 0x48, 0x7c, 0x66, 0x26, 0x26, 0xa6, 0x46, 0x06, 0x34, 0x48, 0x00},
+	{0x00, 0x00, 0xe2, 0xa2, 0xa2, 0xa2, 0xbe, 0xa2, 0xa2, 0xa2, 0xa2, 0xe2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x36, 0x3b, 0x3b, 0x33, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x1e, 0x18, 0x76, 0x3b, 0x3b, 0x33, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x33, 0x4e, 0x06, 0x06, 0x0c, 0x0c, 0x1f, 0x6c, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x71, 0x8e, 0x04, 0x0c, 0x06, 0x03, 0x63, 0xc3, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x46, 0x49, 0x39, 0x1e, 0x18, 0x30, 0x70, 0xb1, 0xba, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0e, 0x19, 0x31, 0x32, 0x64, 0x68, 0x70, 0xe1, 0x66, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd8, 0xff, 0xd8, 0xde, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe2, 0xa2, 0xb2, 0xb2, 0xaa, 0xaa, 0xa6, 0xa6, 0xa2, 0xe2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xcc, 0xcf, 0xed, 0xff, 0xfc, 0xdf, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0xb9, 0xa5, 0xa5, 0xb9, 0xa1, 0xa1, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x40, 0x8e, 0x93, 0xa3, 0x63, 0x4b, 0x6a, 0xa4, 0xb0, 0xb0, 0x60, 0x00},
+	{0x00, 0x00, 0xfc, 0xa2, 0xa2, 0xa2, 0xa2, 0xbc, 0xa0, 0xa0, 0xa0, 0xe0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xaa, 0xa6, 0x7e, 0x01, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3e, 0x4d, 0x4d, 0x19, 0x1e, 0x1c, 0x34, 0x34, 0xb5, 0x62, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x58, 0xa6, 0xa3, 0x6c, 0xb8, 0x26, 0x26, 0x26, 0xa7, 0xc2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0xa2, 0xa2, 0xa2, 0xa2, 0xbc, 0xb0, 0xa8, 0xa4, 0xe2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x6d, 0x67, 0x66, 0xee, 0x08, 0x00, 0x00, 0x00},
+	{0x30, 0x0c, 0xfc, 0xc6, 0xc6, 0xc6, 0xfc, 0xd8, 0xdc, 0xdc, 0xe6, 0xe6, 0x20, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x71, 0xdb, 0x35, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x52, 0x5a, 0x52, 0x5f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf1, 0x5b, 0x55, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x18, 0xce, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xe6, 0x6c, 0x38, 0x50, 0x40, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x0a, 0x14, 0x14, 0x28, 0x28, 0x50, 0x50, 0xa0, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x9c, 0x30, 0xfe, 0x0c, 0x18, 0x38, 0x0c, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00},
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xee, 0x6c, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x26, 0x03, 0x13, 0x0c, 0x13, 0x03, 0x03, 0x66, 0x98, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x6c, 0x38, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x2d, 0x2d, 0x1a, 0x1e, 0x1b, 0x31, 0x31, 0xb2, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x14, 0x6b, 0xc8, 0xcc, 0xc6, 0xc6, 0xcc, 0xc0, 0x63, 0x1c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xe7, 0xff, 0xe0, 0x67, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x44, 0xf8, 0xc0, 0xc8, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x4c, 0x52, 0x3c, 0x10, 0x3c, 0x60, 0xc0, 0xc3, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x73, 0xce, 0x18, 0x3a, 0x5c, 0x18, 0x30, 0x30, 0xb0, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x2c, 0x3c, 0x2c, 0x8c, 0xcc, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x12, 0x12, 0x12, 0x16, 0x36, 0x3e, 0x3a, 0x5a, 0x52, 0x91, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x26, 0x46, 0xc6, 0xc4, 0xc8, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x42, 0xc6, 0xe7, 0x7a, 0x38, 0x5c, 0xce, 0xe7, 0x63, 0xe2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xfc, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x7e, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x40, 0x78, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x7e, 0xf2, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xfe, 0x7e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x38, 0x00, 0x78, 0x38, 0x38, 0x38, 0x38, 0x38, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xff, 0x83, 0x86, 0x82, 0xfe, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x1c, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0xe0, 0x30, 0x62, 0xc6, 0xfc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x1c, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0xe0, 0x30, 0x62, 0xc6, 0xfc, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0xe0, 0x30, 0x62, 0x36, 0xec, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0x30, 0x70, 0xb2, 0xf6, 0x3c, 0x18, 0x30, 0x60, 0xde, 0x98, 0x1c, 0x06, 0x1c, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0xb0, 0x3c, 0x36, 0x1c, 0x00, 0x00},
+	{0x00, 0xf0, 0xc0, 0xe2, 0x36, 0xec, 0x18, 0x30, 0x60, 0xdc, 0xb0, 0x3c, 0x36, 0x1c, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00},
+	{0x00, 0xe0, 0x30, 0x62, 0x36, 0xec, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00},
+	{0x00, 0xf0, 0x80, 0xe2, 0x36, 0xec, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00},
+	{0x00, 0xf0, 0x30, 0x62, 0x66, 0x6c, 0x18, 0x30, 0x60, 0xdc, 0xb6, 0x1c, 0x36, 0x1c, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0xce, 0xc4, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x73, 0x23, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x65, 0x65, 0x65, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xce, 0xce, 0xce, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0x73, 0x73, 0x73, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x95, 0x95, 0x95, 0x65, 0x65, 0x65, 0x95, 0x95, 0x95, 0x95, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xdb, 0xdb, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xce, 0xc4, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x73, 0x23, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x05, 0x05, 0x00, 0x95, 0x95, 0x95, 0x95, 0x95, 0x65, 0x65, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x15, 0x15, 0x00, 0xb5, 0xb5, 0xb5, 0xb5, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0x00, 0xdb, 0xdb, 0xce, 0xce, 0xce, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x00, 0xdb, 0xdb, 0x73, 0x73, 0x73, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x05, 0x05, 0x00, 0x95, 0x95, 0x65, 0x65, 0x95, 0x95, 0x95, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x5a, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0xcc, 0xe6, 0xd6, 0xd6, 0xd6, 0xd6, 0xe6, 0xcc, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x5a, 0x99, 0xbd, 0xdb, 0xdb, 0xbd, 0x99, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0xcc, 0x86, 0x06, 0x06, 0x06, 0x06, 0x86, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xf0, 0xe0, 0xb0, 0x18, 0x0c, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x0f, 0x07, 0x0d, 0x18, 0x30, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x0d, 0x07, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x0c, 0x18, 0xb0, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x62, 0xff, 0x64, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x26, 0xff, 0x46, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xce, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x73, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xff, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x36, 0xff, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x66, 0xfc, 0x66, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x3f, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x63, 0xff, 0x63, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xc6, 0xff, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x33, 0x63, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0xc6, 0x7f, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x3b, 0x6b, 0xfe, 0x68, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x60, 0xdc, 0xd6, 0x7f, 0x16, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x5a, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x6e, 0xff, 0x76, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x30, 0x60, 0x63, 0xff, 0xc6, 0x16, 0x1c, 0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x66, 0x36, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0xcc, 0xd8, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x36, 0x66, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xd8, 0xcc, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x36, 0x66, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x1e, 0x33, 0x33, 0x33, 0x30, 0xfc, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x0c, 0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x00, 0xf0, 0xe0, 0xb0, 0x18, 0x0c, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x98, 0xb0, 0xff, 0xb0, 0x98, 0x19, 0x0d, 0xff, 0x0d, 0x19, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x1e, 0x1c, 0x16, 0x03, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x78, 0x38, 0x68, 0xc0, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x1c, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x06, 0xff, 0x06, 0x0c, 0x30, 0x60, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x2e, 0x3f, 0x24, 0x24, 0x24, 0x24, 0xfc, 0x74, 0x24, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x60, 0xff, 0x60, 0x30, 0x0c, 0x06, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x7e, 0xff, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0xff, 0x7e, 0x24, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xff, 0x00, 0xff, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xff, 0x00, 0xff, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x7f, 0xc4, 0x7f, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x7e, 0xcb, 0x7e, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xfe, 0x23, 0xfe, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x7f, 0xc0, 0x7f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x7c, 0xee, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0x03, 0xfe, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x7e, 0xc3, 0x7e, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x7c, 0xee, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xf0, 0xe0, 0xb0, 0xd8, 0xec, 0xb6, 0x1b, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x0f, 0x07, 0x0d, 0x1b, 0x37, 0x6d, 0xd8, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x20, 0x30, 0xd8, 0x6d, 0x37, 0x1b, 0x0d, 0x07, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x0c, 0x1b, 0xb6, 0xec, 0xd8, 0xb0, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x3f, 0x60, 0xff, 0x60, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0xfc, 0x06, 0xff, 0x06, 0xfc, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x6a, 0xff, 0x65, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xa6, 0xff, 0x56, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x3c, 0x18, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x3c, 0x18, 0x3c, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xd5, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0x66, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0xab, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xb0, 0xff, 0xb0, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0d, 0xff, 0x0d, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x3f, 0x41, 0x81, 0x41, 0x3f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x44, 0x44, 0x44, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0xfc, 0x82, 0x81, 0x82, 0xfc, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0x44, 0x44, 0x44, 0x44, 0x44, 0xc6, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x7c, 0x00, 0x7c, 0x44, 0x7c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x44, 0xc6, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x7c, 0xc6, 0x44, 0x44, 0x44, 0xc6, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x54, 0xd6, 0x54, 0x54, 0x54, 0xd6, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x28, 0x54, 0xee, 0x44, 0xc6, 0x44, 0x44, 0x44, 0x44, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x28, 0x54, 0xee, 0x44, 0xc6, 0x44, 0x44, 0xc6, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xe8, 0xbc, 0x82, 0x81, 0x82, 0xbc, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x80, 0xbc, 0xb8, 0xac, 0x86, 0x83, 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x01, 0x81, 0xc1, 0x61, 0x35, 0x1d, 0x3d, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0xc6, 0x44, 0x44, 0x44, 0xc6, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0xfe, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x06, 0x06, 0x3e, 0x66, 0xc6, 0xc6, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x7e, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0xfe, 0x16, 0x16, 0x16, 0x7e, 0x16, 0x26, 0x26, 0x26, 0xfe, 0x40, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x3e, 0x66, 0xcf, 0xdb, 0xdb, 0xf3, 0x66, 0x7c, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x3e, 0x60, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x3e, 0x64, 0xc8, 0xc8, 0xfe, 0xc8, 0xd0, 0x70, 0x3e, 0x20, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x3e, 0x60, 0xc0, 0xfe, 0xc0, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xf8, 0x0c, 0x06, 0x06, 0xfe, 0x06, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0xf8, 0x1c, 0x16, 0x26, 0xfe, 0x26, 0x26, 0x4c, 0xf8, 0x40, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x0c, 0x06, 0xfe, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe7, 0x00, 0x00},
+	{0x00, 0x00, 0xe7, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0xc1, 0x60, 0x30, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xff, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0xc0, 0xc0, 0x00, 0x00, 0x00},
+	{0x00, 0xc0, 0xc0, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x7e, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x06, 0x06, 0x06, 0x0c, 0xcc, 0x6c, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe3, 0x33, 0x66, 0x36, 0xe6, 0x0c, 0xcc, 0x6c, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x33, 0x73, 0xb6, 0xf6, 0x36, 0x0c, 0xcc, 0x6c, 0x38, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdb, 0xdb, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x16, 0x0c, 0x1c, 0x34, 0x62, 0xff, 0x02, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x1a, 0x1c, 0x38, 0x58, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6c, 0x6c, 0x6c, 0x6e, 0x7c, 0xec, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x1a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00},
+	{0x33, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00},
+	{0x2a, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0xa8, 0x00, 0x00},
+	{0x0c, 0x1a, 0x18, 0x18, 0x3c, 0x5a, 0x99, 0x99, 0x5a, 0x3c, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00},
+	{0x33, 0x66, 0x66, 0x66, 0x7e, 0xe7, 0xe7, 0xe7, 0xe7, 0x7e, 0x66, 0x66, 0x66, 0xcc, 0x00, 0x00},
+	{0x2a, 0x54, 0x54, 0x54, 0x7c, 0xd6, 0xd6, 0xd6, 0xd6, 0x7c, 0x54, 0x54, 0x54, 0xa8, 0x00, 0x00},
+	{0x18, 0x34, 0x30, 0x30, 0x38, 0x35, 0x33, 0x37, 0x30, 0x30, 0x30, 0x30, 0xb0, 0x60, 0x00, 0x00},
+	{0x0c, 0x1a, 0x18, 0x18, 0x3c, 0x5a, 0xfa, 0x5a, 0x5a, 0x3c, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00},
+	{0x0c, 0x1a, 0x18, 0x18, 0x3c, 0x5a, 0x5f, 0x5a, 0x5a, 0x3c, 0x18, 0x18, 0x58, 0x30, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0xfc, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x7e, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x76, 0xdc, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0xdb, 0xdb, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0xdb, 0xdb, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x1c, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x76, 0xdc, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x76, 0xdc, 0x10, 0xfe, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x08, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x08, 0x76, 0xdc, 0x10, 0xfe, 0x20, 0xfe, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x76, 0xdc, 0x10, 0x76, 0xdc, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x00, 0x00, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x66, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0x60, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x06, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf, 0x00, 0x00, 0xdf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x03, 0xfb, 0x00, 0x00, 0xfb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x28, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x10, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x44, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x44, 0x28, 0x10, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x10, 0x7c, 0x28, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x10, 0x28, 0x44, 0x7c, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x26, 0x7c, 0xb4, 0x6c, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x68, 0x54, 0x54, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x08, 0x10, 0x00, 0x10, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x08, 0x7e, 0x08, 0x10, 0x7e, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x08, 0xfe, 0x08, 0x10, 0xfe, 0x10, 0x20, 0xfe, 0x20, 0x40, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x08, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x08, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x1b, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x1b, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x66, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x66, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0xce, 0x7c, 0x10, 0x7c, 0xe6, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x04, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0xe0, 0x38, 0x2e, 0x38, 0xe0, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x04, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0xe0, 0x38, 0x2e, 0x38, 0xe0, 0x40, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x04, 0x0e, 0x38, 0xe8, 0x38, 0x0e, 0x10, 0x76, 0xdc, 0x20, 0x20, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0xe0, 0x38, 0x2e, 0x38, 0xe0, 0x40, 0x76, 0xdc, 0x80, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x0e, 0x38, 0xe8, 0x38, 0x1e, 0xf0, 0x38, 0x2e, 0x38, 0xe0, 0x20, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0xe8, 0x38, 0x0e, 0x38, 0xf0, 0x1e, 0x38, 0xe0, 0x38, 0x2e, 0x20, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0xf2, 0x1c, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x9e, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x06, 0x0c, 0x38, 0xe8, 0x38, 0x1c, 0x16, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0xd0, 0x70, 0x38, 0x2e, 0x38, 0x60, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x7e, 0xc8, 0xc8, 0xd0, 0xd0, 0x7e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0xfc, 0x16, 0x16, 0x26, 0x26, 0xfc, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0x7e, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x7e, 0xc8, 0xc8, 0xd0, 0xd0, 0x7e, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0xfc, 0x16, 0x16, 0x26, 0x26, 0xfc, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0xc0, 0xc0, 0x7e, 0x08, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x82, 0x92, 0xa2, 0xfa, 0xa2, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0xba, 0xba, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0xba, 0x92, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x54, 0x92, 0xfe, 0x92, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0xfe, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0xaa, 0x92, 0xaa, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x8a, 0x92, 0xa2, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x92, 0xba, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x92, 0xaa, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x54, 0xd6, 0xba, 0xd6, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0xba, 0x82, 0xba, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0xba, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x92, 0x92, 0xfe, 0x92, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0xfe, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xaa, 0x92, 0xaa, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x92, 0xba, 0x92, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x7e, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xd8, 0xdf, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xa8, 0xa8, 0xa8, 0xa8, 0xaf, 0xa8, 0xa8, 0xa8, 0xa8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xdf, 0xd8, 0xdf, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc2, 0xc4, 0xc4, 0xff, 0xc8, 0xc8, 0xd0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xc4, 0xc4, 0xff, 0xc8, 0xff, 0xd0, 0xd0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xd8, 0xd9, 0xda, 0xda, 0xdf, 0xda, 0xda, 0xdc, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xd8, 0xd9, 0xda, 0xdf, 0xda, 0xdf, 0xda, 0xdc, 0xd8, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x0c, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x60, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x06, 0x1e, 0x76, 0xc6, 0x76, 0x1e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc0, 0xf0, 0xdc, 0xc6, 0xdc, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x1e, 0x76, 0xc6, 0x76, 0x1e, 0x06, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xf0, 0xdc, 0xc6, 0xdc, 0xf0, 0xc0, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xbf, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0xc6, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xf0, 0xc8, 0xc4, 0xc4, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0b, 0x13, 0x23, 0x43, 0x83, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x38, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x92, 0x44, 0x28, 0x92, 0x28, 0x44, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x82, 0xc6, 0xaa, 0x92, 0xaa, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x82, 0xc4, 0xa8, 0x90, 0xa8, 0xc4, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x82, 0x46, 0x2a, 0x12, 0x2a, 0x46, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x38, 0x38, 0x6c, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc6, 0x6c, 0x6c, 0x38, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x3e, 0x60, 0xce, 0xd8, 0xd8, 0xce, 0x60, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xf8, 0x0c, 0xe6, 0x36, 0x36, 0xe6, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x44, 0x92, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x10, 0x38, 0x54, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x64, 0xce, 0x64, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x4c, 0xe6, 0x4c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x15, 0x2a, 0x54, 0xa8, 0x54, 0x2a, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xa8, 0x54, 0x2a, 0x15, 0x2a, 0x54, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0xfe, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x00},
+	{0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0xfe, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf2, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xc0, 0x70, 0x9e, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0a, 0x0e, 0x1c, 0xf0, 0x1c, 0x16, 0xf2, 0x1c, 0x26, 0x22, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x88, 0xc8, 0x70, 0x1e, 0x70, 0xd0, 0x9e, 0x70, 0xe0, 0xa0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0xfe, 0xc8, 0xc8, 0xd0, 0xd0, 0xfe, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0xfe, 0x16, 0x16, 0x26, 0x26, 0xfe, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x08, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x10, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0e, 0x38, 0xe0, 0x38, 0x0e, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xe0, 0x38, 0x0e, 0x38, 0xe0, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x02, 0x06, 0x1c, 0xf0, 0x1c, 0x06, 0x02, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x80, 0xc0, 0x70, 0x1e, 0x70, 0xc0, 0x80, 0x10, 0x76, 0xdc, 0x10, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x0e, 0x1e, 0x76, 0xd6, 0x76, 0x1e, 0x26, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0xc8, 0xf0, 0xdc, 0xd6, 0xdc, 0xf0, 0xe0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x0e, 0x1e, 0x76, 0xd6, 0x76, 0x1e, 0x26, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0xc8, 0xf0, 0xdc, 0xd6, 0xdc, 0xf0, 0xe0, 0x20, 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x3d, 0x66, 0xc7, 0xcb, 0xd3, 0xe3, 0x66, 0xbc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x42, 0xa5, 0x7e, 0x24, 0x24, 0x7e, 0xa5, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x38, 0x54, 0x8a, 0xf6, 0x82, 0x54, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0xfe, 0xfe, 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x00, 0x00},
+	{0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60, 0x00, 0x00},
+	{0x00, 0x03, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
+	{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
+	{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x03, 0x00, 0x00},
+	{0x00, 0xc0, 0x60, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
+	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
+	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x30, 0x30, 0x60, 0xc0, 0x00, 0x00},
+	{0x00, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
+	{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
+	{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3f, 0x00, 0x00},
+	{0x00, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
+	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
+	{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xfc, 0x00, 0x00},
+	{0x00, 0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0},
+	{0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07},
+	{0x00, 0x00, 0xff, 0xc1, 0xc0, 0x60, 0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x60, 0x60, 0x60, 0x60, 0xc0, 0xc1, 0xff, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xff, 0x00, 0xff, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x78, 0x78, 0x38, 0x38, 0x18, 0x18, 0x00, 0x00},
+	{0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
+	{0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03},
+	{0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x07, 0x05, 0x05, 0x05, 0x05, 0x25, 0x79, 0xc2, 0x7c, 0x20, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd8, 0xd8, 0xf8, 0xd8, 0xd8, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0, 0x0f, 0x0c, 0x0e, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd8, 0xd8, 0xf8, 0x70, 0x20, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xf0, 0xc0, 0xe0, 0xc0, 0xc0, 0x0f, 0x0c, 0x0e, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0xc0, 0xc0, 0xc0, 0x70, 0x1e, 0x1b, 0x1e, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x98, 0xd8, 0xf8, 0xd8, 0xd8, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7c, 0xfe, 0xc6, 0xc6, 0x60, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xfc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0e, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x70, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x70, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x0e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80},
+	{0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01},
+	{0x81, 0x81, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x42, 0x42, 0x81, 0x81},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe},
+	{0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc},
+	{0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8},
+	{0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0},
+	{0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0},
+	{0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
+	{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80},
+	{0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f},
+	{0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44},
+	{0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa},
+	{0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77},
+	{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+	{0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x82, 0xba, 0xba, 0xba, 0xba, 0xba, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x82, 0xfe, 0x82, 0xfe, 0x82, 0xfe, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0xaa, 0xfe, 0xaa, 0xfe, 0xaa, 0xfe, 0xaa, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x8a, 0xc6, 0xa2, 0x92, 0x8a, 0xc6, 0xa2, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0xa2, 0xc6, 0x8a, 0x92, 0xa2, 0xc6, 0x8a, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0xaa, 0xc6, 0xaa, 0x92, 0xaa, 0xc6, 0xaa, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x44, 0x44, 0x44, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x42, 0x84, 0x84, 0xfc, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x44, 0x44, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x80, 0xc0, 0xa0, 0x90, 0x88, 0x84, 0x88, 0x90, 0xa0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, 0x78, 0x70, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, 0x48, 0x70, 0x40, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x98, 0x86, 0x98, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x02, 0x06, 0x0a, 0x12, 0x22, 0x42, 0x22, 0x12, 0x0a, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x38, 0x78, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x38, 0x48, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x32, 0xc2, 0x32, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x82, 0x82, 0x44, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x44, 0x54, 0xba, 0xba, 0x54, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x99, 0xbd, 0xbd, 0xbd, 0xbd, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x28, 0x28, 0x44, 0x82, 0x82, 0x44, 0x28, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x14, 0x40, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x99, 0xa5, 0xa5, 0xa5, 0xa5, 0x99, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x72, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0x72, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x4e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x4e, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x7e, 0xff, 0xff, 0xff, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x4e, 0x8f, 0x8f, 0x8f, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x4e, 0x8f, 0x8f, 0x8f, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x70, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x70, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	{0xff, 0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0xbd, 0xc3, 0xff, 0xff, 0xff, 0xff},
+	{0xff, 0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0xbd, 0xc3, 0xff, 0xff, 0xff, 0xff},
+	{0x00, 0x00, 0x30, 0x40, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0c, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x0f, 0x1f, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f, 0xff, 0xff},
+	{0x80, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfc, 0xfe, 0xfe, 0xff, 0xff},
+	{0xff, 0xff, 0xfe, 0xfe, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, 0xe0, 0xe0, 0xc0, 0xc0, 0x80, 0x80},
+	{0xff, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x07, 0x03, 0x03, 0x01, 0x01},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0xff, 0xfd, 0xf9, 0xf1, 0xf1, 0xe1, 0xc1, 0x81, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x81, 0x83, 0x87, 0x8f, 0x8f, 0x9f, 0xbf, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xff, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x28, 0x28, 0x44, 0x44, 0x92, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x74, 0x74, 0xf2, 0xf2, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x38, 0x5c, 0x5c, 0x9e, 0x9e, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x92, 0x92, 0x92, 0xf2, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0xf2, 0x92, 0x92, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x9e, 0x92, 0x92, 0x92, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xfe, 0x92, 0x92, 0x92, 0x9e, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x4a, 0x89, 0x89, 0x89, 0xf9, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0xf9, 0x89, 0x89, 0x89, 0x4a, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x9f, 0x91, 0x91, 0x91, 0x52, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x52, 0x91, 0x91, 0x91, 0x9f, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x30, 0x7c, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x7c, 0xfe, 0x10, 0x10, 0x10, 0x10, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0xfe, 0x7c, 0x38, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x28, 0xee, 0x44, 0x54, 0x6c, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x34, 0x1c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcd, 0xc7, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x92, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0xa5, 0xa5, 0x42, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x42, 0xa5, 0xa5, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x18, 0x30, 0x70, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0x86, 0x8a, 0xba, 0x92, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0xfe, 0x82, 0xee, 0xba, 0xba, 0xee, 0x82, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x82, 0xc6, 0x6c, 0x7c, 0x38, 0x7c, 0x6c, 0xc6, 0x82, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x7c, 0x82, 0xaa, 0x82, 0x44, 0x7c, 0x44, 0x38, 0x00, 0x44, 0xc6, 0x38, 0xc6, 0x44, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x44, 0xee, 0xfe, 0x92, 0xba, 0x7c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x7e, 0x18, 0x18, 0xff, 0x18, 0x1e, 0x78, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x7e, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x38, 0x10, 0x10, 0x92, 0xfe, 0x92, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x72, 0xe0, 0xc4, 0xdf, 0xce, 0xca, 0xe0, 0x72, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x54, 0x28, 0x54, 0xaa, 0xaa, 0xaa, 0xaa, 0x54, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x5a, 0x99, 0x99, 0x99, 0xbd, 0xff, 0xdb, 0x5a, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x42, 0x81, 0x85, 0xb1, 0xf9, 0xff, 0xdf, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0x81, 0x99, 0xa5, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xa5, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xdb, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x54, 0x28, 0xc6, 0x28, 0x54, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x78, 0x14, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x14, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x28, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x28, 0x1e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x06, 0x0e, 0x1a, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x03, 0x03, 0x7b, 0xcf, 0xcf, 0xcf, 0x0f, 0x1b, 0x33, 0xff, 0x03, 0x03, 0x03, 0x00, 0x00},
+	{0x00, 0x00, 0x60, 0xf0, 0x60, 0x6e, 0x73, 0x63, 0x63, 0x66, 0x66, 0x63, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xd6, 0x54, 0x54, 0x7c, 0x54, 0x54, 0xd6, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x3c, 0xdb, 0xdb, 0xdb, 0xdb, 0x7e, 0x3c, 0x18, 0x3c, 0x18, 0x18, 0x00, 0x00},
+	{0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0xf8, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x42, 0xa5, 0xa5, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0xc3, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00},
+	{0x00, 0x00, 0xc3, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7e, 0xc3, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7e, 0xdb, 0xd8, 0x70, 0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1e, 0x33, 0x33, 0x33, 0x33, 0x1b, 0x7b, 0xdb, 0xdb, 0x73, 0x03, 0x01, 0x00, 0x00},
+	{0x00, 0x00, 0x94, 0x7c, 0x55, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x06, 0x0b, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x24, 0xe7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x94, 0x7c, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x04, 0x03, 0x00, 0x00},
+	{0x00, 0x00, 0x1f, 0x07, 0x8f, 0xdb, 0x73, 0x70, 0xd8, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x90, 0x50, 0x70, 0x68, 0x48, 0x48, 0x4e, 0x49, 0x09, 0x0e, 0x10, 0x20, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x2a, 0x7e, 0xaa, 0x00, 0x00, 0x2a, 0x7e, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc3, 0x66, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0x82, 0x82, 0x82, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x44, 0x82, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x81, 0x81, 0x66, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x18, 0x24, 0x3c, 0xe7, 0xa5, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x30, 0x3c, 0x3e, 0x32, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0x7f, 0x6f, 0x63, 0x63, 0x63, 0x63, 0xe3, 0xe7, 0xc7, 0x06, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x63, 0xe7, 0xe7, 0xc6, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xcc, 0xde, 0xe6, 0xc4, 0xd8, 0xe0, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x40, 0x40, 0x44, 0x5c, 0x74, 0x44, 0x44, 0x5c, 0x74, 0x44, 0x04, 0x04, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x04, 0x46, 0x5c, 0x74, 0xc4, 0x46, 0x5c, 0x74, 0xc4, 0x40, 0x40, 0x00, 0x00},
+	{0x00, 0x00, 0x3b, 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3c, 0x6e, 0x66, 0x60, 0xfe, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x3e, 0x6e, 0x66, 0x66, 0xfe, 0x66, 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6e, 0xdb, 0xdb, 0xd8, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x6f, 0xdb, 0xdb, 0xdb, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xff, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x38, 0x6c, 0x6c, 0x6f, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0xf6, 0x00, 0x00, 0x00, 0x00},
+	{0x06, 0x29, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x06, 0x29, 0x5e, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x14, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x14, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x89, 0x86, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0a, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0a, 0x00, 0x0a, 0x00, 0x06, 0x49, 0x89, 0x86, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x88, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x88, 0x80, 0x88, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x94, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x94, 0x80, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x88, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x94, 0x80, 0x88, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x94, 0x80, 0x94, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x94, 0x80, 0x94, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x28, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x28, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x00, 0x28, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x00, 0x28, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x38, 0x28, 0x70, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x38, 0x28, 0x70, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x00, 0x14, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x01, 0x02, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x01, 0x02, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x30, 0x46, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x30, 0x46, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00},
+	{0x04, 0x09, 0x12, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00},
+	{0x0c, 0x30, 0x46, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00},
+	{0x0c, 0x30, 0x46, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0xa4, 0x09, 0x12, 0x04, 0x08, 0x44, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xa4, 0x09, 0x12, 0x04, 0x08, 0x48, 0x84, 0x82, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xa2, 0x0c, 0x13, 0x0c, 0x10, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xa2, 0x0c, 0x13, 0x0c, 0x10, 0x10, 0x08, 0x04, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x00, 0x01, 0x41, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x1c, 0x14, 0x38, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x38, 0x40, 0x38, 0x40, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x70, 0x80, 0x70, 0x80, 0x10, 0x68, 0x88, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xf0, 0x10, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xf7, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x38, 0x4c, 0x52, 0x32, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x70, 0x80, 0x70, 0x80, 0x08, 0x14, 0x60, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x1c, 0x20, 0x1c, 0x20, 0x00, 0x00, 0x07, 0x18, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x00, 0x29, 0x01, 0x19, 0x21, 0x19, 0xa1, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x00, 0x2a, 0x02, 0x32, 0x42, 0x32, 0xc6, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0x00, 0xa3, 0x0c, 0x10, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0x00, 0xa3, 0x0c, 0x10, 0x10, 0x08, 0x04, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x28, 0x18, 0x10, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x28, 0x18, 0x10, 0x20, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x08, 0x08, 0x08, 0x08, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x23, 0x54, 0x33, 0x24, 0x40, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x3c, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x3c, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x10, 0x00, 0x10},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x10, 0x00, 0x10},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x20, 0x20, 0x20, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x10, 0x10, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x10, 0x10, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x24, 0x98, 0x60, 0xc2, 0x12, 0x92, 0x9c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x02, 0x92, 0x9c, 0x60, 0x0e, 0x70, 0x0e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x60, 0x04, 0x54, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x28, 0x10, 0x60, 0x04, 0x54, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x04, 0x54, 0x58, 0x20, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x04, 0x54, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00},
+	{0x0e, 0xf0, 0x02, 0x92, 0x9c, 0x60, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x24, 0x18, 0x60, 0x02, 0x92, 0x9c, 0x60, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x02, 0x12, 0x9c, 0x60, 0x0e, 0x70, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x28, 0x50, 0x28, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x14, 0x28, 0x14, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x08, 0x10, 0x54, 0x38, 0x54, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x10, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x2a, 0x14, 0x00, 0x21, 0x69, 0xa9, 0x69, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x08, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x20, 0x10, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x04, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x7c, 0x28, 0x7c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x10, 0x2a, 0x24, 0x1a, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x38, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x54, 0x30, 0x18, 0x54, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x08, 0x08, 0x10, 0x10, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x54, 0x58, 0x40, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x06, 0x18, 0x60, 0x06, 0x18, 0x60, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x12, 0xca, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x0c, 0x30, 0x00, 0x00},
+	{0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x06, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x08, 0x14, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x24, 0x14, 0x18, 0x60, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x06, 0x18, 0x60, 0x00, 0x00},
+	{0x0a, 0x2a, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x02, 0x12, 0x92, 0x9c, 0x60, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x20, 0x1e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x02, 0x3c, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x01, 0x3e, 0x40, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x20, 0x1c, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x10, 0x0e, 0x10, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x0c, 0x10, 0x0e, 0x10, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x0c, 0x10, 0x0e, 0x10, 0x00, 0x00},
+	{0x00, 0x30, 0x40, 0x38, 0x40, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x30, 0x40, 0x38, 0x40, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00},
+	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x1c, 0x20, 0x1c, 0x20, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x28, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x50, 0x00, 0x10, 0x10, 0x68, 0x88, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x14, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x14, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x40, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x40, 0x80, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x88, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x88, 0x80, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x80, 0x80, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x20, 0x00, 0x00, 0x70, 0x8f, 0x30, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x00, 0x00, 0x70, 0x8f, 0x32, 0x41, 0x80, 0x80, 0x80, 0x40, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x47, 0x18, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x00, 0x00, 0x70, 0x8f, 0x32, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x00, 0x08, 0x04, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x00, 0x08, 0x08, 0x04, 0x46, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x02, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x07, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x15, 0x88, 0x84, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x15, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0x2a, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x09, 0x31, 0x9e, 0x88, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x29, 0x31, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x20, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0xa2, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x24, 0x20, 0x20, 0x2c, 0x32, 0x22, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0x22, 0x41, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x10, 0x10, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x40, 0x00, 0x00, 0x70, 0x80, 0x8c, 0x70, 0x40, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x08, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0x22, 0x41, 0x80, 0x80, 0x80, 0x41, 0x3e, 0x00, 0x00},
+	{0x00, 0x00, 0x10, 0x00, 0x00, 0x0e, 0x10, 0x10, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x1e, 0x22, 0x1c, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x85, 0x83, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x04, 0x00, 0x06, 0x49, 0x89, 0x86, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x47, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x0a, 0x00, 0x00, 0x06, 0x09, 0x49, 0x87, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x0a, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x14, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x0c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x19, 0x21, 0x19, 0x21, 0x01, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x32, 0x42, 0x32, 0x42, 0x02, 0x86, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x18, 0x20, 0x10, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x06, 0x18, 0x20, 0x20, 0x10, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x42, 0x82, 0x82, 0x84, 0x78, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3c, 0x4b, 0x4a, 0x44, 0x40, 0x40, 0x40, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x32, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x08, 0x00, 0x00, 0x41, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x41, 0x81, 0x81, 0x42, 0x3c, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x10, 0x10, 0x68, 0x88, 0x74, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x40, 0x30, 0x4e, 0x49, 0x39, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x24, 0x28, 0xf3, 0x24, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0e, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x0f, 0x02, 0x04, 0x18, 0x60, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x88, 0x86, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x24, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x88, 0x87, 0x81, 0x7e, 0x00, 0x24, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0xf8, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xf7, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x68, 0x90, 0x02, 0x22, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x68, 0x90, 0x02, 0x32, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x80, 0x72, 0xa2, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x40, 0x3a, 0x52, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x42, 0x22, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x18, 0x20, 0x1c, 0x20, 0x00},
+	{0x00, 0x00, 0x22, 0x12, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x18, 0x20, 0x1c, 0x20, 0x00},
+	{0x00, 0x00, 0x42, 0x22, 0x12, 0x0a, 0x04, 0x0c, 0x12, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x22, 0x12, 0x12, 0x0a, 0x0a, 0x0e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xf1, 0x35, 0x55, 0x8a, 0xe0, 0x06, 0x95, 0xd6, 0xb5, 0x97, 0x00, 0xee, 0x8a, 0xee, 0x28, 0xe8},
+	{0x00, 0x38, 0x7c, 0x7c, 0xc6, 0x92, 0xf2, 0xe6, 0xfe, 0xe6, 0x7c, 0x7c, 0x38, 0x00, 0x00, 0x00},
+	
+	/* Special glyph for unknown character */
+	{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}
+};
+
+/** @}
+ */
Index: uspace/srv/hid/output/gfx/font-8x16.h
===================================================================
--- uspace/srv/hid/output/gfx/font-8x16.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/gfx/font-8x16.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005 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 genarch
+ * @{
+ */
+/** @file
+ */
+
+#ifndef FONT_8X16_H_
+#define FONT_8X16_H_
+
+#include <sys/types.h>
+
+#define FONT_GLYPHS     2899
+#define FONT_WIDTH      8
+#define FONT_SCANLINES  16
+
+extern uint16_t fb_font_glyph(const wchar_t);
+extern uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES];
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/output/output.c
===================================================================
--- uspace/srv/hid/output/output.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/output.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <malloc.h>
+#include <macros.h>
+#include <as.h>
+#include <ipc/output.h>
+#include "port/ega.h"
+#include "port/kchar.h"
+#include "port/niagara.h"
+#include "port/ski.h"
+#include "output.h"
+
+#define MAX_COLS  128
+#define MAX_ROWS  128
+
+typedef struct {
+	link_t link;
+	
+	size_t size;
+	unsigned int flags;
+	void *data;
+} frontbuf_t;
+
+static LIST_INITIALIZE(outdevs);
+static LIST_INITIALIZE(frontbufs);
+
+outdev_t *outdev_register(outdev_ops_t *ops, void *data)
+{
+	assert(ops->get_dimensions);
+	
+	outdev_t *dev = (outdev_t *) malloc(sizeof(outdev_t));
+	if (dev == NULL)
+		return NULL;
+	
+	link_initialize(&dev->link);
+	
+	dev->ops = *ops;
+	dev->data = data;
+	
+	ops->get_dimensions(dev, &dev->cols, &dev->rows);
+	dev->backbuf = chargrid_create(dev->cols, dev->rows,
+	    CHARGRID_FLAG_NONE);
+	if (dev->backbuf == NULL) {
+		free(dev);
+		return NULL;
+	}
+	
+	list_append(&dev->link, &outdevs);
+	return dev;
+}
+
+static void srv_yield(ipc_callid_t iid, ipc_call_t *icall)
+{
+	int ret = EOK;
+	
+	list_foreach(outdevs, link) {
+		outdev_t *dev = list_get_instance(link, outdev_t, link);
+		
+		assert(dev->ops.yield);
+		
+		int rc = dev->ops.yield(dev);
+		if (rc != EOK)
+			ret = rc;
+	}
+	
+	async_answer_0(iid, ret);
+}
+
+static void srv_claim(ipc_callid_t iid, ipc_call_t *icall)
+{
+	int ret = EOK;
+	
+	list_foreach(outdevs, link) {
+		outdev_t *dev = list_get_instance(link, outdev_t, link);
+		
+		assert(dev->ops.claim);
+		
+		int rc = dev->ops.claim(dev);
+		if (rc != EOK)
+			ret = rc;
+	}
+	
+	async_answer_0(iid, ret);
+}
+
+static void srv_get_dimensions(ipc_callid_t iid, ipc_call_t *icall)
+{
+	sysarg_t cols = MAX_COLS;
+	sysarg_t rows = MAX_ROWS;
+	
+	list_foreach(outdevs, link) {
+		outdev_t *dev = list_get_instance(link, outdev_t, link);
+		
+		cols = min(cols, dev->cols);
+		rows = min(rows, dev->rows);
+	}
+	
+	async_answer_2(iid, EOK, cols, rows);
+}
+
+static void srv_get_caps(ipc_callid_t iid, ipc_call_t *icall)
+{
+	console_caps_t caps = 0;
+	
+	list_foreach(outdevs, link) {
+		outdev_t *dev = list_get_instance(link, outdev_t, link);
+		
+		assert(dev->ops.get_caps);
+		
+		caps |= dev->ops.get_caps(dev);
+	}
+	
+	async_answer_1(iid, EOK, caps);
+}
+
+static frontbuf_t *resolve_frontbuf(sysarg_t handle, ipc_callid_t iid)
+{
+	frontbuf_t *frontbuf = NULL;
+	list_foreach(frontbufs, link) {
+		frontbuf_t *cur = list_get_instance(link, frontbuf_t, link);
+		if (cur == (frontbuf_t *) handle) {
+			frontbuf = cur;
+			break;
+		}
+	}
+	
+	if (frontbuf == NULL) {
+		async_answer_0(iid, ENOENT);
+		return NULL;
+	}
+	
+	return frontbuf;
+}
+
+static void srv_frontbuf_create(ipc_callid_t iid, ipc_call_t *icall)
+{
+	frontbuf_t *frontbuf = (frontbuf_t *) malloc(sizeof(frontbuf_t));
+	if (frontbuf == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	link_initialize(&frontbuf->link);
+	
+	ipc_callid_t callid;
+	if (!async_share_out_receive(&callid, &frontbuf->size,
+	    &frontbuf->flags)) {
+		free(frontbuf);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	int rc = async_share_out_finalize(callid, &frontbuf->data);
+	if ((rc != EOK) || (frontbuf->data == AS_MAP_FAILED)) {
+		free(frontbuf);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	list_append(&frontbuf->link, &frontbufs);
+	async_answer_1(iid, EOK, (sysarg_t) frontbuf);
+}
+
+static void srv_frontbuf_destroy(ipc_callid_t iid, ipc_call_t *icall)
+{
+	frontbuf_t *frontbuf = resolve_frontbuf(IPC_GET_ARG1(*icall), iid);
+	if (frontbuf == NULL)
+		return;
+	
+	list_remove(&frontbuf->link);
+	as_area_destroy(frontbuf->data);
+	free(frontbuf);
+	
+	async_answer_0(iid, EOK);
+}
+
+static void srv_cursor_update(ipc_callid_t iid, ipc_call_t *icall)
+{
+	frontbuf_t *frontbuf = resolve_frontbuf(IPC_GET_ARG1(*icall), iid);
+	if (frontbuf == NULL)
+		return;
+	
+	chargrid_t *buf = (chargrid_t *) frontbuf->data;
+	bool visible = chargrid_get_cursor_visibility(buf);
+	
+	sysarg_t col;
+	sysarg_t row;
+	chargrid_get_cursor(buf, &col, &row);
+	
+	list_foreach(outdevs, link) {
+		outdev_t *dev = list_get_instance(link, outdev_t, link);
+		
+		assert(dev->ops.cursor_update);
+		
+		sysarg_t prev_col;
+		sysarg_t prev_row;
+		chargrid_get_cursor(dev->backbuf, &prev_col, &prev_row);
+		
+		chargrid_set_cursor(dev->backbuf, col, row);
+		chargrid_set_cursor_visibility(dev->backbuf, visible);
+		
+		dev->ops.cursor_update(dev, prev_col, prev_row, col, row,
+		    visible);
+	}
+	
+	async_answer_0(iid, EOK);
+}
+
+static void srv_set_style(ipc_callid_t iid, ipc_call_t *icall)
+{
+	list_foreach(outdevs, link) {
+		outdev_t *dev = list_get_instance(link, outdev_t, link);
+		
+		dev->attrs.type = CHAR_ATTR_STYLE;
+		dev->attrs.val.style =
+		    (console_style_t) IPC_GET_ARG1(*icall);
+	}
+	
+	async_answer_0(iid, EOK);
+}
+
+static void srv_set_color(ipc_callid_t iid, ipc_call_t *icall)
+{
+	list_foreach(outdevs, link) {
+		outdev_t *dev = list_get_instance(link, outdev_t, link);
+		
+		dev->attrs.type = CHAR_ATTR_INDEX;
+		dev->attrs.val.index.bgcolor =
+		    (console_color_t) IPC_GET_ARG1(*icall);
+		dev->attrs.val.index.fgcolor =
+		    (console_color_t) IPC_GET_ARG2(*icall);
+		dev->attrs.val.index.attr =
+		    (console_color_attr_t) IPC_GET_ARG3(*icall);
+	}
+	
+	async_answer_0(iid, EOK);
+}
+
+static void srv_set_rgb_color(ipc_callid_t iid, ipc_call_t *icall)
+{
+	list_foreach(outdevs, link) {
+		outdev_t *dev = list_get_instance(link, outdev_t, link);
+		
+		dev->attrs.type = CHAR_ATTR_RGB;
+		dev->attrs.val.rgb.bgcolor = IPC_GET_ARG1(*icall);
+		dev->attrs.val.rgb.fgcolor = IPC_GET_ARG2(*icall);
+	}
+	
+	async_answer_0(iid, EOK);
+}
+
+static bool srv_update_scroll(outdev_t *dev, chargrid_t *buf)
+{
+	assert(dev->ops.char_update);
+	
+	sysarg_t top_row = chargrid_get_top_row(buf);
+	
+	if (dev->top_row == top_row)
+		return false;
+	
+	dev->top_row = top_row;
+	
+	for (sysarg_t y = 0; y < dev->rows; y++) {
+		for (sysarg_t x = 0; x < dev->cols; x++) {
+			charfield_t *front_field =
+			    chargrid_charfield_at(buf, x, y);
+			charfield_t *back_field =
+			    chargrid_charfield_at(dev->backbuf, x, y);
+			bool update = false;
+			
+			if (front_field->ch != back_field->ch) {
+				back_field->ch = front_field->ch;
+				update = true;
+			}
+			
+			if (!attrs_same(front_field->attrs, back_field->attrs)) {
+				back_field->attrs = front_field->attrs;
+				update = true;
+			}
+			
+			front_field->flags &= ~CHAR_FLAG_DIRTY;
+			
+			if (update)
+				dev->ops.char_update(dev, x, y);
+		}
+	}
+	
+	return true;
+}
+
+static void srv_update(ipc_callid_t iid, ipc_call_t *icall)
+{
+	frontbuf_t *frontbuf = resolve_frontbuf(IPC_GET_ARG1(*icall), iid);
+	if (frontbuf == NULL)
+		return;
+	
+	chargrid_t *buf = (chargrid_t *) frontbuf->data;
+	
+	list_foreach(outdevs, link) {
+		outdev_t *dev = list_get_instance(link, outdev_t, link);
+		
+		assert(dev->ops.char_update);
+		
+		if (srv_update_scroll(dev, buf))
+			continue;
+		
+		for (sysarg_t y = 0; y < dev->rows; y++) {
+			for (sysarg_t x = 0; x < dev->cols; x++) {
+				charfield_t *front_field =
+				    chargrid_charfield_at(buf, x, y);
+				charfield_t *back_field =
+				    chargrid_charfield_at(dev->backbuf, x, y);
+				bool update = false;
+				
+				if ((front_field->flags & CHAR_FLAG_DIRTY) ==
+				    CHAR_FLAG_DIRTY) {
+					if (front_field->ch != back_field->ch) {
+						back_field->ch = front_field->ch;
+						update = true;
+					}
+					
+					if (!attrs_same(front_field->attrs,
+					    back_field->attrs)) {
+						back_field->attrs = front_field->attrs;
+						update = true;
+					}
+					
+					front_field->flags &= ~CHAR_FLAG_DIRTY;
+				}
+				
+				if (update)
+					dev->ops.char_update(dev, x, y);
+			}
+		}
+	}
+	
+	async_answer_0(iid, EOK);
+}
+
+static void srv_damage(ipc_callid_t iid, ipc_call_t *icall)
+{
+	frontbuf_t *frontbuf = resolve_frontbuf(IPC_GET_ARG1(*icall), iid);
+	if (frontbuf == NULL)
+		return;
+	
+	chargrid_t *buf = (chargrid_t *) frontbuf->data;
+	
+	list_foreach(outdevs, link) {
+		outdev_t *dev = list_get_instance(link, outdev_t, link);
+		
+		assert(dev->ops.char_update);
+		
+		if (srv_update_scroll(dev, buf))
+			continue;
+		
+		sysarg_t col = IPC_GET_ARG2(*icall);
+		sysarg_t row = IPC_GET_ARG3(*icall);
+		
+		sysarg_t cols = IPC_GET_ARG4(*icall);
+		sysarg_t rows = IPC_GET_ARG5(*icall);
+		
+		for (sysarg_t y = 0; y < rows; y++) {
+			for (sysarg_t x = 0; x < cols; x++) {
+				charfield_t *front_field =
+				    chargrid_charfield_at(buf, col + x, row + y);
+				charfield_t *back_field =
+				    chargrid_charfield_at(dev->backbuf, col + x, row + y);
+				
+				back_field->ch = front_field->ch;
+				back_field->attrs = front_field->attrs;
+				front_field->flags &= ~CHAR_FLAG_DIRTY;
+				dev->ops.char_update(dev, col + x, row + y);
+			}
+		}
+	}
+	
+	async_answer_0(iid, EOK);
+}
+
+static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			async_answer_0(callid, EOK);
+			break;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
+			case OUTPUT_YIELD:
+				srv_yield(callid, &call);
+				break;
+			case OUTPUT_CLAIM:
+				srv_claim(callid, &call);
+				break;
+			case OUTPUT_GET_DIMENSIONS:
+				srv_get_dimensions(callid, &call);
+				break;
+			case OUTPUT_GET_CAPS:
+				srv_get_caps(callid, &call);
+				break;
+			
+			case OUTPUT_FRONTBUF_CREATE:
+				srv_frontbuf_create(callid, &call);
+				break;
+			case OUTPUT_FRONTBUF_DESTROY:
+				srv_frontbuf_destroy(callid, &call);
+				break;
+			
+			case OUTPUT_CURSOR_UPDATE:
+				srv_cursor_update(callid, &call);
+				break;
+			case OUTPUT_SET_STYLE:
+				srv_set_style(callid, &call);
+				break;
+			case OUTPUT_SET_COLOR:
+				srv_set_color(callid, &call);
+				break;
+			case OUTPUT_SET_RGB_COLOR:
+				srv_set_rgb_color(callid, &call);
+				break;
+			
+			case OUTPUT_UPDATE:
+				srv_update(callid, &call);
+				break;
+			case OUTPUT_DAMAGE:
+				srv_damage(callid, &call);
+				break;
+			
+			default:
+				async_answer_0(callid, EINVAL);
+		}
+	}
+}
+
+static void usage(char *name)
+{
+	printf("Usage: %s <service_name>\n", name);
+}
+
+int main(int argc, char *argv[])
+{
+	if (argc < 2) {
+		usage(argv[0]);
+		return 1;
+	}
+	
+	printf("%s: HelenOS output service\n", NAME);
+	
+	/* Register server */
+	async_set_client_connection(client_connection);
+	int rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		printf("%s: Unable to register driver\n", NAME);
+		return rc;
+	}
+	
+	service_id_t service_id;
+	rc = loc_service_register(argv[1], &service_id);
+	if (rc != EOK) {
+		printf("%s: Unable to register service %s\n", NAME, argv[1]);
+		return rc;
+	}
+	
+	ega_init();
+	kchar_init();
+	niagara_init();
+	ski_init();
+	
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
+	async_manager();
+	
+	/* Never reached */
+	return 0;
+}
Index: uspace/srv/hid/output/output.h
===================================================================
--- uspace/srv/hid/output/output.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/output.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#ifndef OUTPUT_OUTPUT_H_
+#define OUTPUT_OUTPUT_H_
+
+#include <sys/types.h>
+#include <bool.h>
+#include <loc.h>
+#include <io/console.h>
+#include <io/style.h>
+#include <io/color.h>
+#include <io/chargrid.h>
+
+#define NAME  "output"
+
+struct outdev;
+
+typedef struct {
+	int (* yield)(struct outdev *dev);
+	int (* claim)(struct outdev *dev);
+	
+	void (* get_dimensions)(struct outdev *dev, sysarg_t *cols,
+	    sysarg_t *rows);
+	console_caps_t (* get_caps)(struct outdev *dev);
+	
+	void (* cursor_update)(struct outdev *dev, sysarg_t prev_col,
+	    sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible);
+	void (* char_update)(struct outdev *dev, sysarg_t col, sysarg_t row);
+} outdev_ops_t;
+
+typedef struct outdev {
+	link_t link;
+	
+	sysarg_t cols;
+	sysarg_t rows;
+	char_attrs_t attrs;
+	
+	chargrid_t *backbuf;
+	sysarg_t top_row;
+	
+	outdev_ops_t ops;
+	void *data;
+} outdev_t;
+
+extern outdev_t *outdev_register(outdev_ops_t *, void *);
+
+#endif
Index: uspace/srv/hid/output/port/ega.c
===================================================================
--- uspace/srv/hid/output/port/ega.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/port/ega.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @file
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <sysinfo.h>
+#include <align.h>
+#include <as.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <io/chargrid.h>
+#include "../output.h"
+#include "ega.h"
+
+#define EGA_IO_BASE  ((ioport8_t *) 0x3d4)
+#define EGA_IO_SIZE  2
+
+#define FB_POS(x, y)  (((y) * ega.cols + (x)) << 1)
+
+typedef struct {
+	sysarg_t cols;
+	sysarg_t rows;
+	
+	uint8_t style_normal;
+	uint8_t style_inverted;
+	
+	size_t size;
+	uint8_t *addr;
+} ega_t;
+
+static ega_t ega;
+
+static uint8_t attrs_attr(char_attrs_t attrs)
+{
+	uint8_t attr = 0;
+	
+	switch (attrs.type) {
+	case CHAR_ATTR_STYLE:
+		switch (attrs.val.style) {
+		case STYLE_NORMAL:
+			attr = ega.style_normal;
+			break;
+		case STYLE_EMPHASIS:
+			attr = (ega.style_normal | 0x04);
+			break;
+		case STYLE_INVERTED:
+			attr = ega.style_inverted;
+			break;
+		case STYLE_SELECTED:
+			attr = (ega.style_inverted | 0x40);
+			break;
+		}
+		break;
+	case CHAR_ATTR_INDEX:
+		attr = ((attrs.val.index.bgcolor & 7) << 4) |
+		    (attrs.val.index.fgcolor & 7);
+		
+		if (attrs.val.index.attr & CATTR_BRIGHT)
+			attr |= 0x08;
+		
+		break;
+	case CHAR_ATTR_RGB:
+		attr = (attrs.val.rgb.bgcolor < attrs.val.rgb.fgcolor) ?
+		    ega.style_inverted : ega.style_normal;
+		break;
+	}
+	
+	return attr;
+}
+
+/** Draw the character at the specified position.
+ *
+ * @param field Character field.
+ * @param col   Horizontal screen position.
+ * @param row   Vertical screen position.
+ *
+ */
+static void draw_char(charfield_t *field, sysarg_t col, sysarg_t row)
+{
+	uint8_t glyph;
+	
+	if (ascii_check(field->ch))
+		glyph = field->ch;
+	else
+		glyph = '?';
+	
+	uint8_t attr = attrs_attr(field->attrs);
+	
+	ega.addr[FB_POS(col, row)] = glyph;
+	ega.addr[FB_POS(col, row) + 1] = attr;
+}
+
+static int ega_yield(outdev_t *dev)
+{
+	return EOK;
+}
+
+static int ega_claim(outdev_t *dev)
+{
+	return EOK;
+}
+
+static void ega_get_dimensions(outdev_t *dev, sysarg_t *cols, sysarg_t *rows)
+{
+	*cols = ega.cols;
+	*rows = ega.rows;
+}
+
+static console_caps_t ega_get_caps(outdev_t *dev)
+{
+	return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED);
+}
+
+static void ega_cursor_update(outdev_t *dev, sysarg_t prev_col,
+    sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
+{
+	/* Cursor position */
+	uint16_t cursor = row * ega.cols + col;
+	
+	pio_write_8(EGA_IO_BASE, 0x0e);
+	pio_write_8(EGA_IO_BASE + 1, (cursor >> 8) & 0xff);
+	pio_write_8(EGA_IO_BASE, 0x0f);
+	pio_write_8(EGA_IO_BASE + 1, cursor & 0xff);
+	
+	/* Cursor visibility */
+	pio_write_8(EGA_IO_BASE, 0x0a);
+	uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
+	
+	pio_write_8(EGA_IO_BASE, 0x0a);
+	
+	if (visible)
+		pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5)));
+	else
+		pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5));
+}
+
+static void ega_char_update(outdev_t *dev, sysarg_t col, sysarg_t row)
+{
+	charfield_t *field =
+	    chargrid_charfield_at(dev->backbuf, col, row);
+	
+	draw_char(field, col, row);
+}
+
+static outdev_ops_t ega_ops = {
+	.yield = ega_yield,
+	.claim = ega_claim,
+	.get_dimensions = ega_get_dimensions,
+	.get_caps = ega_get_caps,
+	.cursor_update = ega_cursor_update,
+	.char_update = ega_char_update
+};
+
+int ega_init(void)
+{
+	sysarg_t present;
+	int rc = sysinfo_get_value("fb", &present);
+	if (rc != EOK)
+		present = false;
+	
+	if (!present)
+		return ENOENT;
+	
+	sysarg_t kind;
+	rc = sysinfo_get_value("fb.kind", &kind);
+	if (rc != EOK)
+		kind = (sysarg_t) -1;
+	
+	if (kind != 2)
+		return EINVAL;
+	
+	sysarg_t paddr;
+	rc = sysinfo_get_value("fb.address.physical", &paddr);
+	if (rc != EOK)
+		return rc;
+	
+	rc = sysinfo_get_value("fb.width", &ega.cols);
+	if (rc != EOK)
+		return rc;
+	
+	rc = sysinfo_get_value("fb.height", &ega.rows);
+	if (rc != EOK)
+		return rc;
+	
+	rc = iospace_enable(task_get_id(), (void *) EGA_IO_BASE,
+	    EGA_IO_SIZE);
+	if (rc != EOK)
+		return rc;
+	
+	ega.size = (ega.cols * ega.rows) << 1;
+	
+	rc = physmem_map((void *) paddr,
+	    ALIGN_UP(ega.size, PAGE_SIZE) >> PAGE_WIDTH,
+	    AS_AREA_READ | AS_AREA_WRITE, (void *) &ega.addr);
+	if (rc != EOK)
+		return rc;
+	
+	sysarg_t blinking;
+	rc = sysinfo_get_value("fb.blinking", &blinking);
+	if (rc != EOK)
+		blinking = false;
+	
+	ega.style_normal = 0xf0;
+	ega.style_inverted = 0x0f;
+	
+	if (blinking) {
+		ega.style_normal &= 0x77;
+		ega.style_inverted &= 0x77;
+	}
+	
+	outdev_t *dev = outdev_register(&ega_ops, (void *) &ega);
+	if (dev == NULL) {
+		as_area_destroy(ega.addr);
+		return EINVAL;
+	}
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/hid/output/port/ega.h
===================================================================
--- uspace/srv/hid/output/port/ega.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/port/ega.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/** @file
+ */
+
+#ifndef OUTPUT_PORT_EGA_H_
+#define OUTPUT_PORT_EGA_H_
+
+extern int ega_init(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/output/port/kchar.c
===================================================================
--- uspace/srv/hid/output/port/kchar.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/port/kchar.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2008 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.
+ */
+
+/** @file
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <str.h>
+#include <sysinfo.h>
+#include <ddi.h>
+#include <align.h>
+#include <as.h>
+#include "../ctl/serial.h"
+#include "kchar.h"
+
+typedef struct {
+	uint8_t *addr;
+} kchar_t;
+
+static kchar_t kchar;
+
+static void kchar_putchar(wchar_t ch)
+{
+	if (ascii_check(ch))
+		*kchar.addr = ch;
+	else
+		*kchar.addr = '?';
+}
+
+static void kchar_control_puts(const char *str)
+{
+	while (*str)
+		*kchar.addr = *(str++);
+}
+
+int kchar_init(void)
+{
+	sysarg_t present;
+	int rc = sysinfo_get_value("fb", &present);
+	if (rc != EOK)
+		present = false;
+	
+	if (!present)
+		return ENOENT;
+	
+	sysarg_t kind;
+	rc = sysinfo_get_value("fb.kind", &kind);
+	if (rc != EOK)
+		kind = (sysarg_t) -1;
+	
+	if (kind != 3)
+		return EINVAL;
+	
+	sysarg_t paddr;
+	rc = sysinfo_get_value("fb.address.physical", &paddr);
+	if (rc != EOK)
+		return rc;
+	
+	rc = physmem_map((void *) paddr,
+	    ALIGN_UP(1, PAGE_SIZE) >> PAGE_WIDTH,
+	    AS_AREA_READ | AS_AREA_WRITE, (void *) &kchar.addr);
+	if (rc != EOK)
+		return rc;
+	
+	return serial_init(kchar_putchar, kchar_control_puts);
+}
+
+/** @}
+ */
Index: uspace/srv/hid/output/port/kchar.h
===================================================================
--- uspace/srv/hid/output/port/kchar.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/port/kchar.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2008 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.
+ */
+
+/** @file
+ */
+
+#ifndef OUTPUT_PORT_KCHAR_H_
+#define OUTPUT_PORT_KCHAR_H_
+
+extern int kchar_init(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/output/port/kfb.c
===================================================================
--- uspace/srv/hid/output/port/kfb.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/port/kfb.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,787 @@
+/*
+ * Copyright (c) 2008 Martin Decky
+ * Copyright (c) 2006 Jakub Vana
+ * 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.
+ */
+
+/** @file
+ */
+
+#include <abi/fb/visuals.h>
+#include <sys/types.h>
+#include <inttypes.h>
+#include <screenbuffer.h>
+#include <imgmap.h>
+#include <errno.h>
+#include <bool.h>
+#include <sysinfo.h>
+#include <ddi.h>
+#include <malloc.h>
+#include <mem.h>
+#include <as.h>
+#include <align.h>
+#include "../gfx/font-8x16.h"
+#include "../fb.h"
+#include "kfb.h"
+
+#define DEFAULT_BGCOLOR  0xffffff
+#define DEFAULT_FGCOLOR  0x000000
+
+#define FB_POS(x, y)  ((y) * kfb.scanline + (x) * kfb.pixel_bytes)
+
+#define COL2X(col)  ((col) * FONT_WIDTH)
+#define ROW2Y(row)  ((row) * FONT_SCANLINES)
+#define X2COL(x)    ((x) / FONT_WIDTH)
+#define Y2ROW(y)    ((y) / FONT_SCANLINES)
+
+#define GLYPH_POS(glyph, y, inverted) \
+	(((glyph) + (inverted) * FONT_GLYPHS) * (kfb.glyph_bytes) + (y) * (kfb.glyph_scanline))
+
+#define POINTER_WIDTH   11
+#define POINTER_HEIGHT  18
+
+static uint8_t pointer[] = {
+	0x01, 0x00, 0x03, 0x00, 0x05, 0x00, 0x09, 0x00, 0x11, 0x00, 0x21, 0x00,
+	0x41, 0x00, 0x81, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x04, 0x01, 0x03,
+	0x81, 0x00, 0x89, 0x00, 0x15, 0x01, 0x23, 0x01, 0x21, 0x01, 0xc0, 0x00
+};
+
+static uint8_t pointer_mask[] = {
+	0x01, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x3f, 0x00,
+	0x7f, 0x00, 0xff, 0x00, 0xff, 0x01, 0xff, 0x03, 0xff, 0x07, 0xff, 0x03,
+	0xff, 0x00, 0xff, 0x00, 0xf7, 0x01, 0xe3, 0x01, 0xe1, 0x01, 0xc0, 0x00
+};
+
+/** Function to draw a character. */
+typedef void (*draw_char_t)(sysarg_t, sysarg_t, bool, wchar_t, pixel_t,
+    pixel_t);
+
+typedef struct {
+	sysarg_t width;
+	sysarg_t height;
+	size_t offset;
+	size_t scanline;
+	visual_t visual;
+	
+	size_t size;
+	uint8_t *addr;
+	
+	pixel2visual_t pixel2visual;
+	visual2pixel_t visual2pixel;
+	visual_mask_t visual_mask;
+	size_t pixel_bytes;
+	
+	sysarg_t pointer_x;
+	sysarg_t pointer_y;
+	bool pointer_visible;
+	imgmap_t *pointer_imgmap;
+	
+	/*
+	 * Pre-rendered mask for rendering
+	 * glyphs. Specific for the framebuffer
+	 * visual.
+	 */
+	
+	size_t glyph_scanline;
+	size_t glyph_bytes;
+	uint8_t *glyphs;
+	
+	uint8_t *backbuf;
+} kfb_t;
+
+typedef struct {
+	/**
+	 * Character drawing function for this viewport.
+	 * Different viewports might use different drawing
+	 * functions depending on whether their scanlines
+	 * are aligned on a word boundary.
+	 */
+	draw_char_t draw_char;
+} kfb_vp_t;
+
+static kfb_t kfb;
+
+static pixel_t color_table[16] = {
+	[COLOR_BLACK]       = 0x000000,
+	[COLOR_BLUE]        = 0x0000f0,
+	[COLOR_GREEN]       = 0x00f000,
+	[COLOR_CYAN]        = 0x00f0f0,
+	[COLOR_RED]         = 0xf00000,
+	[COLOR_MAGENTA]     = 0xf000f0,
+	[COLOR_YELLOW]      = 0xf0f000,
+	[COLOR_WHITE]       = 0xf0f0f0,
+	
+	[COLOR_BLACK + 8]   = 0x000000,
+	[COLOR_BLUE + 8]    = 0x0000ff,
+	[COLOR_GREEN + 8]   = 0x00ff00,
+	[COLOR_CYAN + 8]    = 0x00ffff,
+	[COLOR_RED + 8]     = 0xff0000,
+	[COLOR_MAGENTA + 8] = 0xff00ff,
+	[COLOR_YELLOW + 8]  = 0xffff00,
+	[COLOR_WHITE + 8]   = 0xffffff,
+};
+
+static void put_pixel(sysarg_t x, sysarg_t y, pixel_t pixel)
+{
+	if ((x >= kfb.width) || (y >= kfb.height))
+		return;
+	
+	kfb.pixel2visual(kfb.addr + FB_POS(x, y), pixel);
+}
+
+static pixel_t get_pixel(sysarg_t x, sysarg_t y)
+{
+	if ((x >= kfb.width) || (y >= kfb.height))
+		return 0;
+	
+	return kfb.visual2pixel(kfb.addr + FB_POS(x, y));
+}
+
+static void pointer_show(void)
+{
+	if (kfb.pointer_visible) {
+		for (sysarg_t y = 0; y < POINTER_HEIGHT; y++) {
+			for (sysarg_t x = 0; x < POINTER_WIDTH; x++) {
+				sysarg_t dx = kfb.pointer_x + x;
+				sysarg_t dy = kfb.pointer_y + y;
+				
+				pixel_t pixel = get_pixel(dx, dy);
+				imgmap_put_pixel(kfb.pointer_imgmap, x, y, pixel);
+				
+				size_t offset = y * ((POINTER_WIDTH - 1) / 8 + 1) + x / 8;
+				bool visible = pointer_mask[offset] & (1 << (x % 8));
+				
+				if (visible) {
+					pixel = (pointer[offset] & (1 << (x % 8))) ?
+					    0x000000 : 0xffffff;
+					put_pixel(dx, dy, pixel);
+				}
+			}
+		}
+	}
+}
+
+static void pointer_hide(void)
+{
+	if (kfb.pointer_visible) {
+		for (sysarg_t y = 0; y < POINTER_HEIGHT; y++) {
+			for (sysarg_t x = 0; x < POINTER_WIDTH; x++) {
+				sysarg_t dx = kfb.pointer_x + x;
+				sysarg_t dy = kfb.pointer_y + y;
+				
+				pixel_t pixel =
+				    imgmap_get_pixel(kfb.pointer_imgmap, x, y);
+				put_pixel(dx, dy, pixel);
+			}
+		}
+	}
+}
+
+/** Draw a filled rectangle.
+ *
+ */
+static void draw_filled_rect(sysarg_t x1, sysarg_t y1, sysarg_t x2, sysarg_t y2,
+    pixel_t color)
+{
+	if ((y1 >= y2) || (x1 >= x2))
+		return;
+	
+	uint8_t cbuf[4];
+	kfb.pixel2visual(cbuf, color);
+	
+	for (sysarg_t y = y1; y < y2; y++) {
+		uint8_t *dst = kfb.addr + FB_POS(x1, y);
+		
+		for (sysarg_t x = x1; x < x2; x++) {
+			memcpy(dst, cbuf, kfb.pixel_bytes);
+			dst += kfb.pixel_bytes;
+		}
+	}
+}
+
+static void vp_put_pixel(fbvp_t *vp, sysarg_t x, sysarg_t y, pixel_t pixel)
+{
+	put_pixel(vp->x + x, vp->y + y, pixel);
+}
+
+static void attrs_rgb(char_attrs_t attrs, pixel_t *bgcolor, pixel_t *fgcolor)
+{
+	switch (attrs.type) {
+	case CHAR_ATTR_STYLE:
+		switch (attrs.val.style) {
+		case STYLE_NORMAL:
+			*bgcolor = color_table[COLOR_WHITE];
+			*fgcolor = color_table[COLOR_BLACK];
+			break;
+		case STYLE_EMPHASIS:
+			*bgcolor = color_table[COLOR_WHITE];
+			*fgcolor = color_table[COLOR_RED];
+			break;
+		case STYLE_INVERTED:
+			*bgcolor = color_table[COLOR_BLACK];
+			*fgcolor = color_table[COLOR_WHITE];
+			break;
+		case STYLE_SELECTED:
+			*bgcolor = color_table[COLOR_RED];
+			*fgcolor = color_table[COLOR_WHITE];
+			break;
+		}
+		break;
+	case CHAR_ATTR_INDEX:
+		*bgcolor = color_table[(attrs.val.index.bgcolor & 7) |
+		    ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
+		*fgcolor = color_table[(attrs.val.index.fgcolor & 7) |
+		    ((attrs.val.index.attr & CATTR_BRIGHT) ? 8 : 0)];
+		break;
+	case CHAR_ATTR_RGB:
+		*bgcolor = attrs.val.rgb.bgcolor;
+		*fgcolor = attrs.val.rgb.fgcolor;
+		break;
+	}
+}
+
+/** Draw a character, takes advantage of alignment.
+ *
+ * This version can only be used if the following conditions are met:
+ *
+ *   - word size is divisible by pixel_bytes
+ *   - cell scanline size is divisible by word size
+ *   - cell scanlines are word-aligned
+ *
+ * It makes use of the pre-rendered mask to process (possibly) several
+ * pixels at once (word size / pixel_bytes pixels at a time are processed)
+ * making it very fast. Most notably this version is not applicable at 24 bits
+ * per pixel.
+ *
+ * @param x        X coordinate of top-left corner on screen.
+ * @param y        Y coordinate of top-left corner on screen.
+ * @param inverted Draw inverted character.
+ * @param ch       Character to draw.
+ * @param bgcolor  Background color.
+ * @param fbgcolor Foreground color.
+ *
+ */
+static void draw_char_aligned(sysarg_t x, sysarg_t y, bool inverted, wchar_t ch,
+    pixel_t bgcolor, pixel_t fgcolor)
+{
+	size_t word_size = sizeof(unsigned long);
+	
+	/*
+	 * Prepare a pair of words, one filled with foreground-color
+	 * pattern and the other filled with background-color pattern.
+	 */
+	unsigned long fg_buf;
+	unsigned long bg_buf;
+	
+	for (size_t i = 0; i < word_size / kfb.pixel_bytes; i++) {
+		kfb.pixel2visual(&((uint8_t *) &bg_buf)[i * kfb.pixel_bytes],
+		    bgcolor);
+		kfb.pixel2visual(&((uint8_t *) &fg_buf)[i * kfb.pixel_bytes],
+		    fgcolor);
+	}
+	
+	/* Pointer to the current position in the mask. */
+	unsigned long *maskp =
+	    (unsigned long *) &kfb.glyphs[GLYPH_POS(
+	    fb_font_glyph(ch), 0, inverted)];
+	
+	/* Pointer to the current position on the screen. */
+	unsigned long *dst =
+	    (unsigned long *) &kfb.addr[FB_POS(x, y)];
+	
+	/* Width of the character cell in words. */
+	size_t ww = FONT_WIDTH * kfb.pixel_bytes / word_size;
+	
+	/* Offset to add when moving to another screen scanline. */
+	size_t d_add = kfb.scanline - FONT_WIDTH * kfb.pixel_bytes;
+	
+	for (size_t yd = 0; yd < FONT_SCANLINES; yd++) {
+		/*
+		 * Now process the cell scanline, combining foreground
+		 * and background color patters using the pre-rendered mask.
+		 */
+		for (size_t i = 0; i < ww; i++) {
+			unsigned long mask = *maskp++;
+			*dst++ = (fg_buf & mask) | (bg_buf & ~mask);
+		}
+		
+		/* Move to the beginning of the next scanline of the cell. */
+		dst = (unsigned long *) ((uint8_t *) dst + d_add);
+	}
+}
+
+/** Draw a character, fallback version.
+ *
+ * This version does not make use of the pre-rendered mask, it uses
+ * the font bitmap directly. It works always, but it is slower.
+ *
+ * @param x        X coordinate of top-left corner on screen.
+ * @param y        Y coordinate of top-left corner on screen.
+ * @param inverted Draw inverted character.
+ * @param ch       Character to draw.
+ * @param bgcolor  Background color.
+ * @param fgcolor  Foreground color.
+ *
+ */
+static void draw_char_fallback(sysarg_t x, sysarg_t y, bool inverted,
+    wchar_t ch, pixel_t bgcolor, pixel_t fgcolor)
+{
+	/* Character glyph */
+	uint16_t glyph = fb_font_glyph(ch);
+	
+	/* Pre-render the foreground and background color pixels. */
+	uint8_t fg_buf[4];
+	uint8_t bg_buf[4];
+	
+	if (inverted) {
+		kfb.pixel2visual(bg_buf, fgcolor);
+		kfb.pixel2visual(fg_buf, bgcolor);
+	} else {
+		kfb.pixel2visual(bg_buf, bgcolor);
+		kfb.pixel2visual(fg_buf, fgcolor);
+	}
+	
+	/* Pointer to the current position on the screen. */
+	uint8_t *dst = (uint8_t *) &kfb.addr[FB_POS(x, y)];
+	
+	/* Offset to add when moving to another screen scanline. */
+	size_t d_add = kfb.scanline - FONT_WIDTH * kfb.pixel_bytes;
+	
+	for (size_t yd = 0; yd < FONT_SCANLINES; yd++) {
+		/* Byte containing bits of the glyph scanline. */
+		uint8_t byte = fb_font[glyph][yd];
+		
+		for (size_t i = 0; i < FONT_WIDTH; i++) {
+			/* Choose color based on the current bit. */
+			uint8_t *src = (byte & 0x80) ? fg_buf : bg_buf;
+			
+			/* Copy the pixel. */
+			for (size_t j = 0; j < kfb.pixel_bytes; j++)
+				*dst++ = *src++;
+			
+			/* Move to the next bit. */
+			byte <<= 1;
+		}
+		
+		/* Move to the beginning of the next scanline of the cell. */
+		dst += d_add;
+	}
+}
+
+/** Draw the character at the specified position in viewport.
+ *
+ * @param vp     Viewport.
+ * @param col    Screen position relative to viewport.
+ * @param row    Screen position relative to viewport.
+ *
+ */
+static void draw_vp_char(fbvp_t *vp, sysarg_t col, sysarg_t row)
+{
+	kfb_vp_t *kfb_vp = (kfb_vp_t *) vp->data;
+	
+	sysarg_t x = vp->x + COL2X(col);
+	sysarg_t y = vp->y + ROW2Y(row);
+	
+	charfield_t *field = screenbuffer_field_at(vp->backbuf, col, row);
+	
+	pixel_t bgcolor = 0;
+	pixel_t fgcolor = 0;
+	attrs_rgb(field->attrs, &bgcolor, &fgcolor);
+	
+	bool inverted = (vp->cursor_flash) &&
+	    screenbuffer_cursor_at(vp->backbuf, col, row);
+	
+	(*kfb_vp->draw_char)(x, y, inverted, field->ch, bgcolor, fgcolor);
+}
+
+static int kfb_yield(fbdev_t *dev)
+{
+	if (kfb.backbuf == NULL) {
+		kfb.backbuf =
+		    malloc(kfb.width * kfb.height * kfb.pixel_bytes);
+		if (kfb.backbuf == NULL)
+			return ENOMEM;
+	}
+	
+	for (sysarg_t y = 0; y < kfb.height; y++)
+		memcpy(kfb.backbuf + y * kfb.width * kfb.pixel_bytes,
+		    kfb.addr + FB_POS(0, y), kfb.width * kfb.pixel_bytes);
+	
+	return EOK;
+}
+
+static int kfb_claim(fbdev_t *dev)
+{
+	if (kfb.backbuf == NULL)
+		return ENOENT;
+	
+	for (sysarg_t y = 0; y < kfb.height; y++)
+		memcpy(kfb.addr + FB_POS(0, y),
+		    kfb.backbuf + y * kfb.width * kfb.pixel_bytes,
+		    kfb.width * kfb.pixel_bytes);
+	
+	return EOK;
+}
+
+static void kfb_pointer_update(struct fbdev *dev, sysarg_t x, sysarg_t y,
+    bool visible)
+{
+	pointer_hide();
+	
+	kfb.pointer_x = x;
+	kfb.pointer_y = y;
+	kfb.pointer_visible = visible;
+	
+	pointer_show();
+}
+
+static int kfb_get_resolution(fbdev_t *dev, sysarg_t *width, sysarg_t *height)
+{
+	*width = kfb.width;
+	*height = kfb.height;
+	return EOK;
+}
+
+static void kfb_font_metrics(fbdev_t *dev, sysarg_t width, sysarg_t height,
+    sysarg_t *cols, sysarg_t *rows)
+{
+	*cols = X2COL(width);
+	*rows = Y2ROW(height);
+}
+
+static int kfb_vp_create(fbdev_t *dev, fbvp_t *vp)
+{
+	kfb_vp_t *kfb_vp = malloc(sizeof(kfb_vp_t));
+	if (kfb_vp == NULL)
+		return ENOMEM;
+	
+	/*
+	 * Conditions necessary to select aligned glyph
+	 * drawing variants:
+	 *  - word size is divisible by number of bytes per pixel
+	 *  - cell scanline size is divisible by word size
+	 *  - cell scanlines are word-aligned
+	 *
+	 */
+	size_t word_size = sizeof(unsigned long);
+	
+	if (((word_size % kfb.pixel_bytes) == 0)
+	    && ((FONT_WIDTH * kfb.pixel_bytes) % word_size == 0)
+	    && ((vp->x * kfb.pixel_bytes) % word_size == 0)
+	    && (kfb.scanline % word_size == 0))
+		kfb_vp->draw_char = draw_char_aligned;
+	else
+		kfb_vp->draw_char = draw_char_fallback;
+	
+	vp->attrs.type = CHAR_ATTR_RGB;
+	vp->attrs.val.rgb.bgcolor = DEFAULT_BGCOLOR;
+	vp->attrs.val.rgb.fgcolor = DEFAULT_FGCOLOR;
+	vp->data = (void *) kfb_vp;
+	
+	return EOK;
+}
+
+static void kfb_vp_destroy(fbdev_t *dev, fbvp_t *vp)
+{
+	free(vp->data);
+}
+
+static void kfb_vp_clear(fbdev_t *dev, fbvp_t *vp)
+{
+	pointer_hide();
+	
+	for (sysarg_t row = 0; row < vp->rows; row++) {
+		for (sysarg_t col = 0; col < vp->cols; col++) {
+			charfield_t *field =
+			    screenbuffer_field_at(vp->backbuf, col, row);
+			
+			field->ch = 0;
+			field->attrs = vp->attrs;
+		}
+	}
+	
+	pixel_t bgcolor = 0;
+	pixel_t fgcolor = 0;
+	attrs_rgb(vp->attrs, &bgcolor, &fgcolor);
+	
+	draw_filled_rect(vp->x, vp->y, vp->x + vp->width,
+	    vp->y + vp->height, bgcolor);
+	
+	pointer_show();
+}
+
+static console_caps_t kfb_vp_get_caps(fbdev_t *dev, fbvp_t *vp)
+{
+	return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED | CONSOLE_CAP_RGB);
+}
+
+static void kfb_vp_cursor_update(fbdev_t *dev, fbvp_t *vp, sysarg_t prev_col,
+    sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
+{
+	pointer_hide();
+	draw_vp_char(vp, prev_col, prev_row);
+	draw_vp_char(vp, col, row);
+	pointer_show();
+}
+
+static void kfb_vp_cursor_flash(fbdev_t *dev, fbvp_t *vp, sysarg_t col,
+    sysarg_t row)
+{
+	pointer_hide();
+	draw_vp_char(vp, col, row);
+	pointer_show();
+}
+
+static void kfb_vp_char_update(fbdev_t *dev, fbvp_t *vp, sysarg_t col,
+    sysarg_t row)
+{
+	pointer_hide();
+	draw_vp_char(vp, col, row);
+	pointer_show();
+}
+
+static void kfb_vp_imgmap_damage(fbdev_t *dev, fbvp_t *vp, imgmap_t *imgmap,
+    sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height)
+{
+	pointer_hide();
+	
+	for (sysarg_t y = 0; y < height; y++) {
+		for (sysarg_t x = 0; x < width; x++) {
+			pixel_t pixel = imgmap_get_pixel(imgmap, x0 + x, y0 + y);
+			vp_put_pixel(vp, x0 + x, y0 + y, pixel);
+		}
+	}
+	
+	pointer_show();
+}
+
+static fbdev_ops_t kfb_ops = {
+	.yield = kfb_yield,
+	.claim = kfb_claim,
+	.pointer_update = kfb_pointer_update,
+	.get_resolution = kfb_get_resolution,
+	.font_metrics = kfb_font_metrics,
+	.vp_create = kfb_vp_create,
+	.vp_destroy = kfb_vp_destroy,
+	.vp_clear = kfb_vp_clear,
+	.vp_get_caps = kfb_vp_get_caps,
+	.vp_cursor_update = kfb_vp_cursor_update,
+	.vp_cursor_flash = kfb_vp_cursor_flash,
+	.vp_char_update = kfb_vp_char_update,
+	.vp_imgmap_damage = kfb_vp_imgmap_damage
+};
+
+/** Render glyphs
+ *
+ * Convert glyphs from device independent font
+ * description to current visual representation.
+ *
+ */
+static void render_glyphs(size_t sz)
+{
+	memset(kfb.glyphs, 0, sz);
+	
+	for (unsigned int glyph = 0; glyph < FONT_GLYPHS; glyph++) {
+		for (unsigned int y = 0; y < FONT_SCANLINES; y++) {
+			for (unsigned int x = 0; x < FONT_WIDTH; x++) {
+				kfb.visual_mask(
+				    &kfb.glyphs[GLYPH_POS(glyph, y, false) + x * kfb.pixel_bytes],
+				    (fb_font[glyph][y] & (1 << (7 - x))) ? true : false);
+				kfb.visual_mask(
+				    &kfb.glyphs[GLYPH_POS(glyph, y, true) + x * kfb.pixel_bytes],
+				    (fb_font[glyph][y] & (1 << (7 - x))) ? false : true);
+			}
+		}
+	}
+}
+
+int kfb_init(void)
+{
+	sysarg_t present;
+	int rc = sysinfo_get_value("fb", &present);
+	if (rc != EOK)
+		present = false;
+	
+	if (!present)
+		return ENOENT;
+	
+	sysarg_t kind;
+	rc = sysinfo_get_value("fb.kind", &kind);
+	if (rc != EOK)
+		kind = (sysarg_t) -1;
+	
+	if (kind != 1)
+		return EINVAL;
+	
+	sysarg_t paddr;
+	rc = sysinfo_get_value("fb.address.physical", &paddr);
+	if (rc != EOK)
+		return rc;
+	
+	sysarg_t offset;
+	rc = sysinfo_get_value("fb.offset", &offset);
+	if (rc != EOK)
+		offset = 0;
+	
+	sysarg_t width;
+	rc = sysinfo_get_value("fb.width", &width);
+	if (rc != EOK)
+		return rc;
+	
+	sysarg_t height;
+	rc = sysinfo_get_value("fb.height", &height);
+	if (rc != EOK)
+		return rc;
+	
+	sysarg_t scanline;
+	rc = sysinfo_get_value("fb.scanline", &scanline);
+	if (rc != EOK)
+		return rc;
+	
+	sysarg_t visual;
+	rc = sysinfo_get_value("fb.visual", &visual);
+	if (rc != EOK)
+		return rc;
+	
+	kfb.width = width;
+	kfb.height = height;
+	kfb.offset = offset;
+	kfb.scanline = scanline;
+	kfb.visual = visual;
+	
+	switch (visual) {
+	case VISUAL_INDIRECT_8:
+		kfb.pixel2visual = pixel2bgr_323;
+		kfb.visual2pixel = bgr_323_2pixel;
+		kfb.visual_mask = visual_mask_323;
+		kfb.pixel_bytes = 1;
+		break;
+	case VISUAL_RGB_5_5_5_LE:
+		kfb.pixel2visual = pixel2rgb_555_le;
+		kfb.visual2pixel = rgb_555_le_2pixel;
+		kfb.visual_mask = visual_mask_555;
+		kfb.pixel_bytes = 2;
+		break;
+	case VISUAL_RGB_5_5_5_BE:
+		kfb.pixel2visual = pixel2rgb_555_be;
+		kfb.visual2pixel = rgb_555_be_2pixel;
+		kfb.visual_mask = visual_mask_555;
+		kfb.pixel_bytes = 2;
+		break;
+	case VISUAL_RGB_5_6_5_LE:
+		kfb.pixel2visual = pixel2rgb_565_le;
+		kfb.visual2pixel = rgb_565_le_2pixel;
+		kfb.visual_mask = visual_mask_565;
+		kfb.pixel_bytes = 2;
+		break;
+	case VISUAL_RGB_5_6_5_BE:
+		kfb.pixel2visual = pixel2rgb_565_be;
+		kfb.visual2pixel = rgb_565_be_2pixel;
+		kfb.visual_mask = visual_mask_565;
+		kfb.pixel_bytes = 2;
+		break;
+	case VISUAL_RGB_8_8_8:
+		kfb.pixel2visual = pixel2rgb_888;
+		kfb.visual2pixel = rgb_888_2pixel;
+		kfb.visual_mask = visual_mask_888;
+		kfb.pixel_bytes = 3;
+		break;
+	case VISUAL_BGR_8_8_8:
+		kfb.pixel2visual = pixel2bgr_888;
+		kfb.visual2pixel = bgr_888_2pixel;
+		kfb.visual_mask = visual_mask_888;
+		kfb.pixel_bytes = 3;
+		break;
+	case VISUAL_RGB_8_8_8_0:
+		kfb.pixel2visual = pixel2rgb_8880;
+		kfb.visual2pixel = rgb_8880_2pixel;
+		kfb.visual_mask = visual_mask_8880;
+		kfb.pixel_bytes = 4;
+		break;
+	case VISUAL_RGB_0_8_8_8:
+		kfb.pixel2visual = pixel2rgb_0888;
+		kfb.visual2pixel = rgb_0888_2pixel;
+		kfb.visual_mask = visual_mask_0888;
+		kfb.pixel_bytes = 4;
+		break;
+	case VISUAL_BGR_0_8_8_8:
+		kfb.pixel2visual = pixel2bgr_0888;
+		kfb.visual2pixel = bgr_0888_2pixel;
+		kfb.visual_mask = visual_mask_0888;
+		kfb.pixel_bytes = 4;
+		break;
+	case VISUAL_BGR_8_8_8_0:
+		kfb.pixel2visual = pixel2bgr_8880;
+		kfb.visual2pixel = bgr_8880_2pixel;
+		kfb.visual_mask = visual_mask_8880;
+		kfb.pixel_bytes = 4;
+		break;
+	default:
+		return EINVAL;
+	}
+	
+	kfb.glyph_scanline = FONT_WIDTH * kfb.pixel_bytes;
+	kfb.glyph_bytes = kfb.glyph_scanline * FONT_SCANLINES;
+	
+	size_t sz = 2 * FONT_GLYPHS * kfb.glyph_bytes;
+	kfb.glyphs = (uint8_t *) malloc(sz);
+	if (kfb.glyphs == NULL)
+		return EINVAL;
+	
+	render_glyphs(sz);
+	
+	kfb.size = scanline * height;
+	
+	rc = physmem_map((void *) paddr + offset,
+	    ALIGN_UP(kfb.size, PAGE_SIZE) >> PAGE_WIDTH,
+	    AS_AREA_READ | AS_AREA_WRITE, (void *) &kfb.addr);
+	if (rc != EOK) {
+		free(kfb.glyphs);
+		return rc;
+	}
+	
+	kfb.pointer_x = 0;
+	kfb.pointer_y = 0;
+	kfb.pointer_visible = false;
+	kfb.pointer_imgmap = imgmap_create(POINTER_WIDTH, POINTER_HEIGHT,
+	    VISUAL_RGB_0_8_8_8, IMGMAP_FLAG_NONE);
+	
+	kfb.backbuf = NULL;
+	
+	fbdev_t *dev = fbdev_register(&kfb_ops, (void *) &kfb);
+	if (dev == NULL) {
+		free(kfb.glyphs);
+		as_area_destroy(kfb.addr);
+		return EINVAL;
+	}
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/output/port/kfb.h
===================================================================
--- uspace/srv/hid/output/port/kfb.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/port/kfb.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,44 @@
+/*
+ * 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 fb
+ * @ingroup fbs
+ * @{
+ */
+/** @file
+ */
+
+#ifndef FB_PORT_KFB_H_
+#define FB_PORT_KFB_H_
+
+extern int kfb_init(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/output/port/niagara.c
===================================================================
--- uspace/srv/hid/output/port/niagara.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/port/niagara.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2008 Martin Decky
+ * Copyright (c) 2008 Pavel Rimsky
+ * 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.
+ */
+
+/** @file
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <sysinfo.h>
+#include <ddi.h>
+#include <as.h>
+#include <align.h>
+#include <str.h>
+#include "../ctl/serial.h"
+#include "niagara.h"
+
+#define OUTPUT_FIFO_SIZE  ((PAGE_SIZE) - 2 * sizeof(uint64_t))
+
+typedef volatile struct {
+	uint64_t read_ptr;
+	uint64_t write_ptr;
+	char data[OUTPUT_FIFO_SIZE];
+} __attribute__((packed)) output_fifo_t;
+
+typedef struct {
+	output_fifo_t *fifo;
+} niagara_t;
+
+static niagara_t niagara;
+
+static void niagara_putc(const char c)
+{
+	while (niagara.fifo->write_ptr ==
+	    (niagara.fifo->read_ptr + OUTPUT_FIFO_SIZE - 1)
+	    % OUTPUT_FIFO_SIZE);
+	
+	niagara.fifo->data[niagara.fifo->write_ptr] = c;
+	niagara.fifo->write_ptr =
+	    ((niagara.fifo->write_ptr) + 1) % OUTPUT_FIFO_SIZE;
+}
+
+static void niagara_putchar(wchar_t ch)
+{
+	if (ascii_check(ch))
+		niagara_putc(ch);
+	else
+		niagara_putc('?');
+}
+
+static void niagara_control_puts(const char *str)
+{
+	while (*str)
+		niagara_putc(*(str++));
+}
+
+int niagara_init(void)
+{
+	sysarg_t present;
+	int rc = sysinfo_get_value("fb", &present);
+	if (rc != EOK)
+		present = false;
+	
+	if (!present)
+		return ENOENT;
+	
+	sysarg_t kind;
+	rc = sysinfo_get_value("fb.kind", &kind);
+	if (rc != EOK)
+		kind = (sysarg_t) -1;
+	
+	if (kind != 5)
+		return EINVAL;
+	
+	sysarg_t paddr;
+	rc = sysinfo_get_value("niagara.outbuf.address", &paddr);
+	if (rc != EOK)
+		return rc;
+	
+	rc = physmem_map((void *) paddr, 1,
+	    AS_AREA_READ | AS_AREA_WRITE, (void *) &niagara.fifo);
+	if (rc != EOK)
+		return rc;
+	
+	return serial_init(niagara_putchar, niagara_control_puts);
+}
+
+/** @}
+ */
Index: uspace/srv/hid/output/port/niagara.h
===================================================================
--- uspace/srv/hid/output/port/niagara.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/port/niagara.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2008 Pavel Rimsky
+ * 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.
+ */
+
+/** @file
+ */
+
+#ifndef OUTPUT_PORT_NIAGARA_H_
+#define OUTPUT_PORT_NIAGARA_H_
+
+extern int niagara_init(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/output/port/ski.c
===================================================================
--- uspace/srv/hid/output/port/ski.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/port/ski.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2008 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.
+ */
+
+/** @file
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <sysinfo.h>
+#include "../ctl/serial.h"
+#include "ski.h"
+
+#ifdef UARCH_ia64
+
+#define SKI_PUTCHAR  31
+
+/** Display character on ski debug console
+ *
+ * Use SSC (Simulator System Call) to
+ * display character on debug console.
+ *
+ * @param c Character to be printed.
+ *
+ */
+static void ski_putc(const char c)
+{
+	asm volatile (
+		"mov r15 = %0\n"
+		"mov r32 = %1\n"   /* r32 is in0 */
+		"break 0x80000\n"  /* modifies r8 */
+		:
+		: "i" (SKI_PUTCHAR), "r" (c)
+		: "r15", "in0", "r8"
+	);
+	
+	if (c == '\n')
+		ski_putc('\r');
+}
+
+static void ski_putchar(wchar_t ch)
+{
+	if ((ch >= 0) && (ch < 128))
+		ski_putc(ch);
+	else
+		ski_putc('?');
+}
+
+static void ski_control_puts(const char *str)
+{
+	while (*str)
+		ski_putc(*(str++));
+}
+
+int ski_init(void)
+{
+	sysarg_t present;
+	int rc = sysinfo_get_value("fb", &present);
+	if (rc != EOK)
+		present = false;
+	
+	if (!present)
+		return ENOENT;
+	
+	sysarg_t kind;
+	rc = sysinfo_get_value("fb.kind", &kind);
+	if (rc != EOK)
+		kind = (sysarg_t) -1;
+	
+	if (kind != 6)
+		return EINVAL;
+	
+	return serial_init(ski_putchar, ski_control_puts);
+}
+
+#else /* UARCH_ia64 */
+
+int ski_init(void)
+{
+	return ENOENT;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/output/port/ski.h
===================================================================
--- uspace/srv/hid/output/port/ski.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/port/ski.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2008 Jiri Svoboda
+ * 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 console
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef OUTPUT_PORT_SKI_H_
+#define OUTPUT_PORT_SKI_H_
+
+extern int ski_init(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/output/proto/vt100.c
===================================================================
--- uspace/srv/hid/output/proto/vt100.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/proto/vt100.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @file
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <io/color.h>
+#include "vt100.h"
+
+#define MAX_CONTROL  20
+
+typedef enum {
+	CI_BLACK   = 0,
+	CI_RED     = 1,
+	CI_GREEN   = 2,
+	CI_BROWN   = 3,
+	CI_BLUE    = 4,
+	CI_MAGENTA = 5,
+	CI_CYAN    = 6,
+	CI_WHITE   = 7
+} sgr_color_index_t;
+
+typedef enum {
+	SGR_RESET       = 0,
+	SGR_BOLD        = 1,
+	SGR_UNDERLINE   = 4,
+	SGR_BLINK       = 5,
+	SGR_REVERSE     = 7,
+	SGR_FGCOLOR     = 30,
+	SGR_BGCOLOR     = 40
+} sgr_command_t;
+
+static sgr_color_index_t color_map[] = {
+	[COLOR_BLACK]   = CI_BLACK,
+	[COLOR_BLUE]    = CI_RED,
+	[COLOR_GREEN]   = CI_GREEN,
+	[COLOR_CYAN]    = CI_CYAN,
+	[COLOR_RED]     = CI_RED,
+	[COLOR_MAGENTA] = CI_MAGENTA,
+	[COLOR_YELLOW]  = CI_BROWN,
+	[COLOR_WHITE]   = CI_WHITE
+};
+
+/** ECMA-48 Set Graphics Rendition. */
+static void vt100_sgr(vt100_state_t *state, unsigned int mode)
+{
+	char control[MAX_CONTROL];
+	
+	snprintf(control, MAX_CONTROL, "\033[%um", mode);
+	state->control_puts(control);
+}
+
+static void vt100_set_pos(vt100_state_t *state, sysarg_t col, sysarg_t row)
+{
+	char control[MAX_CONTROL];
+	
+	snprintf(control, MAX_CONTROL, "\033[%" PRIun ";%" PRIun "f",
+	    row + 1, col + 1);
+	state->control_puts(control);
+}
+
+static void vt100_set_sgr(vt100_state_t *state, char_attrs_t attrs)
+{
+	switch (attrs.type) {
+	case CHAR_ATTR_STYLE:
+		switch (attrs.val.style) {
+		case STYLE_NORMAL:
+			vt100_sgr(state, SGR_RESET);
+			vt100_sgr(state, SGR_BGCOLOR + CI_WHITE);
+			vt100_sgr(state, SGR_FGCOLOR + CI_BLACK);
+			break;
+		case STYLE_EMPHASIS:
+			vt100_sgr(state, SGR_RESET);
+			vt100_sgr(state, SGR_BGCOLOR + CI_WHITE);
+			vt100_sgr(state, SGR_FGCOLOR + CI_RED);
+			vt100_sgr(state, SGR_BOLD);
+			break;
+		case STYLE_INVERTED:
+			vt100_sgr(state, SGR_RESET);
+			vt100_sgr(state, SGR_BGCOLOR + CI_BLACK);
+			vt100_sgr(state, SGR_FGCOLOR + CI_WHITE);
+			break;
+		case STYLE_SELECTED:
+			vt100_sgr(state, SGR_RESET);
+			vt100_sgr(state, SGR_BGCOLOR + CI_RED);
+			vt100_sgr(state, SGR_FGCOLOR + CI_WHITE);
+			break;
+		}
+		break;
+	case CHAR_ATTR_INDEX:
+		vt100_sgr(state, SGR_RESET);
+		vt100_sgr(state, SGR_BGCOLOR + color_map[attrs.val.index.bgcolor & 7]);
+		vt100_sgr(state, SGR_FGCOLOR + color_map[attrs.val.index.fgcolor & 7]);
+		
+		if (attrs.val.index.attr & CATTR_BRIGHT)
+			vt100_sgr(state, SGR_BOLD);
+		
+		break;
+	case CHAR_ATTR_RGB:
+		vt100_sgr(state, SGR_RESET);
+		
+		if (attrs.val.rgb.bgcolor <= attrs.val.rgb.fgcolor)
+			vt100_sgr(state, SGR_REVERSE);
+		
+		break;
+	}
+}
+
+vt100_state_t *vt100_state_create(sysarg_t cols, sysarg_t rows,
+    vt100_putchar_t putchar_fn, vt100_control_puts_t control_puts_fn)
+{
+	vt100_state_t *state =
+	    malloc(sizeof(vt100_state_t));
+	if (state == NULL)
+		return NULL;
+	
+	state->putchar = putchar_fn;
+	state->control_puts = control_puts_fn;
+	
+	state->cols = cols;
+	state->rows = rows;
+	
+	state->cur_col = (sysarg_t) -1;
+	state->cur_row = (sysarg_t) -1;
+	
+	state->cur_attrs.type = CHAR_ATTR_STYLE;
+	state->cur_attrs.val.style = STYLE_NORMAL;
+	
+	/* Initialize graphic rendition attributes */
+	vt100_sgr(state, SGR_RESET);
+	vt100_sgr(state, SGR_FGCOLOR + CI_BLACK);
+	vt100_sgr(state, SGR_BGCOLOR + CI_WHITE);
+	state->control_puts("\033[2J");
+	state->control_puts("\033[?25l");
+	
+	return state;
+}
+
+void vt100_state_destroy(vt100_state_t *state)
+{
+	free(state);
+}
+
+void vt100_get_dimensions(vt100_state_t *state, sysarg_t *cols,
+    sysarg_t *rows)
+{
+	*cols = state->cols;
+	*rows = state->rows;
+}
+
+int vt100_yield(vt100_state_t *state)
+{
+	return EOK;
+}
+
+int vt100_claim(vt100_state_t *state)
+{
+	return EOK;
+}
+
+void vt100_goto(vt100_state_t *state, sysarg_t col, sysarg_t row)
+{
+	if ((col >= state->cols) || (row >= state->rows))
+		return;
+	
+	if ((col != state->cur_col) || (row != state->cur_row)) {
+		vt100_set_pos(state, col, row);
+		state->cur_col = col;
+		state->cur_row = row;
+	}
+}
+
+void vt100_set_attr(vt100_state_t *state, char_attrs_t attrs)
+{
+	if (!attrs_same(state->cur_attrs, attrs)) {
+		vt100_set_sgr(state, attrs);
+		state->cur_attrs = attrs;
+	}
+}
+
+void vt100_cursor_visibility(vt100_state_t *state, bool visible)
+{
+	if (visible)
+		state->control_puts("\033[?25h");
+	else
+		state->control_puts("\033[?25l");
+}
+
+void vt100_putchar(vt100_state_t *state, wchar_t ch)
+{
+	state->putchar(ch == 0 ? ' ' : ch);
+	state->cur_col++;
+	
+	if (state->cur_col >= state->cols) {
+		state->cur_row += state->cur_col / state->cols;
+		state->cur_col %= state->cols;
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/hid/output/proto/vt100.h
===================================================================
--- uspace/srv/hid/output/proto/vt100.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/hid/output/proto/vt100.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @file
+ */
+
+#ifndef OUTPUT_PROTO_VT100_H_
+#define OUTPUT_PROTO_VT100_H_
+
+#include <sys/types.h>
+#include <io/charfield.h>
+
+typedef void (* vt100_putchar_t)(wchar_t ch);
+typedef void (* vt100_control_puts_t)(const char *str);
+
+typedef struct {
+	sysarg_t cols;
+	sysarg_t rows;
+	
+	sysarg_t cur_col;
+	sysarg_t cur_row;
+	char_attrs_t cur_attrs;
+	
+	vt100_putchar_t putchar;
+	vt100_control_puts_t control_puts;
+} vt100_state_t;
+
+extern vt100_state_t *vt100_state_create(sysarg_t, sysarg_t, vt100_putchar_t,
+    vt100_control_puts_t);
+extern void vt100_state_destroy(vt100_state_t *);
+
+extern int vt100_yield(vt100_state_t *);
+extern int vt100_claim(vt100_state_t *);
+extern void vt100_get_dimensions(vt100_state_t *, sysarg_t *, sysarg_t *);
+
+extern void vt100_goto(vt100_state_t *, sysarg_t, sysarg_t);
+extern void vt100_set_attr(vt100_state_t *, char_attrs_t);
+extern void vt100_cursor_visibility(vt100_state_t *, bool);
+extern void vt100_putchar(vt100_state_t *, wchar_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/hid/remcons/remcons.c
===================================================================
--- uspace/srv/hid/remcons/remcons.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/remcons/remcons.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -34,10 +34,8 @@
 
 #include <async.h>
+#include <errno.h>
+#include <io/con_srv.h>
 #include <stdio.h>
-#include <adt/prodcons.h>
-#include <ipc/input.h>
-#include <ipc/console.h>
-#include <ipc/vfs.h>
-#include <errno.h>
+#include <stdlib.h>
 #include <str_error.h>
 #include <loc.h>
@@ -45,6 +43,4 @@
 #include <io/keycode.h>
 #include <align.h>
-#include <malloc.h>
-#include <as.h>
 #include <fibril_synch.h>
 #include <task.h>
@@ -75,116 +71,131 @@
     sizeof(telnet_force_character_mode_command) / sizeof(telnet_cmd_t);
 
-
-/** Handling client requests (VFS and console interface).
- *
- * @param user Telnet user the requests belong to.
- */
-static void client_connection_message_loop(telnet_user_t *user)
-{
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = 0;
-
-		/*
-		 * The getterm task might terminate while we are here,
-		 * waiting for a call. Also, the socket might be closed
-		 * meanwhile.
-		 * We want to detect this situation early, so we use a
-		 * timeout variant of async_get_call().
-		 */
-		while (callid == 0) {
-			callid = async_get_call_timeout(&call, 1000);
-
-			if (telnet_user_is_zombie(user)) {
-				if (callid != 0) {
-					async_answer_0(callid, EINTR);
-				}
-				return;
-			}
-		}
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			return;
-		}
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case CONSOLE_GET_SIZE:
-			async_answer_2(callid, EOK, 100, 1);
-			break;
-		case CONSOLE_GET_POS:
-			fibril_mutex_lock(&user->guard);
-			async_answer_2(callid, EOK, user->cursor_x, 0);
-			fibril_mutex_unlock(&user->guard);
-			break;
-		case CONSOLE_GET_EVENT: {
-			kbd_event_t event;
-			int rc = telnet_user_get_next_keyboard_event(user, &event);
-			if (rc != EOK) {
-				/* Silently ignore. */
-				async_answer_0(callid, EOK);
-				break;
-			}
-			async_answer_4(callid, EOK, event.type, event.key, event.mods, event.c);
-			break;
-		}
-		case CONSOLE_GOTO: {
-			int new_x = IPC_GET_ARG1(call);
-			telnet_user_update_cursor_x(user, new_x);
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-		case VFS_OUT_READ:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		case VFS_OUT_WRITE: {
-			uint8_t *buf;
-			size_t size;
-			int rc = async_data_write_accept((void **)&buf, false, 0, 0, 0, &size);
-
-			if (rc != EOK) {
-				async_answer_0(callid, rc);
-				break;
-			}
-
-			rc = telnet_user_send_data(user, buf, size);
-			free(buf);
-
-			if (rc != EOK) {
-				async_answer_0(callid, rc);
-				break;
-			}
-
-			async_answer_1(callid, EOK, size);
-			break;
-		}
-		case VFS_OUT_SYNC:
-			async_answer_0(callid, EOK);
-			break;
-		case CONSOLE_CLEAR:
-			async_answer_0(callid, EOK);
-			break;
-
-		case CONSOLE_GET_COLOR_CAP:
-			async_answer_1(callid, EOK, CONSOLE_CAP_NONE);
-			break;
-		case CONSOLE_SET_STYLE:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		case CONSOLE_SET_COLOR:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		case CONSOLE_SET_RGB_COLOR:
-			async_answer_0(callid, ENOTSUP);
-			break;
-
-		case CONSOLE_CURSOR_VISIBILITY:
-			async_answer_0(callid, ENOTSUP);
-			break;
-
-		default:
-			async_answer_0(callid, EINVAL);
-			break;
-		}
-	}
+static int remcons_open(con_srvs_t *, con_srv_t *);
+static int remcons_close(con_srv_t *);
+static int remcons_write(con_srv_t *, void *, size_t);
+static void remcons_sync(con_srv_t *);
+static void remcons_clear(con_srv_t *);
+static void remcons_set_pos(con_srv_t *, sysarg_t col, sysarg_t row);
+static int remcons_get_pos(con_srv_t *, sysarg_t *, sysarg_t *);
+static int remcons_get_size(con_srv_t *, sysarg_t *, sysarg_t *);
+static int remcons_get_color_cap(con_srv_t *, console_caps_t *);
+static int remcons_get_event(con_srv_t *, kbd_event_t *);
+
+static con_ops_t con_ops = {
+	.open = remcons_open,
+	.close = remcons_close,
+	.read = NULL,
+	.write = remcons_write,
+	.sync = remcons_sync,
+	.clear = remcons_clear,
+	.set_pos = remcons_set_pos,
+	.get_pos = remcons_get_pos,
+	.get_size = remcons_get_size,
+	.get_color_cap = remcons_get_color_cap,
+	.set_style = NULL,
+	.set_color = NULL,
+	.set_rgb_color = NULL,
+	.set_cursor_visibility = NULL,
+	.get_event = remcons_get_event
+};
+
+static telnet_user_t *srv_to_user(con_srv_t *srv)
+{
+	return srv->srvs->sarg;
+}
+
+static int remcons_open(con_srvs_t *srvs, con_srv_t *srv)
+{
+	telnet_user_t *user = srv_to_user(srv);
+
+	telnet_user_log(user, "New client connected (%p).", srv);
+
+	/* Force character mode. */
+	send(user->socket, (void *)telnet_force_character_mode_command,
+	    telnet_force_character_mode_command_count, 0);
+
+	return EOK;
+}
+
+static int remcons_close(con_srv_t *srv)
+{
+	telnet_user_t *user = srv_to_user(srv);
+
+	telnet_user_notify_client_disconnected(user);
+	telnet_user_log(user, "Client disconnected (%p).", srv);
+
+	return EOK;
+}
+
+static int remcons_write(con_srv_t *srv, void *data, size_t size)
+{
+	telnet_user_t *user = srv_to_user(srv);
+	int rc;
+
+	rc = telnet_user_send_data(user, data, size);
+	if (rc != EOK)
+		return rc;
+
+	return size;
+}
+
+static void remcons_sync(con_srv_t *srv)
+{
+	(void) srv;
+}
+
+static void remcons_clear(con_srv_t *srv)
+{
+	(void) srv;
+}
+
+static void remcons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row)
+{
+	telnet_user_t *user = srv_to_user(srv);
+
+	telnet_user_update_cursor_x(user, col);
+}
+
+static int remcons_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row)
+{
+	telnet_user_t *user = srv_to_user(srv);
+
+	*col = user->cursor_x;
+	*row = 0;
+
+	return EOK;
+}
+
+static int remcons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows)
+{
+	(void) srv;
+
+	*cols = 100;
+	*rows = 1;
+
+	return EOK;
+}
+
+static int remcons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps)
+{
+	(void) srv;
+	*ccaps = CONSOLE_CAP_NONE;
+
+	return EOK;
+}
+
+static int remcons_get_event(con_srv_t *srv, kbd_event_t *event)
+{
+	telnet_user_t *user = srv_to_user(srv);
+	int rc;
+
+	rc = telnet_user_get_next_keyboard_event(user, event);
+	if (rc != EOK) {
+		/* XXX What? */
+		memset(event, 0, sizeof(*event));
+		return EOK;
+	}
+
+	return EOK;
 }
 
@@ -198,17 +209,7 @@
 		return;
 	}
-	async_answer_0(iid, EOK);
-
-	telnet_user_log(user, "New client connected (%" PRIxn").", iid);
-
-	/* Force character mode. */
-	send(user->socket, (void *)telnet_force_character_mode_command,
-	    telnet_force_character_mode_command_count, 0);
 
 	/* Handle messages. */
-	client_connection_message_loop(user);
-
-	telnet_user_notify_client_disconnected(user);
-	telnet_user_log(user, "Client disconnected (%" PRIxn").", iid);
+	con_conn(iid, icall, &user->srvs);
 }
 
@@ -232,4 +233,5 @@
 		fibril_mutex_lock(&user->guard);
 		user->task_finished = true;
+		user->srvs.aborted = true;
 		fibril_condvar_signal(&user->refcount_cv);
 		fibril_mutex_unlock(&user->guard);
@@ -251,4 +253,5 @@
 	fibril_mutex_lock(&user->guard);
 	user->task_finished = true;
+	user->srvs.aborted = true;
 	fibril_condvar_signal(&user->refcount_cv);
 	fibril_mutex_unlock(&user->guard);
@@ -295,4 +298,5 @@
 			closesocket(user->socket);
 			user->socket_closed = true;
+			user->srvs.aborted = true;
 			continue;
 		} else if (user->socket_closed) {
@@ -363,4 +367,5 @@
 
 	printf("%s: HelenOS Remote console service\n", NAME);
+	task_retval(0);
 
 	while (true) {
@@ -379,4 +384,11 @@
 		assert(user);
 
+		con_srvs_init(&user->srvs);
+		user->srvs.ops = &con_ops;
+		user->srvs.sarg = user;
+		user->srvs.abort_timeout = 1000;
+
+		telnet_user_add(user);
+
 		fid_t fid = fibril_create(network_user_fibril, user);
 		assert(fid);
Index: uspace/srv/hid/remcons/user.c
===================================================================
--- uspace/srv/hid/remcons/user.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/remcons/user.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -35,7 +35,4 @@
 #include <stdio.h>
 #include <adt/prodcons.h>
-#include <ipc/input.h>
-#include <ipc/console.h>
-#include <ipc/vfs.h>
 #include <errno.h>
 #include <str_error.h>
@@ -95,12 +92,14 @@
 	user->locsrv_connection_count = 0;
 
-
+	user->cursor_x = 0;
+
+	return user;
+}
+
+void telnet_user_add(telnet_user_t *user)
+{
 	fibril_mutex_lock(&users_guard);
 	list_append(&user->link, &users);
 	fibril_mutex_unlock(&users_guard);
-
-	user->cursor_x = 0;
-
-	return user;
 }
 
@@ -199,4 +198,5 @@
 		if ((recv_length == 0) || (recv_length == ENOTCONN)) {
 			user->socket_closed = true;
+			user->srvs.aborted = true;
 			return ENOENT;
 		}
Index: uspace/srv/hid/remcons/user.h
===================================================================
--- uspace/srv/hid/remcons/user.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hid/remcons/user.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,6 +36,8 @@
 #define TELNET_USER_H_
 
+#include <adt/prodcons.h>
 #include <fibril_synch.h>
 #include <inttypes.h>
+#include <io/con_srv.h>
 #include "remcons.h"
 
@@ -55,4 +57,6 @@
 	/** Path name of the service. */
 	char *service_name;
+	/** Console service setup */
+	con_srvs_t srvs;
 
 	/** Producer-consumer of kbd_event_t. */
@@ -77,4 +81,5 @@
 
 extern telnet_user_t *telnet_user_create(int);
+extern void telnet_user_add(telnet_user_t *);
 extern void telnet_user_destroy(telnet_user_t *);
 extern telnet_user_t *telnet_user_get_for_client_connection(service_id_t);
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.c
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -116,9 +116,9 @@
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,	/* will be patched in run-time */
+		.addr = NULL,
 		.dstarg = 1
 	},
 	{
-		.cmd = CMD_BTEST,
+		.cmd = CMD_AND,
 		.value = SR_INT,
 		.srcarg = 1,
Index: uspace/srv/loader/Makefile
===================================================================
--- uspace/srv/loader/Makefile	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/loader/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -44,5 +44,5 @@
 GENERIC_SOURCES = \
 	main.c \
-	interp.s
+	interp.S
 
 SOURCES = \
Index: uspace/srv/loader/interp.S
===================================================================
--- uspace/srv/loader/interp.S	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/loader/interp.S	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,21 @@
+#
+# Provide a string to be included in a special DT_INTERP header, even though
+# this is a statically-linked executable. This will mark the binary as
+# the program loader.
+#
+
+#if ((defined(UARCH_abs32le)) && (defined(COMPILER_gcc_cross)) \
+    && (defined(CROSS_TARGET_arm32)))
+	#define ATSIGN(arg)  % ## arg
+#endif
+
+#ifdef UARCH_arm32
+	#define ATSIGN(arg)  % ## arg
+#endif
+
+#ifndef ATSIGN
+	#define ATSIGN(arg)  @ ## arg
+#endif
+
+.section .interp, "a", ATSIGN(progbits)
+	.string "kernel"
Index: pace/srv/loader/interp.s
===================================================================
--- uspace/srv/loader/interp.s	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ 	(revision )
@@ -1,7 +1,0 @@
-#
-# Provide a string to be included in a special DT_INTERP header, even though
-# this is a statically-linked executable. This will mark the binary as
-# the program loader.
-#
-.section .interp , ""
-	.string "kernel"
Index: uspace/srv/locsrv/locsrv.c
===================================================================
--- uspace/srv/locsrv/locsrv.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/locsrv/locsrv.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -1353,4 +1353,7 @@
 	categ_dir_add_cat(&cdir, cat);
 
+	cat = category_new("clock");
+	categ_dir_add_cat(&cdir, cat);
+
 	cat = category_new("test3");
 	categ_dir_add_cat(&cdir, cat);
@@ -1366,4 +1369,10 @@
 	
 	cat = category_new("nic");
+	categ_dir_add_cat(&cdir, cat);
+
+	cat = category_new("visualizer");
+	categ_dir_add_cat(&cdir, cat);
+
+	cat = category_new("renderer");
 	categ_dir_add_cat(&cdir, cat);
 	
Index: uspace/srv/logger/Makefile
===================================================================
--- uspace/srv/logger/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/logger/Makefile	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,41 @@
+#
+# Copyright (c) 2012 Vojtech Horky
+# 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 = logger
+STATIC_NEEDED = y
+
+SOURCES = \
+	ctl.c \
+	initlvl.c \
+	level.c \
+	logs.c \
+	main.c \
+	writer.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/logger/ctl.c
===================================================================
--- uspace/srv/logger/ctl.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/logger/ctl.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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 logger
+ * @{
+ */
+
+/** @file
+ */
+
+#include <unistd.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <errno.h>
+#include <io/logctl.h>
+#include <ipc/logger.h>
+#include "logger.h"
+
+static int handle_log_level_change(sysarg_t new_level)
+{
+	void *full_name;
+	int rc = async_data_write_accept(&full_name, true, 0, 0, 0, NULL);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	logger_log_t *log = find_log_by_name_and_lock(full_name);
+	free(full_name);
+	if (log == NULL)
+		return ENOENT;
+
+	log->logged_level = new_level;
+
+	log_unlock(log);
+
+	return EOK;
+}
+
+void logger_connection_handler_control(ipc_callid_t callid)
+{
+	async_answer_0(callid, EOK);
+	logger_log("control: new client.\n");
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call))
+			break;
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case LOGGER_CONTROL_SET_DEFAULT_LEVEL: {
+			int rc = set_default_logging_level(IPC_GET_ARG1(call));
+			async_answer_0(callid, rc);
+			break;
+		}
+		case LOGGER_CONTROL_SET_LOG_LEVEL: {
+			int rc = handle_log_level_change(IPC_GET_ARG1(call));
+			async_answer_0(callid, rc);
+			break;
+		}
+		default:
+			async_answer_0(callid, EINVAL);
+			break;
+		}
+	}
+
+	logger_log("control: client terminated.\n");
+}
+
+
+/**
+ * @}
+ */
Index: uspace/srv/logger/initlvl.c
===================================================================
--- uspace/srv/logger/initlvl.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/logger/initlvl.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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 logger
+ * @{
+ */
+
+/** @file
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <sysinfo.h>
+#include <str.h>
+#include "logger.h"
+
+static void parse_single_level_setting(char *setting)
+{
+	char *tmp;
+	char *key = strtok_r(setting, "=", &tmp);
+	char *value = strtok_r(NULL, "=", &tmp);
+	if (key == NULL)
+		return;
+	if (value == NULL) {
+		log_level_t level;
+		int rc = log_level_from_str(key, &level);
+		if (rc != EOK)
+			return;
+		set_default_logging_level(level);
+		return;
+	}
+
+
+	log_level_t level;
+	int rc = log_level_from_str(value, &level);
+	if (rc != EOK)
+		return;
+
+	logger_log_t *log = find_or_create_log_and_lock(key, 0);
+	if (log == NULL)
+		return;
+
+	log->logged_level = level;
+	log->ref_counter++;
+
+	log_unlock(log);
+}
+
+void parse_level_settings(char *settings)
+{
+	char *tmp;
+	char *single_setting = strtok_r(settings, " ", &tmp);
+	while (single_setting != NULL) {
+		parse_single_level_setting(single_setting);
+		single_setting = strtok_r(NULL, " ", &tmp);
+	}
+}
+
+void parse_initial_settings(void)
+{
+	size_t argument_size;
+	void *argument = sysinfo_get_data("init_args.logger", &argument_size);
+	if (argument == NULL)
+		return;
+
+	char level_str[200];
+	str_cpy(level_str, 200, (const char *) argument);
+
+	parse_level_settings(level_str);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/logger/level.c
===================================================================
--- uspace/srv/logger/level.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/logger/level.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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 logger
+ * @{
+ */
+
+/** @file
+ */
+
+#include <errno.h>
+#include "logger.h"
+
+log_level_t default_logging_level = LVL_NOTE;
+static FIBRIL_MUTEX_INITIALIZE(default_logging_level_guard);
+
+log_level_t get_default_logging_level(void)
+{
+	fibril_mutex_lock(&default_logging_level_guard);
+	log_level_t result = default_logging_level;
+	fibril_mutex_unlock(&default_logging_level_guard);
+	return result;
+}
+
+int set_default_logging_level(log_level_t new_level)
+{
+	if (new_level >= LVL_LIMIT)
+		return ERANGE;
+	fibril_mutex_lock(&default_logging_level_guard);
+	default_logging_level = new_level;
+	fibril_mutex_unlock(&default_logging_level_guard);
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/logger/logger.h
===================================================================
--- uspace/srv/logger/logger.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/logger/logger.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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 logger
+ * @{
+ */
+/** @file Common logger service definitions.
+ */
+
+#ifndef LOGGER_H_
+#define LOGGER_H_
+
+#include <adt/list.h>
+#include <adt/prodcons.h>
+#include <io/log.h>
+#include <async.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdio.h>
+
+#define NAME "logger"
+#define LOG_LEVEL_USE_DEFAULT (LVL_LIMIT + 1)
+
+#ifdef LOGGER_LOG
+#define logger_log(fmt, ...) printf(NAME ": " fmt, ##__VA_ARGS__)
+#else
+#define logger_log(fmt, ...) (void)0
+#endif
+
+typedef struct logger_log logger_log_t;
+
+typedef struct {
+	fibril_mutex_t guard;
+	char *filename;
+	FILE *logfile;
+} logger_dest_t;
+
+struct logger_log {
+	link_t link;
+
+	size_t ref_counter;
+
+	fibril_mutex_t guard;
+
+	char *name;
+	char *full_name;
+	logger_log_t *parent;
+	log_level_t logged_level;
+	logger_dest_t *dest;
+};
+
+#define MAX_REFERENCED_LOGS_PER_CLIENT 100
+
+typedef struct {
+	size_t logs_count;
+	logger_log_t *logs[MAX_REFERENCED_LOGS_PER_CLIENT];
+} logger_registered_logs_t;
+
+logger_log_t *find_log_by_name_and_lock(const char *name);
+logger_log_t *find_or_create_log_and_lock(const char *, sysarg_t);
+logger_log_t *find_log_by_id_and_lock(sysarg_t);
+bool shall_log_message(logger_log_t *, log_level_t);
+void log_unlock(logger_log_t *);
+void write_to_log(logger_log_t *, log_level_t, const char *);
+void log_release(logger_log_t *);
+
+void registered_logs_init(logger_registered_logs_t *);
+bool register_log(logger_registered_logs_t *, logger_log_t *);
+void unregister_logs(logger_registered_logs_t *);
+
+log_level_t get_default_logging_level(void);
+int set_default_logging_level(log_level_t);
+
+
+void logger_connection_handler_control(ipc_callid_t);
+void logger_connection_handler_writer(ipc_callid_t);
+
+void parse_initial_settings(void);
+void parse_level_settings(char *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/logger/logs.c
===================================================================
--- uspace/srv/logger/logs.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/logger/logs.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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 logger
+ * @{
+ */
+#include <assert.h>
+#include <malloc.h>
+#include <str.h>
+#include <stdio.h>
+#include <errno.h>
+#include "logger.h"
+
+
+static FIBRIL_MUTEX_INITIALIZE(log_list_guard);
+static LIST_INITIALIZE(log_list);
+
+
+static logger_log_t *find_log_by_name_and_parent_no_list_lock(const char *name, logger_log_t *parent)
+{
+	list_foreach(log_list, it) {
+		logger_log_t *log = list_get_instance(it, logger_log_t, link);
+		if ((parent == log->parent) && (str_cmp(log->name, name) == 0))
+			return log;
+	}
+
+	return NULL;
+}
+
+static int create_dest(const char *name, logger_dest_t **dest)
+{
+	logger_dest_t *result = malloc(sizeof(logger_dest_t));
+	if (result == NULL)
+		return ENOMEM;
+	int rc = asprintf(&result->filename, "/log/%s", name);
+	if (rc < 0) {
+		free(result);
+		return ENOMEM;
+	}
+	result->logfile = NULL;
+	fibril_mutex_initialize(&result->guard);
+	*dest = result;
+	return EOK;
+}
+
+static logger_log_t *create_log_no_locking(const char *name, logger_log_t *parent)
+{
+	logger_log_t *result = calloc(1, sizeof(logger_log_t));
+	if (result == NULL)
+		return NULL;
+
+	result->name = str_dup(name);
+	if (result->name == NULL)
+		goto error;
+
+	/*
+	 * Notice that we create new dest as the last
+	 * operation that can fail and thus there is no code
+	 * to deallocate dest.
+	 */
+	if (parent == NULL) {
+		result->full_name = str_dup(name);
+		if (result->full_name == NULL)
+			goto error;
+		int rc = create_dest(name, &result->dest);
+		if (rc != EOK)
+			goto error;
+	} else {
+		int rc = asprintf(&result->full_name, "%s/%s",
+		    parent->full_name, name);
+		if (rc < 0)
+			goto error;
+		result->dest = parent->dest;
+	}
+
+	/* Following initializations cannot fail. */
+	result->logged_level = LOG_LEVEL_USE_DEFAULT;
+	fibril_mutex_initialize(&result->guard);
+	link_initialize(&result->link);
+	result->parent = parent;
+
+	return result;
+
+error:
+	free(result->name);
+	free(result->full_name);
+	free(result);
+	return NULL;
+
+}
+
+logger_log_t *find_or_create_log_and_lock(const char *name, sysarg_t parent_id)
+{
+	logger_log_t *result = NULL;
+	logger_log_t *parent = (logger_log_t *) parent_id;
+
+	fibril_mutex_lock(&log_list_guard);
+
+	result = find_log_by_name_and_parent_no_list_lock(name, parent);
+	if (result == NULL) {
+		result = create_log_no_locking(name, parent);
+		if (result == NULL)
+			goto leave;
+		list_append(&result->link, &log_list);
+		if (result->parent != NULL) {
+			fibril_mutex_lock(&result->parent->guard);
+			result->parent->ref_counter++;
+			fibril_mutex_unlock(&result->parent->guard);
+		}
+	}
+
+	fibril_mutex_lock(&result->guard);
+
+leave:
+	fibril_mutex_unlock(&log_list_guard);
+
+	return result;
+}
+
+logger_log_t *find_log_by_name_and_lock(const char *name)
+{
+	logger_log_t *result = NULL;
+
+	fibril_mutex_lock(&log_list_guard);
+	list_foreach(log_list, it) {
+		logger_log_t *log = list_get_instance(it, logger_log_t, link);
+		if (str_cmp(log->full_name, name) == 0) {
+			fibril_mutex_lock(&log->guard);
+			result = log;
+			break;
+		}
+	}
+	fibril_mutex_unlock(&log_list_guard);
+
+	return result;
+}
+
+logger_log_t *find_log_by_id_and_lock(sysarg_t id)
+{
+	logger_log_t *result = NULL;
+
+	fibril_mutex_lock(&log_list_guard);
+	list_foreach(log_list, it) {
+		logger_log_t *log = list_get_instance(it, logger_log_t, link);
+		if ((sysarg_t) log == id) {
+			fibril_mutex_lock(&log->guard);
+			result = log;
+			break;
+		}
+	}
+	fibril_mutex_unlock(&log_list_guard);
+
+	return result;
+}
+
+static log_level_t get_actual_log_level(logger_log_t *log)
+{
+	/* Find recursively proper log level. */
+	if (log->logged_level == LOG_LEVEL_USE_DEFAULT) {
+		if (log->parent == NULL)
+			return get_default_logging_level();
+		else
+			return get_actual_log_level(log->parent);
+	}
+	return log->logged_level;
+}
+
+bool shall_log_message(logger_log_t *log, log_level_t level)
+{
+	fibril_mutex_lock(&log_list_guard);
+	bool result = level <= get_actual_log_level(log);
+	fibril_mutex_unlock(&log_list_guard);
+	return result;
+}
+
+void log_unlock(logger_log_t *log)
+{
+	assert(fibril_mutex_is_locked(&log->guard));
+	fibril_mutex_unlock(&log->guard);
+}
+
+/** Decreases reference counter on the log and destory the log if
+ * necessary.
+ *
+ * Precondition: log is locked.
+ *
+ * @param log Log to release from using by the caller.
+ */
+void log_release(logger_log_t *log)
+{
+	assert(fibril_mutex_is_locked(&log->guard));
+	assert(log->ref_counter > 0);
+
+	/* We are definitely not the last ones. */
+	if (log->ref_counter > 1) {
+		log->ref_counter--;
+		fibril_mutex_unlock(&log->guard);
+		return;
+	}
+
+	/*
+	 * To prevent deadlock, we need to get the list lock first.
+	 * Deadlock scenario:
+	 * Us: LOCKED(log), want to LOCK(list)
+	 * Someone else calls find_log_by_name_and_lock(log->fullname) ->
+	 *   LOCKED(list), wants to LOCK(log)
+	 */
+	fibril_mutex_unlock(&log->guard);
+
+	/* Ensuring correct locking order. */
+	fibril_mutex_lock(&log_list_guard);
+	/*
+	 * The reference must be still valid because we have not decreased
+	 * the reference counter.
+	 */
+	fibril_mutex_lock(&log->guard);
+	assert(log->ref_counter > 0);
+	log->ref_counter--;
+
+	if (log->ref_counter > 0) {
+		/*
+		 * Meanwhile, someone else increased the ref counter.
+		 * No big deal, we just return immediatelly.
+		 */
+		fibril_mutex_unlock(&log->guard);
+		fibril_mutex_unlock(&log_list_guard);
+		return;
+	}
+
+	/*
+	 * Here we are on a destroy path. We need to
+	 * - remove ourselves from the list
+	 * - decrease reference of the parent (if not top-level log)
+	 *   - we must do that after we relaase list lock to prevent
+	 *     deadlock with ourselves
+	 * - destroy dest (if top-level log)
+	 */
+	assert(log->ref_counter == 0);
+
+	list_remove(&log->link);
+	fibril_mutex_unlock(&log_list_guard);
+	fibril_mutex_unlock(&log->guard);
+
+	if (log->parent == NULL) {
+		/*
+		 * Due to lazy file opening in write_to_log(),
+		 * it is possible that no file was actually opened.
+		 */
+		if (log->dest->logfile != NULL) {
+			fclose(log->dest->logfile);
+		}
+		free(log->dest->filename);
+		free(log->dest);
+	} else {
+		fibril_mutex_lock(&log->parent->guard);
+		log_release(log->parent);
+	}
+
+	logger_log("Destroyed log %s.\n", log->full_name);
+
+	free(log->name);
+	free(log->full_name);
+
+	free(log);
+}
+
+
+void write_to_log(logger_log_t *log, log_level_t level, const char *message)
+{
+	assert(fibril_mutex_is_locked(&log->guard));
+	assert(log->dest != NULL);
+	fibril_mutex_lock(&log->dest->guard);
+	if (log->dest->logfile == NULL)
+		log->dest->logfile = fopen(log->dest->filename, "a");
+
+	if (log->dest->logfile != NULL) {
+		fprintf(log->dest->logfile, "[%s] %s: %s\n",
+		    log->full_name, log_level_str(level),
+		    (const char *) message);
+		fflush(log->dest->logfile);
+	}
+
+	fibril_mutex_unlock(&log->dest->guard);
+}
+
+void registered_logs_init(logger_registered_logs_t *logs)
+{
+	logs->logs_count = 0;
+}
+
+bool register_log(logger_registered_logs_t *logs, logger_log_t *new_log)
+{
+	if (logs->logs_count >= MAX_REFERENCED_LOGS_PER_CLIENT) {
+		return false;
+	}
+
+	assert(fibril_mutex_is_locked(&new_log->guard));
+	new_log->ref_counter++;
+
+	logs->logs[logs->logs_count] = new_log;
+	logs->logs_count++;
+
+	return true;
+}
+
+void unregister_logs(logger_registered_logs_t *logs)
+{
+	for (size_t i = 0; i < logs->logs_count; i++) {
+		logger_log_t *log = logs->logs[i];
+		fibril_mutex_lock(&log->guard);
+		log_release(log);
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/logger/main.c
===================================================================
--- uspace/srv/logger/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/logger/main.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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.
+ */
+
+/**
+ * @defgroup logger Logging service.
+ * @brief HelenOS logging service.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <ipc/services.h>
+#include <ipc/logger.h>
+#include <io/log.h>
+#include <io/logctl.h>
+#include <ns.h>
+#include <async.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <malloc.h>
+#include "logger.h"
+
+static void connection_handler(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	logger_interface_t iface = IPC_GET_ARG1(*icall);
+
+	switch (iface) {
+	case LOGGER_INTERFACE_CONTROL:
+		logger_connection_handler_control(iid);
+		break;
+	case LOGGER_INTERFACE_WRITER:
+		logger_connection_handler_writer(iid);
+		break;
+	default:
+		async_answer_0(iid, EINVAL);
+		break;
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS Logging Service\n");
+	
+	parse_initial_settings();
+	for (int i = 1; i < argc; i++) {
+		parse_level_settings(argv[i]);
+	}
+
+	async_set_client_connection(connection_handler);
+	
+	int rc = service_register(SERVICE_LOGGER);
+	if (rc != EOK) {
+		printf(NAME ": failed to register: %s.\n", str_error(rc));
+		return -1;
+	}
+	
+	printf(NAME ": Accepting connections\n");
+	async_manager();
+	
+	/* Never reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/logger/writer.c
===================================================================
--- uspace/srv/logger/writer.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
+++ uspace/srv/logger/writer.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012 Vojtech Horky
+ * 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.
+ */
+
+/**
+ * @defgroup logger Logging service.
+ * @brief HelenOS logging service.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <ipc/services.h>
+#include <ipc/logger.h>
+#include <io/log.h>
+#include <io/logctl.h>
+#include <ns.h>
+#include <async.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <malloc.h>
+#include "logger.h"
+
+
+static logger_log_t *handle_create_log(sysarg_t parent)
+{
+	void *name;
+	int rc = async_data_write_accept(&name, true, 1, 0, 0, NULL);
+	if (rc != EOK)
+		return NULL;
+
+	logger_log_t *log = find_or_create_log_and_lock(name, parent);
+
+	free(name);
+
+	return log;
+}
+
+static int handle_receive_message(sysarg_t log_id, sysarg_t level)
+{
+	logger_log_t *log = find_log_by_id_and_lock(log_id);
+	if (log == NULL)
+		return ENOENT;
+
+	void *message = NULL;
+	int rc = async_data_write_accept(&message, true, 1, 0, 0, NULL);
+	if (rc != EOK)
+		goto leave;
+
+	if (!shall_log_message(log, level)) {
+		rc = EOK;
+		goto leave;
+	}
+
+	printf("[%s] %s: %s\n",
+	    log->full_name, log_level_str(level),
+	    (const char *) message);
+	write_to_log(log, level, message);
+
+	rc = EOK;
+
+leave:
+	log_unlock(log);
+	free(message);
+
+	return rc;
+}
+
+void logger_connection_handler_writer(ipc_callid_t callid)
+{
+	/* Acknowledge the connection. */
+	async_answer_0(callid, EOK);
+
+	logger_log("writer: new client.\n");
+
+	logger_registered_logs_t registered_logs;
+	registered_logs_init(&registered_logs);
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call))
+			break;
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case LOGGER_WRITER_CREATE_LOG: {
+			logger_log_t *log = handle_create_log(IPC_GET_ARG1(call));
+			if (log == NULL) {
+				async_answer_0(callid, ENOMEM);
+				break;
+			}
+			if (!register_log(&registered_logs, log)) {
+				log_unlock(log);
+				async_answer_0(callid, ELIMIT);
+				break;
+			}
+			log_unlock(log);
+			async_answer_1(callid, EOK, (sysarg_t) log);
+			break;
+		}
+		case LOGGER_WRITER_MESSAGE: {
+			int rc = handle_receive_message(IPC_GET_ARG1(call),
+			    IPC_GET_ARG2(call));
+			async_answer_0(callid, rc);
+			break;
+		}
+		default:
+			async_answer_0(callid, EINVAL);
+			break;
+		}
+	}
+
+	unregister_logs(&registered_logs);
+	logger_log("writer: client terminated.\n");
+}
+
+
+/**
+ * @}
+ */
Index: uspace/srv/net/ethip/arp.c
===================================================================
--- uspace/srv/net/ethip/arp.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/ethip/arp.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -59,5 +59,5 @@
 	ethip_link_addr_t *laddr;
 
-	log_msg(LVL_DEBUG, "arp_received()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "arp_received()");
 
 	rc = arp_pdu_decode(frame->data, frame->size, &packet);
@@ -65,10 +65,10 @@
 		return;
 
-	log_msg(LVL_DEBUG, "ARP PDU decoded, opcode=%d, tpa=%x",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ARP PDU decoded, opcode=%d, tpa=%x",
 	    packet.opcode, packet.target_proto_addr.ipv4);
 
 	laddr = ethip_nic_addr_find(nic, &packet.target_proto_addr);
 	if (laddr != NULL) {
-		log_msg(LVL_DEBUG, "Request/reply to my address");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Request/reply to my address");
 
 		(void) atrans_add(&packet.sender_proto_addr,
@@ -122,5 +122,5 @@
 	size_t fsize;
 
-	log_msg(LVL_DEBUG, "arp_send_packet()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "arp_send_packet()");
 
 	rc = arp_pdu_encode(packet, &pdata, &psize);
Index: uspace/srv/net/ethip/ethip.c
===================================================================
--- uspace/srv/net/ethip/ethip.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/ethip/ethip.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -77,5 +77,5 @@
 	int rc = loc_server_register(NAME);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering server.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server.");
 		return rc;
 	}
@@ -96,5 +96,5 @@
 	char *svc_name = NULL;
 
-	log_msg(LVL_DEBUG, "ethip_iplink_init()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_iplink_init()");
 
 	iplink_srv_init(&nic->iplink);
@@ -104,5 +104,5 @@
 	rc = asprintf(&svc_name, "net/eth%u", ++link_num);
 	if (rc < 0) {
-		log_msg(LVL_ERROR, "Out of memory.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
 		goto error;
 	}
@@ -110,5 +110,5 @@
 	rc = loc_service_register(svc_name, &sid);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering service %s.", svc_name);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service %s.", svc_name);
 		goto error;
 	}
@@ -118,5 +118,5 @@
 	rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed resolving category 'iplink'.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'iplink'.");
 		goto error;
 	}
@@ -124,5 +124,5 @@
 	rc = loc_service_add_to_cat(sid, iplink_cat);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed adding %s to category.", svc_name);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding %s to category.", svc_name);
 		goto error;
 	}
@@ -142,8 +142,8 @@
 
 	sid = (service_id_t)IPC_GET_ARG1(*icall);
-	log_msg(LVL_DEBUG, "ethip_client_conn(%u)", (unsigned)sid);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_client_conn(%u)", (unsigned)sid);
 	nic = ethip_nic_find_by_iplink_sid(sid);
 	if (nic == NULL) {
-		log_msg(LVL_WARN, "Uknown service ID.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "Uknown service ID.");
 		return;
 	}
@@ -154,5 +154,5 @@
 static int ethip_open(iplink_srv_t *srv)
 {
-	log_msg(LVL_DEBUG, "ethip_open()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_open()");
 	return EOK;
 }
@@ -160,5 +160,5 @@
 static int ethip_close(iplink_srv_t *srv)
 {
-	log_msg(LVL_DEBUG, "ethip_close()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_close()");
 	return EOK;
 }
@@ -173,9 +173,9 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "ethip_send()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_send()");
 
 	rc = arp_translate(nic, &sdu->lsrc, &sdu->ldest, &dest_mac_addr);
 	if (rc != EOK) {
-		log_msg(LVL_WARN, "Failed to look up IP address 0x%" PRIx32,
+		log_msg(LOG_DEFAULT, LVL_WARN, "Failed to look up IP address 0x%" PRIx32,
 		    sdu->ldest.ipv4);
 		return rc;
@@ -200,5 +200,5 @@
 int ethip_received(iplink_srv_t *srv, void *data, size_t size)
 {
-	log_msg(LVL_DEBUG, "ethip_received(): srv=%p", srv);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_received(): srv=%p", srv);
 	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
 	eth_frame_t frame;
@@ -206,10 +206,10 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "ethip_received()");
-
-	log_msg(LVL_DEBUG, " - eth_pdu_decode");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_received()");
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " - eth_pdu_decode");
 	rc = eth_pdu_decode(data, size, &frame);
 	if (rc != EOK) {
-		log_msg(LVL_DEBUG, " - eth_pdu_decode failed");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, " - eth_pdu_decode failed");
 		return rc;
 	}
@@ -220,14 +220,14 @@
 		break;
 	case ETYPE_IP:
-		log_msg(LVL_DEBUG, " - construct SDU");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, " - construct SDU");
 		sdu.lsrc.ipv4 = (192 << 24) | (168 << 16) | (0 << 8) | 1;
 		sdu.ldest.ipv4 = (192 << 24) | (168 << 16) | (0 << 8) | 4;
 		sdu.data = frame.data;
 		sdu.size = frame.size;
-		log_msg(LVL_DEBUG, " - call iplink_ev_recv");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, " - call iplink_ev_recv");
 		rc = iplink_ev_recv(&nic->iplink, &sdu);
 		break;
 	default:
-		log_msg(LVL_DEBUG, "Unknown ethertype 0x%" PRIx16,
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Unknown ethertype 0x%" PRIx16,
 		    frame.etype_len);
 	}
@@ -239,5 +239,5 @@
 static int ethip_get_mtu(iplink_srv_t *srv, size_t *mtu)
 {
-	log_msg(LVL_DEBUG, "ethip_get_mtu()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_get_mtu()");
 	*mtu = 1500;
 	return EOK;
@@ -248,5 +248,5 @@
 	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
 
-	log_msg(LVL_DEBUG, "ethip_addr_add(0x%" PRIx32 ")", addr->ipv4);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_addr_add(0x%" PRIx32 ")", addr->ipv4);
 	return ethip_nic_addr_add(nic, addr);
 }
@@ -256,5 +256,5 @@
 	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
 
-	log_msg(LVL_DEBUG, "ethip_addr_remove(0x%" PRIx32 ")", addr->ipv4);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_addr_remove(0x%" PRIx32 ")", addr->ipv4);
 	return ethip_nic_addr_add(nic, addr);
 }
@@ -266,5 +266,5 @@
 	printf(NAME ": HelenOS IP over Ethernet service\n");
 
-	if (log_init(NAME, LVL_WARN) != EOK) {
+	if (log_init(NAME) != EOK) {
 		printf(NAME ": Failed to initialize logging.\n");
 		return 1;
Index: uspace/srv/net/ethip/ethip_nic.c
===================================================================
--- uspace/srv/net/ethip/ethip_nic.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/ethip/ethip_nic.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -68,5 +68,5 @@
 	rc = loc_category_get_id("nic", &iplink_cat, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed resolving category 'nic'.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'nic'.");
 		fibril_mutex_unlock(&ethip_discovery_lock);
 		return ENOENT;
@@ -75,5 +75,5 @@
 	rc = loc_category_get_svcs(iplink_cat, &svcs, &count);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed getting list of IP links.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting list of IP links.");
 		fibril_mutex_unlock(&ethip_discovery_lock);
 		return EIO;
@@ -93,9 +93,9 @@
 
 		if (!already_known) {
-			log_msg(LVL_DEBUG, "Found NIC '%lu'",
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Found NIC '%lu'",
 			    (unsigned long) svcs[i]);
 			rc = ethip_nic_open(svcs[i]);
 			if (rc != EOK)
-				log_msg(LVL_ERROR, "Could not open NIC.");
+				log_msg(LOG_DEFAULT, LVL_ERROR, "Could not open NIC.");
 		}
 	}
@@ -110,5 +110,5 @@
 
 	if (nic == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating NIC structure. "
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating NIC structure. "
 		    "Out of memory.");
 		return NULL;
@@ -126,5 +126,5 @@
 
 	if (laddr == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating NIC address structure. "
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating NIC address structure. "
 		    "Out of memory.");
 		return NULL;
@@ -153,5 +153,5 @@
 	nic_address_t nic_address;
 	
-	log_msg(LVL_DEBUG, "ethip_nic_open()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_open()");
 	ethip_nic_t *nic = ethip_nic_new();
 	if (nic == NULL)
@@ -160,5 +160,5 @@
 	int rc = loc_service_get_name(sid, &nic->svc_name);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed getting service name.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting service name.");
 		goto error;
 	}
@@ -166,5 +166,5 @@
 	nic->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid, 0);
 	if (nic->sess == NULL) {
-		log_msg(LVL_ERROR, "Failed connecting '%s'", nic->svc_name);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed connecting '%s'", nic->svc_name);
 		goto error;
 	}
@@ -174,10 +174,10 @@
 	rc = nic_callback_create(nic->sess, ethip_nic_cb_conn, nic);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed creating callback connection "
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed creating callback connection "
 		    "from '%s'", nic->svc_name);
 		goto error;
 	}
 
-	log_msg(LVL_DEBUG, "Opened NIC '%s'", nic->svc_name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Opened NIC '%s'", nic->svc_name);
 	list_append(&nic->nic_list, &ethip_nic_list);
 	in_list = true;
@@ -189,5 +189,5 @@
 	rc = nic_get_address(nic->sess, &nic_address);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Error getting MAC address of NIC '%s'.",
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting MAC address of NIC '%s'.",
 		    nic->svc_name);
 		goto error;
@@ -198,10 +198,10 @@
 	rc = nic_set_state(nic->sess, NIC_STATE_ACTIVE);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Error activating NIC '%s'.",
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Error activating NIC '%s'.",
 		    nic->svc_name);
 		goto error;
 	}
 
-	log_msg(LVL_DEBUG, "Initialized IP link service, MAC = 0x%" PRIx64,
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Initialized IP link service, MAC = 0x%" PRIx64,
 	    nic->mac_addr.addr);
 
@@ -225,5 +225,5 @@
     ipc_call_t *call)
 {
-	log_msg(LVL_DEBUG, "ethip_nic_addr_changed()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_addr_changed()");
 	async_answer_0(callid, ENOTSUP);
 }
@@ -236,21 +236,21 @@
 	size_t size;
 
-	log_msg(LVL_DEBUG, "ethip_nic_received() nic=%p", nic);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_received() nic=%p", nic);
 
 	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
 	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "data_write_accept() failed");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "data_write_accept() failed");
 		return;
 	}
 
-	log_msg(LVL_DEBUG, "Ethernet PDU contents (%zu bytes)",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Ethernet PDU contents (%zu bytes)",
 	    size);
 
-	log_msg(LVL_DEBUG, "call ethip_received");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "call ethip_received");
 	rc = ethip_received(&nic->iplink, data, size);
-	log_msg(LVL_DEBUG, "free data");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "free data");
 	free(data);
 
-	log_msg(LVL_DEBUG, "ethip_nic_received() done, rc=%d", rc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_received() done, rc=%d", rc);
 	async_answer_0(callid, rc);
 }
@@ -259,5 +259,5 @@
     ipc_call_t *call)
 {
-	log_msg(LVL_DEBUG, "ethip_nic_device_state()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_device_state()");
 	async_answer_0(callid, ENOTSUP);
 }
@@ -267,5 +267,5 @@
 	ethip_nic_t *nic = (ethip_nic_t *)arg;
 
-	log_msg(LVL_DEBUG, "ethnip_nic_cb_conn()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethnip_nic_cb_conn()");
 
 	while (true) {
@@ -298,5 +298,5 @@
 	int rc = loc_register_cat_change_cb(ethip_nic_cat_change_cb);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering callback for NIC "
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback for NIC "
 		    "discovery (%d).", rc);
 		return rc;
@@ -308,19 +308,19 @@
 ethip_nic_t *ethip_nic_find_by_iplink_sid(service_id_t iplink_sid)
 {
-	log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid(%u)",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_find_by_iplink_sid(%u)",
 	    (unsigned) iplink_sid);
 
 	list_foreach(ethip_nic_list, link) {
-		log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid - element");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_find_by_iplink_sid - element");
 		ethip_nic_t *nic = list_get_instance(link, ethip_nic_t,
 		    nic_list);
 
 		if (nic->iplink_sid == iplink_sid) {
-			log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid - found %p", nic);
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_find_by_iplink_sid - found %p", nic);
 			return nic;
 		}
 	}
 
-	log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid - not found");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_find_by_iplink_sid - not found");
 	return NULL;
 }
@@ -329,7 +329,7 @@
 {
 	int rc;
-	log_msg(LVL_DEBUG, "ethip_nic_send(size=%zu)", size);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_send(size=%zu)", size);
 	rc = nic_send_frame(nic->sess, data, size);
-	log_msg(LVL_DEBUG, "nic_send_frame -> %d", rc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "nic_send_frame -> %d", rc);
 	return rc;
 }
@@ -339,5 +339,5 @@
 	ethip_link_addr_t *laddr;
 
-	log_msg(LVL_DEBUG, "ethip_nic_addr_add()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_addr_add()");
 	laddr = ethip_nic_addr_new(addr);
 	if (laddr == NULL)
@@ -352,5 +352,5 @@
 	ethip_link_addr_t *laddr;
 
-	log_msg(LVL_DEBUG, "ethip_nic_addr_remove()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_addr_remove()");
 
 	laddr = ethip_nic_addr_find(nic, addr);
@@ -366,5 +366,5 @@
     iplink_srv_addr_t *addr)
 {
-	log_msg(LVL_DEBUG, "ethip_nic_addr_find()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_nic_addr_find()");
 
 	list_foreach(nic->addr_list, link) {
Index: uspace/srv/net/ethip/pdu.c
===================================================================
--- uspace/srv/net/ethip/pdu.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/ethip/pdu.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -69,7 +69,8 @@
 	    frame->size);
 
-	log_msg(LVL_DEBUG, "Encoding Ethernet frame src=%llx dest=%llx etype=%x",
-	    frame->src, frame->dest, frame->etype_len);
-	log_msg(LVL_DEBUG, "Encoded Ethernet frame (%zu bytes)", size);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Encoding Ethernet frame "
+	    "src=%" PRIx64 " dest=%" PRIx64 " etype=%x",
+	    frame->src.addr, frame->dest.addr, frame->etype_len);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Encoded Ethernet frame (%zu bytes)", size);
 
 	*rdata = data;
@@ -83,8 +84,8 @@
 	eth_header_t *hdr;
 
-	log_msg(LVL_DEBUG, "eth_pdu_decode()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "eth_pdu_decode()");
 
 	if (size < sizeof(eth_header_t)) {
-		log_msg(LVL_DEBUG, "PDU too short (%zu)", size);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "PDU too short (%zu)", size);
 		return EINVAL;
 	}
@@ -104,7 +105,8 @@
 	    frame->size);
 
-	log_msg(LVL_DEBUG, "Decoding Ethernet frame src=%llx dest=%llx etype=%x",
-	    frame->src, frame->dest, frame->etype_len);
-	log_msg(LVL_DEBUG, "Decoded Ethernet frame payload (%zu bytes)", frame->size);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Decoding Ethernet frame "
+	    "src=%" PRIx64 " dest=%" PRIx64 " etype=%x",
+	    frame->src.addr, frame->dest.addr, frame->etype_len);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Decoded Ethernet frame payload (%zu bytes)", frame->size);
 
 	return EOK;
@@ -143,5 +145,5 @@
 	uint16_t fopcode;
 
-	log_msg(LVL_DEBUG, "arp_pdu_encode()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "arp_pdu_encode()");
 
 	size = sizeof(arp_eth_packet_fmt_t);
@@ -183,8 +185,8 @@
 	arp_eth_packet_fmt_t *pfmt;
 
-	log_msg(LVL_DEBUG, "arp_pdu_decode()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "arp_pdu_decode()");
 
 	if (size < sizeof(arp_eth_packet_fmt_t)) {
-		log_msg(LVL_DEBUG, "ARP PDU too short (%zu)", size);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "ARP PDU too short (%zu)", size);
 		return EINVAL;
 	}
@@ -193,5 +195,5 @@
 
 	if (uint16_t_be2host(pfmt->hw_addr_space) != AHRD_ETHERNET) {
-		log_msg(LVL_DEBUG, "HW address space != %u (%" PRIu16 ")",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "HW address space != %u (%" PRIu16 ")",
 		    AHRD_ETHERNET, uint16_t_be2host(pfmt->hw_addr_space));
 		return EINVAL;
@@ -199,5 +201,5 @@
 
 	if (uint16_t_be2host(pfmt->proto_addr_space) != 0x0800) {
-		log_msg(LVL_DEBUG, "Proto address space != %u (%" PRIu16 ")",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Proto address space != %u (%" PRIu16 ")",
 		    ETYPE_IP, uint16_t_be2host(pfmt->proto_addr_space));
 		return EINVAL;
@@ -205,5 +207,5 @@
 
 	if (pfmt->hw_addr_size != ETH_ADDR_SIZE) {
-		log_msg(LVL_DEBUG, "HW address size != %zu (%zu)",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "HW address size != %zu (%zu)",
 		    (size_t)ETH_ADDR_SIZE, (size_t)pfmt->hw_addr_size);
 		return EINVAL;
@@ -211,5 +213,5 @@
 
 	if (pfmt->proto_addr_size != IPV4_ADDR_SIZE) {
-		log_msg(LVL_DEBUG, "Proto address size != %zu (%zu)",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Proto address size != %zu (%zu)",
 		    (size_t)IPV4_ADDR_SIZE, (size_t)pfmt->proto_addr_size);
 		return EINVAL;
@@ -220,5 +222,5 @@
 	case AOP_REPLY: packet->opcode = aop_reply; break;
 	default:
-		log_msg(LVL_DEBUG, "Invalid ARP opcode (%" PRIu16 ")",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Invalid ARP opcode (%" PRIu16 ")",
 		    uint16_t_be2host(pfmt->opcode));
 		return EINVAL;
@@ -231,5 +233,5 @@
 	packet->target_proto_addr.ipv4 =
 	    uint32_t_be2host(pfmt->target_proto_addr);
-	log_msg(LVL_DEBUG, "packet->tpa = %x\n", pfmt->target_proto_addr);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "packet->tpa = %x\n", pfmt->target_proto_addr);
 
 	return EOK;
Index: uspace/srv/net/inetsrv/addrobj.c
===================================================================
--- uspace/srv/net/inetsrv/addrobj.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/inetsrv/addrobj.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -59,5 +59,5 @@
 
 	if (addr == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating address object. "
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating address object. "
 		    "Out of memory.");
 		return NULL;
@@ -114,5 +114,5 @@
 	uint32_t mask;
 
-	log_msg(LVL_DEBUG, "inet_addrobj_find(%x)", (unsigned)addr->ipv4);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find(%x)", (unsigned)addr->ipv4);
 
 	fibril_mutex_lock(&addr_list_lock);
@@ -125,5 +125,5 @@
 		if ((naddr->naddr.ipv4 & mask) == (addr->ipv4 & mask)) {
 			fibril_mutex_unlock(&addr_list_lock);
-			log_msg(LVL_DEBUG, "inet_addrobj_find: found %p",
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find: found %p",
 			    naddr);
 			return naddr;
@@ -131,5 +131,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "inet_addrobj_find: Not found");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find: Not found");
 	fibril_mutex_unlock(&addr_list_lock);
 
@@ -147,5 +147,5 @@
 	assert(fibril_mutex_is_locked(&addr_list_lock));
 
-	log_msg(LVL_DEBUG, "inet_addrobj_find_by_name_locked('%s', '%s')",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name_locked('%s', '%s')",
 	    name, ilink->svc_name);
 
@@ -155,5 +155,5 @@
 
 		if (naddr->ilink == ilink && str_cmp(naddr->name, name) == 0) {
-			log_msg(LVL_DEBUG, "inet_addrobj_find_by_name_locked: found %p",
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name_locked: found %p",
 			    naddr);
 			return naddr;
@@ -161,5 +161,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "inet_addrobj_find_by_name_locked: Not found");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name_locked: Not found");
 
 	return NULL;
@@ -177,5 +177,5 @@
 	inet_addrobj_t *aobj;
 
-	log_msg(LVL_DEBUG, "inet_addrobj_find_by_name('%s', '%s')",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name('%s', '%s')",
 	    name, ilink->svc_name);
 
@@ -194,5 +194,5 @@
 inet_addrobj_t *inet_addrobj_get_by_id(sysarg_t id)
 {
-	log_msg(LVL_DEBUG, "inet_addrobj_get_by_id(%zu)", (size_t)id);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_get_by_id(%zu)", (size_t)id);
 
 	fibril_mutex_lock(&addr_list_lock);
Index: uspace/srv/net/inetsrv/icmp.c
===================================================================
--- uspace/srv/net/inetsrv/icmp.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/inetsrv/icmp.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -57,5 +57,5 @@
 	uint8_t type;
 
-	log_msg(LVL_DEBUG, "icmp_recv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "icmp_recv()");
 
 	if (dgram->size < 1)
@@ -84,5 +84,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "icmp_recv_echo_request()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "icmp_recv_echo_request()");
 
 	if (dgram->size < sizeof(icmp_echo_t))
@@ -124,5 +124,5 @@
 	uint16_t ident;
 
-	log_msg(LVL_DEBUG, "icmp_recv_echo_reply()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "icmp_recv_echo_reply()");
 
 	if (dgram->size < sizeof(icmp_echo_t))
Index: uspace/srv/net/inetsrv/inet_link.c
===================================================================
--- uspace/srv/net/inetsrv/inet_link.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/inetsrv/inet_link.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -64,14 +64,14 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inet_iplink_recv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_recv()");
 	rc = inet_pdu_decode(sdu->data, sdu->size, &packet);
 	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "failed decoding PDU");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "failed decoding PDU");
 		return rc;
 	}
 
-	log_msg(LVL_DEBUG, "call inet_recv_packet()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet()");
 	rc = inet_recv_packet(&packet);
-	log_msg(LVL_DEBUG, "call inet_recv_packet -> %d", rc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet -> %d", rc);
 	free(packet.data);
 
@@ -91,5 +91,5 @@
 	rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed resolving category 'iplink'.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'iplink'.");
 		fibril_mutex_unlock(&inet_discovery_lock);
 		return ENOENT;
@@ -98,5 +98,5 @@
 	rc = loc_category_get_svcs(iplink_cat, &svcs, &count);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed getting list of IP links.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting list of IP links.");
 		fibril_mutex_unlock(&inet_discovery_lock);
 		return EIO;
@@ -116,9 +116,9 @@
 
 		if (!already_known) {
-			log_msg(LVL_DEBUG, "Found IP link '%lu'",
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Found IP link '%lu'",
 			    (unsigned long) svcs[i]);
 			rc = inet_link_open(svcs[i]);
 			if (rc != EOK)
-				log_msg(LVL_ERROR, "Could not open IP link.");
+				log_msg(LOG_DEFAULT, LVL_ERROR, "Could not open IP link.");
 		}
 	}
@@ -133,5 +133,5 @@
 
 	if (ilink == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating link structure. "
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating link structure. "
 		    "Out of memory.");
 		return NULL;
@@ -156,5 +156,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inet_link_open()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_link_open()");
 	ilink = inet_link_new();
 	if (ilink == NULL)
@@ -166,5 +166,5 @@
 	rc = loc_service_get_name(sid, &ilink->svc_name);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed getting service name.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting service name.");
 		goto error;
 	}
@@ -172,5 +172,5 @@
 	ilink->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid, 0);
 	if (ilink->sess == NULL) {
-		log_msg(LVL_ERROR, "Failed connecting '%s'", ilink->svc_name);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed connecting '%s'", ilink->svc_name);
 		goto error;
 	}
@@ -178,5 +178,5 @@
 	rc = iplink_open(ilink->sess, &inet_iplink_ev_ops, &ilink->iplink);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed opening IP link '%s'",
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed opening IP link '%s'",
 		    ilink->svc_name);
 		goto error;
@@ -185,10 +185,10 @@
 	rc = iplink_get_mtu(ilink->iplink, &ilink->def_mtu);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed determinning MTU of link '%s'",
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed determinning MTU of link '%s'",
 		    ilink->svc_name);
 		goto error;
 	}
 
-	log_msg(LVL_DEBUG, "Opened IP link '%s'", ilink->svc_name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Opened IP link '%s'", ilink->svc_name);
 	list_append(&ilink->link_list, &inet_link_list);
 
@@ -209,5 +209,5 @@
 	rc = inet_addrobj_add(addr);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed setting IP address on internet link.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed setting IP address on internet link.");
 		inet_addrobj_delete(addr);
 		/* XXX Roll back */
@@ -218,5 +218,5 @@
 	rc = iplink_addr_add(ilink->iplink, &iaddr);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed setting IP address on internet link.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed setting IP address on internet link.");
 		inet_addrobj_remove(addr);
 		inet_addrobj_delete(addr);
@@ -245,5 +245,5 @@
 	rc = loc_register_cat_change_cb(inet_link_cat_change_cb);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering callback for IP link "
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback for IP link "
 		    "discovery (%d).", rc);
 		return rc;
Index: uspace/srv/net/inetsrv/inetcfg.c
===================================================================
--- uspace/srv/net/inetsrv/inetcfg.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/inetsrv/inetcfg.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -61,5 +61,5 @@
 	ilink = inet_link_get_by_id(link_id);
 	if (ilink == NULL) {
-		log_msg(LVL_DEBUG, "Link %lu not found.",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Link %lu not found.",
 		    (unsigned long) link_id);
 		return ENOENT;
@@ -77,5 +77,5 @@
 	rc = inet_addrobj_add(addr);
 	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "Duplicate address name '%s'.", addr->name);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Duplicate address name '%s'.", addr->name);
 		inet_addrobj_delete(addr);
 		return rc;
@@ -85,5 +85,5 @@
 	rc = iplink_addr_add(ilink->iplink, &iaddr);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed setting IP address on internet link.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed setting IP address on internet link.");
 		inet_addrobj_remove(addr);
 		inet_addrobj_delete(addr);
@@ -130,5 +130,5 @@
 	ilink = inet_link_get_by_id(link_id);
 	if (ilink == NULL) {
-		log_msg(LVL_DEBUG, "Link %zu not found.", (size_t) link_id);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Link %zu not found.", (size_t) link_id);
 		return ENOENT;
 	}
@@ -136,5 +136,5 @@
 	addr = inet_addrobj_find_by_name(name, ilink);
 	if (addr == NULL) {
-		log_msg(LVL_DEBUG, "Address '%s' not found.", name);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Address '%s' not found.", name);
 		return ENOENT;
 	}
@@ -228,5 +228,5 @@
 	sroute = inet_sroute_find_by_name(name);
 	if (sroute == NULL) {
-		log_msg(LVL_DEBUG, "Static route '%s' not found.", name);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Static route '%s' not found.", name);
 		return ENOENT;
 	}
@@ -245,5 +245,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inetcfg_addr_create_static_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_addr_create_static_srv()");
 
 	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
@@ -269,5 +269,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inetcfg_addr_delete_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_addr_delete_srv()");
 
 	addr_id = IPC_GET_ARG1(*call);
@@ -287,5 +287,5 @@
 
 	addr_id = IPC_GET_ARG1(*call);
-	log_msg(LVL_DEBUG, "inetcfg_addr_get_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_addr_get_srv()");
 
 	ainfo.naddr.ipv4 = 0;
@@ -321,5 +321,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inetcfg_addr_get_id_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_addr_get_id_srv()");
 
 	link_id = IPC_GET_ARG1(*call);
@@ -348,5 +348,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inetcfg_get_addr_list_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_get_addr_list_srv()");
 
 	if (!async_data_read_receive(&rcallid, &max_size)) {
@@ -382,5 +382,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inetcfg_get_link_list_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_get_link_list_srv()");
 
 	if (!async_data_read_receive(&rcallid, &max_size)) {
@@ -415,5 +415,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inetcfg_get_sroute_list_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_get_sroute_list_srv()");
 
 	if (!async_data_read_receive(&rcallid, &max_size)) {
@@ -449,5 +449,5 @@
 
 	link_id = IPC_GET_ARG1(*call);
-	log_msg(LVL_DEBUG, "inetcfg_link_get_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_link_get_srv()");
 
 	linfo.name = NULL;
@@ -482,5 +482,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inetcfg_sroute_create_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_sroute_create_srv()");
 
 	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
@@ -506,5 +506,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inetcfg_sroute_delete_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_sroute_delete_srv()");
 
 	sroute_id = IPC_GET_ARG1(*call);
@@ -524,5 +524,5 @@
 
 	sroute_id = IPC_GET_ARG1(*call);
-	log_msg(LVL_DEBUG, "inetcfg_sroute_get_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_sroute_get_srv()");
 
 	srinfo.dest.ipv4 = 0;
@@ -557,5 +557,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inetcfg_sroute_get_id_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_sroute_get_id_srv()");
 
 	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
@@ -574,5 +574,5 @@
 void inet_cfg_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	log_msg(LVL_DEBUG, "inet_cfg_conn()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_cfg_conn()");
 
 	/* Accept the connection */
Index: uspace/srv/net/inetsrv/inetping.c
===================================================================
--- uspace/srv/net/inetsrv/inetping.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/inetsrv/inetping.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -76,5 +76,5 @@
 	client = inetping_client_find(ident);
 	if (client == NULL) {
-		log_msg(LVL_DEBUG, "Unknown ICMP ident. Dropping.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Unknown ICMP ident. Dropping.");
 		return ENOENT;
 	}
@@ -107,5 +107,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inetping_send_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_send_srv()");
 
 	rc = async_data_write_accept((void **) &sdu.data, false, 0, 0, 0,
@@ -133,5 +133,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inetping_get_srcaddr_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_get_srcaddr_srv()");
 
 	remote.ipv4 = IPC_GET_ARG1(*call);
@@ -192,5 +192,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inetping_conn()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_conn()");
 
 	/* Accept the connection */
Index: uspace/srv/net/inetsrv/inetsrv.c
===================================================================
--- uspace/srv/net/inetsrv/inetsrv.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/inetsrv/inetsrv.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -66,5 +66,5 @@
 static int inet_init(void)
 {
-	log_msg(LVL_DEBUG, "inet_init()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_init()");
 	
 	async_set_client_connection(inet_client_conn);
@@ -72,5 +72,5 @@
 	int rc = loc_server_register(NAME);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering server (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server (%d).", rc);
 		return EEXIST;
 	}
@@ -80,5 +80,5 @@
 	    INET_PORT_DEFAULT);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering service (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service (%d).", rc);
 		return EEXIST;
 	}
@@ -87,5 +87,5 @@
 	    INET_PORT_CFG);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering service (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service (%d).", rc);
 		return EEXIST;
 	}
@@ -94,5 +94,5 @@
 	    INET_PORT_PING);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering service (%d).", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service (%d).", rc);
 		return EEXIST;
 	}
@@ -108,5 +108,5 @@
     ipc_call_t *call)
 {
-	log_msg(LVL_DEBUG, "inet_callback_create_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_callback_create_srv()");
 
 	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
@@ -143,5 +143,5 @@
 
 	if (dir->aobj == NULL) {
-		log_msg(LVL_DEBUG, "inet_send: No route to destination.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_send: No route to destination.");
 		return ENOENT;
 	}
@@ -194,5 +194,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inet_get_srcaddr_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_get_srcaddr_srv()");
 
 	remote.ipv4 = IPC_GET_ARG1(*call);
@@ -212,5 +212,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inet_send_srv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_send_srv()");
 
 	dgram.src.ipv4 = IPC_GET_ARG1(*call);
@@ -238,5 +238,5 @@
 
 	proto = IPC_GET_ARG1(*call);
-	log_msg(LVL_DEBUG, "inet_set_proto_srv(%lu)", (unsigned long) proto);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_set_proto_srv(%lu)", (unsigned long) proto);
 
 	if (proto > UINT8_MAX) {
@@ -272,5 +272,5 @@
 	inet_client_t client;
 
-	log_msg(LVL_DEBUG, "inet_default_conn()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_default_conn()");
 
 	/* Accept the connection */
@@ -378,5 +378,5 @@
 	inet_client_t *client;
 
-	log_msg(LVL_DEBUG, "inet_recv_dgram_local()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_recv_dgram_local()");
 
 	/* ICMP messages are handled internally */
@@ -386,5 +386,5 @@
 	client = inet_client_find(proto);
 	if (client == NULL) {
-		log_msg(LVL_DEBUG, "No client found for protocol 0x%" PRIx8,
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "No client found for protocol 0x%" PRIx8,
 		    proto);
 		return ENOENT;
@@ -428,5 +428,5 @@
 	printf(NAME ": HelenOS Internet Protocol service\n");
 
-	if (log_init(NAME, LVL_WARN) != EOK) {
+	if (log_init(NAME) != EOK) {
 		printf(NAME ": Failed to initialize logging.\n");
 		return 1;
Index: uspace/srv/net/inetsrv/pdu.c
===================================================================
--- uspace/srv/net/inetsrv/pdu.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/inetsrv/pdu.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -204,8 +204,8 @@
 	uint16_t foff;
 
-	log_msg(LVL_DEBUG, "inet_pdu_decode()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_pdu_decode()");
 
 	if (size < sizeof(ip_header_t)) {
-		log_msg(LVL_DEBUG, "PDU too short (%zu)", size);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "PDU too short (%zu)", size);
 		return EINVAL;
 	}
@@ -216,5 +216,5 @@
 	    hdr->ver_ihl);
 	if (version != 4) {
-		log_msg(LVL_DEBUG, "Version (%d) != 4", version);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Version (%d) != 4", version);
 		return EINVAL;
 	}
@@ -222,10 +222,10 @@
 	tot_len = uint16_t_be2host(hdr->tot_len);
 	if (tot_len < sizeof(ip_header_t)) {
-		log_msg(LVL_DEBUG, "Total Length too small (%zu)", tot_len);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Total Length too small (%zu)", tot_len);
 		return EINVAL;
 	}
 
 	if (tot_len > size) {
-		log_msg(LVL_DEBUG, "Total Length = %zu > PDU size = %zu",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Total Length = %zu > PDU size = %zu",
 			tot_len, size);
 		return EINVAL;
@@ -256,5 +256,5 @@
 	packet->data = calloc(packet->size, 1);
 	if (packet->data == NULL) {
-		log_msg(LVL_WARN, "Out of memory.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "Out of memory.");
 		return ENOMEM;
 	}
Index: uspace/srv/net/inetsrv/reass.c
===================================================================
--- uspace/srv/net/inetsrv/reass.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/inetsrv/reass.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -86,5 +86,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "inet_reass_queue_packet()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_reass_queue_packet()");
 
 	fibril_mutex_lock(&reass_dgram_map_lock);
@@ -95,5 +95,5 @@
 		/* Only happens when we are out of memory */
 		fibril_mutex_unlock(&reass_dgram_map_lock);
-		log_msg(LVL_DEBUG, "Allocation failed, packet dropped.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Allocation failed, packet dropped.");
 		return ENOMEM;
 	}
Index: uspace/srv/net/inetsrv/sroute.c
===================================================================
--- uspace/srv/net/inetsrv/sroute.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/inetsrv/sroute.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -57,5 +57,5 @@
 
 	if (sroute == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating static route object. "
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating static route object. "
 		    "Out of memory.");
 		return NULL;
@@ -100,5 +100,5 @@
 	inet_sroute_t *best;
 
-	log_msg(LVL_DEBUG, "inet_sroute_find(%x)", (unsigned)addr->ipv4);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_find(%x)", (unsigned)addr->ipv4);
 
 	fibril_mutex_lock(&sroute_list_lock);
@@ -117,5 +117,5 @@
 		if ((sroute->dest.ipv4 & mask) == (addr->ipv4 & mask)) {
 			fibril_mutex_unlock(&sroute_list_lock);
-			log_msg(LVL_DEBUG, "inet_sroute_find: found %p",
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_find: found %p",
 			    sroute);
 			return sroute;
@@ -123,5 +123,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "inet_sroute_find: Not found");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_find: Not found");
 	fibril_mutex_unlock(&sroute_list_lock);
 
@@ -136,5 +136,5 @@
 inet_sroute_t *inet_sroute_find_by_name(const char *name)
 {
-	log_msg(LVL_DEBUG, "inet_sroute_find_by_name('%s')",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_find_by_name('%s')",
 	    name);
 
@@ -147,5 +147,5 @@
 		if (str_cmp(sroute->name, name) == 0) {
 			fibril_mutex_unlock(&sroute_list_lock);
-			log_msg(LVL_DEBUG, "inet_sroute_find_by_name: found %p",
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_find_by_name: found %p",
 			    sroute);
 			return sroute;
@@ -153,5 +153,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "inet_sroute_find_by_name: Not found");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_find_by_name: Not found");
 	fibril_mutex_unlock(&sroute_list_lock);
 
@@ -166,5 +166,5 @@
 inet_sroute_t *inet_sroute_get_by_id(sysarg_t id)
 {
-	log_msg(LVL_DEBUG, "inet_sroute_get_by_id(%zu)", (size_t)id);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_get_by_id(%zu)", (size_t)id);
 
 	fibril_mutex_lock(&sroute_list_lock);
Index: uspace/srv/net/loopip/loopip.c
===================================================================
--- uspace/srv/net/loopip/loopip.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/loopip/loopip.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -75,5 +75,5 @@
 {
 	while (true) {
-		log_msg(LVL_DEBUG, "loopip_recv_fibril(): Wait for one item");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_recv_fibril(): Wait for one item");
 		link_t *link = prodcons_consume(&loopip_rcv_queue);
 		rqueue_entry_t *rqe = list_get_instance(link, rqueue_entry_t, link);
@@ -96,5 +96,5 @@
 	rc = loc_server_register(NAME);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering server.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server.");
 		return rc;
 	}
@@ -108,5 +108,5 @@
 	rc = loc_service_register(svc_name, &sid);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering service %s.", svc_name);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service %s.", svc_name);
 		return rc;
 	}
@@ -114,5 +114,5 @@
 	rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed resolving category 'iplink'.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'iplink'.");
 		return rc;
 	}
@@ -120,5 +120,5 @@
 	rc = loc_service_add_to_cat(sid, iplink_cat);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed adding %s to category.", svc_name);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding %s to category.", svc_name);
 		return rc;
 	}
@@ -135,5 +135,5 @@
 static void loopip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	log_msg(LVL_DEBUG, "loopip_client_conn()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_client_conn()");
 	iplink_conn(iid, icall, &loopip_iplink);
 }
@@ -141,5 +141,5 @@
 static int loopip_open(iplink_srv_t *srv)
 {
-	log_msg(LVL_DEBUG, "loopip_open()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_open()");
 	return EOK;
 }
@@ -147,5 +147,5 @@
 static int loopip_close(iplink_srv_t *srv)
 {
-	log_msg(LVL_DEBUG, "loopip_close()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_close()");
 	return EOK;
 }
@@ -155,5 +155,5 @@
 	rqueue_entry_t *rqe;
 
-	log_msg(LVL_DEBUG, "loopip_send()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_send()");
 
 	rqe = calloc(1, sizeof(rqueue_entry_t));
@@ -184,5 +184,5 @@
 static int loopip_get_mtu(iplink_srv_t *srv, size_t *mtu)
 {
-	log_msg(LVL_DEBUG, "loopip_get_mtu()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_get_mtu()");
 	*mtu = 1500;
 	return EOK;
@@ -191,5 +191,5 @@
 static int loopip_addr_add(iplink_srv_t *srv, iplink_srv_addr_t *addr)
 {
-	log_msg(LVL_DEBUG, "loopip_addr_add(0x%" PRIx32 ")", addr->ipv4);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_addr_add(0x%" PRIx32 ")", addr->ipv4);
 	return EOK;
 }
@@ -197,5 +197,5 @@
 static int loopip_addr_remove(iplink_srv_t *srv, iplink_srv_addr_t *addr)
 {
-	log_msg(LVL_DEBUG, "loopip_addr_remove(0x%" PRIx32 ")", addr->ipv4);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_addr_remove(0x%" PRIx32 ")", addr->ipv4);
 	return EOK;
 }
@@ -207,5 +207,5 @@
 	printf(NAME ": HelenOS loopback IP link provider\n");
 
-	if (log_init(NAME, LVL_WARN) != EOK) {
+	if (log_init(NAME) != EOK) {
 		printf(NAME ": Failed to initialize logging.\n");
 		return 1;
Index: uspace/srv/net/tcp/conn.c
===================================================================
--- uspace/srv/net/tcp/conn.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/tcp/conn.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -164,5 +164,5 @@
 static void tcp_conn_free(tcp_conn_t *conn)
 {
-	log_msg(LVL_DEBUG, "%s: tcp_conn_free(%p)", conn->name, conn);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_free(%p)", conn->name, conn);
 	tcp_tqueue_fini(&conn->retransmit);
 
@@ -184,5 +184,5 @@
 void tcp_conn_addref(tcp_conn_t *conn)
 {
-	log_msg(LVL_DEBUG2, "%s: tcp_conn_addref(%p)", conn->name, conn);
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_addref(%p)", conn->name, conn);
 	atomic_inc(&conn->refcnt);
 }
@@ -196,5 +196,5 @@
 void tcp_conn_delref(tcp_conn_t *conn)
 {
-	log_msg(LVL_DEBUG2, "%s: tcp_conn_delref(%p)", conn->name, conn);
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "%s: tcp_conn_delref(%p)", conn->name, conn);
 
 	if (atomic_predec(&conn->refcnt) == 0)
@@ -211,5 +211,5 @@
 void tcp_conn_delete(tcp_conn_t *conn)
 {
-	log_msg(LVL_DEBUG, "%s: tcp_conn_delete(%p)", conn->name, conn);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_delete(%p)", conn->name, conn);
 
 	assert(conn->deleted == false);
@@ -245,5 +245,5 @@
 	tcp_cstate_t old_state;
 
-	log_msg(LVL_DEBUG, "tcp_conn_state_set(%p)", conn);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set(%p)", conn);
 
 	old_state = conn->cstate;
@@ -253,8 +253,8 @@
 	/* Run user callback function */
 	if (conn->cstate_cb != NULL) {
-		log_msg(LVL_DEBUG, "tcp_conn_state_set() - run user CB");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set() - run user CB");
 		conn->cstate_cb(conn, conn->cstate_cb_arg);
 	} else {
-		log_msg(LVL_DEBUG, "tcp_conn_state_set() - no user CB");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_state_set() - no user CB");
 	}
 
@@ -293,13 +293,13 @@
 	case st_syn_received:
 	case st_established:
-		log_msg(LVL_DEBUG, "%s: FIN sent -> Fin-Wait-1", conn->name);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN sent -> Fin-Wait-1", conn->name);
 		tcp_conn_state_set(conn, st_fin_wait_1);
 		break;
 	case st_close_wait:
-		log_msg(LVL_DEBUG, "%s: FIN sent -> Last-Ack", conn->name);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN sent -> Last-Ack", conn->name);
 		tcp_conn_state_set(conn, st_last_ack);
 		break;
 	default:
-		log_msg(LVL_ERROR, "%s: Connection state %d", conn->name,
+		log_msg(LOG_DEFAULT, LVL_ERROR, "%s: Connection state %d", conn->name,
 		    conn->cstate);
 		assert(false);
@@ -312,5 +312,5 @@
 static bool tcp_socket_match(tcp_sock_t *sock, tcp_sock_t *patt)
 {
-	log_msg(LVL_DEBUG2, "tcp_socket_match(sock=(%x,%u), pat=(%x,%u))",
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_socket_match(sock=(%x,%u), pat=(%x,%u))",
 	    sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
 
@@ -323,5 +323,5 @@
 		return false;
 
-	log_msg(LVL_DEBUG2, " -> match");
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, " -> match");
 
 	return true;
@@ -331,5 +331,5 @@
 static bool tcp_sockpair_match(tcp_sockpair_t *sp, tcp_sockpair_t *pattern)
 {
-	log_msg(LVL_DEBUG2, "tcp_sockpair_match(%p, %p)", sp, pattern);
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_sockpair_match(%p, %p)", sp, pattern);
 
 	if (!tcp_socket_match(&sp->local, &pattern->local))
@@ -353,5 +353,5 @@
 tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
 {
-	log_msg(LVL_DEBUG, "tcp_conn_find_ref(%p)", sp);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref(%p)", sp);
 
 	fibril_mutex_lock(&conn_list_lock);
@@ -360,5 +360,5 @@
 		tcp_conn_t *conn = list_get_instance(link, tcp_conn_t, link);
 		tcp_sockpair_t *csp = &conn->ident;
-		log_msg(LVL_DEBUG2, "compare with conn (f:(%x,%u), l:(%x,%u))",
+		log_msg(LOG_DEFAULT, LVL_DEBUG2, "compare with conn (f:(%x,%u), l:(%x,%u))",
 		    csp->foreign.addr.ipv4, csp->foreign.port,
 		    csp->local.addr.ipv4, csp->local.port);
@@ -380,5 +380,5 @@
 static void tcp_conn_reset(tcp_conn_t *conn)
 {
-	log_msg(LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
 	tcp_conn_state_set(conn, st_closed);
 	conn->reset = true;
@@ -398,5 +398,5 @@
 {
 	/* TODO */
-	log_msg(LVL_DEBUG, "%s: tcp_reset_signal()", conn->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_reset_signal()", conn->name);
 }
 
@@ -422,5 +422,5 @@
 		return true;
 	case st_closed:
-		log_msg(LVL_WARN, "state=%d", (int) conn->cstate);
+		log_msg(LOG_DEFAULT, LVL_WARN, "state=%d", (int) conn->cstate);
 		assert(false);
 	}
@@ -436,13 +436,13 @@
 static void tcp_conn_sa_listen(tcp_conn_t *conn, tcp_segment_t *seg)
 {
-	log_msg(LVL_DEBUG, "tcp_conn_sa_listen(%p, %p)", conn, seg);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_sa_listen(%p, %p)", conn, seg);
 
 	if ((seg->ctrl & CTL_RST) != 0) {
-		log_msg(LVL_DEBUG, "Ignoring incoming RST.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Ignoring incoming RST.");
 		return;
 	}
 
 	if ((seg->ctrl & CTL_ACK) != 0) {
-		log_msg(LVL_DEBUG, "Incoming ACK, send acceptable RST.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Incoming ACK, send acceptable RST.");
 		tcp_reply_rst(&conn->ident, seg);
 		return;
@@ -450,9 +450,9 @@
 
 	if ((seg->ctrl & CTL_SYN) == 0) {
-		log_msg(LVL_DEBUG, "SYN not present. Ignoring segment.");
-		return;
-	}
-
-	log_msg(LVL_DEBUG, "Got SYN, sending SYN, ACK.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "SYN not present. Ignoring segment.");
+		return;
+	}
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Got SYN, sending SYN, ACK.");
 
 	conn->rcv_nxt = seg->seq + 1;
@@ -460,8 +460,8 @@
 
 
-	log_msg(LVL_DEBUG, "rcv_nxt=%u", conn->rcv_nxt);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "rcv_nxt=%u", conn->rcv_nxt);
 
 	if (seg->len > 1)
-		log_msg(LVL_WARN, "SYN combined with data, ignoring data.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "SYN combined with data, ignoring data.");
 
 	/* XXX select ISS */
@@ -493,15 +493,15 @@
 static void tcp_conn_sa_syn_sent(tcp_conn_t *conn, tcp_segment_t *seg)
 {
-	log_msg(LVL_DEBUG, "tcp_conn_sa_syn_sent(%p, %p)", conn, seg);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_sa_syn_sent(%p, %p)", conn, seg);
 
 	if ((seg->ctrl & CTL_ACK) != 0) {
-		log_msg(LVL_DEBUG, "snd_una=%u, seg.ack=%u, snd_nxt=%u",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "snd_una=%u, seg.ack=%u, snd_nxt=%u",
 		    conn->snd_una, seg->ack, conn->snd_nxt);
 		if (!seq_no_ack_acceptable(conn, seg->ack)) {
 			if ((seg->ctrl & CTL_RST) == 0) {
-				log_msg(LVL_WARN, "ACK not acceptable, send RST");
+				log_msg(LOG_DEFAULT, LVL_WARN, "ACK not acceptable, send RST");
 				tcp_reply_rst(&conn->ident, seg);
 			} else {
-				log_msg(LVL_WARN, "RST,ACK not acceptable, drop");
+				log_msg(LOG_DEFAULT, LVL_WARN, "RST,ACK not acceptable, drop");
 			}
 			return;
@@ -512,5 +512,5 @@
 		/* If we get here, we have either an acceptable ACK or no ACK */
 		if ((seg->ctrl & CTL_ACK) != 0) {
-			log_msg(LVL_DEBUG, "%s: Connection reset. -> Closed",
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: Connection reset. -> Closed",
 			    conn->name);
 			/* Reset connection */
@@ -518,5 +518,5 @@
 			return;
 		} else {
-			log_msg(LVL_DEBUG, "%s: RST without ACK, drop",
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: RST without ACK, drop",
 			    conn->name);
 			return;
@@ -527,5 +527,5 @@
 
 	if ((seg->ctrl & CTL_SYN) == 0) {
-		log_msg(LVL_DEBUG, "No SYN bit, ignoring segment.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "No SYN bit, ignoring segment.");
 		return;
 	}
@@ -544,5 +544,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "Sent SYN, got SYN.");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Sent SYN, got SYN.");
 
 	/*
@@ -551,5 +551,5 @@
 	 * will always be accepted as new window setting.
 	 */
-	log_msg(LVL_DEBUG, "SND.WND := %" PRIu32 ", SND.WL1 := %" PRIu32 ", "
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "SND.WND := %" PRIu32 ", SND.WL1 := %" PRIu32 ", "
 	    "SND.WL2 = %" PRIu32, seg->wnd, seg->seq, seg->seq);
 	conn->snd_wnd = seg->wnd;
@@ -558,9 +558,9 @@
 
 	if (seq_no_syn_acked(conn)) {
-		log_msg(LVL_DEBUG, "%s: syn acked -> Established", conn->name);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: syn acked -> Established", conn->name);
 		tcp_conn_state_set(conn, st_established);
 		tcp_tqueue_ctrl_seg(conn, CTL_ACK /* XXX */);
 	} else {
-		log_msg(LVL_DEBUG, "%s: syn not acked -> Syn-Received",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: syn not acked -> Syn-Received",
 		    conn->name);
 		tcp_conn_state_set(conn, st_syn_received);
@@ -582,9 +582,9 @@
 	tcp_segment_t *pseg;
 
-	log_msg(LVL_DEBUG, "tcp_conn_sa_seq(%p, %p)", conn, seg);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_sa_seq(%p, %p)", conn, seg);
 
 	/* Discard unacceptable segments ("old duplicates") */
 	if (!seq_no_segment_acceptable(conn, seg)) {
-		log_msg(LVL_DEBUG, "Replying ACK to unacceptable segment.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Replying ACK to unacceptable segment.");
 		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
 		tcp_segment_delete(seg);
@@ -682,5 +682,5 @@
 	assert(seq_no_in_rcv_wnd(conn, seg->seq));
 
-	log_msg(LVL_WARN, "SYN is in receive window, should send reset. XXX");
+	log_msg(LOG_DEFAULT, LVL_WARN, "SYN is in receive window, should send reset. XXX");
 
 	/*
@@ -705,5 +705,5 @@
 	if (!seq_no_ack_acceptable(conn, seg->ack)) {
 		/* ACK is not acceptable, send RST. */
-		log_msg(LVL_WARN, "Segment ACK not acceptable, sending RST.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "Segment ACK not acceptable, sending RST.");
 		tcp_reply_rst(&conn->ident, seg);
 		tcp_segment_delete(seg);
@@ -711,5 +711,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "%s: SYN ACKed -> Established", conn->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: SYN ACKed -> Established", conn->name);
 
 	tcp_conn_state_set(conn, st_established);
@@ -730,14 +730,14 @@
 static cproc_t tcp_conn_seg_proc_ack_est(tcp_conn_t *conn, tcp_segment_t *seg)
 {
-	log_msg(LVL_DEBUG, "tcp_conn_seg_proc_ack_est(%p, %p)", conn, seg);
-
-	log_msg(LVL_DEBUG, "SEG.ACK=%u, SND.UNA=%u, SND.NXT=%u",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_seg_proc_ack_est(%p, %p)", conn, seg);
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "SEG.ACK=%u, SND.UNA=%u, SND.NXT=%u",
 	    (unsigned)seg->ack, (unsigned)conn->snd_una,
 	    (unsigned)conn->snd_nxt);
 
 	if (!seq_no_ack_acceptable(conn, seg->ack)) {
-		log_msg(LVL_DEBUG, "ACK not acceptable.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "ACK not acceptable.");
 		if (!seq_no_ack_duplicate(conn, seg->ack)) {
-			log_msg(LVL_WARN, "Not acceptable, not duplicate. "
+			log_msg(LOG_DEFAULT, LVL_WARN, "Not acceptable, not duplicate. "
 			    "Send ACK and drop.");
 			/* Not acceptable, not duplicate. Send ACK and drop. */
@@ -746,5 +746,5 @@
 			return cp_done;
 		} else {
-			log_msg(LVL_DEBUG, "Ignoring duplicate ACK.");
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Ignoring duplicate ACK.");
 		}
 	} else {
@@ -758,5 +758,5 @@
 		conn->snd_wl2 = seg->ack;
 
-		log_msg(LVL_DEBUG, "Updating send window, SND.WND=%" PRIu32
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Updating send window, SND.WND=%" PRIu32
 		    ", SND.WL1=%" PRIu32 ", SND.WL2=%" PRIu32,
 		    conn->snd_wnd, conn->snd_wl1, conn->snd_wl2);
@@ -785,5 +785,5 @@
 
 	if (conn->fin_is_acked) {
-		log_msg(LVL_DEBUG, "%s: FIN acked -> Fin-Wait-2", conn->name);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN acked -> Fin-Wait-2", conn->name);
 		tcp_conn_state_set(conn, st_fin_wait_2);
 	}
@@ -850,5 +850,5 @@
 
 	if (conn->fin_is_acked) {
-		log_msg(LVL_DEBUG, "%s: FIN acked -> Closed", conn->name);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN acked -> Closed", conn->name);
 		tcp_conn_remove(conn);
 		tcp_conn_state_set(conn, st_closed);
@@ -881,9 +881,9 @@
 static cproc_t tcp_conn_seg_proc_ack(tcp_conn_t *conn, tcp_segment_t *seg)
 {
-	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_ack(%p, %p)",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_seg_proc_ack(%p, %p)",
 	    conn->name, conn, seg);
 
 	if ((seg->ctrl & CTL_ACK) == 0) {
-		log_msg(LVL_WARN, "Segment has no ACK. Dropping.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "Segment has no ACK. Dropping.");
 		tcp_segment_delete(seg);
 		return cp_done;
@@ -940,5 +940,5 @@
 	size_t xfer_size;
 
-	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_text(%p, %p)",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_seg_proc_text(%p, %p)",
 	    conn->name, conn, seg);
 
@@ -982,5 +982,5 @@
 	fibril_condvar_broadcast(&conn->rcv_buf_cv);
 
-	log_msg(LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
 
 	/* Advance RCV.NXT */
@@ -998,7 +998,7 @@
 		tcp_conn_trim_seg_to_wnd(conn, seg);
 	} else {
-		log_msg(LVL_DEBUG, "%s: Nothing left in segment, dropping "
-		    "(xfer_size=%zu, SEG.LEN=%zu, seg->ctrl=%u)",
-		    conn->name, xfer_size, seg->len, (unsigned)seg->ctrl);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: Nothing left in segment, dropping "
+		    "(xfer_size=%zu, SEG.LEN=%" PRIu32 ", seg->ctrl=%u)",
+		    conn->name, xfer_size, seg->len, (unsigned int) seg->ctrl);
 		/* Nothing left in segment */
 		tcp_segment_delete(seg);
@@ -1018,12 +1018,12 @@
 static cproc_t tcp_conn_seg_proc_fin(tcp_conn_t *conn, tcp_segment_t *seg)
 {
-	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_fin(%p, %p)",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_seg_proc_fin(%p, %p)",
 	    conn->name, conn, seg);
-	log_msg(LVL_DEBUG, " seg->len=%zu, seg->ctl=%u", (size_t) seg->len,
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " seg->len=%zu, seg->ctl=%u", (size_t) seg->len,
 	    (unsigned) seg->ctrl);
 
 	/* Only process FIN if no text is left in segment. */
 	if (tcp_segment_text_size(seg) == 0 && (seg->ctrl & CTL_FIN) != 0) {
-		log_msg(LVL_DEBUG, " - FIN found in segment.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, " - FIN found in segment.");
 
 		/* Send ACK */
@@ -1042,15 +1042,15 @@
 		case st_syn_received:
 		case st_established:
-			log_msg(LVL_DEBUG, "%s: FIN received -> Close-Wait",
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN received -> Close-Wait",
 			    conn->name);
 			tcp_conn_state_set(conn, st_close_wait);
 			break;
 		case st_fin_wait_1:
-			log_msg(LVL_DEBUG, "%s: FIN received -> Closing",
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN received -> Closing",
 			    conn->name);
 			tcp_conn_state_set(conn, st_closing);
 			break;
 		case st_fin_wait_2:
-			log_msg(LVL_DEBUG, "%s: FIN received -> Time-Wait",
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN received -> Time-Wait",
 			    conn->name);
 			tcp_conn_state_set(conn, st_time_wait);
@@ -1091,5 +1091,5 @@
 static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg)
 {
-	log_msg(LVL_DEBUG, "tcp_conn_seg_process(%p, %p)", conn, seg);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_seg_process(%p, %p)", conn, seg);
 	tcp_segment_dump(seg);
 
@@ -1097,5 +1097,5 @@
 	/* XXX Permit valid ACKs, URGs and RSTs */
 /*	if (!seq_no_segment_acceptable(conn, seg)) {
-		log_msg(LVL_WARN, "Segment not acceptable, dropping.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "Segment not acceptable, dropping.");
 		if ((seg->ctrl & CTL_RST) == 0) {
 			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
@@ -1131,5 +1131,5 @@
 	 */
 	if (seg->len > 0) {
-		log_msg(LVL_DEBUG, "Re-insert segment %p. seg->len=%zu",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Re-insert segment %p. seg->len=%zu",
 		    seg, (size_t) seg->len);
 		tcp_iqueue_insert_seg(&conn->incoming, seg);
@@ -1146,5 +1146,5 @@
 void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg)
 {
-	log_msg(LVL_DEBUG, "%c: tcp_conn_segment_arrived(%p)",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_segment_arrived(%p)",
 	    conn->name, seg);
 
@@ -1165,5 +1165,5 @@
 		tcp_conn_sa_queue(conn, seg); break;
 	case st_closed:
-		log_msg(LVL_DEBUG, "state=%d", (int) conn->cstate);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "state=%d", (int) conn->cstate);
 		assert(false);
 	}
@@ -1178,10 +1178,10 @@
 	tcp_conn_t *conn = (tcp_conn_t *) arg;
 
-	log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tw_timeout_func(%p)", conn);
 
 	fibril_mutex_lock(&conn->lock);
 
 	if (conn->cstate == st_closed) {
-		log_msg(LVL_DEBUG, "Connection already closed.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Connection already closed.");
 		fibril_mutex_unlock(&conn->lock);
 		tcp_conn_delref(conn);
@@ -1189,5 +1189,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name);
 	tcp_conn_remove(conn);
 	tcp_conn_state_set(conn, st_closed);
@@ -1240,5 +1240,5 @@
 void tcp_unexpected_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
 {
-	log_msg(LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", sp, seg);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", sp, seg);
 
 	if ((seg->ctrl & CTL_RST) == 0)
@@ -1268,5 +1268,5 @@
 	tcp_segment_t *rseg;
 
-	log_msg(LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);
 
 	rseg = tcp_segment_make_rst(seg);
Index: uspace/srv/net/tcp/iqueue.c
===================================================================
--- uspace/srv/net/tcp/iqueue.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/tcp/iqueue.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -67,9 +67,9 @@
 	tcp_iqueue_entry_t *qe;
 	link_t *link;
-	log_msg(LVL_DEBUG, "tcp_iqueue_insert_seg()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_iqueue_insert_seg()");
 
 	iqe = calloc(1, sizeof(tcp_iqueue_entry_t));
 	if (iqe == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating IQE.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating IQE.");
 		return;
 	}
@@ -108,9 +108,9 @@
 	link_t *link;
 
-	log_msg(LVL_DEBUG, "tcp_get_ready_seg()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_get_ready_seg()");
 
 	link = list_first(&iqueue->list);
 	if (link == NULL) {
-		log_msg(LVL_DEBUG, "iqueue is empty");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "iqueue is empty");
 		return ENOENT;
 	}
@@ -119,5 +119,5 @@
 
 	while (!seq_no_segment_acceptable(iqueue->conn, iqe->seg)) {
-		log_msg(LVL_DEBUG, "Skipping unacceptable segment (RCV.NXT=%"
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Skipping unacceptable segment (RCV.NXT=%"
 		    PRIu32 ", RCV.NXT+RCV.WND=%" PRIu32 ", SEG.SEQ=%" PRIu32
 		    ", SEG.LEN=%" PRIu32 ")", iqueue->conn->rcv_nxt,
@@ -130,5 +130,5 @@
          	link = list_first(&iqueue->list);
 		if (link == NULL) {
-			log_msg(LVL_DEBUG, "iqueue is empty");
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "iqueue is empty");
 			return ENOENT;
 		}
@@ -139,5 +139,5 @@
 	/* Do not return segments that are not ready for processing */
 	if (!seq_no_segment_ready(iqueue->conn, iqe->seg)) {
-		log_msg(LVL_DEBUG, "Next segment not ready: SEG.SEQ=%u, "
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Next segment not ready: SEG.SEQ=%u, "
 		    "RCV.NXT=%u, SEG.LEN=%u", iqe->seg->seq,
 		    iqueue->conn->rcv_nxt, iqe->seg->len);
@@ -145,5 +145,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "Returning ready segment %p", iqe->seg);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Returning ready segment %p", iqe->seg);
 	list_remove(&iqe->link);
 	*seg = iqe->seg;
Index: uspace/srv/net/tcp/ncsim.c
===================================================================
--- uspace/srv/net/tcp/ncsim.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/tcp/ncsim.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -74,5 +74,5 @@
 	link_t *link;
 
-	log_msg(LVL_DEBUG, "tcp_ncsim_bounce_seg()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ncsim_bounce_seg()");
 	tcp_rqueue_bounce_seg(sp, seg);
 	return;
@@ -80,5 +80,5 @@
 	if (0 /*random() % 4 == 3*/) {
 		/* Drop segment */
-		log_msg(LVL_ERROR, "NCSim dropping segment");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "NCSim dropping segment");
 		tcp_segment_delete(seg);
 		return;
@@ -87,5 +87,5 @@
 	sqe = calloc(1, sizeof(tcp_squeue_entry_t));
 	if (sqe == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating SQE.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating SQE.");
 		return;
 	}
@@ -126,5 +126,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "tcp_ncsim_fibril()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ncsim_fibril()");
 
 
@@ -139,5 +139,5 @@
 			sqe = list_get_instance(link, tcp_squeue_entry_t, link);
 
-			log_msg(LVL_DEBUG, "NCSim - Sleep");
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "NCSim - Sleep");
 			rc = fibril_condvar_wait_timeout(&sim_queue_cv,
 			    &sim_queue_lock, sqe->delay);
@@ -147,5 +147,5 @@
 		fibril_mutex_unlock(&sim_queue_lock);
 
-		log_msg(LVL_DEBUG, "NCSim - End Sleep");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "NCSim - End Sleep");
 		tcp_rqueue_bounce_seg(&sqe->sp, sqe->seg);
 		free(sqe);
@@ -161,9 +161,9 @@
 	fid_t fid;
 
-	log_msg(LVL_DEBUG, "tcp_ncsim_fibril_start()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_ncsim_fibril_start()");
 
 	fid = fibril_create(tcp_ncsim_fibril, NULL);
 	if (fid == 0) {
-		log_msg(LVL_ERROR, "Failed creating ncsim fibril.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed creating ncsim fibril.");
 		return;
 	}
Index: uspace/srv/net/tcp/rqueue.c
===================================================================
--- uspace/srv/net/tcp/rqueue.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/tcp/rqueue.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -74,5 +74,5 @@
 	tcp_sockpair_t rident;
 
-	log_msg(LVL_DEBUG, "tcp_rqueue_bounce_seg()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_rqueue_bounce_seg()");
 
 #ifdef BOUNCE_TRANSCODE
@@ -81,10 +81,10 @@
 
 	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "Not enough memory. Segment dropped.");
 		return;
 	}
 
 	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "Not enough memory. Segment dropped.");
 		return;
 	}
@@ -112,5 +112,5 @@
 {
 	tcp_rqueue_entry_t *rqe;
-	log_msg(LVL_DEBUG, "tcp_rqueue_insert_seg()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_rqueue_insert_seg()");
 
 	tcp_segment_dump(seg);
@@ -118,5 +118,5 @@
 	rqe = calloc(1, sizeof(tcp_rqueue_entry_t));
 	if (rqe == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating RQE.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating RQE.");
 		return;
 	}
@@ -134,5 +134,5 @@
 	tcp_rqueue_entry_t *rqe;
 
-	log_msg(LVL_DEBUG, "tcp_rqueue_fibril()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_rqueue_fibril()");
 
 	while (true) {
@@ -152,9 +152,9 @@
 	fid_t fid;
 
-	log_msg(LVL_DEBUG, "tcp_rqueue_fibril_start()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_rqueue_fibril_start()");
 
 	fid = fibril_create(tcp_rqueue_fibril, NULL);
 	if (fid == 0) {
-		log_msg(LVL_ERROR, "Failed creating rqueue fibril.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed creating rqueue fibril.");
 		return;
 	}
Index: uspace/srv/net/tcp/segment.c
===================================================================
--- uspace/srv/net/tcp/segment.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/tcp/segment.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -248,11 +248,11 @@
 void tcp_segment_dump(tcp_segment_t *seg)
 {
-	log_msg(LVL_DEBUG2, "Segment dump:");
-	log_msg(LVL_DEBUG2, " - ctrl = %u", (unsigned)seg->ctrl);
-	log_msg(LVL_DEBUG2, " - seq = % " PRIu32, seg->seq);
-	log_msg(LVL_DEBUG2, " - ack = % " PRIu32, seg->ack);
-	log_msg(LVL_DEBUG2, " - len = % " PRIu32, seg->len);
-	log_msg(LVL_DEBUG2, " - wnd = % " PRIu32, seg->wnd);
-	log_msg(LVL_DEBUG2, " - up = % " PRIu32, seg->up);
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, "Segment dump:");
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, " - ctrl = %u", (unsigned)seg->ctrl);
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, " - seq = %" PRIu32, seg->seq);
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, " - ack = %" PRIu32, seg->ack);
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, " - len = %" PRIu32, seg->len);
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, " - wnd = %" PRIu32, seg->wnd);
+	log_msg(LOG_DEFAULT, LVL_DEBUG2, " - up = %" PRIu32, seg->up);
 }
 
Index: uspace/srv/net/tcp/sock.c
===================================================================
--- uspace/srv/net/tcp/sock.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/tcp/sock.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -91,5 +91,5 @@
 static void tcp_sock_notify_data(socket_core_t *sock_core)
 {
-	log_msg(LVL_DEBUG, "tcp_sock_notify_data(%d)", sock_core->socket_id);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_notify_data(%d)", sock_core->socket_id);
 	async_exch_t *exch = async_exchange_begin(sock_core->sess);
 	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id,
@@ -100,5 +100,5 @@
 static void tcp_sock_notify_aconn(socket_core_t *lsock_core)
 {
-	log_msg(LVL_DEBUG, "tcp_sock_notify_aconn(%d)", lsock_core->socket_id);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_notify_aconn(%d)", lsock_core->socket_id);
 	async_exch_t *exch = async_exchange_begin(lsock_core->sess);
 	async_msg_5(exch, NET_SOCKET_ACCEPTED, (sysarg_t)lsock_core->socket_id,
@@ -111,8 +111,8 @@
 	tcp_sockdata_t *sock;
 
-	log_msg(LVL_DEBUG, "tcp_sock_create()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_create()");
 	*rsock = NULL;
 
-	sock = calloc(sizeof(tcp_sockdata_t), 1);
+	sock = calloc(1, sizeof(tcp_sockdata_t));
 	if (sock == NULL)
 		return ENOMEM;
@@ -133,5 +133,5 @@
 static void tcp_sock_uncreate(tcp_sockdata_t *sock)
 {
-	log_msg(LVL_DEBUG, "tcp_sock_uncreate()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_uncreate()");
 	free(sock);
 }
@@ -142,5 +142,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "tcp_sock_finish_setup()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_finish_setup()");
 
 	sock->recv_fibril = fibril_create(tcp_sock_recv_fibril, sock);
@@ -171,5 +171,5 @@
 	ipc_call_t answer;
 
-	log_msg(LVL_DEBUG, "tcp_sock_socket()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_socket()");
 
 	rc = tcp_sock_create(client, &sock);
@@ -208,6 +208,6 @@
 	tcp_sockdata_t *socket;
 
-	log_msg(LVL_DEBUG, "tcp_sock_bind()");
-	log_msg(LVL_DEBUG, " - async_data_write_accept");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_bind()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " - async_data_write_accept");
 	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
 	if (rc != EOK) {
@@ -216,5 +216,5 @@
 	}
 
-	log_msg(LVL_DEBUG, " - call socket_bind");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_bind");
 	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
 	    addr, addr_len, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
@@ -225,5 +225,5 @@
 	}
 
-	log_msg(LVL_DEBUG, " - call socket_cores_find");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_cores_find");
 	sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
 	if (sock_core != NULL) {
@@ -233,5 +233,5 @@
 	}
 
-	log_msg(LVL_DEBUG, " - success");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " - success");
 	async_answer_0(callid, EOK);
 }
@@ -250,5 +250,5 @@
 	int i;
 
-	log_msg(LVL_DEBUG, "tcp_sock_listen()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_listen()");
 
 	socket_id = SOCKET_GET_SOCKET_ID(call);
@@ -277,5 +277,5 @@
 
 	socket->backlog = backlog;
-	socket->lconn = calloc(sizeof(tcp_conn_t *), backlog);
+	socket->lconn = calloc(backlog, sizeof(tcp_conn_t *));
 	if (socket->lconn == NULL) {
 		fibril_mutex_unlock(&socket->lock);
@@ -284,5 +284,5 @@
 	}
 
-	log_msg(LVL_DEBUG, " - open connections");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " - open connections");
 
 	lsocket.addr.ipv4 = TCP_IPV4_ANY;
@@ -293,5 +293,5 @@
 	for (i = 0; i < backlog; i++) {
 
-		lconn = calloc(sizeof(tcp_sock_lconn_t), 1);
+		lconn = calloc(1, sizeof(tcp_sock_lconn_t));
 		if (lconn == NULL) {
 			/* XXX Clean up */
@@ -337,5 +337,5 @@
 	tcp_sock_t fsocket;
 
-	log_msg(LVL_DEBUG, "tcp_sock_connect()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_connect()");
 
 	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
@@ -377,5 +377,5 @@
 			fibril_mutex_unlock(&socket->lock);
 			async_answer_0(callid, rc);
-			log_msg(LVL_DEBUG, "tcp_sock_connect: Failed to "
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_connect: Failed to "
 			    "determine local address.");
 			return;
@@ -383,5 +383,5 @@
 
 		socket->laddr.ipv4 = loc_addr.ipv4;
-		log_msg(LVL_DEBUG, "Local IP address is %x", socket->laddr.ipv4);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Local IP address is %x", socket->laddr.ipv4);
 	}
 
@@ -431,5 +431,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "tcp_sock_accept()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_accept()");
 
 	socket_id = SOCKET_GET_SOCKET_ID(call);
@@ -445,5 +445,5 @@
 	fibril_mutex_lock(&socket->lock);
 
-	log_msg(LVL_DEBUG, " - verify socket->conn");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " - verify socket->conn");
 	if (socket->conn != NULL) {
 		fibril_mutex_unlock(&socket->lock);
@@ -498,5 +498,5 @@
 
 	asocket->conn = conn;
-	log_msg(LVL_DEBUG, "tcp_sock_accept():create asocket\n");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_accept():create asocket\n");
 
 	rc = tcp_sock_finish_setup(asocket, &asock_id);
@@ -510,5 +510,5 @@
 	fibril_add_ready(asocket->recv_fibril);
 
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): find acore\n");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_accept(): find acore\n");
 
 	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE);
@@ -521,5 +521,5 @@
 	
 	/* Push one fragment notification to client's queue */
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_accept(): notify data\n");
 	fibril_mutex_unlock(&socket->lock);
 }
@@ -539,5 +539,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "tcp_sock_send()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_send()");
 	socket_id = SOCKET_GET_SOCKET_ID(call);
 	fragments = SOCKET_GET_DATA_FRAGMENTS(call);
@@ -611,5 +611,5 @@
 static void tcp_sock_sendto(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
 {
-	log_msg(LVL_DEBUG, "tcp_sock_sendto()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_sendto()");
 	async_answer_0(callid, ENOTSUP);
 }
@@ -629,5 +629,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "%p: tcp_sock_recv[from]()", client);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%p: tcp_sock_recv[from]()", client);
 
 	socket_id = SOCKET_GET_SOCKET_ID(call);
@@ -651,13 +651,13 @@
 	(void)flags;
 
-	log_msg(LVL_DEBUG, "tcp_sock_recvfrom(): lock recv_buffer_lock");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_recvfrom(): lock recv_buffer_lock");
 	fibril_mutex_lock(&socket->recv_buffer_lock);
 	while (socket->recv_buffer_used == 0 && socket->recv_error == TCP_EOK) {
-		log_msg(LVL_DEBUG, "wait for recv_buffer_cv + recv_buffer_used != 0");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "wait for recv_buffer_cv + recv_buffer_used != 0");
 		fibril_condvar_wait(&socket->recv_buffer_cv,
 		    &socket->recv_buffer_lock);
 	}
 
-	log_msg(LVL_DEBUG, "Got data in sock recv_buffer");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Got data in sock recv_buffer");
 
 	data_len = socket->recv_buffer_used;
@@ -679,5 +679,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "**** recv result -> %d", rc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "**** recv result -> %d", rc);
 	if (rc != EOK) {
 		fibril_mutex_unlock(&socket->recv_buffer_lock);
@@ -694,5 +694,5 @@
 		addr.sin_port = host2uint16_t_be(rsock->port);
 
-		log_msg(LVL_DEBUG, "addr read receive");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "addr read receive");
 		if (!async_data_read_receive(&rcallid, &addr_length)) {
 			fibril_mutex_unlock(&socket->recv_buffer_lock);
@@ -705,5 +705,5 @@
 			addr_length = sizeof(addr);
 
-		log_msg(LVL_DEBUG, "addr read finalize");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "addr read finalize");
 		rc = async_data_read_finalize(rcallid, &addr, addr_length);
 		if (rc != EOK) {
@@ -715,5 +715,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "data read receive");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "data read receive");
 	if (!async_data_read_receive(&rcallid, &length)) {
 		fibril_mutex_unlock(&socket->recv_buffer_lock);
@@ -726,9 +726,9 @@
 		length = data_len;
 
-	log_msg(LVL_DEBUG, "data read finalize");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "data read finalize");
 	rc = async_data_read_finalize(rcallid, socket->recv_buffer, length);
 
 	socket->recv_buffer_used -= length;
-	log_msg(LVL_DEBUG, "tcp_sock_recvfrom: %zu left in buffer",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_recvfrom: %zu left in buffer",
 	    socket->recv_buffer_used);
 	if (socket->recv_buffer_used > 0) {
@@ -758,5 +758,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "tcp_sock_close()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close()");
 	socket_id = SOCKET_GET_SOCKET_ID(call);
 
@@ -779,4 +779,9 @@
 	}
 
+	/* Grab recv_buffer_lock because of CV wait in tcp_sock_recv_fibril() */
+	fibril_mutex_lock(&socket->recv_buffer_lock);
+	socket->sock_core = NULL;
+	fibril_mutex_unlock(&socket->recv_buffer_lock);
+
 	rc = socket_destroy(NULL, socket_id, &client->sockets, &gsock,
 	    tcp_free_sock_data);
@@ -793,5 +798,5 @@
 static void tcp_sock_getsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
 {
-	log_msg(LVL_DEBUG, "tcp_sock_getsockopt()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_getsockopt()");
 	async_answer_0(callid, ENOTSUP);
 }
@@ -799,5 +804,5 @@
 static void tcp_sock_setsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
 {
-	log_msg(LVL_DEBUG, "tcp_sock_setsockopt()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_setsockopt()");
 	async_answer_0(callid, ENOTSUP);
 }
@@ -810,5 +815,5 @@
 	tcp_sockdata_t *socket = lconn->socket;
 
-	log_msg(LVL_DEBUG, "tcp_sock_cstate_cb()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_cstate_cb()");
 	fibril_mutex_lock(&socket->lock);
 	assert(conn == lconn->conn);
@@ -823,5 +828,5 @@
 	list_append(&lconn->ready_list, &socket->ready);
 
-	log_msg(LVL_DEBUG, "tcp_sock_cstate_cb(): notify accept");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_cstate_cb(): notify accept");
 
 	/* Push one accept notification to client's queue */
@@ -837,10 +842,11 @@
 	tcp_error_t trc;
 
-	log_msg(LVL_DEBUG, "tcp_sock_recv_fibril()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_recv_fibril()");
+
+	fibril_mutex_lock(&sock->recv_buffer_lock);
 
 	while (true) {
-		log_msg(LVL_DEBUG, "call tcp_uc_receive()");
-		fibril_mutex_lock(&sock->recv_buffer_lock);
-		while (sock->recv_buffer_used != 0)
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "call tcp_uc_receive()");
+		while (sock->recv_buffer_used != 0 && sock->sock_core != NULL)
 			fibril_condvar_wait(&sock->recv_buffer_cv,
 			    &sock->recv_buffer_lock);
@@ -852,16 +858,18 @@
 			sock->recv_error = trc;
 			fibril_condvar_broadcast(&sock->recv_buffer_cv);
-			fibril_mutex_unlock(&sock->recv_buffer_lock);
-			tcp_sock_notify_data(sock->sock_core);
-			break;
-		}
-
-		log_msg(LVL_DEBUG, "got data - broadcast recv_buffer_cv");
+			if (sock->sock_core != NULL)
+				tcp_sock_notify_data(sock->sock_core);
+			break;
+		}
+
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "got data - broadcast recv_buffer_cv");
 
 		sock->recv_buffer_used = data_len;
 		fibril_condvar_broadcast(&sock->recv_buffer_cv);
-		fibril_mutex_unlock(&sock->recv_buffer_lock);
-		tcp_sock_notify_data(sock->sock_core);
-	}
+		if (sock->sock_core != NULL)
+			tcp_sock_notify_data(sock->sock_core);
+	}
+
+	fibril_mutex_unlock(&sock->recv_buffer_lock);
 
 	tcp_uc_delete(sock->conn);
@@ -887,5 +895,5 @@
 			break;
 
-		log_msg(LVL_DEBUG, "tcp_sock_connection: METHOD=%d\n",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_connection: METHOD=%d\n",
 		    (int)IPC_GET_IMETHOD(call));
 
@@ -932,5 +940,5 @@
 
 	/* Clean up */
-	log_msg(LVL_DEBUG, "tcp_sock_connection: Clean up");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_connection: Clean up");
 	async_hangup(client.sess);
 	socket_cores_release(NULL, &client.sockets, &gsock, tcp_free_sock_data);
Index: uspace/srv/net/tcp/tcp.c
===================================================================
--- uspace/srv/net/tcp/tcp.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/tcp/tcp.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -69,5 +69,5 @@
 	size_t pdu_raw_size;
 
-	log_msg(LVL_DEBUG, "tcp_inet_ev_recv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_inet_ev_recv()");
 
 	pdu_raw = dgram->data;
@@ -76,5 +76,5 @@
 	/* Split into header and payload. */
 
-	log_msg(LVL_DEBUG, "tcp_inet_ev_recv() - split header/payload");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_inet_ev_recv() - split header/payload");
 
 	tcp_pdu_t *pdu;
@@ -84,5 +84,5 @@
 
 	if (pdu_raw_size < sizeof(tcp_header_t)) {
-		log_msg(LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
+		log_msg(LOG_DEFAULT, LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
 		    pdu_raw_size, sizeof(tcp_header_t));
 		return EINVAL;
@@ -96,5 +96,5 @@
 
 	if (pdu_raw_size < hdr_size) {
-		log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
+		log_msg(LOG_DEFAULT, LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
 		    pdu_raw_size, hdr_size);
 		return EINVAL;
@@ -102,14 +102,14 @@
 
 	if (hdr_size < sizeof(tcp_header_t)) {
-		log_msg(LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
+		log_msg(LOG_DEFAULT, LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
 		    hdr_size, sizeof(tcp_header_t));		return EINVAL;
 	}
 
-	log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu",
 	    pdu_raw_size, hdr_size);
 	pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size,
 	    pdu_raw_size - hdr_size);
 	if (pdu == NULL) {
-		log_msg(LVL_WARN, "Failed creating PDU. Dropped.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "Failed creating PDU. Dropped.");
 		return ENOMEM;
 	}
@@ -117,5 +117,5 @@
 	pdu->src_addr.ipv4 = dgram->src.ipv4;
 	pdu->dest_addr.ipv4 = dgram->dest.ipv4;
-	log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
 	    pdu->src_addr.ipv4, pdu->dest_addr.ipv4);
 
@@ -137,5 +137,5 @@
 	pdu_raw = malloc(pdu_raw_size);
 	if (pdu_raw == NULL) {
-		log_msg(LVL_ERROR, "Failed to transmit PDU. Out of memory.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to transmit PDU. Out of memory.");
 		return;
 	}
@@ -153,5 +153,5 @@
 	rc = inet_send(&dgram, INET_TTL_MAX, 0);
 	if (rc != EOK)
-		log_msg(LVL_ERROR, "Failed to transmit PDU.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to transmit PDU.");
 }
 
@@ -162,8 +162,8 @@
 	tcp_sockpair_t rident;
 
-	log_msg(LVL_DEBUG, "tcp_received_pdu()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_received_pdu()");
 
 	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "Not enough memory. PDU dropped.");
 		return;
 	}
@@ -177,5 +177,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "tcp_init()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_init()");
 
 	tcp_rqueue_init();
@@ -189,5 +189,5 @@
 	rc = inet_init(IP_PROTO_TCP, &tcp_inet_ev_ops);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed connecting to internet service.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed connecting to internet service.");
 		return ENOENT;
 	}
@@ -195,5 +195,5 @@
 	rc = tcp_sock_init();
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed initializing socket service.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing socket service.");
 		return ENOENT;
 	}
@@ -208,5 +208,5 @@
 	printf(NAME ": TCP (Transmission Control Protocol) network module\n");
 
-	rc = log_init(NAME, LVL_WARN);
+	rc = log_init(NAME);
 	if (rc != EOK) {
 		printf(NAME ": Failed to initialize log.\n");
Index: uspace/srv/net/tcp/tqueue.c
===================================================================
--- uspace/srv/net/tcp/tqueue.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/tcp/tqueue.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -88,5 +88,5 @@
 	tcp_segment_t *seg;
 
-	log_msg(LVL_DEBUG, "tcp_tqueue_ctrl_seg(%p, %u)", conn, ctrl);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_tqueue_ctrl_seg(%p, %u)", conn, ctrl);
 
 	seg = tcp_segment_make_ctrl(ctrl);
@@ -99,5 +99,5 @@
 	tcp_tqueue_entry_t *tqe;
 
-	log_msg(LVL_DEBUG, "%s: tcp_tqueue_seg(%p, %p)", conn->name, conn,
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_tqueue_seg(%p, %p)", conn->name, conn,
 	    seg);
 
@@ -109,5 +109,5 @@
 		rt_seg = tcp_segment_dup(seg);
 		if (rt_seg == NULL) {
-			log_msg(LVL_ERROR, "Memory allocation failed.");
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Memory allocation failed.");
 			/* XXX Handle properly */
 			return;
@@ -116,5 +116,5 @@
 		tqe = calloc(1, sizeof(tcp_tqueue_entry_t));
 		if (tqe == NULL) {
-			log_msg(LVL_ERROR, "Memory allocation failed.");
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Memory allocation failed.");
 			/* XXX Handle properly */
 			return;
@@ -165,5 +165,5 @@
 	tcp_segment_t *seg;
 
-	log_msg(LVL_DEBUG, "%s: tcp_tqueue_new_data()", conn->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_tqueue_new_data()", conn->name);
 
 	/* Number of free sequence numbers in send window */
@@ -172,5 +172,5 @@
 
 	xfer_seqlen = min(snd_buf_seqlen, avail_wnd);
-	log_msg(LVL_DEBUG, "%s: snd_buf_seqlen = %zu, SND.WND = %zu, "
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: snd_buf_seqlen = %zu, SND.WND = %" PRIu32 ", "
 	    "xfer_seqlen = %zu", conn->name, snd_buf_seqlen, conn->snd_wnd,
 	    xfer_seqlen);
@@ -185,5 +185,5 @@
 
 	if (send_fin) {
-		log_msg(LVL_DEBUG, "%s: Sending out FIN.", conn->name);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: Sending out FIN.", conn->name);
 		/* We are sending out FIN */
 		ctrl = CTL_FIN;
@@ -194,5 +194,5 @@
 	seg = tcp_segment_make_data(ctrl, conn->snd_buf, data_size);
 	if (seg == NULL) {
-		log_msg(LVL_ERROR, "Memory allocation failure.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Memory allocation failure.");
 		return;
 	}
@@ -223,5 +223,5 @@
 	link_t *cur, *next;
 
-	log_msg(LVL_DEBUG, "%s: tcp_tqueue_ack_received(%p)", conn->name,
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_tqueue_ack_received(%p)", conn->name,
 	    conn);
 
@@ -239,6 +239,6 @@
 
 			if ((tqe->seg->ctrl & CTL_FIN) != 0) {
-				log_msg(LVL_DEBUG, "Fin has been acked");
-				log_msg(LVL_DEBUG, "SND.UNA=%" PRIu32
+				log_msg(LOG_DEFAULT, LVL_DEBUG, "Fin has been acked");
+				log_msg(LOG_DEFAULT, LVL_DEBUG, "SND.UNA=%" PRIu32
 				    " SEG.SEQ=%" PRIu32 " SEG.LEN=%" PRIu32,
 				    conn->snd_una, tqe->seg->seq, tqe->seg->len);
@@ -267,5 +267,5 @@
 void tcp_conn_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
 {
-	log_msg(LVL_DEBUG, "%s: tcp_conn_transmit_segment(%p, %p)",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_transmit_segment(%p, %p)",
 	    conn->name, conn, seg);
 
@@ -282,9 +282,9 @@
 void tcp_transmit_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
 {
-	log_msg(LVL_DEBUG, "tcp_transmit_segment(f:(%x,%u),l:(%x,%u), %p)",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_transmit_segment(f:(%x,%u),l:(%x,%u), %p)",
 	    sp->foreign.addr.ipv4, sp->foreign.port,
 	    sp->local.addr.ipv4, sp->local.port, seg);
 
-	log_msg(LVL_DEBUG, "SEG.SEQ=%" PRIu32 ", SEG.WND=%" PRIu32,
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "SEG.SEQ=%" PRIu32 ", SEG.WND=%" PRIu32,
 	    seg->seq, seg->wnd);
 
@@ -300,5 +300,5 @@
 
 	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "Not enough memory. Segment dropped.");
 		return;
 	}
@@ -315,10 +315,10 @@
 	link_t *link;
 
-	log_msg(LVL_DEBUG, "### %s: retransmit_timeout_func(%p)", conn->name, conn);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: retransmit_timeout_func(%p)", conn->name, conn);
 
 	fibril_mutex_lock(&conn->lock);
 
 	if (conn->cstate == st_closed) {
-		log_msg(LVL_DEBUG, "Connection already closed.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Connection already closed.");
 		fibril_mutex_unlock(&conn->lock);
 		tcp_conn_delref(conn);
@@ -328,5 +328,5 @@
 	link = list_first(&conn->retransmit.list);
 	if (link == NULL) {
-		log_msg(LVL_DEBUG, "Nothing to retransmit");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Nothing to retransmit");
 		fibril_mutex_unlock(&conn->lock);
 		tcp_conn_delref(conn);
@@ -338,5 +338,5 @@
 	rt_seg = tcp_segment_dup(tqe->seg);
 	if (rt_seg == NULL) {
-		log_msg(LVL_ERROR, "Memory allocation failed.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Memory allocation failed.");
 		fibril_mutex_unlock(&conn->lock);
 		tcp_conn_delref(conn);
@@ -345,5 +345,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "### %s: retransmitting segment", conn->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: retransmitting segment", conn->name);
 	tcp_conn_transmit_segment(tqe->conn, rt_seg);
 
@@ -358,5 +358,5 @@
 static void tcp_tqueue_timer_set(tcp_conn_t *conn)
 {
-	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_set()", conn->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: tcp_tqueue_timer_set()", conn->name);
 
 	/* Clear first to make sure we update refcnt correctly */
@@ -371,5 +371,5 @@
 static void tcp_tqueue_timer_clear(tcp_conn_t *conn)
 {
-	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_clear()", conn->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: tcp_tqueue_timer_clear()", conn->name);
 
 	if (fibril_timer_clear(conn->retransmit.timer) == fts_active)
Index: uspace/srv/net/tcp/ucall.c
===================================================================
--- uspace/srv/net/tcp/ucall.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/tcp/ucall.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -70,5 +70,5 @@
 	tcp_conn_t *nconn;
 
-	log_msg(LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %s, %p)",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %s, %p)",
 	    lsock, fsock, acpass == ap_active ? "active" : "passive",
 	    oflags == tcp_open_nonblock ? "nonblock" : "none", conn);
@@ -88,5 +88,5 @@
 
 	/* Wait for connection to be established or reset */
-	log_msg(LVL_DEBUG, "tcp_uc_open: Wait for connection.");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_open: Wait for connection.");
 	fibril_mutex_lock(&nconn->lock);
 	while (nconn->cstate == st_listen ||
@@ -97,5 +97,5 @@
 
 	if (nconn->cstate != st_established) {
-		log_msg(LVL_DEBUG, "tcp_uc_open: Connection was reset.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_open: Connection was reset.");
 		assert(nconn->cstate == st_closed);
 		fibril_mutex_unlock(&nconn->lock);
@@ -104,8 +104,8 @@
 
 	fibril_mutex_unlock(&nconn->lock);
-	log_msg(LVL_DEBUG, "tcp_uc_open: Connection was established.");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_open: Connection was established.");
 
 	*conn = nconn;
-	log_msg(LVL_DEBUG, "tcp_uc_open -> %p", nconn);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_open -> %p", nconn);
 	return TCP_EOK;
 }
@@ -118,5 +118,5 @@
 	size_t xfer_size;
 
-	log_msg(LVL_DEBUG, "%s: tcp_uc_send()", conn->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_uc_send()", conn->name);
 
 	fibril_mutex_lock(&conn->lock);
@@ -141,5 +141,5 @@
 		buf_free = conn->snd_buf_size - conn->snd_buf_used;
 		while (buf_free == 0 && !conn->reset) {
-			log_msg(LVL_DEBUG, "%s: buf_free == 0, waiting.",
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: buf_free == 0, waiting.",
 			    conn->name);
 			fibril_condvar_wait(&conn->snd_buf_cv, &conn->lock);
@@ -175,5 +175,5 @@
 	size_t xfer_size;
 
-	log_msg(LVL_DEBUG, "%s: tcp_uc_receive()", conn->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_uc_receive()", conn->name);
 
 	fibril_mutex_lock(&conn->lock);
@@ -186,5 +186,5 @@
 	/* Wait for data to become available */
 	while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin && !conn->reset) {
-		log_msg(LVL_DEBUG, "tcp_uc_receive() - wait for data");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_receive() - wait for data");
 		fibril_condvar_wait(&conn->rcv_buf_cv, &conn->lock);
 	}
@@ -223,5 +223,5 @@
 	tcp_tqueue_ctrl_seg(conn, CTL_ACK);
 
-	log_msg(LVL_DEBUG, "%s: tcp_uc_receive() - returning %zu bytes",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_uc_receive() - returning %zu bytes",
 	    conn->name, xfer_size);
 
@@ -234,5 +234,5 @@
 tcp_error_t tcp_uc_close(tcp_conn_t *conn)
 {
-	log_msg(LVL_DEBUG, "%s: tcp_uc_close()", conn->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_uc_close()", conn->name);
 
 	fibril_mutex_lock(&conn->lock);
@@ -258,5 +258,5 @@
 void tcp_uc_abort(tcp_conn_t *conn)
 {
-	log_msg(LVL_DEBUG, "tcp_uc_abort()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_abort()");
 }
 
@@ -264,5 +264,5 @@
 void tcp_uc_status(tcp_conn_t *conn, tcp_conn_status_t *cstatus)
 {
-	log_msg(LVL_DEBUG, "tcp_uc_status()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_status()");
 	cstatus->cstate = conn->cstate;
 }
@@ -276,5 +276,5 @@
 void tcp_uc_delete(tcp_conn_t *conn)
 {
-	log_msg(LVL_DEBUG, "tcp_uc_delete()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_delete()");
 	tcp_conn_delete(conn);
 }
@@ -282,5 +282,5 @@
 void tcp_uc_set_cstate_cb(tcp_conn_t *conn, tcp_cstate_cb_t cb, void *arg)
 {
-	log_msg(LVL_DEBUG, "tcp_uc_set_ctate_cb(%p, %p, %p)",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_set_ctate_cb(%p, %p, %p)",
 	    conn, cb, arg);
 
@@ -298,5 +298,5 @@
 	tcp_conn_t *conn;
 
-	log_msg(LVL_DEBUG, "tcp_as_segment_arrived(f:(%x,%u), l:(%x,%u))",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_as_segment_arrived(f:(%x,%u), l:(%x,%u))",
 	    sp->foreign.addr.ipv4, sp->foreign.port,
 	    sp->local.addr.ipv4, sp->local.port);
@@ -304,5 +304,5 @@
 	conn = tcp_conn_find_ref(sp);
 	if (conn == NULL) {
-		log_msg(LVL_WARN, "No connection found.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "No connection found.");
 		tcp_unexpected_segment(sp, seg);
 		return;
@@ -312,5 +312,5 @@
 
 	if (conn->cstate == st_closed) {
-		log_msg(LVL_WARN, "Connection is closed.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "Connection is closed.");
 		tcp_unexpected_segment(sp, seg);
 		fibril_mutex_unlock(&conn->lock);
@@ -339,5 +339,5 @@
 void tcp_to_user(void)
 {
-	log_msg(LVL_DEBUG, "tcp_to_user()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_to_user()");
 }
 
Index: uspace/srv/net/udp/assoc.c
===================================================================
--- uspace/srv/net/udp/assoc.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/udp/assoc.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -104,5 +104,5 @@
 static void udp_assoc_free(udp_assoc_t *assoc)
 {
-	log_msg(LVL_DEBUG, "%s: udp_assoc_free(%p)", assoc->name, assoc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: udp_assoc_free(%p)", assoc->name, assoc);
 
 	while (!list_empty(&assoc->rcv_queue)) {
@@ -127,5 +127,5 @@
 void udp_assoc_addref(udp_assoc_t *assoc)
 {
-	log_msg(LVL_DEBUG, "%s: upd_assoc_addref(%p)", assoc->name, assoc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: upd_assoc_addref(%p)", assoc->name, assoc);
 	atomic_inc(&assoc->refcnt);
 }
@@ -139,5 +139,5 @@
 void udp_assoc_delref(udp_assoc_t *assoc)
 {
-	log_msg(LVL_DEBUG, "%s: udp_assoc_delref(%p)", assoc->name, assoc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: udp_assoc_delref(%p)", assoc->name, assoc);
 
 	if (atomic_predec(&assoc->refcnt) == 0)
@@ -154,5 +154,5 @@
 void udp_assoc_delete(udp_assoc_t *assoc)
 {
-	log_msg(LVL_DEBUG, "%s: udp_assoc_delete(%p)", assoc->name, assoc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: udp_assoc_delete(%p)", assoc->name, assoc);
 
 	assert(assoc->deleted == false);
@@ -192,5 +192,5 @@
 void udp_assoc_set_foreign(udp_assoc_t *assoc, udp_sock_t *fsock)
 {
-	log_msg(LVL_DEBUG, "udp_assoc_set_foreign(%p, %p)", assoc, fsock);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_foreign(%p, %p)", assoc, fsock);
 	fibril_mutex_lock(&assoc->lock);
 	assoc->ident.foreign = *fsock;
@@ -205,5 +205,5 @@
 void udp_assoc_set_local(udp_assoc_t *assoc, udp_sock_t *lsock)
 {
-	log_msg(LVL_DEBUG, "udp_assoc_set_local(%p, %p)", assoc, lsock);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_set_local(%p, %p)", assoc, lsock);
 	fibril_mutex_lock(&assoc->lock);
 	assoc->ident.local = *lsock;
@@ -228,5 +228,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "udp_assoc_send(%p, %p, %p)",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_send(%p, %p, %p)",
 	    assoc, fsock, msg);
 
@@ -261,19 +261,19 @@
 	udp_rcv_queue_entry_t *rqe;
 
-	log_msg(LVL_DEBUG, "udp_assoc_recv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_recv()");
 
 	fibril_mutex_lock(&assoc->lock);
 	while (list_empty(&assoc->rcv_queue) && !assoc->reset) {
-		log_msg(LVL_DEBUG, "udp_assoc_recv() - waiting");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_recv() - waiting");
 		fibril_condvar_wait(&assoc->rcv_queue_cv, &assoc->lock);
 	}
 
 	if (assoc->reset) {
-		log_msg(LVL_DEBUG, "udp_assoc_recv() - association was reset");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_recv() - association was reset");
 		fibril_mutex_unlock(&assoc->lock);
 		return ECONNABORTED;
 	}
 
-	log_msg(LVL_DEBUG, "udp_assoc_recv() - got a message");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_recv() - got a message");
 	link = list_first(&assoc->rcv_queue);
 	rqe = list_get_instance(link, udp_rcv_queue_entry_t, link);
@@ -297,9 +297,9 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "udp_assoc_received(%p, %p)", rsp, msg);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_received(%p, %p)", rsp, msg);
 
 	assoc = udp_assoc_find_ref(rsp);
 	if (assoc == NULL) {
-		log_msg(LVL_DEBUG, "No association found. Message dropped.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "No association found. Message dropped.");
 		/* XXX Generate ICMP error. */
 		/* XXX Might propagate error directly by error return. */
@@ -309,5 +309,5 @@
 	rc = udp_assoc_queue_msg(assoc, rsp, msg);
 	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "Out of memory. Message dropped.");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Out of memory. Message dropped.");
 		/* XXX Generate ICMP error? */
 	}
@@ -332,5 +332,5 @@
 	udp_rcv_queue_entry_t *rqe;
 
-	log_msg(LVL_DEBUG, "udp_assoc_queue_msg(%p, %p, %p)",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_queue_msg(%p, %p, %p)",
 	    assoc, sp, msg);
 
@@ -355,5 +355,5 @@
 static bool udp_socket_match(udp_sock_t *sock, udp_sock_t *patt)
 {
-	log_msg(LVL_DEBUG, "udp_socket_match(sock=(%x,%u), pat=(%x,%u))",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_socket_match(sock=(%x,%u), pat=(%x,%u))",
 	    sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
 
@@ -366,5 +366,5 @@
 		return false;
 
-	log_msg(LVL_DEBUG, " -> match");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " -> match");
 
 	return true;
@@ -374,5 +374,5 @@
 static bool udp_sockpair_match(udp_sockpair_t *sp, udp_sockpair_t *pattern)
 {
-	log_msg(LVL_DEBUG, "udp_sockpair_match(%p, %p)", sp, pattern);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sockpair_match(%p, %p)", sp, pattern);
 
 	if (!udp_socket_match(&sp->local, &pattern->local))
@@ -382,5 +382,5 @@
 		return false;
 
-	log_msg(LVL_DEBUG, "Socket pair matched.");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Socket pair matched.");
 	return true;
 }
@@ -398,5 +398,5 @@
 static udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *sp)
 {
-	log_msg(LVL_DEBUG, "udp_assoc_find_ref(%p)", sp);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_find_ref(%p)", sp);
 
 	fibril_mutex_lock(&assoc_list_lock);
@@ -405,5 +405,5 @@
 		udp_assoc_t *assoc = list_get_instance(link, udp_assoc_t, link);
 		udp_sockpair_t *asp = &assoc->ident;
-		log_msg(LVL_DEBUG, "compare with assoc (f:(%x,%u), l:(%x,%u))",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "compare with assoc (f:(%x,%u), l:(%x,%u))",
 		    asp->foreign.addr.ipv4, asp->foreign.port,
 		    asp->local.addr.ipv4, asp->local.port);
@@ -414,5 +414,5 @@
 
 		if (udp_sockpair_match(sp, asp)) {
-			log_msg(LVL_DEBUG, "Returning assoc %p", assoc);
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "Returning assoc %p", assoc);
 			udp_assoc_addref(assoc);
 			fibril_mutex_unlock(&assoc_list_lock);
Index: uspace/srv/net/udp/sock.c
===================================================================
--- uspace/srv/net/udp/sock.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/udp/sock.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -88,5 +88,5 @@
 static void udp_sock_notify_data(socket_core_t *sock_core)
 {
-	log_msg(LVL_DEBUG, "udp_sock_notify_data(%d)", sock_core->socket_id);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_notify_data(%d)", sock_core->socket_id);
 	async_exch_t *exch = async_exchange_begin(sock_core->sess);
 	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id,
@@ -103,6 +103,6 @@
 	ipc_call_t answer;
 
-	log_msg(LVL_DEBUG, "udp_sock_socket()");
-	sock = calloc(sizeof(udp_sockdata_t), 1);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_socket()");
+	sock = calloc(1, sizeof(udp_sockdata_t));
 	if (sock == NULL) {
 		async_answer_0(callid, ENOMEM);
@@ -167,6 +167,6 @@
 	udp_error_t urc;
 
-	log_msg(LVL_DEBUG, "udp_sock_bind()");
-	log_msg(LVL_DEBUG, " - async_data_write_accept");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_bind()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " - async_data_write_accept");
 
 	addr = NULL;
@@ -178,5 +178,5 @@
 	}
 
-	log_msg(LVL_DEBUG, " - call socket_bind");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_bind");
 	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
 	    addr, addr_size, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
@@ -192,5 +192,5 @@
 	}
 
-	log_msg(LVL_DEBUG, " - call socket_cores_find");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " - call socket_cores_find");
 	sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
 	if (sock_core == NULL) {
@@ -222,5 +222,5 @@
 	}
 
-	log_msg(LVL_DEBUG, " - success");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, " - success");
 	async_answer_0(callid, rc);
 out:
@@ -231,5 +231,5 @@
 static void udp_sock_listen(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
 {
-	log_msg(LVL_DEBUG, "udp_sock_listen()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_listen()");
 	async_answer_0(callid, ENOTSUP);
 }
@@ -237,5 +237,5 @@
 static void udp_sock_connect(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
 {
-	log_msg(LVL_DEBUG, "udp_sock_connect()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connect()");
 	async_answer_0(callid, ENOTSUP);
 }
@@ -243,5 +243,5 @@
 static void udp_sock_accept(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
 {
-	log_msg(LVL_DEBUG, "udp_sock_accept()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_accept()");
 	async_answer_0(callid, ENOTSUP);
 }
@@ -264,5 +264,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "udp_sock_send()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_send()");
 
 	addr = NULL;
@@ -323,5 +323,5 @@
 			fibril_mutex_unlock(&socket->lock);
 			async_answer_0(callid, rc);
-			log_msg(LVL_DEBUG, "udp_sock_sendto: Failed to "
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_sendto: Failed to "
 			    "determine local address.");
 			return;
@@ -329,5 +329,5 @@
 
 		socket->assoc->ident.local.addr.ipv4 = loc_addr.ipv4;
-		log_msg(LVL_DEBUG, "Local IP address is %x",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "Local IP address is %x",
 		    socket->assoc->ident.local.addr.ipv4);
 	}
@@ -405,5 +405,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "%p: udp_sock_recv[from]()", client);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%p: udp_sock_recv[from]()", client);
 
 	socket_id = SOCKET_GET_SOCKET_ID(call);
@@ -427,13 +427,13 @@
 	(void)flags;
 
-	log_msg(LVL_DEBUG, "udp_sock_recvfrom(): lock recv_buffer lock");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recvfrom(): lock recv_buffer lock");
 	fibril_mutex_lock(&socket->recv_buffer_lock);
 	while (socket->recv_buffer_used == 0 && socket->recv_error == UDP_EOK) {
-		log_msg(LVL_DEBUG, "udp_sock_recvfrom(): wait for cv");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recvfrom(): wait for cv");
 		fibril_condvar_wait(&socket->recv_buffer_cv,
 		    &socket->recv_buffer_lock);
 	}
 
-	log_msg(LVL_DEBUG, "Got data in sock recv_buffer");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "Got data in sock recv_buffer");
 
 	rsock = socket->recv_fsock;
@@ -441,5 +441,5 @@
 	urc = socket->recv_error;
 
-	log_msg(LVL_DEBUG, "**** recv data_len=%zu", data_len);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "**** recv data_len=%zu", data_len);
 
 	switch (urc) {
@@ -458,5 +458,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "**** udp_uc_receive -> %d", rc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "**** udp_uc_receive -> %d", rc);
 	if (rc != EOK) {
 		fibril_mutex_unlock(&socket->recv_buffer_lock);
@@ -472,5 +472,5 @@
 		addr.sin_port = host2uint16_t_be(rsock.port);
 
-		log_msg(LVL_DEBUG, "addr read receive");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "addr read receive");
 		if (!async_data_read_receive(&rcallid, &addr_length)) {
 			fibril_mutex_unlock(&socket->recv_buffer_lock);
@@ -483,5 +483,5 @@
 			addr_length = sizeof(addr);
 
-		log_msg(LVL_DEBUG, "addr read finalize");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "addr read finalize");
 		rc = async_data_read_finalize(rcallid, &addr, addr_length);
 		if (rc != EOK) {
@@ -493,5 +493,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "data read receive");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "data read receive");
 	if (!async_data_read_receive(&rcallid, &length)) {
 		fibril_mutex_unlock(&socket->recv_buffer_lock);
@@ -504,5 +504,5 @@
 		length = data_len;
 
-	log_msg(LVL_DEBUG, "data read finalize");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "data read finalize");
 	rc = async_data_read_finalize(rcallid, socket->recv_buffer, length);
 
@@ -510,5 +510,5 @@
 		rc = EOVERFLOW;
 
-	log_msg(LVL_DEBUG, "read_data_length <- %zu", length);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "read_data_length <- %zu", length);
 	IPC_SET_ARG2(answer, 0);
 	SOCKET_SET_READ_DATA_LENGTH(answer, length);
@@ -531,5 +531,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "udp_sock_close()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_sock_close()");
 	socket_id = SOCKET_GET_SOCKET_ID(call);
 
@@ -544,5 +544,5 @@
 
 	fibril_mutex_lock(&socket->recv_buffer_lock);
-	log_msg(LVL_DEBUG, "udp_sock_close - set socket->sock_core = NULL");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_close - set socket->sock_core = NULL");
 	socket->sock_core = NULL;
 	fibril_mutex_unlock(&socket->recv_buffer_lock);
@@ -553,5 +553,5 @@
 	    udp_free_sock_data);
 	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "udp_sock_close - socket_destroy failed");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_close - socket_destroy failed");
 		fibril_mutex_unlock(&socket->lock);
 		async_answer_0(callid, rc);
@@ -559,5 +559,5 @@
 	}
 
-	log_msg(LVL_DEBUG, "udp_sock_close - broadcast recv_buffer_cv");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_close - broadcast recv_buffer_cv");
 	fibril_condvar_broadcast(&socket->recv_buffer_cv);
 
@@ -568,5 +568,5 @@
 static void udp_sock_getsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
 {
-	log_msg(LVL_DEBUG, "udp_sock_getsockopt()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_getsockopt()");
 	async_answer_0(callid, ENOTSUP);
 }
@@ -574,5 +574,5 @@
 static void udp_sock_setsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
 {
-	log_msg(LVL_DEBUG, "udp_sock_setsockopt()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_setsockopt()");
 	async_answer_0(callid, ENOTSUP);
 }
@@ -585,10 +585,10 @@
 	size_t rcvd;
 
-	log_msg(LVL_DEBUG, "udp_sock_recv_fibril()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recv_fibril()");
 
 	fibril_mutex_lock(&sock->recv_buffer_lock);
 
 	while (true) {
-		log_msg(LVL_DEBUG, "[] wait for rcv buffer empty()");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "[] wait for rcv buffer empty()");
 		while (sock->recv_buffer_used != 0 && sock->sock_core != NULL) {
 			fibril_condvar_wait(&sock->recv_buffer_cv,
@@ -596,10 +596,10 @@
 		}
 
-		log_msg(LVL_DEBUG, "[] call udp_uc_receive()");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "[] call udp_uc_receive()");
 		urc = udp_uc_receive(sock->assoc, sock->recv_buffer,
 		    UDP_FRAGMENT_SIZE, &rcvd, &xflags, &sock->recv_fsock);
 		sock->recv_error = urc;
 
-		log_msg(LVL_DEBUG, "[] udp_uc_receive -> %d", urc);
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "[] udp_uc_receive -> %d", urc);
 
 		if (sock->sock_core != NULL)
@@ -607,10 +607,10 @@
 
 		if (urc != UDP_EOK) {
-			log_msg(LVL_DEBUG, "[] urc != UDP_EOK, break");
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "[] urc != UDP_EOK, break");
 			fibril_condvar_broadcast(&sock->recv_buffer_cv);
 			break;
 		}
 
-		log_msg(LVL_DEBUG, "[] got data - broadcast recv_buffer_cv");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "[] got data - broadcast recv_buffer_cv");
 
 		sock->recv_buffer_used = rcvd;
@@ -618,9 +618,9 @@
 	}
 
-	log_msg(LVL_DEBUG, "udp_sock_recv_fibril() exited loop");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recv_fibril() exited loop");
 	fibril_mutex_unlock(&sock->recv_buffer_lock);
 	udp_uc_destroy(sock->assoc);
 
-	log_msg(LVL_DEBUG, "udp_sock_recv_fibril() terminated");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_recv_fibril() terminated");
 
 	return 0;
@@ -640,10 +640,10 @@
 
 	while (true) {
-		log_msg(LVL_DEBUG, "udp_sock_connection: wait");
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: wait");
 		callid = async_get_call(&call);
 		if (!IPC_GET_IMETHOD(call))
 			break;
 
-		log_msg(LVL_DEBUG, "udp_sock_connection: METHOD=%d",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: METHOD=%d",
 		    (int)IPC_GET_IMETHOD(call));
 
@@ -688,5 +688,5 @@
 
 	/* Clean up */
-	log_msg(LVL_DEBUG, "udp_sock_connection: Clean up");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_sock_connection: Clean up");
 	async_hangup(client.sess);
 	socket_cores_release(NULL, &client.sockets, &gsock, udp_free_sock_data);
Index: uspace/srv/net/udp/ucall.c
===================================================================
--- uspace/srv/net/udp/ucall.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/udp/ucall.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -47,5 +47,5 @@
 	udp_assoc_t *nassoc;
 
-	log_msg(LVL_DEBUG, "udp_uc_create()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_create()");
 	nassoc = udp_assoc_new(NULL, NULL);
 	if (nassoc == NULL)
@@ -59,5 +59,5 @@
 udp_error_t udp_uc_set_foreign(udp_assoc_t *assoc, udp_sock_t *fsock)
 {
-	log_msg(LVL_DEBUG, "udp_uc_set_foreign(%p, %p)", assoc, fsock);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_set_foreign(%p, %p)", assoc, fsock);
 
 	udp_assoc_set_foreign(assoc, fsock);
@@ -67,5 +67,5 @@
 udp_error_t udp_uc_set_local(udp_assoc_t *assoc, udp_sock_t *lsock)
 {
-	log_msg(LVL_DEBUG, "udp_uc_set_local(%p, %p)", assoc, lsock);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_set_local(%p, %p)", assoc, lsock);
 
 	udp_assoc_set_local(assoc, lsock);
@@ -79,5 +79,5 @@
 	udp_msg_t msg;
 
-	log_msg(LVL_DEBUG, "%s: udp_uc_send()", assoc->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: udp_uc_send()", assoc->name);
 
 	msg.data = data;
@@ -103,7 +103,7 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "%s: udp_uc_receive()", assoc->name);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: udp_uc_receive()", assoc->name);
 	rc = udp_assoc_recv(assoc, &msg, fsock);
-	log_msg(LVL_DEBUG, "udp_assoc_recv -> %d", rc);
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_assoc_recv -> %d", rc);
 	switch (rc) {
 	case EOK:
@@ -125,5 +125,5 @@
 void udp_uc_status(udp_assoc_t *assoc, udp_assoc_status_t *astatus)
 {
-	log_msg(LVL_DEBUG, "udp_uc_status()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_status()");
 //	cstatus->cstate = conn->cstate;
 }
@@ -131,5 +131,5 @@
 void udp_uc_destroy(udp_assoc_t *assoc)
 {
-	log_msg(LVL_DEBUG, "udp_uc_destroy()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_uc_destroy()");
 	udp_assoc_reset(assoc);
 	udp_assoc_remove(assoc);
Index: uspace/srv/net/udp/udp.c
===================================================================
--- uspace/srv/net/udp/udp.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/udp/udp.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -50,9 +50,9 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "udp_init()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_init()");
 
 	rc = udp_inet_init();
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed connecting to internet service.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed connecting to internet service.");
 		return ENOENT;
 	}
@@ -60,5 +60,5 @@
 	rc = udp_sock_init();
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed initializing socket service.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing socket service.");
 		return ENOENT;
 	}
@@ -73,5 +73,5 @@
 	printf(NAME ": UDP (User Datagram Protocol) service\n");
 
-	rc = log_init(NAME, LVL_DEBUG);
+	rc = log_init(NAME);
 	if (rc != EOK) {
 		printf(NAME ": Failed to initialize log.\n");
Index: uspace/srv/net/udp/udp_inet.c
===================================================================
--- uspace/srv/net/udp/udp_inet.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/net/udp/udp_inet.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -61,5 +61,5 @@
 	udp_pdu_t *pdu;
 
-	log_msg(LVL_DEBUG, "udp_inet_ev_recv()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_inet_ev_recv()");
 
 	pdu = udp_pdu_new();
@@ -69,5 +69,5 @@
 	pdu->src.ipv4 = dgram->src.ipv4;
 	pdu->dest.ipv4 = dgram->dest.ipv4;
-	log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
 	    pdu->src.ipv4, pdu->dest.ipv4);
 
@@ -84,5 +84,5 @@
 	inet_dgram_t dgram;
 
-	log_msg(LVL_DEBUG, "udp_transmit_pdu()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_transmit_pdu()");
 
 	dgram.src.ipv4 = pdu->src.ipv4;
@@ -94,5 +94,5 @@
 	rc = inet_send(&dgram, INET_TTL_MAX, 0);
 	if (rc != EOK)
-		log_msg(LVL_ERROR, "Failed to transmit PDU.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to transmit PDU.");
 
 	return rc;
@@ -105,8 +105,8 @@
 	udp_sockpair_t rident;
 
-	log_msg(LVL_DEBUG, "udp_received_pdu()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_received_pdu()");
 
 	if (udp_pdu_decode(pdu, &rident, &dmsg) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
+		log_msg(LOG_DEFAULT, LVL_WARN, "Not enough memory. PDU dropped.");
 		return;
 	}
@@ -124,9 +124,9 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "udp_inet_init()");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "udp_inet_init()");
 
 	rc = inet_init(IP_PROTO_UDP, &udp_inet_ev_ops);
 	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed connecting to internet service.");
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed connecting to internet service.");
 		return ENOENT;
 	}
Index: uspace/srv/ns/service.c
===================================================================
--- uspace/srv/ns/service.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/ns/service.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -40,9 +40,8 @@
 #include "ns.h"
 
-#define SERVICE_HASH_TABLE_CHAINS  20
 
 /** Service hash table item. */
 typedef struct {
-	link_t link;
+	ht_link_t link;
 	sysarg_t service;        /**< Service ID. */
 	sysarg_t phone;          /**< Phone registered with the service. */
@@ -50,63 +49,29 @@
 } hashed_service_t;
 
-/** Compute hash index into service hash table.
- *
- * @param key Pointer keys. However, only the first key (i.e. service number)
- *            is used to compute the hash index.
- *
- * @return Hash index corresponding to key[0].
- *
- */
-static hash_index_t service_hash(unsigned long key[])
+
+static size_t service_key_hash(void *key)
 {
-	assert(key);
-	return (key[0] % SERVICE_HASH_TABLE_CHAINS);
+	return *(sysarg_t*)key;
 }
 
-/** Compare a key with hashed item.
- *
- * This compare function always ignores the third key.
- * It exists only to make it possible to remove records
- * originating from connection with key[1] in_phone_hash
- * value. Note that this is close to being classified
- * as a nasty hack.
- *
- * @param key  Array of keys.
- * @param keys Must be lesser or equal to 3.
- * @param item Pointer to a hash table item.
- *
- * @return Non-zero if the key matches the item, zero otherwise.
- *
- */
-static int service_compare(unsigned long key[], hash_count_t keys, link_t *item)
+static size_t service_hash(const ht_link_t *item)
 {
-	assert(key);
-	assert(keys <= 3);
-	assert(item);
-	
-	hashed_service_t *hs = hash_table_get_instance(item, hashed_service_t, link);
-	
-	if (keys == 2)
-		return ((key[0] == hs->service) && (key[1] == hs->in_phone_hash));
-	else
-		return (key[0] == hs->service);
+	hashed_service_t *hs = hash_table_get_inst(item, hashed_service_t, link);
+	return hs->service;
 }
 
-/** Perform actions after removal of item from the hash table.
- *
- * @param item Item that was removed from the hash table.
- *
- */
-static void service_remove(link_t *item)
+static bool service_key_equal(void *key, const ht_link_t *item)
 {
-	assert(item);
-	free(hash_table_get_instance(item, hashed_service_t, link));
+	hashed_service_t *hs = hash_table_get_inst(item, hashed_service_t, link);
+	return hs->service == *(sysarg_t*)key;
 }
 
 /** Operations for service hash table. */
-static hash_table_operations_t service_hash_table_ops = {
+static hash_table_ops_t service_hash_table_ops = {
 	.hash = service_hash,
-	.compare = service_compare,
-	.remove_callback = service_remove
+	.key_hash = service_key_hash,
+	.key_equal = service_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
 };
 
@@ -127,6 +92,5 @@
 int service_init(void)
 {
-	if (!hash_table_create(&service_hash_table, SERVICE_HASH_TABLE_CHAINS,
-	    3, &service_hash_table_ops)) {
+	if (!hash_table_create(&service_hash_table, 0, 0, &service_hash_table_ops)) {
 		printf(NAME ": No memory available for services\n");
 		return ENOMEM;
@@ -145,15 +109,9 @@
 		pending_conn_t *pr = list_get_instance(cur, pending_conn_t, link);
 		
-		unsigned long keys[3] = {
-			pr->service,
-			0,
-			0
-		};
-		
-		link_t *link = hash_table_find(&service_hash_table, keys);
+		ht_link_t *link = hash_table_find(&service_hash_table, &pr->service);
 		if (!link)
 			continue;
 		
-		hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
+		hashed_service_t *hs = hash_table_get_inst(link, hashed_service_t, link);
 		(void) ipc_forward_fast(pr->callid, hs->phone, pr->arg2,
 		    pr->arg3, 0, IPC_FF_NONE);
@@ -176,11 +134,5 @@
 int register_service(sysarg_t service, sysarg_t phone, ipc_call_t *call)
 {
-	unsigned long keys[3] = {
-		service,
-		call->in_phone_hash,
-		0
-	};
-	
-	if (hash_table_find(&service_hash_table, keys))
+	if (hash_table_find(&service_hash_table, &service))
 		return EEXISTS;
 	
@@ -189,9 +141,8 @@
 		return ENOMEM;
 	
-	link_initialize(&hs->link);
 	hs->service = service;
 	hs->phone = phone;
 	hs->in_phone_hash = call->in_phone_hash;
-	hash_table_insert(&service_hash_table, keys, &hs->link);
+	hash_table_insert(&service_hash_table, &hs->link);
 	
 	return EOK;
@@ -210,11 +161,6 @@
 {
 	sysarg_t retval;
-	unsigned long keys[3] = {
-		service,
-		0,
-		0
-	};
 	
-	link_t *link = hash_table_find(&service_hash_table, keys);
+	ht_link_t *link = hash_table_find(&service_hash_table, &service);
 	if (!link) {
 		if (IPC_GET_ARG4(*call) & IPC_FLAG_BLOCKING) {
@@ -239,5 +185,5 @@
 	}
 	
-	hashed_service_t *hs = hash_table_get_instance(link, hashed_service_t, link);
+	hashed_service_t *hs = hash_table_get_inst(link, hashed_service_t, link);
 	(void) ipc_forward_fast(callid, hs->phone, IPC_GET_ARG2(*call),
 	    IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
Index: uspace/srv/ns/task.c
===================================================================
--- uspace/srv/ns/task.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/ns/task.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -43,6 +43,4 @@
 #include "ns.h"
 
-#define TASK_HASH_TABLE_CHAINS  256
-#define P2I_HASH_TABLE_CHAINS   256
 
 /* TODO:
@@ -55,5 +53,5 @@
 /** Task hash table item. */
 typedef struct {
-	link_t link;
+	ht_link_t link;
 	
 	task_id_t id;    /**< Task ID. */
@@ -63,57 +61,34 @@
 } hashed_task_t;
 
-/** Compute hash index into task hash table.
- *
- * @param key Pointer keys. However, only the first key (i.e. truncated task
- *            number) is used to compute the hash index.
- *
- * @return Hash index corresponding to key[0].
- *
- */
-static hash_index_t task_hash(unsigned long key[])
-{
-	assert(key);
-	return (LOWER32(key[0]) % TASK_HASH_TABLE_CHAINS);
-}
-
-/** Compare a key with hashed item.
- *
- * @param key  Array of keys.
- * @param keys Must be less than or equal to 2.
- * @param item Pointer to a hash table item.
- *
- * @return Non-zero if the key matches the item, zero otherwise.
- *
- */
-static int task_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	assert(key);
-	assert(keys <= 2);
-	assert(item);
-	
-	hashed_task_t *ht = hash_table_get_instance(item, hashed_task_t, link);
-	
-	if (keys == 2)
-		return ((LOWER32(key[1]) == UPPER32(ht->id))
-		    && (LOWER32(key[0]) == LOWER32(ht->id)));
-	else
-		return (LOWER32(key[0]) == LOWER32(ht->id));
-}
-
-/** Perform actions after removal of item from the hash table.
- *
- * @param item Item that was removed from the hash table.
- *
- */
-static void task_remove(link_t *item)
-{
-	assert(item);
-	free(hash_table_get_instance(item, hashed_task_t, link));
+
+static size_t task_key_hash(void *key)
+{
+	return *(task_id_t*)key;
+}
+
+static size_t task_hash(const ht_link_t  *item)
+{
+	hashed_task_t *ht = hash_table_get_inst(item, hashed_task_t, link);
+	return ht->id;
+}
+
+static bool task_key_equal(void *key, const ht_link_t *item)
+{
+	hashed_task_t *ht = hash_table_get_inst(item, hashed_task_t, link);
+	return ht->id == *(task_id_t*)key;
+}
+
+/** Perform actions after removal of item from the hash table. */
+static void task_remove(ht_link_t *item)
+{
+	free(hash_table_get_inst(item, hashed_task_t, link));
 }
 
 /** Operations for task hash table. */
-static hash_table_operations_t task_hash_table_ops = {
+static hash_table_ops_t task_hash_table_ops = {
 	.hash = task_hash,
-	.compare = task_compare,
+	.key_hash = task_key_hash,
+	.key_equal = task_key_equal,
+	.equal = NULL,
 	.remove_callback = task_remove
 };
@@ -123,57 +98,48 @@
 
 typedef struct {
-	link_t link;
+	ht_link_t link;
 	sysarg_t in_phone_hash;  /**< Incoming phone hash. */
 	task_id_t id;            /**< Task ID. */
 } p2i_entry_t;
 
-/** Compute hash index into task hash table.
- *
- * @param key Array of keys.
- *
- * @return Hash index corresponding to key[0].
- *
- */
-static hash_index_t p2i_hash(unsigned long key[])
-{
-	assert(key);
-	return (key[0] % TASK_HASH_TABLE_CHAINS);
-}
-
-/** Compare a key with hashed item.
- *
- * @param key  Array of keys.
- * @param keys Must be less than or equal to 1.
- * @param item Pointer to a hash table item.
- *
- * @return Non-zero if the key matches the item, zero otherwise.
- *
- */
-static int p2i_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	assert(key);
-	assert(keys == 1);
+/* phone-to-id hash table operations */
+
+static size_t p2i_key_hash(void *key)
+{
+	sysarg_t in_phone_hash = *(sysarg_t*)key;
+	return in_phone_hash;
+}
+
+static size_t p2i_hash(const ht_link_t *item)
+{
+	p2i_entry_t *entry = hash_table_get_inst(item, p2i_entry_t, link);
+	return entry->in_phone_hash;
+}
+
+static bool p2i_key_equal(void *key, const ht_link_t *item)
+{
+	sysarg_t in_phone_hash = *(sysarg_t*)key;
+	p2i_entry_t *entry = hash_table_get_inst(item, p2i_entry_t, link);
+	
+	return (in_phone_hash == entry->in_phone_hash);
+}
+
+/** Perform actions after removal of item from the hash table.
+ *
+ * @param item Item that was removed from the hash table.
+ *
+ */
+static void p2i_remove(ht_link_t *item)
+{
 	assert(item);
-	
-	p2i_entry_t *entry = hash_table_get_instance(item, p2i_entry_t, link);
-	
-	return (key[0] == entry->in_phone_hash);
-}
-
-/** Perform actions after removal of item from the hash table.
- *
- * @param item Item that was removed from the hash table.
- *
- */
-static void p2i_remove(link_t *item)
-{
-	assert(item);
-	free(hash_table_get_instance(item, p2i_entry_t, link));
+	free(hash_table_get_inst(item, p2i_entry_t, link));
 }
 
 /** Operations for task hash table. */
-static hash_table_operations_t p2i_ops = {
+static hash_table_ops_t p2i_ops = {
 	.hash = p2i_hash,
-	.compare = p2i_compare,
+	.key_hash = p2i_key_hash,
+	.key_equal = p2i_key_equal,
+	.equal = NULL,
 	.remove_callback = p2i_remove
 };
@@ -193,12 +159,10 @@
 int task_init(void)
 {
-	if (!hash_table_create(&task_hash_table, TASK_HASH_TABLE_CHAINS,
-	    2, &task_hash_table_ops)) {
+	if (!hash_table_create(&task_hash_table, 0, 0, &task_hash_table_ops)) {
 		printf(NAME ": No memory available for tasks\n");
 		return ENOMEM;
 	}
 	
-	if (!hash_table_create(&phone_to_id, P2I_HASH_TABLE_CHAINS,
-	    1, &p2i_ops)) {
+	if (!hash_table_create(&phone_to_id, 0, 0, &p2i_ops)) {
 		printf(NAME ": No memory available for tasks\n");
 		return ENOMEM;
@@ -218,14 +182,9 @@
 		pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link);
 		
-		unsigned long keys[2] = {
-			LOWER32(pr->id),
-			UPPER32(pr->id)
-		};
-		
-		link_t *link = hash_table_find(&task_hash_table, keys);
+		ht_link_t *link = hash_table_find(&task_hash_table, &pr->id);
 		if (!link)
 			continue;
 		
-		hashed_task_t *ht = hash_table_get_instance(link, hashed_task_t, link);
+		hashed_task_t *ht = hash_table_get_inst(link, hashed_task_t, link);
 		if (!ht->finished)
 			continue;
@@ -238,5 +197,5 @@
 		}
 		
-		hash_table_remove(&task_hash_table, keys, 2);
+		hash_table_remove(&task_hash_table, &pr->id);
 		list_remove(cur);
 		free(pr);
@@ -250,12 +209,7 @@
 	task_exit_t texit;
 	
-	unsigned long keys[2] = {
-		LOWER32(id),
-		UPPER32(id)
-	};
-	
-	link_t *link = hash_table_find(&task_hash_table, keys);
+	ht_link_t *link = hash_table_find(&task_hash_table, &id);
 	hashed_task_t *ht = (link != NULL) ?
-	    hash_table_get_instance(link, hashed_task_t, link) : NULL;
+	    hash_table_get_inst(link, hashed_task_t, link) : NULL;
 	
 	if (ht == NULL) {
@@ -281,5 +235,5 @@
 	}
 	
-	hash_table_remove(&task_hash_table, keys, 2);
+	hash_table_remove_item(&task_hash_table, link);
 	retval = EOK;
 	
@@ -293,10 +247,8 @@
 int ns_task_id_intro(ipc_call_t *call)
 {
-	unsigned long keys[2];
 	
 	task_id_t id = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
-	keys[0] = call->in_phone_hash;
-	
-	link_t *link = hash_table_find(&phone_to_id, keys);
+
+	ht_link_t *link = hash_table_find(&phone_to_id, &call->in_phone_hash);
 	if (link != NULL)
 		return EEXISTS;
@@ -314,8 +266,7 @@
 	 */
 	
-	link_initialize(&entry->link);
 	entry->in_phone_hash = call->in_phone_hash;
 	entry->id = id;
-	hash_table_insert(&phone_to_id, keys, &entry->link);
+	hash_table_insert(&phone_to_id, &entry->link);
 	
 	/*
@@ -323,13 +274,9 @@
 	 */
 	
-	keys[0] = LOWER32(id);
-	keys[1] = UPPER32(id);
-	
-	link_initialize(&ht->link);
 	ht->id = id;
 	ht->finished = false;
 	ht->have_rval = false;
 	ht->retval = -1;
-	hash_table_insert(&task_hash_table, keys, &ht->link);
+	hash_table_insert(&task_hash_table, &ht->link);
 	
 	return EOK;
@@ -338,11 +285,9 @@
 static int get_id_by_phone(sysarg_t phone_hash, task_id_t *id)
 {
-	unsigned long keys[1] = {phone_hash};
-	
-	link_t *link = hash_table_find(&phone_to_id, keys);
+	ht_link_t *link = hash_table_find(&phone_to_id, &phone_hash);
 	if (link == NULL)
 		return ENOENT;
 	
-	p2i_entry_t *entry = hash_table_get_instance(link, p2i_entry_t, link);
+	p2i_entry_t *entry = hash_table_get_inst(link, p2i_entry_t, link);
 	*id = entry->id;
 	
@@ -357,12 +302,7 @@
 		return rc;
 	
-	unsigned long keys[2] = {
-		LOWER32(id),
-		UPPER32(id)
-	};
-	
-	link_t *link = hash_table_find(&task_hash_table, keys);
+	ht_link_t *link = hash_table_find(&task_hash_table, &id);
 	hashed_task_t *ht = (link != NULL) ?
-	    hash_table_get_instance(link, hashed_task_t, link) : NULL;
+	    hash_table_get_inst(link, hashed_task_t, link) : NULL;
 	
 	if ((ht == NULL) || (ht->finished))
@@ -378,6 +318,4 @@
 int ns_task_disconnect(ipc_call_t *call)
 {
-	unsigned long keys[2];
-	
 	task_id_t id;
 	int rc = get_id_by_phone(call->in_phone_hash, &id);
@@ -386,16 +324,12 @@
 	
 	/* Delete from phone-to-id map. */
-	keys[0] = call->in_phone_hash;
-	hash_table_remove(&phone_to_id, keys, 1);
+	hash_table_remove(&phone_to_id, &call->in_phone_hash);
 	
 	/* Mark task as finished. */
-	keys[0] = LOWER32(id);
-	keys[1] = UPPER32(id);
-	
-	link_t *link = hash_table_find(&task_hash_table, keys);
-	hashed_task_t *ht =
-	    hash_table_get_instance(link, hashed_task_t, link);
-	if (ht == NULL)
+	ht_link_t *link = hash_table_find(&task_hash_table, &id);
+	if (link == NULL)
 		return EOK;
+
+	hashed_task_t *ht = hash_table_get_inst(link, hashed_task_t, link);
 	
 	ht->finished = true;
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/vfs/vfs.h	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,4 +36,5 @@
 #include <async.h>
 #include <adt/list.h>
+#include <adt/hash_table.h>
 #include <fibril_synch.h>
 #include <sys/types.h>
@@ -112,5 +113,5 @@
 	unsigned lnkcnt;
 
-	link_t nh_link;		/**< Node hash-table link. */
+	ht_link_t nh_link;		/**< Node hash-table link. */
 
 	vfs_node_type_t type;	/**< Partial info about the node type. */
Index: uspace/srv/vfs/vfs_node.c
===================================================================
--- uspace/srv/vfs/vfs_node.c	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ uspace/srv/vfs/vfs_node.c	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -41,4 +41,5 @@
 #include <fibril_synch.h>
 #include <adt/hash_table.h>
+#include <adt/hash.h>
 #include <assert.h>
 #include <async.h>
@@ -58,13 +59,16 @@
 #define KEY_INDEX	2
 
-static hash_index_t nodes_hash(unsigned long []);
-static int nodes_compare(unsigned long [], hash_count_t, link_t *);
-static void nodes_remove_callback(link_t *);
+static size_t nodes_key_hash(void *);
+static size_t nodes_hash(const ht_link_t *);
+static bool nodes_key_equal(void *, const ht_link_t *);
+static vfs_triplet_t node_triplet(vfs_node_t *node);
 
 /** VFS node hash table operations. */
-hash_table_operations_t nodes_ops = {
+hash_table_ops_t nodes_ops = {
 	.hash = nodes_hash,
-	.compare = nodes_compare,
-	.remove_callback = nodes_remove_callback
+	.key_hash = nodes_key_hash,
+	.key_equal = nodes_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL,
 };
 
@@ -75,5 +79,5 @@
 bool vfs_nodes_init(void)
 {
-	return hash_table_create(&nodes, NODES_BUCKETS, 3, &nodes_ops);
+	return hash_table_create(&nodes, 0, 0, &nodes_ops);
 }
 
@@ -114,11 +118,5 @@
 		 */
 		
-		unsigned long key[] = {
-			[KEY_FS_HANDLE] = node->fs_handle,
-			[KEY_DEV_HANDLE] = node->service_id,
-			[KEY_INDEX] = node->index
-		};
-		
-		hash_table_remove(&nodes, key, 3);
+		hash_table_remove_item(&nodes, &node->nh_link);
 		free_vfs_node = true;
 		
@@ -158,10 +156,5 @@
 {
 	fibril_mutex_lock(&nodes_mutex);
-	unsigned long key[] = {
-		[KEY_FS_HANDLE] = node->fs_handle,
-		[KEY_DEV_HANDLE] = node->service_id,
-		[KEY_INDEX] = node->index
-	};
-	hash_table_remove(&nodes, key, 3);
+	hash_table_remove_item(&nodes, &node->nh_link);
 	fibril_mutex_unlock(&nodes_mutex);
 	free(node);
@@ -182,14 +175,8 @@
 vfs_node_t *vfs_node_get(vfs_lookup_res_t *result)
 {
-	unsigned long key[] = {
-		[KEY_FS_HANDLE] = result->triplet.fs_handle,
-		[KEY_DEV_HANDLE] = result->triplet.service_id,
-		[KEY_INDEX] = result->triplet.index
-	};
-	link_t *tmp;
 	vfs_node_t *node;
 
 	fibril_mutex_lock(&nodes_mutex);
-	tmp = hash_table_find(&nodes, key);
+	ht_link_t *tmp = hash_table_find(&nodes, &result->triplet);
 	if (!tmp) {
 		node = (vfs_node_t *) malloc(sizeof(vfs_node_t));
@@ -205,9 +192,8 @@
 		node->lnkcnt = result->lnkcnt;
 		node->type = result->type;
-		link_initialize(&node->nh_link);
 		fibril_rwlock_initialize(&node->contents_rwlock);
-		hash_table_insert(&nodes, key, &node->nh_link);
+		hash_table_insert(&nodes, &node->nh_link);
 	} else {
-		node = hash_table_get_instance(tmp, vfs_node_t, nh_link);
+		node = hash_table_get_inst(tmp, vfs_node_t, nh_link);
 		if (node->type == VFS_NODE_UNKNOWN &&
 		    result->type != VFS_NODE_UNKNOWN) {
@@ -240,24 +226,4 @@
 }
 
-hash_index_t nodes_hash(unsigned long key[])
-{
-	hash_index_t a = key[KEY_FS_HANDLE] << (NODES_BUCKETS_LOG / 4);
-	hash_index_t b = (a | key[KEY_DEV_HANDLE]) << (NODES_BUCKETS_LOG / 2);
-	
-	return (b | key[KEY_INDEX]) & (NODES_BUCKETS - 1);
-}
-
-int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	vfs_node_t *node = hash_table_get_instance(item, vfs_node_t, nh_link);
-	return (node->fs_handle == (fs_handle_t) key[KEY_FS_HANDLE]) &&
-	    (node->service_id == key[KEY_DEV_HANDLE]) &&
-	    (node->index == key[KEY_INDEX]);
-}
-
-void nodes_remove_callback(link_t *item)
-{
-}
-
 struct refcnt_data {
 	/** Sum of all reference counts for this file system instance. */
@@ -267,7 +233,7 @@
 };
 
-static void refcnt_visitor(link_t *item, void *arg)
-{
-	vfs_node_t *node = hash_table_get_instance(item, vfs_node_t, nh_link);
+static bool refcnt_visitor(ht_link_t *item, void *arg)
+{
+	vfs_node_t *node = hash_table_get_inst(item, vfs_node_t, nh_link);
 	struct refcnt_data *rd = (void *) arg;
 
@@ -275,4 +241,6 @@
 	    (node->service_id == rd->service_id))
 		rd->refcnt += node->refcnt;
+	
+	return true;
 }
 
@@ -315,4 +283,39 @@
 }
 
+
+static size_t nodes_key_hash(void *key)
+{
+	vfs_triplet_t *tri = key;
+	size_t hash = hash_combine(tri->fs_handle, tri->index);
+	return hash_combine(hash, tri->service_id);
+}
+
+static size_t nodes_hash(const ht_link_t *item)
+{
+	vfs_node_t *node = hash_table_get_inst(item, vfs_node_t, nh_link);
+	vfs_triplet_t tri = node_triplet(node);
+	return nodes_key_hash(&tri);
+}
+
+static bool nodes_key_equal(void *key, const ht_link_t *item)
+{
+	vfs_triplet_t *tri = key;
+	vfs_node_t *node = hash_table_get_inst(item, vfs_node_t, nh_link);
+	return node->fs_handle == tri->fs_handle 
+		&& node->service_id == tri->service_id
+		&& node->index == tri->index;
+}
+
+static inline vfs_triplet_t node_triplet(vfs_node_t *node)
+{
+	vfs_triplet_t tri = {
+		.fs_handle = node->fs_handle,
+		.service_id = node->service_id,
+		.index = node->index
+	};
+	
+	return tri;
+}
+
 /**
  * @}
Index: version
===================================================================
--- version	(revision 141a20dc6c36e09dab74a968f1a80bf74ddeacc6)
+++ version	(revision a1e2df13d3b8476ed4b89d3959aef8eeed6ac73f)
@@ -36,6 +36,6 @@
 
 VERSION = 0
-PATCHLEVEL = 4
-SUBLEVEL = 3
+PATCHLEVEL = 5
+SUBLEVEL = 0
 
 ifdef EXTRAVERSION
@@ -45,4 +45,4 @@
 endif
 
-NAME = Sashimi
+NAME = Fajtl
 COPYRIGHT = Copyright (c) 2001-2012 HelenOS project
