Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ HelenOS.config	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -73,4 +73,5 @@
 @ "athlon_xp" Athlon XP
 @ "athlon_mp" Athlon MP
+@ "i486" i486
 ! [PLATFORM=ia32] PROCESSOR (choice)
 
@@ -88,4 +89,5 @@
 @ "tmpfs" TMPFS image
 @ "fat" FAT16 image
+@ "ext2fs" EXT2 image
 ! RDFMT (choice)
 
@@ -573,5 +575,7 @@
 ! CONFIG_RUN_VIRTUAL_USB_HC (n/y)
 
-% Polling UHCI & OHCI (no interrupts)
-! [PLATFORM=ia32|PLATFORM=amd64] CONFIG_USBHC_NO_INTERRUPTS (n/y)
-
+% OHCI root hub port power switching
+@ "no" All root hub ports are always powered.
+@ "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)
Index: Makefile
===================================================================
--- Makefile	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -54,5 +54,5 @@
 
 cscope:
-	find kernel boot uspace -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE).out
+	find abi kernel boot uspace -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE).out
 
 # Pre-integration build check
Index: abi/include/ddi/arg.h
===================================================================
--- abi/include/ddi/arg.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/ddi/arg.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2006 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 genericddi
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_DDI_ARG_H_
+#define ABI_DDI_ARG_H_
+
+/** Structure encapsulating arguments for SYS_PHYSMEM_MAP syscall. */
+typedef struct {
+	/** ID of the destination task. */
+	uint64_t task_id;
+	/** Physical address of starting frame. */
+	void *phys_base;
+	/** Virtual address of starting page. */
+	void *virt_base;
+	/** Number of pages to map. */
+	size_t pages;
+	/** Address space area flags for the mapping. */
+	unsigned int flags;
+} ddi_memarg_t;
+
+/** Structure encapsulating arguments for SYS_ENABLE_IOSPACE syscall. */
+typedef struct {
+	uint64_t task_id;  /**< ID of the destination task. */
+	void *ioaddr;      /**< Starting I/O space address. */
+	size_t size;       /**< Number of bytes. */
+} ddi_ioarg_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/ddi/irq.h
===================================================================
--- abi/include/ddi/irq.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/ddi/irq.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2006 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 genericddi
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_DDI_IRQ_H_
+#define ABI_DDI_IRQ_H_
+
+typedef enum {
+	/** Read 1 byte from the I/O space. */
+	CMD_PIO_READ_8 = 1,
+	/** Read 2 bytes from the I/O space. */
+	CMD_PIO_READ_16,
+	/** Read 4 bytes from the I/O space. */
+	CMD_PIO_READ_32,
+	
+	/** Write 1 byte to the I/O space. */
+	CMD_PIO_WRITE_8,
+	/** Write 2 bytes to the I/O space. */
+	CMD_PIO_WRITE_16,
+	/** Write 4 bytes to the I/O space. */
+	CMD_PIO_WRITE_32,
+	
+	/**
+	 * Write 1 byte from the source argument
+	 * to the I/O space.
+	 */
+	CMD_PIO_WRITE_A_8,
+	/**
+	 * Write 2 bytes from the source argument
+	 * to the I/O space.
+	 */
+	CMD_PIO_WRITE_A_16,
+	/**
+	 * Write 4 bytes from the source argument
+	 * to the I/O space.
+	 */
+	CMD_PIO_WRITE_A_32,
+	
+	/** Read 1 byte from the memory space. */
+	CMD_MEM_READ_8,
+	/** Read 2 bytes from the memory space. */
+	CMD_MEM_READ_16,
+	/** Read 4 bytes from the memory space. */
+	CMD_MEM_READ_32,
+	
+	/** Write 1 byte to the memory space. */
+	CMD_MEM_WRITE_8,
+	/** Write 2 bytes to the memory space. */
+	CMD_MEM_WRITE_16,
+	/** Write 4 bytes to the memory space. */
+	CMD_MEM_WRITE_32,
+	
+	/** Write 1 byte from the source argument to the memory space. */
+	CMD_MEM_WRITE_A_8,
+	/** Write 2 bytes from the source argument to the memory space. */
+	CMD_MEM_WRITE_A_16,
+	/** Write 4 bytes from the source argument to the memory space. */
+	CMD_MEM_WRITE_A_32,
+	
+	/**
+	 * Perform a bit masking on the source argument
+	 * and store the result into the destination argument.
+	 */
+	CMD_BTEST,
+	
+	/**
+	 * Predicate the execution of the following
+	 * N commands by the boolean value of the source
+	 * argument.
+	 */
+	CMD_PREDICATE,
+	
+	/** Accept the interrupt. */
+	CMD_ACCEPT,
+	
+	/** Decline the interrupt. */
+	CMD_DECLINE,
+	CMD_LAST
+} irq_cmd_type;
+
+typedef struct {
+	irq_cmd_type cmd;
+	void *addr;
+	uint32_t value;
+	uintptr_t srcarg;
+	uintptr_t dstarg;
+} irq_cmd_t;
+
+typedef struct {
+	size_t cmdcount;
+	irq_cmd_t *cmds;
+} irq_code_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/elf.h
===================================================================
--- abi/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2006 Sergey Bondari
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_ELF_H_
+#define ABI_ELF_H_
+
+/**
+ * Current ELF version
+ */
+#define EV_CURRENT  1
+
+/**
+ * ELF types
+ */
+#define ET_NONE    0       /* No type */
+#define ET_REL     1       /* Relocatable file */
+#define ET_EXEC    2       /* Executable */
+#define ET_DYN     3       /* Shared object */
+#define ET_CORE    4       /* Core */
+#define ET_LOPROC  0xff00  /* Processor specific */
+#define ET_HIPROC  0xffff  /* Processor specific */
+
+/**
+ * ELF machine types
+ */
+#define EM_NO           0   /* No machine */
+#define EM_SPARC        2   /* SPARC */
+#define EM_386          3   /* i386 */
+#define EM_MIPS         8   /* MIPS RS3000 */
+#define EM_MIPS_RS3_LE  10  /* MIPS RS3000 LE */
+#define EM_PPC          20  /* PPC32 */
+#define EM_PPC64        21  /* PPC64 */
+#define EM_ARM          40  /* ARM */
+#define EM_SPARCV9      43  /* SPARC64 */
+#define EM_IA_64        50  /* IA-64 */
+#define EM_X86_64       62  /* AMD64/EMT64 */
+
+/**
+ * ELF identification indexes
+ */
+#define EI_MAG0        0
+#define EI_MAG1        1
+#define EI_MAG2        2
+#define EI_MAG3        3
+#define EI_CLASS       4   /* File class */
+#define EI_DATA        5   /* Data encoding */
+#define EI_VERSION     6   /* File version */
+#define EI_OSABI       7
+#define EI_ABIVERSION  8
+#define EI_PAD         9   /* Start of padding bytes */
+#define EI_NIDENT      16  /* ELF identification table size */
+
+/**
+ * ELF magic number
+ */
+#define ELFMAG0  0x7f
+#define ELFMAG1  'E'
+#define ELFMAG2  'L'
+#define ELFMAG3  'F'
+
+/**
+ * ELF file classes
+ */
+#define ELFCLASSNONE  0
+#define ELFCLASS32    1
+#define ELFCLASS64    2
+
+/**
+ * ELF data encoding types
+ */
+#define ELFDATANONE  0
+#define ELFDATA2LSB  1  /* Least significant byte first (little endian) */
+#define ELFDATA2MSB  2  /* Most signigicant byte first (big endian) */
+
+/**
+ * ELF section types
+ */
+#define SHT_NULL      0
+#define SHT_PROGBITS  1
+#define SHT_SYMTAB    2
+#define SHT_STRTAB    3
+#define SHT_RELA      4
+#define SHT_HASH      5
+#define SHT_DYNAMIC   6
+#define SHT_NOTE      7
+#define SHT_NOBITS    8
+#define SHT_REL       9
+#define SHT_SHLIB     10
+#define SHT_DYNSYM    11
+#define SHT_LOOS      0x60000000
+#define SHT_HIOS      0x6fffffff
+#define SHT_LOPROC    0x70000000
+#define SHT_HIPROC    0x7fffffff
+#define SHT_LOUSER    0x80000000
+#define SHT_HIUSER    0xffffffff
+
+/**
+ * ELF section flags
+ */
+#define SHF_WRITE      0x1
+#define SHF_ALLOC      0x2
+#define SHF_EXECINSTR  0x4
+#define SHF_TLS        0x400
+#define SHF_MASKPROC   0xf0000000
+
+/** Macros for decomposing elf_symbol.st_info into binging and type */
+#define ELF_ST_BIND(i)     ((i) >> 4)
+#define ELF_ST_TYPE(i)     ((i) & 0x0f)
+#define ELF_ST_INFO(b, t)  (((b) << 4) + ((t) & 0x0f))
+
+/**
+ * Symbol binding
+ */
+#define STB_LOCAL   0
+#define STB_GLOBAL  1
+#define STB_WEAK    2
+#define STB_LOPROC  13
+#define STB_HIPROC  15
+
+/**
+ * Symbol types
+ */
+#define STT_NOTYPE   0
+#define STT_OBJECT   1
+#define STT_FUNC     2
+#define STT_SECTION  3
+#define STT_FILE     4
+#define STT_LOPROC   13
+#define STT_HIPROC   15
+
+/**
+ * Program segment types
+ */
+#define PT_NULL     0
+#define PT_LOAD     1
+#define PT_DYNAMIC  2
+#define PT_INTERP   3
+#define PT_NOTE     4
+#define PT_SHLIB    5
+#define PT_PHDR     6
+#define PT_LOPROC   0x70000000
+#define PT_HIPROC   0x7fffffff
+
+/**
+ * Program segment attributes.
+ */
+#define PF_X  1
+#define PF_W  2
+#define PF_R  4
+
+/**
+ * ELF data types
+ *
+ * These types are found to be identical in both 32-bit and 64-bit
+ * ELF object file specifications. They are the only types used
+ * in ELF header.
+ */
+typedef uint64_t elf_xword;
+typedef int64_t elf_sxword;
+typedef uint32_t elf_word;
+typedef int32_t elf_sword;
+typedef uint16_t elf_half;
+
+/**
+ * 32-bit ELF data types.
+ *
+ * These types are specific for 32-bit format.
+ */
+typedef uint32_t elf32_addr;
+typedef uint32_t elf32_off;
+
+/**
+ * 64-bit ELF data types.
+ *
+ * These types are specific for 64-bit format.
+ */
+typedef uint64_t elf64_addr;
+typedef uint64_t elf64_off;
+
+/** ELF header */
+struct elf32_header {
+	uint8_t e_ident[EI_NIDENT];
+	elf_half e_type;
+	elf_half e_machine;
+	elf_word e_version;
+	elf32_addr e_entry;
+	elf32_off e_phoff;
+	elf32_off e_shoff;
+	elf_word e_flags;
+	elf_half e_ehsize;
+	elf_half e_phentsize;
+	elf_half e_phnum;
+	elf_half e_shentsize;
+	elf_half e_shnum;
+	elf_half e_shstrndx;
+};
+
+struct elf64_header {
+	uint8_t e_ident[EI_NIDENT];
+	elf_half e_type;
+	elf_half e_machine;
+	elf_word e_version;
+	elf64_addr e_entry;
+	elf64_off e_phoff;
+	elf64_off e_shoff;
+	elf_word e_flags;
+	elf_half e_ehsize;
+	elf_half e_phentsize;
+	elf_half e_phnum;
+	elf_half e_shentsize;
+	elf_half e_shnum;
+	elf_half e_shstrndx;
+};
+
+/**
+ * ELF segment header.
+ * Segments headers are also known as program headers.
+ */
+struct elf32_segment_header {
+	elf_word p_type;
+	elf32_off p_offset;
+	elf32_addr p_vaddr;
+	elf32_addr p_paddr;
+	elf_word p_filesz;
+	elf_word p_memsz;
+	elf_word p_flags;
+	elf_word p_align;
+};
+
+struct elf64_segment_header {
+	elf_word p_type;
+	elf_word p_flags;
+	elf64_off p_offset;
+	elf64_addr p_vaddr;
+	elf64_addr p_paddr;
+	elf_xword p_filesz;
+	elf_xword p_memsz;
+	elf_xword p_align;
+};
+
+/**
+ * ELF section header
+ */
+struct elf32_section_header {
+	elf_word sh_name;
+	elf_word sh_type;
+	elf_word sh_flags;
+	elf32_addr sh_addr;
+	elf32_off sh_offset;
+	elf_word sh_size;
+	elf_word sh_link;
+	elf_word sh_info;
+	elf_word sh_addralign;
+	elf_word sh_entsize;
+};
+
+struct elf64_section_header {
+	elf_word sh_name;
+	elf_word sh_type;
+	elf_xword sh_flags;
+	elf64_addr sh_addr;
+	elf64_off sh_offset;
+	elf_xword sh_size;
+	elf_word sh_link;
+	elf_word sh_info;
+	elf_xword sh_addralign;
+	elf_xword sh_entsize;
+};
+
+/**
+ * ELF symbol table entry
+ */
+struct elf32_symbol {
+	elf_word st_name;
+	elf32_addr st_value;
+	elf_word st_size;
+	uint8_t st_info;
+	uint8_t st_other;
+	elf_half st_shndx;
+};
+
+struct elf64_symbol {
+	elf_word st_name;
+	uint8_t st_info;
+	uint8_t st_other;
+	elf_half st_shndx;
+	elf64_addr st_value;
+	elf_xword st_size;
+};
+
+/*
+ * ELF note segment entry
+ */
+struct elf32_note {
+	elf_word namesz;
+	elf_word descsz;
+	elf_word type;
+};
+
+/*
+ * NOTE: namesz, descsz and type should be 64-bits wide (elf_xword)
+ * per the 64-bit ELF spec. The Linux kernel however screws up and
+ * defines them as Elf64_Word, which is 32-bits wide(!). We are trying
+ * to make our core files compatible with Linux GDB target so we copy
+ * the blunder here.
+ */
+struct elf64_note {
+	elf_word namesz;
+	elf_word descsz;
+	elf_word type;
+};
+
+#ifdef __32_BITS__
+typedef struct elf32_header elf_header_t;
+typedef struct elf32_segment_header elf_segment_header_t;
+typedef struct elf32_section_header elf_section_header_t;
+typedef struct elf32_symbol elf_symbol_t;
+typedef struct elf32_note elf_note_t;
+#endif
+
+#ifdef __64_BITS__
+typedef struct elf64_header elf_header_t;
+typedef struct elf64_segment_header elf_segment_header_t;
+typedef struct elf64_section_header elf_section_header_t;
+typedef struct elf64_symbol elf_symbol_t;
+typedef struct elf64_note elf_note_t;
+#endif
+
+#endif
+
+/** @}
+ */
Index: abi/include/errno.h
===================================================================
--- abi/include/errno.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/errno.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,77 @@
+/*
+ * 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 generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_ERRNO_H_
+#define ABI_ERRNO_H_
+
+/**
+ * Values in the range [-1, -255] are kernel error codes,
+ * values in the range [-256, -512] are user error codes.
+ */
+
+#define EOK             0   /* No error */
+#define ENOENT         -1   /* No such entry */
+#define ENOMEM         -2   /* Not enough memory */
+#define ELIMIT         -3   /* Limit exceeded */
+#define EREFUSED       -4   /* Connection refused */
+#define EFORWARD       -5   /* Forward error */
+#define EPERM          -6   /* Permission denied */
+
+/*
+ * Answerbox closed connection, call
+ * sys_ipc_hangup() to close the connection.
+ * Used by answerbox to close the connection.
+ */
+#define EHANGUP        -7
+
+/*
+ * The other party encountered an error when
+ * receiving the call.
+ */
+#define EPARTY         -8
+
+#define EEXISTS        -9   /* Entry already exists */
+#define EBADMEM        -10  /* Bad memory pointer */
+#define ENOTSUP        -11  /* Not supported */
+#define EADDRNOTAVAIL  -12  /* Address not available. */
+#define ETIMEOUT       -13  /* Timeout expired */
+#define EINVAL         -14  /* Invalid value */
+#define EBUSY          -15  /* Resource is busy */
+#define EOVERFLOW      -16  /* The result does not fit its size. */
+#define EINTR          -17  /* Operation was interrupted. */
+
+#endif
+
+/** @}
+ */
Index: abi/include/fb/visuals.h
===================================================================
--- abi/include/fb/visuals.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/fb/visuals.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2006 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 ABI_VISUALS_H_
+#define ABI_VISUALS_H_
+
+typedef enum {
+	VISUAL_UNKNOWN = 0,
+	VISUAL_INDIRECT_8,
+	VISUAL_RGB_5_5_5_LE,
+	VISUAL_RGB_5_5_5_BE,
+	VISUAL_RGB_5_6_5_LE,
+	VISUAL_RGB_5_6_5_BE,
+	VISUAL_BGR_8_8_8,
+	VISUAL_BGR_0_8_8_8,
+	VISUAL_BGR_8_8_8_0,
+	VISUAL_RGB_8_8_8,
+	VISUAL_RGB_0_8_8_8,
+	VISUAL_RGB_8_8_8_0
+} visual_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/ipc/event.h
===================================================================
--- abi/include/ipc/event.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/ipc/event.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2009 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_IPC_EVENT_H_
+#define ABI_IPC_EVENT_H_
+
+/** Global events */
+typedef enum event_type {
+	/** New data available in kernel log */
+	EVENT_KLOG = 0,
+	/** Returning from kernel console to uspace */
+	EVENT_KCONSOLE,
+	/** A task/thread has faulted and will be terminated */
+	EVENT_FAULT,
+	EVENT_END
+} event_type_t;
+
+/** Per-task events. */
+typedef enum event_task_type {
+	EVENT_TASK_STATE_CHANGE = EVENT_END,
+	EVENT_TASK_END
+} event_task_type_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/ipc/ipc.h
===================================================================
--- abi/include/ipc/ipc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/ipc/ipc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,126 @@
+/*
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_IPC_IPC_H_
+#define ABI_IPC_IPC_H_
+
+/** Length of data being transfered with IPC call
+ *
+ * The uspace may not be able to utilize full length
+ *
+ */
+#define IPC_CALL_LEN  6
+
+/** Maximum active async calls per phone */
+#define IPC_MAX_ASYNC_CALLS  4
+
+/* Flags for calls */
+
+/** This is answer to a call */
+#define IPC_CALL_ANSWERED  (1 << 0)
+
+/** Answer will not be passed to userspace, will be discarded */
+#define IPC_CALL_DISCARD_ANSWER  (1 << 1)
+
+/** Call was forwarded */
+#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)
+
+
+/** Bits used in call hashes.
+ *
+ * The addresses are aligned at least to 4 that is why we can use the 2 least
+ * significant bits of the call address.
+ *
+ */
+
+/** Type of this call is 'answer' */
+#define IPC_CALLID_ANSWERED  1
+
+/** Type of this call is 'notification' */
+#define IPC_CALLID_NOTIFICATION  2
+
+/* Return values from sys_ipc_call_async(). */
+#define IPC_CALLRET_FATAL      -1
+#define IPC_CALLRET_TEMPORARY  -2
+
+
+/* Macros for manipulating calling data */
+#define IPC_SET_RETVAL(data, retval)  ((data).args[0] = (retval))
+#define IPC_SET_IMETHOD(data, val)    ((data).args[0] = (val))
+#define IPC_SET_ARG1(data, val)       ((data).args[1] = (val))
+#define IPC_SET_ARG2(data, val)       ((data).args[2] = (val))
+#define IPC_SET_ARG3(data, val)       ((data).args[3] = (val))
+#define IPC_SET_ARG4(data, val)       ((data).args[4] = (val))
+#define IPC_SET_ARG5(data, val)       ((data).args[5] = (val))
+
+#define IPC_GET_IMETHOD(data)  ((data).args[0])
+#define IPC_GET_RETVAL(data)   ((data).args[0])
+
+#define IPC_GET_ARG1(data)  ((data).args[1])
+#define IPC_GET_ARG2(data)  ((data).args[2])
+#define IPC_GET_ARG3(data)  ((data).args[3])
+#define IPC_GET_ARG4(data)  ((data).args[4])
+#define IPC_GET_ARG5(data)  ((data).args[5])
+
+/* Forwarding flags. */
+#define IPC_FF_NONE  0
+
+/**
+ * The call will be routed as though it was initially sent via the phone used to
+ * forward it. This feature is intended to support the situation in which the
+ * forwarded call needs to be handled by the same connection fibril as any other
+ * calls that were initially sent by the forwarder to the same destination. This
+ * flag has no imapct on routing replies.
+ */
+#define IPC_FF_ROUTE_FROM_ME  (1 << 0)
+
+/* Data transfer flags. */
+#define IPC_XF_NONE  0
+
+/** Restrict the transfer size if necessary. */
+#define IPC_XF_RESTRICT  (1 << 0)
+
+/** User-defined IPC methods */
+#define IPC_FIRST_USER_METHOD  1024
+
+#endif
+
+/** @}
+ */
Index: abi/include/ipc/methods.h
===================================================================
--- abi/include/ipc/methods.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/ipc/methods.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,196 @@
+/*
+ * 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 genericipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_IPC_METHODS_H_
+#define ABI_IPC_METHODS_H_
+
+/* Well known phone descriptors */
+#define PHONE_NS  0
+
+/** Kernel IPC interfaces
+ *
+ */
+#define IPC_IF_KERNEL  0
+
+/** System-specific IPC methods
+ *
+ * These methods have special behaviour. These methods also
+ * have the implicit kernel interface zero (0).
+ *
+ */
+
+/** This message is sent to answerbox when the phone is hung up
+ *
+ * The numerical value zero (0) of this method is important,
+ * so as the value can be easily tested in conditions.
+ *
+ */
+#define IPC_M_PHONE_HUNGUP  0
+
+/** Clone connection.
+ *
+ * The calling task clones one of its phones for the callee.
+ *
+ * - ARG1 - The caller sets ARG1 to the phone of the cloned connection.
+ *        - The callee gets the new phone from ARG1.
+ *
+ * - on answer, the callee acknowledges the new connection by sending EOK back
+ *   or the kernel closes it
+ *
+ */
+#define IPC_M_CONNECTION_CLONE  1
+
+/** Protocol for CONNECT - ME
+ *
+ * Through this call, the recipient learns about the new cloned connection.
+ *
+ * - ARG5 - the kernel sets ARG5 to contain the hash of the used phone
+ * - on answer, the callee acknowledges the new connection by sending EOK back
+ *   or the kernel closes it
+ *
+ */
+#define IPC_M_CONNECT_ME  2
+
+/** Protocol for CONNECT - TO - ME
+ *
+ * Calling process asks the callee to create a callback connection,
+ * so that it can start initiating new messages.
+ *
+ * The protocol for negotiating is:
+ * - sys_connect_to_me - sends a message IPC_M_CONNECT_TO_ME
+ * - recipient         - upon receipt tries to allocate new phone
+ *                       - if it fails, responds with ELIMIT
+ *                     - passes call to userspace. If userspace
+ *                       responds with error, phone is deallocated and
+ *                       error is sent back to caller. Otherwise 
+ *                       the call is accepted and the response is sent back.
+ *                     - the hash of the allocated phone is passed to userspace
+ *                       (on the receiving side) as ARG5 of the call.
+ *
+ */
+#define IPC_M_CONNECT_TO_ME  3
+
+/** Protocol for CONNECT - ME - TO
+ *
+ * Calling process asks the callee to create for him a new connection.
+ * E.g. the caller wants a name server to connect him to print server.
+ *
+ * The protocol for negotiating is:
+ * - sys_connect_me_to - send a synchronous message to name server
+ *                       indicating that it wants to be connected to some
+ *                       service
+ *                     - arg1/2/3 are user specified, arg5 contains
+ *                       address of the phone that should be connected
+ *                       (TODO: it leaks to userspace)
+ *  - recipient        -  if ipc_answer == 0, then accept connection
+ *                     -  otherwise connection refused
+ *                     -  recepient may forward message.
+ *
+ */
+#define IPC_M_CONNECT_ME_TO  4
+
+/** Send as_area over IPC.
+ * - ARG1 - source as_area base address
+ * - ARG2 - size of source as_area (filled automatically by kernel)
+ * - ARG3 - flags of the as_area being sent
+ *
+ * on answer, the recipient must set:
+ * - ARG1 - dst as_area base adress
+ *
+ */
+#define IPC_M_SHARE_OUT  5
+
+/** Receive as_area over IPC.
+ * - ARG1 - destination as_area base address
+ * - ARG2 - destination as_area size
+ * - ARG3 - user defined argument
+ *
+ * on answer, the recipient must set:
+ *
+ * - ARG1 - source as_area base address
+ * - ARG2 - flags that will be used for sharing
+ *
+ */
+#define IPC_M_SHARE_IN  6
+
+/** Send data to another address space over IPC.
+ * - ARG1 - source address space virtual address
+ * - ARG2 - size of data to be copied, may be overriden by the recipient
+ *
+ * on answer, the recipient must set:
+ *
+ * - ARG1 - final destination address space virtual address
+ * - ARG2 - final size of data to be copied
+ *
+ */
+#define IPC_M_DATA_WRITE  7
+
+/** Receive data from another address space over IPC.
+ * - ARG1 - destination virtual address in the source address space
+ * - ARG2 - size of data to be received, may be cropped by the recipient 
+ *
+ * on answer, the recipient must set:
+ *
+ * - ARG1 - source virtual address in the destination address space
+ * - ARG2 - final size of data to be copied
+ *
+ */
+#define IPC_M_DATA_READ  8
+
+/** Authorize change of recipient's state in a third party task.
+ * - ARG1 - user protocol defined data
+ * - ARG2 - user protocol defined data
+ * - ARG3 - user protocol defined data
+ * - ARG5 - sender's phone to the third party task
+ *
+ * on EOK answer, the recipient must set:
+ *
+ * - ARG1 - recipient's phone to the third party task
+ */
+#define IPC_M_STATE_CHANGE_AUTHORIZE	9
+
+/** Debug the recipient.
+ * - ARG1 - specifies the debug method (from udebug_method_t)
+ * - other arguments are specific to the debug method
+ *
+ */
+#define IPC_M_DEBUG 10
+
+/** Last system IPC method */
+#define IPC_M_LAST_SYSTEM  511
+
+#endif
+
+/** @}
+ */
Index: abi/include/mm/as.h
===================================================================
--- abi/include/mm/as.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/mm/as.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010 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 genericmm
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_AS_H_
+#define ABI_AS_H_
+
+/** Address space area flags. */
+#define AS_AREA_READ       1
+#define AS_AREA_WRITE      2
+#define AS_AREA_EXEC       4
+#define AS_AREA_CACHEABLE  8
+
+/** Address space area info exported to uspace. */
+typedef struct {
+	/** Starting address */
+	uintptr_t start_addr;
+	
+	/** Area size */
+	size_t size;
+	
+	/** Area flags */
+	unsigned int flags;
+} as_area_info_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/proc/uarg.h
===================================================================
--- abi/include/proc/uarg.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/proc/uarg.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2006 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 genericproc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_PROC_UARG_H_
+#define ABI_PROC_UARG_H_
+
+/** Structure passed to uinit kernel thread as argument. */
+typedef struct uspace_arg {
+	void *uspace_entry;
+	void *uspace_stack;
+	
+	void (* uspace_thread_function)();
+	void *uspace_thread_arg;
+	
+	struct uspace_arg *uspace_uarg;
+} uspace_arg_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/synch.h
===================================================================
--- abi/include/synch.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/synch.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2001-2004 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 sync
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_SYNCH_H_
+#define ABI_SYNCH_H_
+
+/** Request with no timeout. */
+#define SYNCH_NO_TIMEOUT  0
+
+/** No flags specified. */
+#define SYNCH_FLAGS_NONE           0
+/** Non-blocking operation request. */
+#define SYNCH_FLAGS_NON_BLOCKING   (1 << 0)
+/** Interruptible operation. */
+#define SYNCH_FLAGS_INTERRUPTIBLE  (1 << 1)
+
+/** Could not satisfy the request without going to sleep. */
+#define ESYNCH_WOULD_BLOCK  1
+/** Timeout occurred. */
+#define ESYNCH_TIMEOUT      2
+/** Sleep was interrupted. */
+#define ESYNCH_INTERRUPTED  4
+/** Operation succeeded without sleeping. */
+#define ESYNCH_OK_ATOMIC    8
+/** Operation succeeded and did sleep. */
+#define ESYNCH_OK_BLOCKED   16
+
+#define SYNCH_FAILED(rc) \
+	((rc) & (ESYNCH_WOULD_BLOCK | ESYNCH_TIMEOUT | ESYNCH_INTERRUPTED))
+
+#define SYNCH_OK(rc) \
+	((rc) & (ESYNCH_OK_ATOMIC | ESYNCH_OK_BLOCKED))
+
+#endif
+
+/** @}
+ */
Index: abi/include/syscall.h
===================================================================
--- abi/include/syscall.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/syscall.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,104 @@
+/*
+ * 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 generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_SYSCALL_H_
+#define ABI_SYSCALL_H_
+
+typedef enum {
+	SYS_KLOG = 0,
+	SYS_TLS_SET = 1,  /* Hardcoded for AMD64, IA-32 (fibril.S in uspace) */
+	
+	SYS_THREAD_CREATE,
+	SYS_THREAD_EXIT,
+	SYS_THREAD_GET_ID,
+	SYS_THREAD_USLEEP,
+	SYS_THREAD_UDELAY,
+	
+	SYS_TASK_GET_ID,
+	SYS_TASK_SET_NAME,
+	SYS_TASK_KILL,
+	SYS_TASK_EXIT,
+	SYS_PROGRAM_SPAWN_LOADER,
+	
+	SYS_FUTEX_SLEEP,
+	SYS_FUTEX_WAKEUP,
+	SYS_SMC_COHERENCE,
+	
+	SYS_AS_AREA_CREATE,
+	SYS_AS_AREA_RESIZE,
+	SYS_AS_AREA_CHANGE_FLAGS,
+	SYS_AS_AREA_DESTROY,
+	SYS_AS_GET_UNMAPPED_AREA,
+	
+	SYS_PAGE_FIND_MAPPING,
+	
+	SYS_IPC_CALL_SYNC_FAST,
+	SYS_IPC_CALL_SYNC_SLOW,
+	SYS_IPC_CALL_ASYNC_FAST,
+	SYS_IPC_CALL_ASYNC_SLOW,
+	SYS_IPC_ANSWER_FAST,
+	SYS_IPC_ANSWER_SLOW,
+	SYS_IPC_FORWARD_FAST,
+	SYS_IPC_FORWARD_SLOW,
+	SYS_IPC_WAIT,
+	SYS_IPC_POKE,
+	SYS_IPC_HANGUP,
+	SYS_IPC_CONNECT_KBOX,
+	
+	SYS_EVENT_SUBSCRIBE,
+	SYS_EVENT_UNMASK,
+	
+	SYS_CAP_GRANT,
+	SYS_CAP_REVOKE,
+	
+	SYS_DEVICE_ASSIGN_DEVNO,
+	SYS_PHYSMEM_MAP,
+	SYS_IOSPACE_ENABLE,
+	SYS_REGISTER_IRQ,
+	SYS_UNREGISTER_IRQ,
+	
+	SYS_SYSINFO_GET_TAG,
+	SYS_SYSINFO_GET_VALUE,
+	SYS_SYSINFO_GET_DATA_SIZE,
+	SYS_SYSINFO_GET_DATA,
+	
+	SYS_DEBUG_ACTIVATE_CONSOLE,
+	
+	SYSCALL_END
+} syscall_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/sysinfo.h
===================================================================
--- abi/include/sysinfo.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/sysinfo.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2010 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
+ * Data structures passed between kernel sysinfo and user space.
+ */
+
+#ifndef ABI_SYSINFO_H_
+#define ABI_SYSINFO_H_
+
+/** Number of load components */
+#define LOAD_STEPS  3
+
+/** Maximum name sizes */
+#define TASK_NAME_BUFLEN  20
+#define EXC_NAME_BUFLEN   20
+
+/** Thread states */
+typedef enum {
+	/** It is an error, if thread is found in this state. */
+	Invalid,
+	/** State of a thread that is currently executing on some CPU. */
+	Running,
+	/** Thread in this state is waiting for an event. */
+	Sleeping,
+	/** State of threads in a run queue. */
+	Ready,
+	/** Threads are in this state before they are first readied. */
+	Entering,
+	/** After a thread calls thread_exit(), it is put into Exiting state. */
+	Exiting,
+	/** Threads that were not detached but exited are Lingering. */
+	Lingering
+} state_t;
+
+/** Statistics about a single CPU
+ *
+ */
+typedef struct {
+	unsigned int id;         /**< CPU ID as stored by kernel */
+	bool active;             /**< CPU is activate */
+	uint16_t frequency_mhz;  /**< Frequency in MHz */
+	uint64_t idle_cycles;    /**< Number of idle cycles */
+	uint64_t busy_cycles;    /**< Number of busy cycles */
+} stats_cpu_t;
+
+/** Physical memory statistics
+ *
+ */
+typedef struct {
+	uint64_t total;    /**< Total physical memory (bytes) */
+	uint64_t unavail;  /**< Unavailable (reserved, firmware) bytes */
+	uint64_t used;     /**< Allocated physical memory (bytes) */
+	uint64_t free;     /**< Free physical memory (bytes) */
+} stats_physmem_t;
+
+/** IPC statistics
+ *
+ * Associated with a task.
+ *
+ */
+typedef struct {
+	uint64_t call_sent;           /**< IPC calls sent */
+	uint64_t call_received;       /**< IPC calls received */
+	uint64_t answer_sent;         /**< IPC answers sent */
+	uint64_t answer_received;     /**< IPC answers received */
+	uint64_t irq_notif_received;  /**< IPC IRQ notifications */
+	uint64_t forwarded;           /**< IPC messages forwarded */
+} stats_ipc_t;
+
+/** Statistics about a single task
+ *
+ */
+typedef struct {
+	task_id_t task_id;            /**< Task ID */
+	char name[TASK_NAME_BUFLEN];  /**< Task name (in kernel) */
+	size_t virtmem;               /**< Size of VAS (bytes) */
+	size_t resmem;                /**< Size of resident (used) memory (bytes) */
+	size_t threads;               /**< Number of threads */
+	uint64_t ucycles;             /**< Number of CPU cycles in user space */
+	uint64_t kcycles;             /**< Number of CPU cycles in kernel */
+	stats_ipc_t ipc_info;         /**< IPC statistics */
+} stats_task_t;
+
+/** Statistics about a single thread
+ *
+ */
+typedef struct {
+	thread_id_t thread_id;  /**< Thread ID */
+	task_id_t task_id;      /**< Associated task ID */
+	state_t state;          /**< Thread state */
+	int priority;           /**< Thread priority */
+	uint64_t ucycles;       /**< Number of CPU cycles in user space */
+	uint64_t kcycles;       /**< Number of CPU cycles in kernel */
+	bool on_cpu;            /**< Associated with a CPU */
+	unsigned int cpu;       /**< Associated CPU ID (if on_cpu is true) */
+} stats_thread_t;
+
+/** Statistics about a single exception
+ *
+ */
+typedef struct {
+	unsigned int id;             /**< Exception ID */
+	char desc[EXC_NAME_BUFLEN];  /**< Description */
+	bool hot;                    /**< Active or inactive exception */
+	uint64_t cycles;             /**< Number of CPU cycles in the handler */
+	uint64_t count;              /**< Number of handled exceptions */
+} stats_exc_t;
+
+/** Load fixed-point value */
+typedef uint32_t load_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/udebug.h
===================================================================
--- abi/include/udebug.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ abi/include/udebug.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,184 @@
+/*
+ * 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 generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_UDEBUG_H_
+#define ABI_UDEBUG_H_
+
+#define UDEBUG_EVMASK(event)  (1 << ((event) - 1))
+
+typedef enum { /* udebug_method_t */
+	
+	/** Start debugging the recipient.
+	 *
+	 * Causes all threads in the receiving task to stop. When they
+	 * are all stoped, an answer with retval 0 is generated.
+	 *
+	 */
+	UDEBUG_M_BEGIN = 1,
+	
+	/** Finish debugging the recipient.
+	 *
+	 * Answers all pending GO and GUARD messages.
+	 *
+	 */
+	UDEBUG_M_END,
+	
+	/** Set which events should be captured. */
+	UDEBUG_M_SET_EVMASK,
+	
+	/** Make sure the debugged task is still there.
+	 *
+	 * This message is answered when the debugged task dies
+	 * or the debugging session ends.
+	 *
+	 */
+	UDEBUG_M_GUARD,
+	
+	/** Run a thread until a debugging event occurs.
+	 *
+	 * This message is answered when the thread stops
+	 * in a debugging event.
+	 *
+	 * - ARG2 - id of the thread to run
+	 *
+	 */
+	UDEBUG_M_GO,
+	
+	/** Stop a thread being debugged.
+	 *
+	 * Creates a special STOP event in the thread, causing
+	 * it to answer a pending GO message (if any).
+	 *
+	 */
+	UDEBUG_M_STOP,
+	
+	/** Read arguments of a syscall.
+	 *
+	 * - ARG2 - thread identification
+	 * - ARG3 - destination address in the caller's address space
+	 *
+	 */
+	UDEBUG_M_ARGS_READ,
+	
+	/** Read thread's userspace register state (istate_t).
+	 *
+	 * - ARG2 - thread identification
+	 * - ARG3 - destination address in the caller's address space
+	 *
+	 * or, on error, retval will be
+	 * - ENOENT - thread does not exist
+	 * - EBUSY - register state not available
+	 */
+	UDEBUG_M_REGS_READ,
+	
+	/** Read the list of the debugged tasks's threads.
+	 *
+	 * - ARG2 - destination address in the caller's address space
+	 * - ARG3 - size of receiving buffer in bytes
+	 *
+	 * The kernel fills the buffer with a series of sysarg_t values
+	 * (thread ids). On answer, the kernel will set:
+	 *
+	 * - ARG2 - number of bytes that were actually copied
+	 * - ARG3 - number of bytes of the complete data
+	 *
+	 */
+	UDEBUG_M_THREAD_READ,
+	
+	/** Read the name of the debugged task.
+	 *
+	 * - ARG2 - destination address in the caller's address space
+	 * - ARG3 - size of receiving buffer in bytes
+	 *
+	 * The kernel fills the buffer with a non-terminated string.
+	 *
+	 * - ARG2 - number of bytes that were actually copied
+	 * - ARG3 - number of bytes of the complete data
+	 *
+	 */
+	UDEBUG_M_NAME_READ,
+	
+	/** Read the list of the debugged task's address space areas.
+	 *
+	 * - ARG2 - destination address in the caller's address space
+	 * - ARG3 - size of receiving buffer in bytes
+	 *
+	 * The kernel fills the buffer with a series of as_area_info_t structures.
+	 * Upon answer, the kernel will set:
+	 *
+	 * - ARG2 - number of bytes that were actually copied
+	 * - ARG3 - number of bytes of the complete data
+	 *
+	 */
+	UDEBUG_M_AREAS_READ,
+	
+	/** Read the debugged tasks's memory.
+	 *
+	 * - ARG2 - destination address in the caller's address space
+	 * - ARG3 - source address in the recipient's address space
+	 * - ARG4 - size of receiving buffer in bytes
+	 *
+	 */
+	UDEBUG_M_MEM_READ
+} udebug_method_t;
+
+typedef enum {
+	UDEBUG_EVENT_FINISHED = 1,  /**< Debuging session has finished */
+	UDEBUG_EVENT_STOP,          /**< Stopped on DEBUG_STOP request */
+	UDEBUG_EVENT_SYSCALL_B,     /**< Before beginning syscall execution */
+	UDEBUG_EVENT_SYSCALL_E,     /**< After finishing syscall execution */
+	UDEBUG_EVENT_THREAD_B,      /**< The task created a new thread */
+	UDEBUG_EVENT_THREAD_E       /**< A thread exited */
+} udebug_event_t;
+
+typedef enum {
+	UDEBUG_EM_FINISHED = UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED),
+	UDEBUG_EM_STOP = UDEBUG_EVMASK(UDEBUG_EVENT_STOP),
+	UDEBUG_EM_SYSCALL_B = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B),
+	UDEBUG_EM_SYSCALL_E = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E),
+	UDEBUG_EM_THREAD_B = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B),
+	UDEBUG_EM_THREAD_E = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E),
+	UDEBUG_EM_ALL =
+	    (UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_STOP) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E))
+} udebug_evmask_t;
+
+#endif
+
+/** @}
+ */
Index: boot/Makefile
===================================================================
--- boot/Makefile	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ boot/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -50,4 +50,7 @@
 	$(MKFAT) 1048576 $(DIST_PATH) $@
 endif
+ifeq ($(RDFMT),ext2fs)
+	$(MKEXT2) 1048576 $(DIST_PATH) $@
+endif
 
 build_dist: clean_dist
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ boot/Makefile.common	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -56,4 +56,5 @@
 MKTMPFS = $(TOOLS_PATH)/mktmpfs.py
 MKFAT = $(TOOLS_PATH)/mkfat.py
+MKEXT2 = $(TOOLS_PATH)/mkext2.py
 MKUIMAGE = $(TOOLS_PATH)/mkuimage.py
 
@@ -72,5 +73,5 @@
 	$(USPACE_PATH)/srv/loader/loader \
 	$(USPACE_PATH)/app/init/init \
-	$(USPACE_PATH)/srv/devmap/devmap \
+	$(USPACE_PATH)/srv/loc/loc \
 	$(USPACE_PATH)/srv/bd/rd/rd \
 	$(USPACE_PATH)/srv/vfs/vfs
@@ -82,4 +83,8 @@
 ifeq ($(RDFMT),fat)
 	INIT_TASKS += $(USPACE_PATH)/srv/fs/fat/fat
+endif
+
+ifeq ($(RDFMT),ext2fs)
+	INIT_TASKS += $(USPACE_PATH)/srv/fs/ext2fs/ext2fs
 endif
 
@@ -88,5 +93,5 @@
 	$(USPACE_PATH)/srv/hid/input/input \
 	$(USPACE_PATH)/srv/hid/console/console \
-	$(USPACE_PATH)/srv/fs/devfs/devfs
+	$(USPACE_PATH)/srv/fs/locfs/locfs
 
 RD_SRVS_NON_ESSENTIAL = \
@@ -138,4 +143,5 @@
 	$(USPACE_PATH)/app/blkdump/blkdump \
 	$(USPACE_PATH)/app/bnchmark/bnchmark \
+	$(USPACE_PATH)/app/devctl/devctl \
 	$(USPACE_PATH)/app/dltest/dltest \
 	$(USPACE_PATH)/app/dltest2/dltest2 \
@@ -145,4 +151,5 @@
 	$(USPACE_PATH)/app/kill/kill \
 	$(USPACE_PATH)/app/killall/killall \
+	$(USPACE_PATH)/app/locinfo/locinfo \
 	$(USPACE_PATH)/app/mkfat/mkfat \
 	$(USPACE_PATH)/app/lsusb/lsusb \
Index: boot/arch/mips32/src/asm.S
===================================================================
--- boot/arch/mips32/src/asm.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ boot/arch/mips32/src/asm.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -44,5 +44,5 @@
 	 * Setup the CP0 configuration
 	 *  - Disable 64-bit kernel addressing mode
-	 *  - DIsable 64-bit supervisor adressing mode
+	 *  - Disable 64-bit supervisor adressing mode
 	 *  - Disable 64-bit user addressing mode
 	 */
Index: boot/arch/mips64/src/asm.S
===================================================================
--- boot/arch/mips64/src/asm.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ boot/arch/mips64/src/asm.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -47,7 +47,7 @@
 	 *  - Enable 64-bit user addressing mode
 	 */
-	dmfc0 $a0, $status
+	mfc0 $a0, $status
 	ori $a0, 0x00e0
-	dmtc0 $a0, $status
+	mtc0 $a0, $status
 	
 	/*
Index: contrib/bazaar/bzreml/__init__.py
===================================================================
--- contrib/bazaar/bzreml/__init__.py	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ contrib/bazaar/bzreml/__init__.py	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -134,42 +134,10 @@
 				body.write("New Revision: %s%s\n" % (revision_ac_no, merge_marker(revision_ac)))
 				body.write("New Id: %s\n" % revision_ac_id)
-				
-				body.write("\n")
-				
 				for parent_id in revision_ac.parent_ids:
 					body.write("Parent: %s\n" % parent_id)
-					
-					tree_old = branch.repository.revision_tree(parent_id)
-					tree_ac = branch.repository.revision_tree(revision_ac_id)
-					
-					delta = tree_ac.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")
-				
+				
+				body.write("\n")
+				
+				commit_message = ""
 				body.write("Log:\n")
 				if (not revision_ac.message):
@@ -179,4 +147,9 @@
 					for line in log.split("\n"):
 						body.write("%s\n" % line)
+						if (commit_message == ""):
+							commit_message = line
+				
+				if (commit_message == ""):
+					commit_message = "(empty)"
 				
 				body.write("\n")
@@ -184,4 +157,34 @@
 			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()
@@ -196,25 +199,5 @@
 				tree_old.unlock()
 			
-			revision_new_no = branch.revision_id_to_revno(revision_new_id)
-			
-			delta = tree_new.changes_from(tree_old)
-			files = []
-			
-			for item in delta.added:
-				files.append(item[0])
-			
-			for item in delta.removed:
-				files.append(item[0])
-			
-			for item in delta.renamed:
-				files.append(item[0])
-			
-			for item in delta.kind_changed:
-				files.append(item[0])
-			
-			for item in delta.modified:
-				files.append(item[0])
-			
-			subject = "r%d - %s" % (revision_new_no, " ".join(files))
+			subject = "r%d - %s" % (revision_new_no, commit_message)
 			
 			send_smtp("localhost", config_sender(config), config_to(config), subject, body.getvalue())
Index: contrib/bazaar/bzreml/setup.py
===================================================================
--- contrib/bazaar/bzreml/setup.py	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ contrib/bazaar/bzreml/setup.py	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -7,5 +7,5 @@
 	description = 'Commit email plugin for Bazaar',
 	keywords = 'plugin bzr email',
-	version = '1.0',
+	version = '1.2',
 	url = 'http://www.decky.cz/',
 	license = 'BSD',
Index: contrib/conf/ppc32-qe.sh
===================================================================
--- contrib/conf/ppc32-qe.sh	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ contrib/conf/ppc32-qe.sh	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,3 +1,3 @@
 #!/bin/sh
 
-qemu-system-ppc $@ -M mac99 -boot d -cdrom image.iso
+qemu-system-ppc $@ -M g3beige -boot d -cdrom image.iso
Index: contrib/tools/gen_vga323.c
===================================================================
--- contrib/tools/gen_vga323.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ contrib/tools/gen_vga323.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -33,5 +33,6 @@
 #define BLUE(i)   ((i) & ((1 << 3) - 1))
 
-int main(int argc, char *argv[]) {
+int main(int argc, char *argv[])
+{
 	unsigned int i;
 	
Index: defaults/amd64/Makefile.config
===================================================================
--- defaults/amd64/Makefile.config	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ defaults/amd64/Makefile.config	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -65,2 +65,4 @@
 CONFIG_MOUNT_DATA = n
 
+# OHCI root hub power switch, ganged is enough
+OHCI_POWER_SWITCH = ganged
Index: defaults/ia32/Makefile.config
===================================================================
--- defaults/ia32/Makefile.config	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ defaults/ia32/Makefile.config	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -71,2 +71,4 @@
 CONFIG_MOUNT_DATA = n
 
+# OHCI root hub power switch, ganged is enough
+OHCI_POWER_SWITCH = ganged
Index: kernel/Makefile
===================================================================
--- kernel/Makefile	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -59,4 +59,5 @@
 REAL_MAP = generic/src/debug/real_map
 
+ABI_INCLUDE = generic/include/abi
 ARCH_INCLUDE = generic/include/arch
 GENARCH_INCLUDE = generic/include/genarch
@@ -75,5 +76,5 @@
 
 clean:
-	rm -f $(DEPEND) $(DEPEND_PREV) $(RAW) $(BIN) $(MAP) $(JOB) $(MAP_PREV) $(DISASM) $(DUMP) $(REAL_MAP).* $(ARCH_INCLUDE) $(GENARCH_INCLUDE) arch/*/_link.ld arch/*/include/common.h
+	rm -f $(DEPEND) $(DEPEND_PREV) $(RAW) $(BIN) $(MAP) $(JOB) $(MAP_PREV) $(DISASM) $(DUMP) $(REAL_MAP).* $(ABI_INCLUDE) $(ARCH_INCLUDE) $(GENARCH_INCLUDE) arch/*/_link.ld arch/*/include/common.h
 	find generic/src/ arch/*/src/ genarch/src/ test/ -name '*.o' -follow -exec rm \{\} \;
 
@@ -432,8 +433,11 @@
 	$(GENMAP) $(MAP_PREV) $(DUMP) $@
 
-$(DEPEND): $(ARCH_INCLUDE) $(GENARCH_INCLUDE) $(COMMON_HEADER_ARCH)
+$(DEPEND): $(ABI_INCLUDE) $(ARCH_INCLUDE) $(GENARCH_INCLUDE) $(COMMON_HEADER_ARCH)
 	makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENARCH_SOURCES) $(GENERIC_SOURCES) > $@ 2> /dev/null
 	-[ -f $(DEPEND_PREV) ] && diff -q $(DEPEND_PREV) $@ && mv -f $(DEPEND_PREV) $@
 
+$(ABI_INCLUDE): ../abi/include/
+	ln -sfn ../../$< $@
+
 $(ARCH_INCLUDE): arch/$(KARCH)/include/
 	ln -sfn ../../$< $@
Index: kernel/arch/abs32le/include/istate.h
===================================================================
--- kernel/arch/abs32le/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/abs32le/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,15 +36,12 @@
 #define KERN_abs32le_ISTATE_H_
 
+#include <trace.h>
+
 #ifdef KERNEL
 
-#include <typedefs.h>
 #include <verify.h>
-#include <trace.h>
 
 #else /* KERNEL */
 
-#include <sys/types.h>
-
-#define NO_TRACE
 #define REQUIRES_EXTENT_MUTABLE(arg)
 #define WRITES(arg)
Index: kernel/arch/abs32le/include/mm/frame.h
===================================================================
--- kernel/arch/abs32le/include/mm/frame.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/abs32le/include/mm/frame.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,6 +39,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
-
 #include <typedefs.h>
 
@@ -46,6 +44,4 @@
 extern void physmem_print(void);
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/abs32le/include/mm/page.h
===================================================================
--- kernel/arch/abs32le/include/mm/page.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/abs32le/include/mm/page.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,6 +41,4 @@
 #define PAGE_WIDTH  FRAME_WIDTH
 #define PAGE_SIZE   FRAME_SIZE
-
-#ifdef KERNEL
 
 #define KA2PA(x)  (((uintptr_t) (x)) - UINT32_C(0x80000000))
@@ -178,6 +176,4 @@
 extern void page_fault(unsigned int, istate_t *);
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/abs32le/src/userspace.c
===================================================================
--- kernel/arch/abs32le/src/userspace.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/abs32le/src/userspace.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,7 +36,6 @@
 #include <typedefs.h>
 #include <arch.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <mm/as.h>
-
 
 void userspace(uspace_arg_t *kernel_uarg)
Index: kernel/arch/amd64/include/asm.h
===================================================================
--- kernel/arch/amd64/include/asm.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/amd64/include/asm.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,4 +41,6 @@
 #include <trace.h>
 
+#define IO_SPACE_BOUNDARY	((void *) (64 * 1024))
+
 /** Return base address of current stack.
  *
@@ -87,13 +89,16 @@
 NO_TRACE static inline uint8_t pio_read_8(ioport8_t *port)
 {
-	uint8_t val;
-	
-	asm volatile (
-		"inb %w[port], %b[val]\n"
-		: [val] "=a" (val)
-		: [port] "d" (port)
-	);
-	
-	return val;
+	if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
+		uint8_t val;
+		
+		asm volatile (
+			"inb %w[port], %b[val]\n"
+			: [val] "=a" (val)
+			: [port] "d" (port)
+		);
+		
+		return val;
+	} else
+		return (uint8_t) *port;
 }
 
@@ -108,13 +113,16 @@
 NO_TRACE static inline uint16_t pio_read_16(ioport16_t *port)
 {
-	uint16_t val;
-	
-	asm volatile (
-		"inw %w[port], %w[val]\n"
-		: [val] "=a" (val)
-		: [port] "d" (port)
-	);
-	
-	return val;
+	if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
+		uint16_t val;
+		
+		asm volatile (
+			"inw %w[port], %w[val]\n"
+			: [val] "=a" (val)
+			: [port] "d" (port)
+		);
+		
+		return val;
+	} else
+		return (uint16_t) *port;
 }
 
@@ -129,13 +137,16 @@
 NO_TRACE static inline uint32_t pio_read_32(ioport32_t *port)
 {
-	uint32_t val;
-	
-	asm volatile (
-		"inl %w[port], %[val]\n"
-		: [val] "=a" (val)
-		: [port] "d" (port)
-	);
-	
-	return val;
+	if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
+		uint32_t val;
+		
+		asm volatile (
+			"inl %w[port], %[val]\n"
+			: [val] "=a" (val)
+			: [port] "d" (port)
+		);
+		
+		return val;
+	} else
+		return (uint32_t) *port;
 }
 
@@ -150,9 +161,11 @@
 NO_TRACE static inline void pio_write_8(ioport8_t *port, uint8_t val)
 {
-	asm volatile (
-		"outb %b[val], %w[port]\n"
-		:: [val] "a" (val),
-		   [port] "d" (port)
-	);
+	if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
+		asm volatile (
+			"outb %b[val], %w[port]\n"
+			:: [val] "a" (val), [port] "d" (port)
+		);	
+	} else
+		*port = val;
 }
 
@@ -167,9 +180,11 @@
 NO_TRACE static inline void pio_write_16(ioport16_t *port, uint16_t val)
 {
-	asm volatile (
-		"outw %w[val], %w[port]\n"
-		:: [val] "a" (val),
-		   [port] "d" (port)
-	);
+	if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
+		asm volatile (
+			"outw %w[val], %w[port]\n"
+			:: [val] "a" (val), [port] "d" (port)
+		);
+	} else
+		*port = val;
 }
 
@@ -184,9 +199,11 @@
 NO_TRACE static inline void pio_write_32(ioport32_t *port, uint32_t val)
 {
-	asm volatile (
-		"outl %[val], %w[port]\n"
-		:: [val] "a" (val),
-		   [port] "d" (port)
-	);
+	if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
+		asm volatile (
+			"outl %[val], %w[port]\n"
+			:: [val] "a" (val), [port] "d" (port)
+		);
+	} else
+		*port = val;
 }
 
Index: kernel/arch/amd64/include/context.h
===================================================================
--- kernel/arch/amd64/include/context.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/amd64/include/context.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,6 +36,4 @@
 #define KERN_amd64_CONTEXT_H_
 
-#ifdef KERNEL
-
 #include <typedefs.h>
 
@@ -52,6 +50,4 @@
 		(c)->rbp = 0; \
 	} while (0)
-
-#endif /* KERNEL */
 
 /* We include only registers that must be preserved
Index: kernel/arch/amd64/include/istate.h
===================================================================
--- kernel/arch/amd64/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/amd64/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,16 +36,5 @@
 #define KERN_amd64_ISTATE_H_
 
-#ifdef KERNEL
-
-#include <typedefs.h>
 #include <trace.h>
-
-#else /* KERNEL */
-
-#include <sys/types.h>
-
-#define NO_TRACE
-
-#endif /* KERNEL */
 
 /** This is passed to interrupt handlers */
Index: kernel/arch/amd64/include/mm/frame.h
===================================================================
--- kernel/arch/amd64/include/mm/frame.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/amd64/include/mm/frame.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -49,5 +48,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/amd64/include/mm/page.h
===================================================================
--- kernel/arch/amd64/include/mm/page.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/amd64/include/mm/page.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -50,6 +50,4 @@
 #define PAGE_WIDTH  FRAME_WIDTH
 #define PAGE_SIZE   FRAME_SIZE
-
-#ifdef KERNEL
 
 #ifndef __ASM__
@@ -231,6 +229,4 @@
 #endif /* __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/amd64/src/userspace.c
===================================================================
--- kernel/arch/amd64/src/userspace.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/amd64/src/userspace.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,7 +38,6 @@
 #include <typedefs.h>
 #include <arch.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <mm/as.h>
-
 
 /** Enter userspace
Index: kernel/arch/arm32/include/istate.h
===================================================================
--- kernel/arch/arm32/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/arm32/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -35,13 +35,15 @@
 #define KERN_arm32_ISTATE_H_
 
+#include <trace.h>
+
+#ifdef KERNEL
+
 #include <arch/regutils.h>
 
-#ifdef KERNEL
-#include <typedefs.h>
-#include <trace.h>
-#else
-#include <sys/types.h>
-#define NO_TRACE
-#endif
+#else /* KERNEL */
+
+#include <libarch/regutils.h>
+
+#endif /* KERNEL */
 
 /** Struct representing CPU state saved when an exception occurs. */
Index: kernel/arch/arm32/include/mm/frame.h
===================================================================
--- kernel/arch/arm32/include/mm/frame.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/arm32/include/mm/frame.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -40,5 +40,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -69,5 +68,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/arm32/include/mm/page.h
===================================================================
--- kernel/arch/arm32/include/mm/page.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/arm32/include/mm/page.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -52,6 +52,4 @@
 #	define PA2KA(x)	((x) + 0x80000000)
 #endif
-
-#ifdef KERNEL
 
 /* Number of entries in each level. */
@@ -320,6 +318,4 @@
 #endif /* __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/arm32/include/regutils.h
===================================================================
--- kernel/arch/arm32/include/regutils.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/arm32/include/regutils.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -30,5 +30,5 @@
  * @{
  */
-/** 
+/**
  * @file
  * @brief Utilities for convenient manipulation with ARM registers.
@@ -38,52 +38,49 @@
 #define KERN_arm32_REGUTILS_H_
 
-#define STATUS_REG_IRQ_DISABLED_BIT (1 << 7)
-#define STATUS_REG_MODE_MASK        0x1f
+#define STATUS_REG_IRQ_DISABLED_BIT  (1 << 7)
+#define STATUS_REG_MODE_MASK         0x1f
 
-#define CP15_R1_HIGH_VECTORS_BIT    (1 << 13)
-
+#define CP15_R1_HIGH_VECTORS_BIT     (1 << 13)
 
 /* ARM Processor Operation Modes */
-#define USER_MODE         0x10
-#define FIQ_MODE          0x11
-#define	IRQ_MODE          0x12
-#define	SUPERVISOR_MODE   0x13
-#define	ABORT_MODE        0x17
-#define	UNDEFINED_MODE    0x1b
-#define	SYSTEM_MODE       0x1f
+#define USER_MODE        0x10
+#define FIQ_MODE         0x11
+#define IRQ_MODE         0x12
+#define SUPERVISOR_MODE  0x13
+#define ABORT_MODE       0x17
+#define UNDEFINED_MODE   0x1b
+#define SYSTEM_MODE      0x1f
 
 /* [CS]PRS manipulation macros */
-#define GEN_STATUS_READ(nm,reg) \
-static inline uint32_t nm## _status_reg_read(void) \
-{ \
-	uint32_t retval; \
-	asm volatile( \
-		"mrs %[retval], " #reg \
-		: [retval] "=r" (retval) \
-	); \
-	return retval; \
-}
+#define GEN_STATUS_READ(nm, reg) \
+	static inline uint32_t nm## _status_reg_read(void) \
+	{ \
+		uint32_t retval; \
+		\
+		asm volatile ( \
+			"mrs %[retval], " #reg \
+			: [retval] "=r" (retval) \
+		); \
+		\
+		return retval; \
+	}
 
-#define GEN_STATUS_WRITE(nm,reg,fieldname, field) \
-static inline void nm## _status_reg_ ##fieldname## _write(uint32_t value) \
-{ \
-	asm volatile( \
-		"msr " #reg "_" #field ", %[value]" \
-		:: [value] "r" (value) \
-	); \
-}
+#define GEN_STATUS_WRITE(nm, reg, fieldname, field) \
+	static inline void nm## _status_reg_ ##fieldname## _write(uint32_t value) \
+	{ \
+		asm volatile ( \
+			"msr " #reg "_" #field ", %[value]" \
+			:: [value] "r" (value) \
+		); \
+	}
 
+/** Return the value of CPSR (Current Program Status Register). */
+GEN_STATUS_READ(current, cpsr);
 
-/** Returns the value of CPSR (Current Program Status Register). */
-GEN_STATUS_READ(current, cpsr)
-
-
-/** Sets control bits of CPSR. */
+/** Set control bits of CPSR. */
 GEN_STATUS_WRITE(current, cpsr, control, c);
 
-
-/** Returns the value of SPSR (Saved Program Status Register). */
-GEN_STATUS_READ(saved, spsr)
-
+/** Return the value of SPSR (Saved Program Status Register). */
+GEN_STATUS_READ(saved, spsr);
 
 #endif
Index: kernel/arch/arm32/src/arm32.c
===================================================================
--- kernel/arch/arm32/src/arm32.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/arm32/src/arm32.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,5 +37,5 @@
 #include <config.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <sysinfo/sysinfo.h>
 #include <console/console.h>
Index: kernel/arch/arm32/src/mach/gta02/gta02.c
===================================================================
--- kernel/arch/arm32/src/mach/gta02/gta02.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/arm32/src/mach/gta02/gta02.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,5 @@
 #include <mm/page.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <genarch/drivers/s3c24xx_uart/s3c24xx_uart.h>
 #include <genarch/drivers/s3c24xx_irqc/s3c24xx_irqc.h>
Index: kernel/arch/arm32/src/mach/integratorcp/integratorcp.c
===================================================================
--- kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -48,5 +48,5 @@
 #include <arch/mach/integratorcp/integratorcp.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <ddi/ddi.h>
 #include <print.h>
Index: kernel/arch/arm32/src/mach/testarm/testarm.c
===================================================================
--- kernel/arch/arm32/src/mach/testarm/testarm.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/arm32/src/mach/testarm/testarm.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,5 @@
 #include <mm/page.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <genarch/drivers/dsrln/dsrlnin.h>
 #include <genarch/drivers/dsrln/dsrlnout.h>
Index: kernel/arch/ia32/Makefile.inc
===================================================================
--- kernel/arch/ia32/Makefile.inc	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/Makefile.inc	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -43,4 +43,8 @@
 ## Accepted CPUs
 #
+
+ifeq ($(PROCESSOR),i486)
+	CMN2 = -march=i486
+endif
 
 ifeq ($(PROCESSOR),athlon_xp)
Index: kernel/arch/ia32/include/asm.h
===================================================================
--- kernel/arch/ia32/include/asm.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/include/asm.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -101,4 +101,6 @@
 GEN_WRITE_REG(dr7)
 
+#define IO_SPACE_BOUNDARY	((void *) (64 * 1024))
+
 /** Byte to port
  *
@@ -111,9 +113,11 @@
 NO_TRACE static inline void pio_write_8(ioport8_t *port, uint8_t val)
 {
-	asm volatile (
-		"outb %b[val], %w[port]\n"
-		:: [val] "a" (val),
-		   [port] "d" (port)
-	);
+	if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
+		asm volatile (
+			"outb %b[val], %w[port]\n"
+			:: [val] "a" (val), [port] "d" (port)
+		);	
+	} else
+		*port = val;
 }
 
@@ -128,9 +132,11 @@
 NO_TRACE static inline void pio_write_16(ioport16_t *port, uint16_t val)
 {
-	asm volatile (
-		"outw %w[val], %w[port]\n"
-		:: [val] "a" (val),
-		   [port] "d" (port)
-	);
+	if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
+		asm volatile (
+			"outw %w[val], %w[port]\n"
+			:: [val] "a" (val), [port] "d" (port)
+		);
+	} else
+		*port = val;
 }
 
@@ -145,9 +151,11 @@
 NO_TRACE static inline void pio_write_32(ioport32_t *port, uint32_t val)
 {
-	asm volatile (
-		"outl %[val], %w[port]\n"
-		:: [val] "a" (val),
-		   [port] "d" (port)
-	);
+	if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
+		asm volatile (
+			"outl %[val], %w[port]\n"
+			:: [val] "a" (val), [port] "d" (port)
+		);
+	} else
+		*port = val;
 }
 
@@ -162,13 +170,16 @@
 NO_TRACE static inline uint8_t pio_read_8(ioport8_t *port)
 {
-	uint8_t val;
-	
-	asm volatile (
-		"inb %w[port], %b[val]\n"
-		: [val] "=a" (val)
-		: [port] "d" (port)
-	);
-	
-	return val;
+	if (((void *)port) < IO_SPACE_BOUNDARY) {
+		uint8_t val;
+		
+		asm volatile (
+			"inb %w[port], %b[val]\n"
+			: [val] "=a" (val)
+			: [port] "d" (port)
+		);
+		
+		return val;
+	} else
+		return (uint8_t) *port;
 }
 
@@ -183,13 +194,16 @@
 NO_TRACE static inline uint16_t pio_read_16(ioport16_t *port)
 {
-	uint16_t val;
-	
-	asm volatile (
-		"inw %w[port], %w[val]\n"
-		: [val] "=a" (val)
-		: [port] "d" (port)
-	);
-	
-	return val;
+	if (((void *)port) < IO_SPACE_BOUNDARY) {
+		uint16_t val;
+		
+		asm volatile (
+			"inw %w[port], %w[val]\n"
+			: [val] "=a" (val)
+			: [port] "d" (port)
+		);
+		
+		return val;
+	} else
+		return (uint16_t) *port;
 }
 
@@ -204,13 +218,16 @@
 NO_TRACE static inline uint32_t pio_read_32(ioport32_t *port)
 {
-	uint32_t val;
-	
-	asm volatile (
-		"inl %w[port], %[val]\n"
-		: [val] "=a" (val)
-		: [port] "d" (port)
-	);
-	
-	return val;
+	if (((void *)port) < IO_SPACE_BOUNDARY) {
+		uint32_t val;
+		
+		asm volatile (
+			"inl %w[port], %[val]\n"
+			: [val] "=a" (val)
+			: [port] "d" (port)
+		);
+		
+		return val;
+	} else
+		return (uint32_t) *port;
 }
 
@@ -311,4 +328,6 @@
 }
 
+#ifndef PROCESSOR_i486
+
 /** Write to MSR */
 NO_TRACE static inline void write_msr(uint32_t msr, uint64_t value)
@@ -335,4 +354,6 @@
 	return ((uint64_t) dx << 32) | ax;
 }
+
+#endif /* PROCESSOR_i486 */
 
 
Index: kernel/arch/ia32/include/atomic.h
===================================================================
--- kernel/arch/ia32/include/atomic.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/include/atomic.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -121,5 +121,7 @@
 	asm volatile (
 		"0:\n"
+#ifndef PROCESSOR_i486
 		"pause\n"        /* Pentium 4's HT love this instruction */
+#endif
 		"mov %[count], %[tmp]\n"
 		"testl %[tmp], %[tmp]\n"
Index: kernel/arch/ia32/include/boot/boot.h
===================================================================
--- kernel/arch/ia32/include/boot/boot.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/include/boot/boot.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -43,4 +43,6 @@
 #define MULTIBOOT_HEADER_FLAGS  0x00010003
 
+#define MULTIBOOT_LOADER_MAGIC  0x2BADB002
+
 #ifndef __ASM__
 
Index: kernel/arch/ia32/include/context.h
===================================================================
--- kernel/arch/ia32/include/context.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/include/context.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,6 +36,4 @@
 #define KERN_ia32_CONTEXT_H_
 
-#ifdef KERNEL
-
 #include <typedefs.h>
 
@@ -57,6 +55,4 @@
 	} while (0)
 
-#endif /* KERNEL */
-
 /*
  * Only save registers that must be preserved across
Index: kernel/arch/ia32/include/cycle.h
===================================================================
--- kernel/arch/ia32/include/cycle.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/include/cycle.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -40,4 +40,7 @@
 NO_TRACE static inline uint64_t get_cycle(void)
 {
+#ifdef PROCESSOR_i486
+	return 0;
+#else
 	uint64_t v;
 	
@@ -48,4 +51,5 @@
 	
 	return v;
+#endif
 }
 
Index: kernel/arch/ia32/include/elf.h
===================================================================
--- kernel/arch/ia32/include/elf.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup ia32	
+/** @addtogroup ia32
  * @{
  */
@@ -36,7 +36,7 @@
 #define KERN_ia32_ELF_H_
 
-#define	ELF_MACHINE		EM_386
-#define ELF_DATA_ENCODING	ELFDATA2LSB
-#define ELF_CLASS		ELFCLASS32
+#define ELF_MACHINE        EM_386
+#define ELF_DATA_ENCODING  ELFDATA2LSB
+#define ELF_CLASS          ELFCLASS32
 
 #endif
Index: kernel/arch/ia32/include/istate.h
===================================================================
--- kernel/arch/ia32/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,16 +36,5 @@
 #define KERN_ia32_ISTATE_H_
 
-#ifdef KERNEL
-
-#include <typedefs.h>
 #include <trace.h>
-
-#else /* KERNEL */
-
-#include <sys/types.h>
-
-#define NO_TRACE
-
-#endif /* KERNEL */
 
 typedef struct istate {
Index: kernel/arch/ia32/include/mm/frame.h
===================================================================
--- kernel/arch/ia32/include/mm/frame.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/include/mm/frame.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -50,5 +49,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/ia32/include/mm/page.h
===================================================================
--- kernel/arch/ia32/include/mm/page.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/include/mm/page.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,6 +42,4 @@
 #define PAGE_SIZE   FRAME_SIZE
 
-#ifdef KERNEL
-
 #ifndef __ASM__
 
@@ -201,6 +199,4 @@
 #endif /* __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/ia32/src/asm.S
===================================================================
--- kernel/arch/ia32/src/asm.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/src/asm.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -405,5 +405,11 @@
 	xorl %eax, %eax
 	cmpl $(GDT_SELECTOR(KTEXT_DES)), ISTATE_OFFSET_CS(%esp)
+#ifdef PROCESSOR_i486
+	jz 0f
+		movl %eax, %ebp
+	0:
+#else
 	cmovnzl %eax, %ebp
+#endif
 
 	movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp)
Index: kernel/arch/ia32/src/boot/boot.S
===================================================================
--- kernel/arch/ia32/src/boot/boot.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/src/boot/boot.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -97,4 +97,10 @@
 	pm_status $status_prot
 	
+#include "vesa_prot.inc"
+	
+#ifndef PROCESSOR_i486
+	
+	pm_status $status_prot2
+	
 	movl $(INTEL_CPUID_LEVEL), %eax
 	cpuid
@@ -105,16 +111,20 @@
 	cpuid
 	bt $(INTEL_PSE), %edx
-	jc pse_supported
+	jnc pse_unsupported
+		
+		/* Map kernel and turn paging on */
+		pm_status $status_pse
+		call map_kernel_pse
+		jmp stack_init
+	
+#endif /* PROCESSOR_i486 */
 	
 	pse_unsupported:
 		
-		pm_error $err_pse
-	
-	pse_supported:
-	
-#include "vesa_prot.inc"
-	
-	/* Map kernel and turn paging on */
-	call map_kernel
+		/* Map kernel and turn paging on */
+		pm_status $status_non_pse
+		call map_kernel
+	
+	stack_init:
 	
 	/* Create the first stack frame */
@@ -122,5 +132,5 @@
 	movl %esp, %ebp
 	
-	pm2_status $status_prot2
+	pm2_status $status_prot3
 	
 	/* Call arch_pre_main(grub_eax, grub_ebx) */
@@ -140,5 +150,5 @@
 		jmp hlt0
 
-/** Setup mapping for the kernel.
+/** Setup mapping for the kernel (PSE variant)
  *
  * Setup mapping for both the unmapped and mapped sections
@@ -146,6 +156,7 @@
  *
  */
-.global map_kernel
-map_kernel:
+.global map_kernel_pse
+map_kernel_pse:
+	/* Paging features */
 	movl %cr4, %ecx
 	orl $(1 << 4), %ecx      /* PSE on */
@@ -158,5 +169,5 @@
 	xorl %ebx, %ebx
 	
-	floop:
+	floop_pse:
 		movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
 		orl %ebx, %eax
@@ -169,5 +180,5 @@
 		incl %ecx
 		cmpl $512, %ecx
-		jl floop
+		jl floop_pse
 	
 	movl %esi, %cr3
@@ -177,4 +188,179 @@
 	movl %ebx, %cr0
 	ret
+
+/** Setup mapping for the kernel (non-PSE variant).
+ *
+ * Setup mapping for both the unmapped and mapped sections
+ * of the kernel. For simplicity, we map the entire 4G space.
+ *
+ */
+.global map_kernel
+map_kernel:
+	/* Paging features */
+	movl %cr4, %ecx
+	andl $(~(1 << 5)), %ecx  /* PAE off */
+	movl %ecx, %cr4
+	
+	call calc_kernel_end
+	call find_mem_for_pt
+	
+	mov kernel_end, %esi
+	mov free_area, %ecx
+	
+	cmpl %esi, %ecx
+	jbe use_kernel_end
+		
+		mov %ecx, %esi
+		
+		/* Align address down to 4k */
+		andl $(~4095), %esi
+		
+	use_kernel_end:
+		
+		/* Align address to 4k */
+		addl $4095, %esi
+		andl $(~4095), %esi
+		
+		/* Allocate space for page tables */
+		movl %esi, pt_loc
+		movl $ballocs, %edi
+		andl $0x7fffffff, %edi
+		
+		movl %esi, (%edi)
+		addl $4, %edi
+		movl $(2 * 1024 * 1024), (%edi)
+		
+		/* Fill page tables */
+		xorl %ecx, %ecx
+		xorl %ebx, %ebx
+		
+		floop_pt:
+			movl $((1 << 1) | (1 << 0)), %eax
+			orl %ebx, %eax
+			movl %eax, (%esi, %ecx, 4)
+			addl $(4 * 1024), %ebx
+			
+			incl %ecx
+			cmpl $(512 * 1024), %ecx
+			
+			jl floop_pt
+		
+		/* Fill page directory */
+		movl $(page_directory + 0), %esi
+		movl $(page_directory + 2048), %edi
+		xorl %ecx, %ecx
+		movl pt_loc, %ebx
+		
+		floop:
+			movl $((1 << 1) | (1 << 0)), %eax
+			orl %ebx, %eax
+			
+			/* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
+			movl %eax, (%esi, %ecx, 4)
+			
+			/* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
+			movl %eax, (%edi, %ecx, 4)
+			addl $(4 * 1024), %ebx
+			
+			incl %ecx
+			cmpl $512, %ecx
+			
+			jl floop
+		
+		movl %esi, %cr3
+		
+		movl %cr0, %ebx
+		orl $(1 << 31), %ebx  /* paging on */
+		movl %ebx, %cr0
+		
+		ret
+
+/** Calculate unmapped address of the end of the kernel. */
+calc_kernel_end:
+	movl $hardcoded_load_address, %edi
+	andl $0x7fffffff, %edi
+	movl (%edi), %esi
+	andl $0x7fffffff, %esi
+	
+	movl $hardcoded_ktext_size, %edi
+	andl $0x7fffffff, %edi
+	addl (%edi), %esi
+	andl $0x7fffffff, %esi
+	
+	movl $hardcoded_kdata_size, %edi
+	andl $0x7fffffff, %edi
+	addl (%edi), %esi
+	andl $0x7fffffff, %esi
+	movl %esi, kernel_end
+	
+	ret
+
+/** Find free 2M (+4k for alignment) region where to store page tables */
+find_mem_for_pt:
+	/* Check if multiboot info is present */
+	cmpl $MULTIBOOT_LOADER_MAGIC, grub_eax
+	je check_multiboot_map
+		
+		ret
+	
+	check_multiboot_map:
+		
+		/* Copy address of the multiboot info to ebx */
+		movl grub_ebx, %ebx
+		
+		/* Check if memory map flag is present */
+		movl (%ebx), %edx
+		andl $(1 << 6), %edx
+		jnz use_multiboot_map
+			
+			ret
+		
+	use_multiboot_map:
+		
+		/* Copy address of the memory map to edx */
+		movl 48(%ebx), %edx
+		movl %edx, %ecx
+		
+		addl 44(%ebx), %ecx
+		
+		/* Find a free region at least 2M in size */
+		check_memmap_loop:
+			
+			/* Is this a free region? */
+			cmp $1, 20(%edx)
+			jnz next_region
+			
+			/* Check size */
+			cmp $0, 16(%edx)
+			jnz next_region
+			
+			cmpl $(2 * 1024 * 1024 + 4 * 1024), 12(%edx)
+			jbe next_region
+			
+			cmp $0, 8(%edx)
+			jz found_region
+		
+		next_region:
+			
+			cmp %ecx, %edx
+			jbe next_region_do
+			
+				ret
+		
+		next_region_do:
+			
+			addl (%edx), %edx
+			addl $4, %edx
+			jmp check_memmap_loop
+			
+		found_region:
+			
+			/* Use end of the found region */
+			mov 4(%edx), %ecx
+			add 12(%edx), %ecx
+			sub $(2 * 1024 * 1024), %ecx
+			mov %ecx, free_area
+			
+			ret
 
 /** Print string to EGA display (in light red) and halt.
@@ -521,13 +707,20 @@
 grub_eax:
 	.long 0
-
 grub_ebx:
 	.long 0
 
-err_pse:
-	.asciz "Page Size Extension not supported. System halted."
+pt_loc:
+	.long 0
+kernel_end:
+	.long 0
+free_area:
+	.long 0
 
 status_prot:
 	.asciz "[prot] "
+status_pse:
+	.asciz "[pse] "
+status_non_pse:
+	.asciz "[non_pse] "
 status_vesa_copy:
 	.asciz "[vesa_copy] "
@@ -538,4 +731,6 @@
 status_prot2:
 	.asciz "[prot2] "
+status_prot3:
+	.asciz "[prot3] "
 status_main:
 	.asciz "[main] "
Index: kernel/arch/ia32/src/cpu/cpu.c
===================================================================
--- kernel/arch/ia32/src/cpu/cpu.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/src/cpu/cpu.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -118,9 +118,11 @@
 		);
 	}
-	
+
+#ifndef PROCESSOR_i486
 	if (CPU->arch.fi.bits.sep) {
 		/* Setup fast SYSENTER/SYSEXIT syscalls */
 		syscall_setup_cpu();
 	}
+#endif
 }
 
Index: kernel/arch/ia32/src/drivers/vesa.c
===================================================================
--- kernel/arch/ia32/src/drivers/vesa.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/src/drivers/vesa.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,4 @@
 
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
 #include <arch/drivers/vesa.h>
 #include <console/chardev.h>
Index: kernel/arch/ia32/src/proc/scheduler.c
===================================================================
--- kernel/arch/ia32/src/proc/scheduler.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/src/proc/scheduler.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -60,8 +60,10 @@
 	uintptr_t kstk = (uintptr_t) &THREAD->kstack[STACK_SIZE];
 	
+#ifndef PROCESSOR_i486
 	if (CPU->arch.fi.bits.sep) {
 		/* Set kernel stack for CP3 -> CPL0 switch via SYSENTER */
 		write_msr(IA32_MSR_SYSENTER_ESP, kstk - sizeof(istate_t));
 	}
+#endif
 	
 	/* Set kernel stack for CPL3 -> CPL0 switch via interrupt */
Index: kernel/arch/ia32/src/smp/smp.c
===================================================================
--- kernel/arch/ia32/src/smp/smp.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/src/smp/smp.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,5 +42,4 @@
 #include <config.h>
 #include <synch/waitq.h>
-#include <synch/synch.h>
 #include <arch/pm.h>
 #include <func.h>
Index: kernel/arch/ia32/src/syscall.c
===================================================================
--- kernel/arch/ia32/src/syscall.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/src/syscall.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,4 +39,6 @@
 #include <arch/pm.h>
 
+#ifndef PROCESSOR_i486
+
 /** Enable & setup support for SYSENTER/SYSEXIT */
 void syscall_setup_cpu(void)
@@ -50,4 +52,6 @@
 }
 
+#endif /* PROCESSOR_i486 */
+
 /** @}
  */
Index: kernel/arch/ia32/src/userspace.c
===================================================================
--- kernel/arch/ia32/src/userspace.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia32/src/userspace.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,7 +37,6 @@
 #include <typedefs.h>
 #include <arch.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <mm/as.h>
-
 
 /** Enter userspace
Index: kernel/arch/ia64/include/elf.h
===================================================================
--- kernel/arch/ia64/include/elf.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia64/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup ia64	
+/** @addtogroup ia64
  * @{
  */
@@ -36,7 +36,7 @@
 #define KERN_ia64_ELF_H_
 
-#define	ELF_MACHINE		EM_IA_64
-#define ELF_DATA_ENCODING	ELFDATA2LSB
-#define ELF_CLASS		ELFCLASS64
+#define ELF_MACHINE        EM_IA_64
+#define ELF_DATA_ENCODING  ELFDATA2LSB
+#define ELF_CLASS          ELFCLASS64
 
 #endif
Index: kernel/arch/ia64/include/istate.h
===================================================================
--- kernel/arch/ia64/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia64/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,13 +36,15 @@
 #define KERN_ia64_ISTATE_H_
 
+#include <trace.h>
+
+#ifdef KERNEL
+
 #include <arch/register.h>
 
-#ifdef KERNEL
-#include <typedefs.h>
-#include <trace.h>
-#else
-#include <sys/types.h>
-#define NO_TRACE
-#endif
+#else /* KERNEL */
+
+#include <libarch/register.h>
+
+#endif /* KERNEL */
 
 typedef struct istate {
Index: kernel/arch/ia64/include/mm/frame.h
===================================================================
--- kernel/arch/ia64/include/mm/frame.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia64/include/mm/frame.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -50,5 +49,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/ia64/include/mm/page.h
===================================================================
--- kernel/arch/ia64/include/mm/page.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia64/include/mm/page.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,6 +41,4 @@
 #define PAGE_SIZE   FRAME_SIZE
 #define PAGE_WIDTH  FRAME_WIDTH
-
-#ifdef KERNEL
 
 /** Bit width of the TLB-locked portion of kernel address space. */
@@ -316,6 +314,4 @@
 #endif /* __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/ia64/include/register.h
===================================================================
--- kernel/arch/ia64/include/register.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia64/include/register.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -61,6 +61,6 @@
 #define PSR_CPL_MASK_SHIFTED  3
 
-#define PSR_RI_SHIFT	41
-#define PSR_RI_LEN	2
+#define PSR_RI_SHIFT  41
+#define PSR_RI_LEN    2
 
 #define PFM_MASK  (~0x3fffffffff)
@@ -145,10 +145,4 @@
 #ifndef __ASM__
 
-#ifdef KERNEL
-#include <typedefs.h>
-#else
-#include <sys/types.h>
-#endif
-
 /** Processor Status Register. */
 typedef union {
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ia64/src/ia64.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -50,5 +50,5 @@
 #include <userspace.h>
 #include <console/console.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <syscall/syscall.h>
 #include <ddi/irq.h>
Index: kernel/arch/mips32/include/context_offset.h
===================================================================
--- kernel/arch/mips32/include/context_offset.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/mips32/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -63,119 +63,126 @@
 #ifdef __ASM__
 
+#ifdef KERNEL
+
 #include <arch/asm/regname.h>
 
-# ctx: address of the structure with saved context
+#else /* KERNEL */
+
+#include <libarch/regname.h>
+
+#endif /* KERNEL */
+
+/* ctx: address of the structure with saved context */
 .macro CONTEXT_SAVE_ARCH_CORE ctx:req
-	sw $s0,OFFSET_S0(\ctx)
-	sw $s1,OFFSET_S1(\ctx)
-	sw $s2,OFFSET_S2(\ctx)
-	sw $s3,OFFSET_S3(\ctx)
-	sw $s4,OFFSET_S4(\ctx)
-	sw $s5,OFFSET_S5(\ctx)
-	sw $s6,OFFSET_S6(\ctx)
-	sw $s7,OFFSET_S7(\ctx)
-	sw $s8,OFFSET_S8(\ctx)
-	sw $gp,OFFSET_GP(\ctx)
-
+	sw $s0, OFFSET_S0(\ctx)
+	sw $s1, OFFSET_S1(\ctx)
+	sw $s2, OFFSET_S2(\ctx)
+	sw $s3, OFFSET_S3(\ctx)
+	sw $s4, OFFSET_S4(\ctx)
+	sw $s5, OFFSET_S5(\ctx)
+	sw $s6, OFFSET_S6(\ctx)
+	sw $s7, OFFSET_S7(\ctx)
+	sw $s8, OFFSET_S8(\ctx)
+	sw $gp, OFFSET_GP(\ctx)
+	
 #ifndef KERNEL
-	sw $k1,OFFSET_TLS(\ctx)
-
+	sw $k1, OFFSET_TLS(\ctx)
+	
 #ifdef CONFIG_FPU
-	mfc1 $t0,$20
+	mfc1 $t0, $20
 	sw $t0, OFFSET_F20(\ctx)
-
-	mfc1 $t0,$21
+	
+	mfc1 $t0, $21
 	sw $t0, OFFSET_F21(\ctx)
-
-	mfc1 $t0,$22
+	
+	mfc1 $t0, $22
 	sw $t0, OFFSET_F22(\ctx)
-
-	mfc1 $t0,$23
+	
+	mfc1 $t0, $23
 	sw $t0, OFFSET_F23(\ctx)
-
-	mfc1 $t0,$24
+	
+	mfc1 $t0, $24
 	sw $t0, OFFSET_F24(\ctx)
-
-	mfc1 $t0,$25
+	
+	mfc1 $t0, $25
 	sw $t0, OFFSET_F25(\ctx)
-
-	mfc1 $t0,$26
+	
+	mfc1 $t0, $26
 	sw $t0, OFFSET_F26(\ctx)
-
-	mfc1 $t0,$27
+	
+	mfc1 $t0, $27
 	sw $t0, OFFSET_F27(\ctx)
-
-	mfc1 $t0,$28
+	
+	mfc1 $t0, $28
 	sw $t0, OFFSET_F28(\ctx)
-
-	mfc1 $t0,$29
+	
+	mfc1 $t0, $29
 	sw $t0, OFFSET_F29(\ctx)
 	
-	mfc1 $t0,$30
+	mfc1 $t0, $30
 	sw $t0, OFFSET_F30(\ctx)
 #endif /* CONFIG_FPU */
 #endif /* KERNEL */
-
-	sw $ra,OFFSET_PC(\ctx)
-	sw $sp,OFFSET_SP(\ctx)
+	
+	sw $ra, OFFSET_PC(\ctx)
+	sw $sp, OFFSET_SP(\ctx)
 .endm
 
-# ctx: address of the structure with saved context
+/* ctx: address of the structure with saved context */
 .macro CONTEXT_RESTORE_ARCH_CORE ctx:req
-	lw $s0,OFFSET_S0(\ctx)
-	lw $s1,OFFSET_S1(\ctx)
-	lw $s2,OFFSET_S2(\ctx)
-	lw $s3,OFFSET_S3(\ctx)
-	lw $s4,OFFSET_S4(\ctx)
-	lw $s5,OFFSET_S5(\ctx)
-	lw $s6,OFFSET_S6(\ctx)
-	lw $s7,OFFSET_S7(\ctx)
-	lw $s8,OFFSET_S8(\ctx)
-	lw $gp,OFFSET_GP(\ctx)
+	lw $s0, OFFSET_S0(\ctx)
+	lw $s1, OFFSET_S1(\ctx)
+	lw $s2, OFFSET_S2(\ctx)
+	lw $s3, OFFSET_S3(\ctx)
+	lw $s4, OFFSET_S4(\ctx)
+	lw $s5, OFFSET_S5(\ctx)
+	lw $s6, OFFSET_S6(\ctx)
+	lw $s7, OFFSET_S7(\ctx)
+	lw $s8, OFFSET_S8(\ctx)
+	lw $gp, OFFSET_GP(\ctx)
 #ifndef KERNEL
-	lw $k1,OFFSET_TLS(\ctx)
-
+	lw $k1, OFFSET_TLS(\ctx)
+	
 #ifdef CONFIG_FPU
 	lw $t0, OFFSET_F20(\ctx)
-	mtc1 $t0,$20
-
+	mtc1 $t0, $20
+	
 	lw $t0, OFFSET_F21(\ctx)
-	mtc1 $t0,$21
-
+	mtc1 $t0, $21
+	
 	lw $t0, OFFSET_F22(\ctx)
-	mtc1 $t0,$22
-
+	mtc1 $t0, $22
+	
 	lw $t0, OFFSET_F23(\ctx)
-	mtc1 $t0,$23
-
+	mtc1 $t0, $23
+	
 	lw $t0, OFFSET_F24(\ctx)
-	mtc1 $t0,$24
-
+	mtc1 $t0, $24
+	
 	lw $t0, OFFSET_F25(\ctx)
-	mtc1 $t0,$25
-
+	mtc1 $t0, $25
+	
 	lw $t0, OFFSET_F26(\ctx)
-	mtc1 $t0,$26
-
+	mtc1 $t0, $26
+	
 	lw $t0, OFFSET_F27(\ctx)
-	mtc1 $t0,$27
-
+	mtc1 $t0, $27
+	
 	lw $t0, OFFSET_F28(\ctx)
-	mtc1 $t0,$28
-
+	mtc1 $t0, $28
+	
 	lw $t0, OFFSET_F29(\ctx)
-	mtc1 $t0,$29
-
+	mtc1 $t0, $29
+	
 	lw $t0, OFFSET_F30(\ctx)
-	mtc1 $t0,$30
+	mtc1 $t0, $30
 #endif /* CONFIG_FPU */
 #endif /* KERNEL */
-
-	lw $ra,OFFSET_PC(\ctx)
-	lw $sp,OFFSET_SP(\ctx)
+	
+	lw $ra, OFFSET_PC(\ctx)
+	lw $sp, OFFSET_SP(\ctx)
 .endm
 
-#endif
-
+#endif /* __ASM__ */
 
 #endif
Index: kernel/arch/mips32/include/cp0.h
===================================================================
--- kernel/arch/mips32/include/cp0.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/mips32/include/cp0.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,10 +36,4 @@
 #define KERN_mips32_CP0_H_
 
-#ifdef KERNEL
-#include <typedefs.h>
-#else
-#include <sys/types.h>
-#endif
-
 #define cp0_status_ie_enabled_bit     (1 << 0)
 #define cp0_status_exl_exception_bit  (1 << 1)
@@ -49,33 +43,50 @@
 #define cp0_status_fpu_bit            (1 << 29)
 
-#define cp0_status_im_shift		8
-#define cp0_status_im_mask              0xff00
+#define cp0_status_im_shift  8
+#define cp0_status_im_mask   0xff00
 
-#define cp0_cause_excno(cause) ((cause >> 2) & 0x1f)
-#define cp0_cause_coperr(cause) ((cause >> 28) & 0x3)
+#define cp0_cause_excno(cause)   ((cause >> 2) & 0x1f)
+#define cp0_cause_coperr(cause)  ((cause >> 28) & 0x3)
 
-#define fpu_cop_id 1
+#define fpu_cop_id  1
 
 /*
  * Magic value for use in msim.
  */
-#define cp0_compare_value 		100000
+#define cp0_compare_value  100000
 
-#define cp0_mask_all_int() cp0_status_write(cp0_status_read() & ~(cp0_status_im_mask))
-#define cp0_unmask_all_int() cp0_status_write(cp0_status_read() | cp0_status_im_mask)
-#define cp0_mask_int(it) cp0_status_write(cp0_status_read() & ~(1 << (cp0_status_im_shift + (it))))
-#define cp0_unmask_int(it) cp0_status_write(cp0_status_read() | (1 << (cp0_status_im_shift + (it))))
+#define cp0_mask_all_int() \
+	cp0_status_write(cp0_status_read() & ~(cp0_status_im_mask))
 
-#define GEN_READ_CP0(nm,reg) static inline uint32_t cp0_ ##nm##_read(void) \
-  { \
-      uint32_t retval; \
-      asm volatile ("mfc0 %0, $" #reg : "=r"(retval)); \
-      return retval; \
-  }
+#define cp0_unmask_all_int() \
+	cp0_status_write(cp0_status_read() | cp0_status_im_mask)
 
-#define GEN_WRITE_CP0(nm,reg) static inline void cp0_ ##nm##_write(uint32_t val) \
- { \
-    asm volatile ("mtc0 %0, $" #reg : : "r"(val) ); \
- }
+#define cp0_mask_int(it) \
+	cp0_status_write(cp0_status_read() & ~(1 << (cp0_status_im_shift + (it))))
+
+#define cp0_unmask_int(it) \
+	cp0_status_write(cp0_status_read() | (1 << (cp0_status_im_shift + (it))))
+
+#define GEN_READ_CP0(nm, reg) \
+	static inline uint32_t cp0_ ##nm##_read(void) \
+	{ \
+		uint32_t retval; \
+		\
+		asm volatile ( \
+			"mfc0 %0, $" #reg \
+			: "=r"(retval) \
+		); \
+		\
+		return retval; \
+	}
+
+#define GEN_WRITE_CP0(nm, reg) \
+	static inline void cp0_ ##nm##_write(uint32_t val) \
+	{ \
+		asm volatile ( \
+			"mtc0 %0, $" #reg \
+			:: "r"(val) \
+		); \
+	}
 
 GEN_READ_CP0(index, 0);
Index: kernel/arch/mips32/include/istate.h
===================================================================
--- kernel/arch/mips32/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/mips32/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,13 +36,15 @@
 #define KERN_mips32_ISTATE_H_
 
+#include <trace.h>
+
+#ifdef KERNEL
+
 #include <arch/cp0.h>
 
-#ifdef KERNEL
-#include <typedefs.h>
-#include <trace.h>
-#else
-#include <sys/types.h>
-#define NO_TRACE
-#endif
+#else /* KERNEL */
+
+#include <libarch/cp0.h>
+
+#endif /* KERNEL */
 
 typedef struct istate {
Index: kernel/arch/mips32/include/mm/frame.h
===================================================================
--- kernel/arch/mips32/include/mm/frame.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/mips32/include/mm/frame.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -46,5 +45,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/mips32/include/mm/page.h
===================================================================
--- kernel/arch/mips32/include/mm/page.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/mips32/include/mm/page.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -49,6 +49,4 @@
 #	define PA2KA(x)	((x) + 0x80000000)
 #endif
-
-#ifdef KERNEL
 
 /*
@@ -188,6 +186,4 @@
 #endif /* __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/mips32/src/mips32.c
===================================================================
--- kernel/arch/mips32/src/mips32.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/mips32/src/mips32.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,5 +41,5 @@
 #include <memstr.h>
 #include <proc/thread.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <print.h>
 #include <console/console.h>
@@ -52,5 +52,5 @@
 #include <arch/debugger.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <genarch/drivers/dsrln/dsrlnin.h>
 #include <genarch/drivers/dsrln/dsrlnout.h>
Index: kernel/arch/mips64/include/context_offset.h
===================================================================
--- kernel/arch/mips64/include/context_offset.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/mips64/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -63,7 +63,15 @@
 #ifdef __ASM__
 
+#ifdef KERNEL
+
 #include <arch/asm/regname.h>
 
-# ctx: address of the structure with saved context
+#else /* KERNEL */
+
+#include <libarch/regname.h>
+
+#endif /* KERNEL */
+
+/* ctx: address of the structure with saved context */
 .macro CONTEXT_SAVE_ARCH_CORE ctx:req
 	sd $s0, OFFSET_S0(\ctx)
@@ -121,5 +129,5 @@
 .endm
 
-# ctx: address of the structure with saved context
+/* ctx: address of the structure with saved context */
 .macro CONTEXT_RESTORE_ARCH_CORE ctx:req
 	ld $s0, OFFSET_S0(\ctx)
Index: kernel/arch/mips64/include/cp0.h
===================================================================
--- kernel/arch/mips64/include/cp0.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/mips64/include/cp0.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -35,14 +35,4 @@
 #ifndef KERN_mips64_CP0_H_
 #define KERN_mips64_CP0_H_
-
-#ifdef KERNEL
-
-#include <typedefs.h>
-
-#else
-
-#include <sys/types.h>
-
-#endif
 
 #define cp0_status_ie_enabled_bit     (1 << 0)
Index: kernel/arch/mips64/include/istate.h
===================================================================
--- kernel/arch/mips64/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/mips64/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,17 +36,15 @@
 #define KERN_mips64_ISTATE_H_
 
-#include <arch/cp0.h>
+#include <trace.h>
 
 #ifdef KERNEL
 
-#include <typedefs.h>
-#include <trace.h>
+#include <arch/cp0.h>
 
-#else
+#else /* KERNEL */
 
-#include <sys/types.h>
-#define NO_TRACE
+#include <libarch/cp0.h>
 
-#endif
+#endif /* KERNEL */
 
 typedef struct istate {
Index: kernel/arch/mips64/include/mm/frame.h
===================================================================
--- kernel/arch/mips64/include/mm/frame.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/mips64/include/mm/frame.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -46,5 +45,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/mips64/include/mm/page.h
===================================================================
--- kernel/arch/mips64/include/mm/page.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/mips64/include/mm/page.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -50,5 +50,4 @@
 #endif
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -56,5 +55,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/mips64/src/mips64.c
===================================================================
--- kernel/arch/mips64/src/mips64.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/mips64/src/mips64.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,5 +41,5 @@
 #include <memstr.h>
 #include <proc/thread.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <print.h>
 #include <console/console.h>
@@ -52,5 +52,5 @@
 #include <arch/debugger.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <genarch/drivers/dsrln/dsrlnin.h>
 #include <genarch/drivers/dsrln/dsrlnout.h>
Index: kernel/arch/ppc32/include/asm.h
===================================================================
--- kernel/arch/ppc32/include/asm.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ppc32/include/asm.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,5 @@
 #include <typedefs.h>
 #include <config.h>
-#include <arch/cpu.h>
+#include <arch/msr.h>
 #include <arch/mm/asid.h>
 #include <trace.h>
Index: kernel/arch/ppc32/include/context_offset.h
===================================================================
--- kernel/arch/ppc32/include/context_offset.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ppc32/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -75,7 +75,16 @@
 
 #ifdef __ASM__
-# include <arch/asm/regname.h>
 
-# ctx: address of the structure with saved context
+#ifdef KERNEL
+
+#include <arch/asm/regname.h>
+
+#else /* KERNEL */
+
+#include <libarch/regname.h>
+
+#endif /* KERNEL */
+
+/* ctx: address of the structure with saved context */
 .macro CONTEXT_SAVE_ARCH_CORE ctx:req
 	stw sp, OFFSET_SP(\ctx)
@@ -102,5 +111,5 @@
 .endm
 
-# ctx: address of the structure with saved context
+/* ctx: address of the structure with saved context */
 .macro CONTEXT_RESTORE_ARCH_CORE ctx:req
 	lwz sp, OFFSET_SP(\ctx)
Index: kernel/arch/ppc32/include/cpu.h
===================================================================
--- kernel/arch/ppc32/include/cpu.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ppc32/include/cpu.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,19 +36,4 @@
 #define KERN_ppc32_CPU_H_
 
-/* MSR bits */
-#define MSR_DR  (1 << 4)
-#define MSR_IR  (1 << 5)
-#define MSR_PR  (1 << 14)
-#define MSR_EE  (1 << 15)
-
-/* HID0 bits */
-#define HID0_STEN  (1 << 24)
-#define HID0_ICE   (1 << 15)
-#define HID0_DCE   (1 << 14)
-#define HID0_ICFI  (1 << 11)
-#define HID0_DCI   (1 << 10)
-
-#ifndef __ASM__
-
 #include <typedefs.h>
 #include <trace.h>
@@ -67,6 +52,4 @@
 }
 
-#endif /* __ASM__ */
-
 #endif
 
Index: kernel/arch/ppc32/include/exception.h
===================================================================
--- kernel/arch/ppc32/include/exception.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ppc32/include/exception.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,5 +37,5 @@
 
 #include <typedefs.h>
-#include <arch/cpu.h>
+#include <arch/msr.h>
 #include <trace.h>
 
Index: kernel/arch/ppc32/include/istate.h
===================================================================
--- kernel/arch/ppc32/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ppc32/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,7 +36,15 @@
 #define KERN_ppc32_EXCEPTION_H_
 
-#include <typedefs.h>
-#include <arch/cpu.h>
 #include <trace.h>
+
+#ifdef KERNEL
+
+#include <arch/msr.h>
+
+#else /* KERNEL */
+
+#include <libarch/msr.h>
+
+#endif /* KERNEL */
 
 typedef struct istate {
Index: kernel/arch/ppc32/include/mm/frame.h
===================================================================
--- kernel/arch/ppc32/include/mm/frame.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ppc32/include/mm/frame.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -63,5 +62,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/ppc32/include/mm/page.h
===================================================================
--- kernel/arch/ppc32/include/mm/page.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ppc32/include/mm/page.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,6 +41,4 @@
 #define PAGE_WIDTH  FRAME_WIDTH
 #define PAGE_SIZE   FRAME_SIZE
-
-#ifdef KERNEL
 
 #ifndef __ASM__
@@ -181,6 +179,4 @@
 #endif /* __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/ppc32/include/msr.h
===================================================================
--- kernel/arch/ppc32/include/msr.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ kernel/arch/ppc32/include/msr.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,54 @@
+/*
+ * 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 ppc32
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_ppc32_MSR_H_
+#define KERN_ppc32_MSR_H_
+
+/* MSR bits */
+#define MSR_DR  (1 << 4)
+#define MSR_IR  (1 << 5)
+#define MSR_PR  (1 << 14)
+#define MSR_EE  (1 << 15)
+
+/* HID0 bits */
+#define HID0_STEN  (1 << 24)
+#define HID0_ICE   (1 << 15)
+#define HID0_DCE   (1 << 14)
+#define HID0_ICFI  (1 << 11)
+#define HID0_DCI   (1 << 10)
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/ppc32/src/asm.S
===================================================================
--- kernel/arch/ppc32/src/asm.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ppc32/src/asm.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -28,5 +28,5 @@
 
 #include <arch/asm/regname.h>
-#include <arch/cpu.h>
+#include <arch/msr.h>
 
 .text
Index: kernel/arch/ppc32/src/exception.S
===================================================================
--- kernel/arch/ppc32/src/exception.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ppc32/src/exception.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -28,5 +28,5 @@
 
 #include <arch/asm/regname.h>
-#include <arch/cpu.h>
+#include <arch/msr.h>
 #include <arch/mm/page.h>
 
Index: kernel/arch/ppc32/src/ppc32.c
===================================================================
--- kernel/arch/ppc32/src/ppc32.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/ppc32/src/ppc32.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,10 +41,10 @@
 #include <interrupt.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <genarch/ofw/ofw_tree.h>
 #include <genarch/ofw/pci.h>
 #include <userspace.h>
 #include <mm/page.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <console/console.h>
 #include <sysinfo/sysinfo.h>
Index: kernel/arch/sparc64/include/barrier.h
===================================================================
--- kernel/arch/sparc64/include/barrier.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/sparc64/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,14 +37,4 @@
 
 #include <trace.h>
-
-#ifdef KERNEL
-
-#include <typedefs.h>
-
-#else
-
-#include <stdint.h>
-
-#endif
 
 /*
Index: kernel/arch/sparc64/include/elf.h
===================================================================
--- kernel/arch/sparc64/include/elf.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/sparc64/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup sparc64	
+/** @addtogroup sparc64
  * @{
  */
@@ -36,7 +36,7 @@
 #define KERN_sparc64_ELF_H_
 
-#define	ELF_MACHINE		EM_SPARCV9
-#define ELF_DATA_ENCODING	ELFDATA2MSB
-#define ELF_CLASS		ELFCLASS64
+#define ELF_MACHINE        EM_SPARCV9
+#define ELF_DATA_ENCODING  ELFDATA2MSB
+#define ELF_CLASS          ELFCLASS64
 
 #endif
Index: kernel/arch/sparc64/include/istate.h
===================================================================
--- kernel/arch/sparc64/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/sparc64/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,13 +37,15 @@
 #define KERN_sparc64_ISTATE_H_
 
+#include <trace.h>
+
+#ifdef KERNEL
+
 #include <arch/regdef.h>
 
-#ifdef KERNEL
-#include <typedefs.h>
-#include <trace.h>
-#else
-#include <sys/types.h>
-#define NO_TRACE
-#endif
+#else /* KERNEL */
+
+#include <libarch/regdef.h>
+
+#endif /* KERNEL */
 
 typedef struct istate {
Index: kernel/arch/sparc64/include/mm/page.h
===================================================================
--- kernel/arch/sparc64/include/mm/page.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/sparc64/include/mm/page.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -54,6 +54,4 @@
 #define MMU_PAGES_PER_PAGE	(1 << (PAGE_WIDTH - MMU_PAGE_WIDTH))
 
-#ifdef KERNEL
-
 #ifndef __ASM__
 
@@ -77,6 +75,4 @@
 #endif /* !def __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/sparc64/include/mm/sun4u/frame.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4u/frame.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/sparc64/include/mm/sun4u/frame.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -52,5 +52,4 @@
 #define FRAME_SIZE		(1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -80,5 +79,4 @@
 
 #endif
-#endif
 
 #endif
Index: kernel/arch/sparc64/include/mm/sun4v/frame.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4v/frame.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/sparc64/include/mm/sun4v/frame.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,5 +42,4 @@
 #define FRAME_SIZE		(1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -52,5 +51,4 @@
 
 #endif
-#endif
 
 #endif
Index: kernel/arch/sparc64/include/mm/sun4v/page.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4v/page.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/sparc64/include/mm/sun4v/page.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -46,6 +46,4 @@
 #define MMU_PAGES_PER_PAGE	(1 << (PAGE_WIDTH - MMU_PAGE_WIDTH))
 
-#ifdef KERNEL
-
 #ifndef __ASM__
 
@@ -69,6 +67,4 @@
 #endif /* !def __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/sparc64/include/sun4v/regdef.h
===================================================================
--- kernel/arch/sparc64/include/sun4v/regdef.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/sparc64/include/sun4v/regdef.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -28,5 +28,5 @@
  */
 
-/** @addtogroup sparc64	
+/** @addtogroup sparc64
  * @{
  */
@@ -37,17 +37,8 @@
 #define KERN_sparc64_sun4v_REGDEF_H_
 
-#define PSTATE_IE_BIT	(1 << 1)
-#define PSTATE_PRIV_BIT	(1 << 2)
-#define PSTATE_PEF_BIT	(1 << 4)
+#define TSTATE_CWP_MASK  0x1f
 
-#define TSTATE_PSTATE_SHIFT	8
-#define TSTATE_PRIV_BIT		(PSTATE_PRIV_BIT << TSTATE_PSTATE_SHIFT)
-#define TSTATE_CWP_MASK		0x1f
-#define TSTATE_IE_BIT		(PSTATE_IE_BIT << TSTATE_PSTATE_SHIFT)
-
-#define WSTATE_NORMAL(n)	(n)
-#define WSTATE_OTHER(n)		((n) << 3)
-
-#define TSTATE_PEF_BIT		(PSTATE_PEF_BIT << TSTATE_PSTATE_SHIFT)
+#define WSTATE_NORMAL(n)  (n)
+#define WSTATE_OTHER(n)   ((n) << 3)
 
 #endif
Index: kernel/arch/sparc64/src/drivers/scr.c
===================================================================
--- kernel/arch/sparc64/src/drivers/scr.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/sparc64/src/drivers/scr.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,5 @@
 #include <genarch/ofw/upa.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <console/chardev.h>
 #include <console/console.h>
Index: kernel/arch/sparc64/src/smp/sun4u/smp.c
===================================================================
--- kernel/arch/sparc64/src/smp/sun4u/smp.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/sparc64/src/smp/sun4u/smp.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,5 +42,4 @@
 #include <macros.h>
 #include <typedefs.h>
-#include <synch/synch.h>
 #include <synch/waitq.h>
 #include <print.h>
Index: kernel/arch/sparc64/src/smp/sun4v/smp.c
===================================================================
--- kernel/arch/sparc64/src/smp/sun4v/smp.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/sparc64/src/smp/sun4v/smp.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -45,5 +45,4 @@
 #include <func.h>
 #include <typedefs.h>
-#include <synch/synch.h>
 #include <synch/waitq.h>
 #include <print.h>
Index: kernel/arch/sparc64/src/sun4v/start.S
===================================================================
--- kernel/arch/sparc64/src/sun4v/start.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/arch/sparc64/src/sun4v/start.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -30,4 +30,5 @@
 #include <arch/arch.h>
 #include <arch/stack.h>
+#include <arch/regdef.h>
 #include <arch/context_offset.h>
 #include <arch/sun4v/regdef.h>
Index: kernel/genarch/include/fb/fb.h
===================================================================
--- kernel/genarch/include/fb/fb.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/genarch/include/fb/fb.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,6 +37,6 @@
 
 #include <typedefs.h>
+#include <abi/fb/visuals.h>
 #include <console/chardev.h>
-#include <genarch/fb/visuals.h>
 
 /**
Index: rnel/genarch/include/fb/visuals.h
===================================================================
--- kernel/genarch/include/fb/visuals.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,56 +1,0 @@
-/*
- * Copyright (c) 2006 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 KERN_VISUALS_H_
-#define KERN_VISUALS_H_
-
-typedef enum {
-	VISUAL_UNKNOWN = 0,
-	VISUAL_INDIRECT_8,
-	VISUAL_RGB_5_5_5_LE,
-	VISUAL_RGB_5_5_5_BE,
-	VISUAL_RGB_5_6_5_LE,
-	VISUAL_RGB_5_6_5_BE,
-	VISUAL_BGR_8_8_8,
-	VISUAL_BGR_0_8_8_8,
-	VISUAL_BGR_8_8_8_0,
-	VISUAL_RGB_8_8_8,
-	VISUAL_RGB_0_8_8_8,
-	VISUAL_RGB_8_8_8_0
-} visual_t;
-
-#endif
-
-/** @}
- */
Index: kernel/genarch/src/fb/fb.c
===================================================================
--- kernel/genarch/src/fb/fb.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/genarch/src/fb/fb.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,5 +36,4 @@
 #include <genarch/fb/font-8x16.h>
 #include <genarch/fb/logo-196x66.h>
-#include <genarch/fb/visuals.h>
 #include <genarch/fb/fb.h>
 #include <console/chardev.h>
Index: kernel/generic/include/console/console.h
===================================================================
--- kernel/generic/include/console/console.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/console/console.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -63,5 +63,5 @@
 
 extern void klog_init(void);
-extern void klog_update(void);
+extern void klog_update(void *);
 
 extern wchar_t getc(indev_t *indev);
Index: kernel/generic/include/ddi/ddi.h
===================================================================
--- kernel/generic/include/ddi/ddi.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/ddi/ddi.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,6 +36,6 @@
 #define KERN_DDI_H_
 
-#include <ddi/ddi_arg.h>
 #include <typedefs.h>
+#include <abi/ddi/arg.h>
 #include <proc/task.h>
 #include <adt/list.h>
Index: rnel/generic/include/ddi/ddi_arg.h
===================================================================
--- kernel/generic/include/ddi/ddi_arg.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,68 +1,0 @@
-/*
- * Copyright (c) 2006 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 genericddi
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_DDI_ARG_H_
-#define KERN_DDI_ARG_H_
-
-#ifdef KERNEL
-
-#include <typedefs.h>
-
-#endif /* KERNEL */
-
-/** Structure encapsulating arguments for SYS_PHYSMEM_MAP syscall. */
-typedef struct {
-	/** ID of the destination task. */
-	uint64_t task_id;
-	/** Physical address of starting frame. */
-	void *phys_base;
-	/** Virtual address of starting page. */
-	void *virt_base;
-	/** Number of pages to map. */
-	size_t pages;
-	/** Address space area flags for the mapping. */
-	unsigned int flags;
-} ddi_memarg_t;
-
-/** Structure encapsulating arguments for SYS_ENABLE_IOSPACE syscall. */
-typedef struct {
-	uint64_t task_id;  /**< ID of the destination task. */
-	void *ioaddr;      /**< Starting I/O space address. */
-	size_t size;       /**< Number of bytes. */
-} ddi_ioarg_t;
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/ddi/irq.h
===================================================================
--- kernel/generic/include/ddi/irq.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/ddi/irq.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -33,10 +33,9 @@
  */
 
-#ifndef KERN_IRQ_H_
-#define KERN_IRQ_H_
-
-#ifdef KERNEL
+#ifndef KERN_DDI_IRQ_H_
+#define KERN_DDI_IRQ_H_
 
 #include <typedefs.h>
+#include <abi/ddi/irq.h>
 #include <adt/list.h>
 #include <adt/hash_table.h>
@@ -44,94 +43,4 @@
 #include <proc/task.h>
 #include <ipc/ipc.h>
-
-#endif /* KERNEL */
-
-typedef enum {
-	/** Read 1 byte from the I/O space. */
-	CMD_PIO_READ_8 = 1,
-	/** Read 2 bytes from the I/O space. */
-	CMD_PIO_READ_16,
-	/** Read 4 bytes from the I/O space. */
-	CMD_PIO_READ_32,
-	
-	/** Write 1 byte to the I/O space. */
-	CMD_PIO_WRITE_8,
-	/** Write 2 bytes to the I/O space. */
-	CMD_PIO_WRITE_16,
-	/** Write 4 bytes to the I/O space. */
-	CMD_PIO_WRITE_32,
-	
-	/**
-	 * Write 1 byte from the source argument
-	 * to the I/O space.
-	 */
-	CMD_PIO_WRITE_A_8,
-	/**
-	 * Write 2 bytes from the source argument
-	 * to the I/O space.
-	 */
-	CMD_PIO_WRITE_A_16,
-	/**
-	 * Write 4 bytes from the source argument
-	 * to the I/O space.
-	 */
-	CMD_PIO_WRITE_A_32,
-
-	/** Read 1 byte from the memory space. */
-	CMD_MEM_READ_8,
-	/** Read 2 bytes from the memory space. */
-	CMD_MEM_READ_16,
-	/** Read 4 bytes from the memory space. */
-	CMD_MEM_READ_32,
-
-	/** Write 1 byte to the memory space. */
-	CMD_MEM_WRITE_8,
-	/** Write 2 bytes to the memory space. */
-	CMD_MEM_WRITE_16,
-	/** Write 4 bytes to the memory space. */
-	CMD_MEM_WRITE_32,
-
-	/** Write 1 byte from the source argument to the memory space. */
-	CMD_MEM_WRITE_A_8,
-	/** Write 2 bytes from the source argument to the memory space. */
-	CMD_MEM_WRITE_A_16,
-	/** Write 4 bytes from the source argument to the memory space. */
-	CMD_MEM_WRITE_A_32,
-
-	/**
-	 * Perform a bit masking on the source argument
-	 * and store the result into the destination argument.
-	 */
-	CMD_BTEST,
-	
-	/**
-	 * Predicate the execution of the following
-	 * N commands by the boolean value of the source
-	 * argument.
-	 */
-	CMD_PREDICATE,
-	
-	/** Accept the interrupt. */
-	CMD_ACCEPT,
-	
-	/** Decline the interrupt. */
-	CMD_DECLINE,
-	CMD_LAST
-} irq_cmd_type;
-
-typedef struct {
-	irq_cmd_type cmd;
-	void *addr;
-	uint32_t value;
-	uintptr_t srcarg;
-	uintptr_t dstarg;
-} irq_cmd_t;
-
-typedef struct {
-	size_t cmdcount;
-	irq_cmd_t *cmds;
-} irq_code_t;
-
-#ifdef KERNEL
 
 typedef enum {
@@ -146,4 +55,5 @@
 
 struct irq;
+
 typedef void (* irq_handler_t)(struct irq *);
 
@@ -224,5 +134,5 @@
 	/** Notification configuration structure. */
 	ipc_notif_cfg_t notif_cfg; 
-
+	
 	as_t *driver_as;
 } irq_t;
@@ -238,6 +148,4 @@
 extern irq_t *irq_dispatch_and_lock(inr_t);
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/generic/include/errno.h
===================================================================
--- kernel/generic/include/errno.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/errno.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup generic	
+/** @addtogroup generic
  * @{
  */
@@ -36,29 +36,5 @@
 #define KERN_ERRNO_H_
 
-/* 1-255 are kernel error codes, 256-512 are user error codes */
-
-#define EOK		0	/* No error */
-#define ENOENT		-1	/* No such entry */
-#define ENOMEM		-2	/* Not enough memory */
-#define ELIMIT		-3	/* Limit exceeded */
-#define EREFUSED	-4	/* Connection refused */
-#define EFORWARD	-5	/* Forward error */
-#define EPERM		-6	/* Permission denied */
-#define EHANGUP		-7	/* Answerbox closed connection, call
-				 * sys_ipc_hangup() to close the connection.
-				 * Used by answerbox to close the connection.
-				 */
-#define EPARTY		-8	/* The other party encountered an error when
-				 * receiving the call.
-				 */
-#define EEXISTS		-9	/* Entry already exists */
-#define EBADMEM		-10	/* Bad memory pointer */
-#define ENOTSUP		-11	/* Not supported */
-#define EADDRNOTAVAIL	-12	/* Address not available. */
-#define ETIMEOUT        -13     /* Timeout expired */
-#define EINVAL          -14     /* Invalid value */
-#define EBUSY           -15     /* Resource is busy */
-#define EOVERFLOW	-16	/* The result does not fit its size. */
-#define EINTR		-17	/* Operation was interrupted. */
+#include <abi/errno.h>
 
 #endif
Index: kernel/generic/include/ipc/event.h
===================================================================
--- kernel/generic/include/ipc/event.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/ipc/event.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,10 +36,12 @@
 #define KERN_EVENT_H_
 
-#include <ipc/event_types.h>
+#include <abi/ipc/event.h>
 #include <typedefs.h>
 #include <synch/spinlock.h>
 #include <ipc/ipc.h>
 
-typedef void (*event_callback_t)(void);
+struct task;
+
+typedef void (*event_callback_t)(void *);
 
 /** Event notification structure. */
@@ -61,6 +63,9 @@
 
 extern void event_init(void);
+extern void event_task_init(struct task *);
 extern void event_cleanup_answerbox(answerbox_t *);
 extern void event_set_unmask_callback(event_type_t, event_callback_t);
+extern void event_task_set_unmask_callback(struct task *, event_task_type_t,
+    event_callback_t);
 
 #define event_notify_0(e, m) \
@@ -77,6 +82,21 @@
 	event_notify((e), (m), (a1), (a2), (a3), (a4), (a5))
 
+#define event_task_notify_0(t, e, m) \
+	event_task_notify((t), (e), (m), 0, 0, 0, 0, 0)
+#define event_task_notify_1(t, e, m, a1) \
+	event_task_notify((t), (e), (m), (a1), 0, 0, 0, 0)
+#define event_task_notify_2(t, e, m, a1, a2) \
+	event_task_notify((t), (e), (m), (a1), (a2), 0, 0, 0)
+#define event_task_notify_3(t, e, m, a1, a2, a3) \
+	event_task_notify((t), (e), (m), (a1), (a2), (a3), 0, 0)
+#define event_task_notify_4(t, e, m, a1, a2, a3, a4) \
+	event_task_notify((t), (e), (m), (a1), (a2), (a3), (a4), 0)
+#define event_task_notify_5(t, e, m, a1, a2, a3, a4, a5) \
+	event_task_notify((t), (e), (m), (a1), (a2), (a3), (a4), (a5))
+
 extern int event_notify(event_type_t, bool, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t);
+extern int event_task_notify(struct task *, event_task_type_t, bool, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t);
 
 extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);
Index: rnel/generic/include/ipc/event_types.h
===================================================================
--- kernel/generic/include/ipc/event_types.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,51 +1,0 @@
-/*
- * Copyright (c) 2009 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup generic
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_EVENT_TYPES_H_
-#define KERN_EVENT_TYPES_H_
-
-typedef enum event_type {
-	/** New data available in kernel log */
-	EVENT_KLOG = 0,
-	/** Returning from kernel console to uspace */
-	EVENT_KCONSOLE,
-	/** A task/thread has faulted and will be terminated */
-	EVENT_FAULT,
-	EVENT_END
-} event_type_t;
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/ipc/ipc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,97 +36,11 @@
 #define KERN_IPC_H_
 
-/** Length of data being transfered with IPC call
- *
- * The uspace may not be able to utilize full length
- *
- */
-#define IPC_CALL_LEN  6
-
-/** Maximum active async calls per phone */
-#define IPC_MAX_ASYNC_CALLS  4
-
-/* Flags for calls */
-
-/** This is answer to a call */
-#define IPC_CALL_ANSWERED  (1 << 0)
-
-/** Answer will not be passed to userspace, will be discarded */
-#define IPC_CALL_DISCARD_ANSWER  (1 << 1)
-
-/** Call was forwarded */
-#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)
-
-
-/** Bits used in call hashes.
- *
- * The addresses are aligned at least to 4 that is why we can use the 2 least
- * significant bits of the call address.
- *
- */
-
-/** Type of this call is 'answer' */
-#define IPC_CALLID_ANSWERED  1
-
-/** Type of this call is 'notification' */
-#define IPC_CALLID_NOTIFICATION  2
-
-/* Return values from sys_ipc_call_async(). */
-#define IPC_CALLRET_FATAL      -1
-#define IPC_CALLRET_TEMPORARY  -2
-
-
-/* Macros for manipulating calling data */
-#define IPC_SET_RETVAL(data, retval)  ((data).args[0] = (retval))
-#define IPC_SET_IMETHOD(data, val)    ((data).args[0] = (val))
-#define IPC_SET_ARG1(data, val)       ((data).args[1] = (val))
-#define IPC_SET_ARG2(data, val)       ((data).args[2] = (val))
-#define IPC_SET_ARG3(data, val)       ((data).args[3] = (val))
-#define IPC_SET_ARG4(data, val)       ((data).args[4] = (val))
-#define IPC_SET_ARG5(data, val)       ((data).args[5] = (val))
-
-#define IPC_GET_IMETHOD(data)  ((data).args[0])
-#define IPC_GET_RETVAL(data)   ((data).args[0])
-
-#define IPC_GET_ARG1(data)  ((data).args[1])
-#define IPC_GET_ARG2(data)  ((data).args[2])
-#define IPC_GET_ARG3(data)  ((data).args[3])
-#define IPC_GET_ARG4(data)  ((data).args[4])
-#define IPC_GET_ARG5(data)  ((data).args[5])
-
-/* Forwarding flags. */
-#define IPC_FF_NONE  0
-
-/**
- * The call will be routed as though it was initially sent via the phone used to
- * forward it. This feature is intended to support the situation in which the
- * forwarded call needs to be handled by the same connection fibril as any other
- * calls that were initially sent by the forwarder to the same destination. This
- * flag has no imapct on routing replies.
- *
- */
-#define IPC_FF_ROUTE_FROM_ME  (1 << 0)
-
-/* Data transfer flags. */
-#define IPC_XF_NONE  0
-
-/** Restrict the transfer size if necessary. */
-#define IPC_XF_RESTRICT  (1 << 0)
-
-/** User-defined IPC methods */
-#define IPC_FIRST_USER_METHOD  1024
-
-#ifdef KERNEL
-
-#define IPC_MAX_PHONES  32
-
+#include <abi/ipc/ipc.h>
 #include <synch/spinlock.h>
 #include <synch/mutex.h>
 #include <synch/waitq.h>
+#include <typedefs.h>
+
+#define IPC_MAX_PHONES  32
 
 struct answerbox;
@@ -184,6 +98,9 @@
 typedef struct {
 	sysarg_t args[IPC_CALL_LEN];
-	/** Task which made or forwarded the call with IPC_FF_ROUTE_FROM_ME. */
-	struct task *task;
+	/**
+	 * Task which made or forwarded the call with IPC_FF_ROUTE_FROM_ME,
+	 * or the task which answered the call.
+	 */
+	task_id_t task_id;
 	/** Phone which made or last masqueraded this call. */
 	phone_t *phone;
@@ -247,6 +164,4 @@
 extern void ipc_print_task(task_id_t);
 
-#endif /* KERNEL */
-
 #endif
 
Index: rnel/generic/include/ipc/ipc_methods.h
===================================================================
--- kernel/generic/include/ipc/ipc_methods.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,186 +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 genericipc
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_IPC_METHODS_H_
-#define KERN_IPC_METHODS_H_
-
-/* Well known phone descriptors */
-#define PHONE_NS  0
-
-/** Kernel IPC interfaces
- *
- */
-#define IPC_IF_KERNEL  0
-
-/** System-specific IPC methods
- *
- * These methods have special behaviour. These methods also
- * have the implicit kernel interface zero (0).
- *
- */
-
-/** This message is sent to answerbox when the phone is hung up
- *
- * The numerical value zero (0) of this method is important,
- * so as the value can be easily tested in conditions.
- *
- */
-#define IPC_M_PHONE_HUNGUP  0
-
-/** Clone connection.
- *
- * The calling task clones one of its phones for the callee.
- *
- * - ARG1 - The caller sets ARG1 to the phone of the cloned connection.
- *        - The callee gets the new phone from ARG1.
- *
- * - on answer, the callee acknowledges the new connection by sending EOK back
- *   or the kernel closes it
- *
- */
-#define IPC_M_CONNECTION_CLONE  1
-
-/** Protocol for CONNECT - ME
- *
- * Through this call, the recipient learns about the new cloned connection.
- *
- * - ARG5 - the kernel sets ARG5 to contain the hash of the used phone
- * - on answer, the callee acknowledges the new connection by sending EOK back
- *   or the kernel closes it
- *
- */
-#define IPC_M_CONNECT_ME  2
-
-/** Protocol for CONNECT - TO - ME
- *
- * Calling process asks the callee to create a callback connection,
- * so that it can start initiating new messages.
- *
- * The protocol for negotiating is:
- * - sys_connect_to_me - sends a message IPC_M_CONNECT_TO_ME
- * - recipient         - upon receipt tries to allocate new phone
- *                       - if it fails, responds with ELIMIT
- *                     - passes call to userspace. If userspace
- *                       responds with error, phone is deallocated and
- *                       error is sent back to caller. Otherwise 
- *                       the call is accepted and the response is sent back.
- *                     - the hash of the client task is passed to userspace
- *                       (on the receiving side) as ARG4 of the call.
- *                     - the hash of the allocated phone is passed to userspace
- *                       (on the receiving side) as ARG5 of the call.
- *
- */
-#define IPC_M_CONNECT_TO_ME  3
-
-/** Protocol for CONNECT - ME - TO
- *
- * Calling process asks the callee to create for him a new connection.
- * E.g. the caller wants a name server to connect him to print server.
- *
- * The protocol for negotiating is:
- * - sys_connect_me_to - send a synchronous message to name server
- *                       indicating that it wants to be connected to some
- *                       service
- *                     - arg1/2/3 are user specified, arg5 contains
- *                       address of the phone that should be connected
- *                       (TODO: it leaks to userspace)
- *  - recipient        -  if ipc_answer == 0, then accept connection
- *                     -  otherwise connection refused
- *                     -  recepient may forward message.
- *
- */
-#define IPC_M_CONNECT_ME_TO  4
-
-/** Send as_area over IPC.
- * - ARG1 - source as_area base address
- * - ARG2 - size of source as_area (filled automatically by kernel)
- * - ARG3 - flags of the as_area being sent
- *
- * on answer, the recipient must set:
- * - ARG1 - dst as_area base adress
- *
- */
-#define IPC_M_SHARE_OUT  5
-
-/** Receive as_area over IPC.
- * - ARG1 - destination as_area base address
- * - ARG2 - destination as_area size
- * - ARG3 - user defined argument
- *
- * on answer, the recipient must set:
- *
- * - ARG1 - source as_area base address
- * - ARG2 - flags that will be used for sharing
- *
- */
-#define IPC_M_SHARE_IN  6
-
-/** Send data to another address space over IPC.
- * - ARG1 - source address space virtual address
- * - ARG2 - size of data to be copied, may be overriden by the recipient
- *
- * on answer, the recipient must set:
- *
- * - ARG1 - final destination address space virtual address
- * - ARG2 - final size of data to be copied
- *
- */
-#define IPC_M_DATA_WRITE  7
-
-/** Receive data from another address space over IPC.
- * - ARG1 - destination virtual address in the source address space
- * - ARG2 - size of data to be received, may be cropped by the recipient 
- *
- * on answer, the recipient must set:
- *
- * - ARG1 - source virtual address in the destination address space
- * - ARG2 - final size of data to be copied
- *
- */
-#define IPC_M_DATA_READ  8
-
-/** Debug the recipient.
- * - ARG1 - specifies the debug method (from udebug_method_t)
- * - other arguments are specific to the debug method
- *
- */
-#define IPC_M_DEBUG  9
-
-/** Last system IPC method */
-#define IPC_M_LAST_SYSTEM  511
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/lib/elf.h
===================================================================
--- kernel/generic/include/lib/elf.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/lib/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,315 +36,7 @@
 #define KERN_ELF_H_
 
+#include <typedefs.h>
+#include <abi/elf.h>
 #include <arch/elf.h>
-#include <typedefs.h>
-
-/**
- * current ELF version
- */
-#define EV_CURRENT  1
-
-/**
- * ELF types
- */
-#define ET_NONE    0       /* No type */
-#define ET_REL     1       /* Relocatable file */
-#define ET_EXEC    2       /* Executable */
-#define ET_DYN     3       /* Shared object */
-#define ET_CORE    4       /* Core */
-#define ET_LOPROC  0xff00  /* Processor specific */
-#define ET_HIPROC  0xffff  /* Processor specific */
-
-/**
- * ELF machine types
- */
-#define EM_NO           0   /* No machine */
-#define EM_SPARC        2   /* SPARC */
-#define EM_386          3   /* i386 */
-#define EM_MIPS         8   /* MIPS RS3000 */
-#define EM_MIPS_RS3_LE  10  /* MIPS RS3000 LE */
-#define EM_PPC          20  /* PPC32 */
-#define EM_PPC64        21  /* PPC64 */
-#define EM_ARM          40  /* ARM */
-#define EM_SPARCV9      43  /* SPARC64 */
-#define EM_IA_64        50  /* IA-64 */
-#define EM_X86_64       62  /* AMD64/EMT64 */
-
-/**
- * ELF identification indexes
- */
-#define EI_MAG0        0
-#define EI_MAG1        1
-#define EI_MAG2        2
-#define EI_MAG3        3
-#define EI_CLASS       4   /* File class */
-#define EI_DATA        5   /* Data encoding */
-#define EI_VERSION     6   /* File version */
-#define EI_OSABI       7
-#define EI_ABIVERSION  8
-#define EI_PAD         9   /* Start of padding bytes */
-#define EI_NIDENT      16  /* ELF identification table size */
-
-/**
- * ELF magic number
- */
-#define ELFMAG0  0x7f
-#define ELFMAG1  'E'
-#define ELFMAG2  'L'
-#define ELFMAG3  'F'
-
-/**
- * ELF file classes
- */
-#define ELFCLASSNONE  0
-#define ELFCLASS32    1
-#define ELFCLASS64    2
-
-/**
- * ELF data encoding types
- */
-#define ELFDATANONE  0
-#define ELFDATA2LSB  1  /* Least significant byte first (little endian) */
-#define ELFDATA2MSB  2  /* Most signigicant byte first (big endian) */
-
-/**
- * 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
-
-/**
- * ELF section types
- */
-#define SHT_NULL      0
-#define SHT_PROGBITS  1
-#define SHT_SYMTAB    2
-#define SHT_STRTAB    3
-#define SHT_RELA      4
-#define SHT_HASH      5
-#define SHT_DYNAMIC   6
-#define SHT_NOTE      7
-#define SHT_NOBITS    8
-#define SHT_REL       9
-#define SHT_SHLIB     10
-#define SHT_DYNSYM    11
-#define SHT_LOOS      0x60000000
-#define SHT_HIOS      0x6fffffff
-#define SHT_LOPROC    0x70000000
-#define SHT_HIPROC    0x7fffffff
-#define SHT_LOUSER    0x80000000
-#define SHT_HIUSER    0xffffffff
-
-/**
- * ELF section flags
- */
-#define SHF_WRITE      0x1
-#define SHF_ALLOC      0x2
-#define SHF_EXECINSTR  0x4
-#define SHF_TLS        0x400
-#define SHF_MASKPROC   0xf0000000
-
-/**
- * Symbol binding
- */
-#define STB_LOCAL   0
-#define STB_GLOBAL  1
-#define STB_WEAK    2
-#define STB_LOPROC  13
-#define STB_HIPROC  15
-
-/**
- * Symbol types
- */
-#define STT_NOTYPE   0
-#define STT_OBJECT   1
-#define STT_FUNC     2
-#define STT_SECTION  3
-#define STT_FILE     4
-#define STT_LOPROC   13
-#define STT_HIPROC   15
-
-/**
- * Program segment types
- */
-#define PT_NULL     0
-#define PT_LOAD     1
-#define PT_DYNAMIC  2
-#define PT_INTERP   3
-#define PT_NOTE     4
-#define PT_SHLIB    5
-#define PT_PHDR     6
-#define PT_LOPROC   0x70000000
-#define PT_HIPROC   0x7fffffff
-
-/**
- * Program segment attributes.
- */
-#define PF_X  1
-#define PF_W  2
-#define PF_R  4
-
-/**
- * ELF data types
- *
- * These types are found to be identical in both 32-bit and 64-bit
- * ELF object file specifications. They are the only types used
- * in ELF header.
- *
- */
-typedef uint64_t elf_xword;
-typedef int64_t elf_sxword;
-typedef uint32_t elf_word;
-typedef int32_t elf_sword;
-typedef uint16_t elf_half;
-
-/**
- * 32-bit ELF data types.
- *
- * These types are specific for 32-bit format.
- *
- */
-typedef uint32_t elf32_addr;
-typedef uint32_t elf32_off;
-
-/**
- * 64-bit ELF data types.
- *
- * These types are specific for 64-bit format.
- *
- */
-typedef uint64_t elf64_addr;
-typedef uint64_t elf64_off;
-
-/** ELF header */
-struct elf32_header {
-	uint8_t e_ident[EI_NIDENT];
-	elf_half e_type;
-	elf_half e_machine;
-	elf_word e_version;
-	elf32_addr e_entry;
-	elf32_off e_phoff;
-	elf32_off e_shoff;
-	elf_word e_flags;
-	elf_half e_ehsize;
-	elf_half e_phentsize;
-	elf_half e_phnum;
-	elf_half e_shentsize;
-	elf_half e_shnum;
-	elf_half e_shstrndx;
-};
-
-struct elf64_header {
-	uint8_t e_ident[EI_NIDENT];
-	elf_half e_type;
-	elf_half e_machine;
-	elf_word e_version;
-	elf64_addr e_entry;
-	elf64_off e_phoff;
-	elf64_off e_shoff;
-	elf_word e_flags;
-	elf_half e_ehsize;
-	elf_half e_phentsize;
-	elf_half e_phnum;
-	elf_half e_shentsize;
-	elf_half e_shnum;
-	elf_half e_shstrndx;
-};
-
-/**
- * ELF segment header.
- * Segments headers are also known as program headers.
- */
-struct elf32_segment_header {
-	elf_word p_type;
-	elf32_off p_offset;
-	elf32_addr p_vaddr;
-	elf32_addr p_paddr;
-	elf_word p_filesz;
-	elf_word p_memsz;
-	elf_word p_flags;
-	elf_word p_align;
-};
-
-struct elf64_segment_header {
-	elf_word p_type;
-	elf_word p_flags;
-	elf64_off p_offset;
-	elf64_addr p_vaddr;
-	elf64_addr p_paddr;
-	elf_xword p_filesz;
-	elf_xword p_memsz;
-	elf_xword p_align;
-};
-
-/**
- * ELF section header
- */
-struct elf32_section_header {
-	elf_word sh_name;
-	elf_word sh_type;
-	elf_word sh_flags;
-	elf32_addr sh_addr;
-	elf32_off sh_offset;
-	elf_word sh_size;
-	elf_word sh_link;
-	elf_word sh_info;
-	elf_word sh_addralign;
-	elf_word sh_entsize;
-};
-
-struct elf64_section_header {
-	elf_word sh_name;
-	elf_word sh_type;
-	elf_xword sh_flags;
-	elf64_addr sh_addr;
-	elf64_off sh_offset;
-	elf_xword sh_size;
-	elf_word sh_link;
-	elf_word sh_info;
-	elf_xword sh_addralign;
-	elf_xword sh_entsize;
-};
-
-/**
- * ELF symbol table entry
- */
-struct elf32_symbol {
-	elf_word st_name;
-	elf32_addr st_value;
-	elf_word st_size;
-	uint8_t st_info;
-	uint8_t st_other;
-	elf_half st_shndx;
-};
-
-struct elf64_symbol {
-	elf_word st_name;
-	uint8_t st_info;
-	uint8_t st_other;
-	elf_half st_shndx;
-	elf64_addr st_value;
-	elf_xword st_size;
-};
-
-#ifdef __32_BITS__
-typedef struct elf32_header elf_header_t;
-typedef struct elf32_segment_header elf_segment_header_t;
-typedef struct elf32_section_header elf_section_header_t;
-typedef struct elf32_symbol elf_symbol_t;
-#endif
-
-#ifdef __64_BITS__
-typedef struct elf64_header elf_header_t;
-typedef struct elf64_segment_header elf_segment_header_t;
-typedef struct elf64_section_header elf_section_header_t;
-typedef struct elf64_symbol elf_symbol_t;
-#endif
-
-extern const char *elf_error(unsigned int rc);
 
 /** Interpreter string used to recognize the program loader */
Index: kernel/generic/include/lib/elf_load.h
===================================================================
--- kernel/generic/include/lib/elf_load.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ kernel/generic/include/lib/elf_load.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2006 Sergey Bondari
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING 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_ELF_LOAD_H_
+#define KERN_ELF_LOAD_H_
+
+#include <arch/elf.h>
+#include <typedefs.h>
+
+/**
+ * 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
+
+/**
+ * This flags is passed when running the loader, otherwise elf_load()
+ * would return with a EE_LOADER error code.
+ *
+ */
+#define ELD_F_NONE    0
+#define ELD_F_LOADER  1
+
+extern unsigned int elf_load(elf_header_t *, as_t *, unsigned int);
+extern const char *elf_error(unsigned int rc);
+
+#endif
+
+/** @}
+ */
Index: kernel/generic/include/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/mm/as.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,30 +36,6 @@
 #define KERN_AS_H_
 
-#ifdef KERNEL
-	#include <typedefs.h>
-#else
-	#include <sys/types.h>
-#endif
-
-/** Address space area flags. */
-#define AS_AREA_READ       1
-#define AS_AREA_WRITE      2
-#define AS_AREA_EXEC       4
-#define AS_AREA_CACHEABLE  8
-
-/** Address space area info exported to userspace. */
-typedef struct {
-	/** Starting address */
-	uintptr_t start_addr;
-	
-	/** Area size */
-	size_t size;
-	
-	/** Area flags */
-	unsigned int flags;
-} as_area_info_t;
-
-#ifdef KERNEL
-
+#include <typedefs.h>
+#include <abi/mm/as.h>
 #include <arch/mm/page.h>
 #include <arch/mm/as.h>
@@ -307,14 +283,4 @@
 extern mem_backend_t phys_backend;
 
-/**
- * This flags is passed when running the loader, otherwise elf_load()
- * would return with a EE_LOADER error code.
- *
- */
-#define ELD_F_NONE    0
-#define ELD_F_LOADER  1
-
-extern unsigned int elf_load(elf_header_t *, as_t *, unsigned int);
-
 /* Address space area related syscalls. */
 extern sysarg_t sys_as_area_create(uintptr_t, size_t, unsigned int);
@@ -328,6 +294,4 @@
 extern void as_print(as_t *);
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/proc/task.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,4 +38,6 @@
 #include <cpu.h>
 #include <ipc/ipc.h>
+#include <ipc/event.h>
+#include <ipc/kbox.h>
 #include <synch/spinlock.h>
 #include <synch/mutex.h>
@@ -53,7 +55,6 @@
 #include <proc/scheduler.h>
 #include <udebug/udebug.h>
-#include <ipc/kbox.h>
 #include <mm/as.h>
-#include <sysinfo/abi.h>
+#include <abi/sysinfo.h>
 
 struct thread;
@@ -93,6 +94,6 @@
 	phone_t phones[IPC_MAX_PHONES];
 	stats_ipc_t ipc_info;   /**< IPC statistics */
-	/** List of synchronous answerboxes. */
-	list_t sync_boxes;
+	list_t sync_boxes;      /**< List of synchronous answerboxes. */
+	event_t events[EVENT_TASK_END - EVENT_END];
 	
 #ifdef CONFIG_UDEBUG
Index: kernel/generic/include/proc/thread.h
===================================================================
--- kernel/generic/include/proc/thread.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/proc/thread.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -45,7 +45,7 @@
 #include <arch/cpu.h>
 #include <mm/tlb.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <udebug/udebug.h>
-#include <sysinfo/abi.h>
+#include <abi/sysinfo.h>
 
 #define THREAD_NAME_BUFLEN  20
Index: rnel/generic/include/proc/uarg.h
===================================================================
--- kernel/generic/include/proc/uarg.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,52 +1,0 @@
-/*
- * Copyright (c) 2006 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 genericproc
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_UARG_H_
-#define KERN_UARG_H_
-
-/** Structure passed to uinit kernel thread as argument. */
-typedef struct uspace_arg {
-	void *uspace_entry;
-	void *uspace_stack;
-	
-	void (* uspace_thread_function)();
-	void *uspace_thread_arg;
-	
-	struct uspace_arg *uspace_uarg;
-} uspace_arg_t;
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/synch/condvar.h
===================================================================
--- kernel/generic/include/synch/condvar.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/synch/condvar.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,5 @@
 #include <synch/waitq.h>
 #include <synch/mutex.h>
-#include <synch/synch.h>
+#include <abi/synch.h>
 
 typedef struct {
Index: kernel/generic/include/synch/mutex.h
===================================================================
--- kernel/generic/include/synch/mutex.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/synch/mutex.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,5 @@
 #include <typedefs.h>
 #include <synch/semaphore.h>
-#include <synch/synch.h>
+#include <abi/synch.h>
 
 typedef enum {
Index: kernel/generic/include/synch/semaphore.h
===================================================================
--- kernel/generic/include/synch/semaphore.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/synch/semaphore.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,5 @@
 #include <typedefs.h>
 #include <synch/waitq.h>
-#include <synch/synch.h>
+#include <abi/synch.h>
 
 typedef struct {
Index: rnel/generic/include/synch/synch.h
===================================================================
--- kernel/generic/include/synch/synch.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,67 +1,0 @@
-/*
- * Copyright (c) 2001-2004 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 sync
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_SYNCH_H_
-#define KERN_SYNCH_H_
-
-/** Request with no timeout. */
-#define SYNCH_NO_TIMEOUT	0
-
-/** No flags specified. */
-#define SYNCH_FLAGS_NONE		0
-/** Non-blocking operation request. */
-#define SYNCH_FLAGS_NON_BLOCKING	(1 << 0)
-/** Interruptible operation. */
-#define SYNCH_FLAGS_INTERRUPTIBLE	(1 << 1)
-
-/** Could not satisfy the request without going to sleep. */
-#define ESYNCH_WOULD_BLOCK	1
-/** Timeout occurred. */
-#define ESYNCH_TIMEOUT		2
-/** Sleep was interrupted. */
-#define ESYNCH_INTERRUPTED	4
-/** Operation succeeded without sleeping. */
-#define ESYNCH_OK_ATOMIC	8
-/** Operation succeeded and did sleep. */
-#define ESYNCH_OK_BLOCKED	16
-
-#define SYNCH_FAILED(rc) \
-	((rc) & (ESYNCH_WOULD_BLOCK | ESYNCH_TIMEOUT | ESYNCH_INTERRUPTED))
-#define SYNCH_OK(rc) \
-	((rc) & (ESYNCH_OK_ATOMIC | ESYNCH_OK_BLOCKED))
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/synch/waitq.h
===================================================================
--- kernel/generic/include/synch/waitq.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/synch/waitq.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,5 @@
 #include <typedefs.h>
 #include <synch/spinlock.h>
-#include <synch/synch.h>
+#include <abi/synch.h>
 #include <adt/list.h>
 
Index: kernel/generic/include/syscall/syscall.h
===================================================================
--- kernel/generic/include/syscall/syscall.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/syscall/syscall.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,70 +36,6 @@
 #define KERN_SYSCALL_H_
 
-typedef enum {
-	SYS_KLOG = 0,
-	SYS_TLS_SET = 1,  /* Hardcoded for AMD64, IA-32 (fibril.S in uspace) */
-	
-	SYS_THREAD_CREATE,
-	SYS_THREAD_EXIT,
-	SYS_THREAD_GET_ID,
-	SYS_THREAD_USLEEP,
-	SYS_THREAD_UDELAY,
-	
-	SYS_TASK_GET_ID,
-	SYS_TASK_SET_NAME,
-	SYS_TASK_KILL,
-	SYS_TASK_EXIT,
-	SYS_PROGRAM_SPAWN_LOADER,
-	
-	SYS_FUTEX_SLEEP,
-	SYS_FUTEX_WAKEUP,
-	SYS_SMC_COHERENCE,
-	
-	SYS_AS_AREA_CREATE,
-	SYS_AS_AREA_RESIZE,
-	SYS_AS_AREA_CHANGE_FLAGS,
-	SYS_AS_AREA_DESTROY,
-	SYS_AS_GET_UNMAPPED_AREA,
-	
-	SYS_PAGE_FIND_MAPPING,
-	
-	SYS_IPC_CALL_SYNC_FAST,
-	SYS_IPC_CALL_SYNC_SLOW,
-	SYS_IPC_CALL_ASYNC_FAST,
-	SYS_IPC_CALL_ASYNC_SLOW,
-	SYS_IPC_ANSWER_FAST,
-	SYS_IPC_ANSWER_SLOW,
-	SYS_IPC_FORWARD_FAST,
-	SYS_IPC_FORWARD_SLOW,
-	SYS_IPC_WAIT,
-	SYS_IPC_POKE,
-	SYS_IPC_HANGUP,
-	SYS_IPC_CONNECT_KBOX,
-	
-	SYS_EVENT_SUBSCRIBE,
-	SYS_EVENT_UNMASK,
-	
-	SYS_CAP_GRANT,
-	SYS_CAP_REVOKE,
-	
-	SYS_DEVICE_ASSIGN_DEVNO,
-	SYS_PHYSMEM_MAP,
-	SYS_IOSPACE_ENABLE,
-	SYS_REGISTER_IRQ,
-	SYS_UNREGISTER_IRQ,
-	
-	SYS_SYSINFO_GET_TAG,
-	SYS_SYSINFO_GET_VALUE,
-	SYS_SYSINFO_GET_DATA_SIZE,
-	SYS_SYSINFO_GET_DATA,
-	
-	SYS_DEBUG_ACTIVATE_CONSOLE,
-	
-	SYSCALL_END
-} syscall_t;
-
-#ifdef KERNEL
-
 #include <typedefs.h>
+#include <abi/syscall.h>
 
 typedef sysarg_t (*syshandler_t)(sysarg_t, sysarg_t, sysarg_t, sysarg_t,
@@ -113,6 +49,4 @@
 #endif
 
-#endif
-
 /** @}
  */
Index: rnel/generic/include/sysinfo/abi.h
===================================================================
--- kernel/generic/include/sysinfo/abi.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,144 +1,0 @@
-/*
- * Copyright (c) 2010 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
- * Data structures passed between kernel sysinfo and user space.
- */
-
-#ifndef KERN_ABI_H_
-#define KERN_ABI_H_
-
-/** Number of load components */
-#define LOAD_STEPS  3
-
-/** Maximum name sizes */
-#define TASK_NAME_BUFLEN  20
-#define EXC_NAME_BUFLEN   20
-
-/** Thread states */
-typedef enum {
-	/** It is an error, if thread is found in this state. */
-	Invalid,
-	/** State of a thread that is currently executing on some CPU. */
-	Running,
-	/** Thread in this state is waiting for an event. */
-	Sleeping,
-	/** State of threads in a run queue. */
-	Ready,
-	/** Threads are in this state before they are first readied. */
-	Entering,
-	/** After a thread calls thread_exit(), it is put into Exiting state. */
-	Exiting,
-	/** Threads that were not detached but exited are Lingering. */
-	Lingering
-} state_t;
-
-/** Statistics about a single CPU
- *
- */
-typedef struct {
-	unsigned int id;         /**< CPU ID as stored by kernel */
-	bool active;             /**< CPU is activate */
-	uint16_t frequency_mhz;  /**< Frequency in MHz */
-	uint64_t idle_cycles;    /**< Number of idle cycles */
-	uint64_t busy_cycles;    /**< Number of busy cycles */
-} stats_cpu_t;
-
-/** Physical memory statistics
- *
- */
-typedef struct {
-	uint64_t total;    /**< Total physical memory (bytes) */
-	uint64_t unavail;  /**< Unavailable (reserved, firmware) bytes */
-	uint64_t used;     /**< Allocated physical memory (bytes) */
-	uint64_t free;     /**< Free physical memory (bytes) */
-} stats_physmem_t;
-
-/** IPC statistics
- *
- * Associated with a task.
- *
- */
-typedef struct {
-	uint64_t call_sent;           /**< IPC calls sent */
-	uint64_t call_received;       /**< IPC calls received */
-	uint64_t answer_sent;         /**< IPC answers sent */
-	uint64_t answer_received;     /**< IPC answers received */
-	uint64_t irq_notif_received;  /**< IPC IRQ notifications */
-	uint64_t forwarded;           /**< IPC messages forwarded */
-} stats_ipc_t;
-
-/** Statistics about a single task
- *
- */
-typedef struct {
-	task_id_t task_id;            /**< Task ID */
-	char name[TASK_NAME_BUFLEN];  /**< Task name (in kernel) */
-	size_t virtmem;               /**< Size of VAS (bytes) */
-	size_t resmem;                /**< Size of resident (used) memory (bytes) */
-	size_t threads;               /**< Number of threads */
-	uint64_t ucycles;             /**< Number of CPU cycles in user space */
-	uint64_t kcycles;             /**< Number of CPU cycles in kernel */
-	stats_ipc_t ipc_info;         /**< IPC statistics */
-} stats_task_t;
-
-/** Statistics about a single thread
- *
- */
-typedef struct {
-	thread_id_t thread_id;  /**< Thread ID */
-	task_id_t task_id;      /**< Associated task ID */
-	state_t state;          /**< Thread state */
-	int priority;           /**< Thread priority */
-	uint64_t ucycles;       /**< Number of CPU cycles in user space */
-	uint64_t kcycles;       /**< Number of CPU cycles in kernel */
-	bool on_cpu;            /**< Associated with a CPU */
-	unsigned int cpu;       /**< Associated CPU ID (if on_cpu is true) */
-} stats_thread_t;
-
-/** Statistics about a single exception
- *
- */
-typedef struct {
-	unsigned int id;             /**< Exception ID */
-	char desc[EXC_NAME_BUFLEN];  /**< Description */
-	bool hot;                    /**< Active or inactive exception */
-	uint64_t cycles;             /**< Number of CPU cycles in the handler */
-	uint64_t count;              /**< Number of handled exceptions */
-} stats_exc_t;
-
-/** Load fixed-point value */
-typedef uint32_t load_t;
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/udebug/udebug.h
===================================================================
--- kernel/generic/include/udebug/udebug.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/include/udebug/udebug.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,149 +36,5 @@
 #define KERN_UDEBUG_H_
 
-#define UDEBUG_EVMASK(event)  (1 << ((event) - 1))
-
-typedef enum { /* udebug_method_t */
-	
-	/** Start debugging the recipient.
-	 *
-	 * Causes all threads in the receiving task to stop. When they
-	 * are all stoped, an answer with retval 0 is generated.
-	 *
-	 */
-	UDEBUG_M_BEGIN = 1,
-	
-	/** Finish debugging the recipient.
-	 *
-	 * Answers all pending GO and GUARD messages.
-	 *
-	 */
-	UDEBUG_M_END,
-	
-	/** Set which events should be captured. */
-	UDEBUG_M_SET_EVMASK,
-	
-	/** Make sure the debugged task is still there.
-	 *
-	 * This message is answered when the debugged task dies
-	 * or the debugging session ends.
-	 *
-	 */
-	UDEBUG_M_GUARD,
-	
-	/** Run a thread until a debugging event occurs.
-	 *
-	 * This message is answered when the thread stops
-	 * in a debugging event.
-	 *
-	 * - ARG2 - id of the thread to run
-	 *
-	 */
-	UDEBUG_M_GO,
-	
-	/** Stop a thread being debugged.
-	 *
-	 * Creates a special STOP event in the thread, causing
-	 * it to answer a pending GO message (if any).
-	 *
-	 */
-	UDEBUG_M_STOP,
-	
-	/** Read arguments of a syscall.
-	 *
-	 * - ARG2 - thread identification
-	 * - ARG3 - destination address in the caller's address space
-	 *
-	 */
-	UDEBUG_M_ARGS_READ,
-	
-	/** Read thread's userspace register state (istate_t).
-	 *
-	 * - ARG2 - thread identification
-	 * - ARG3 - destination address in the caller's address space
-	 *
-	 * or, on error, retval will be
-	 * - ENOENT - thread does not exist
-	 * - EBUSY - register state not available
-	 */
-	UDEBUG_M_REGS_READ,
-	
-	/** Read the list of the debugged tasks's threads.
-	 *
-	 * - ARG2 - destination address in the caller's address space
-	 * - ARG3 - size of receiving buffer in bytes
-	 *
-	 * The kernel fills the buffer with a series of sysarg_t values
-	 * (thread ids). On answer, the kernel will set:
-	 *
-	 * - ARG2 - number of bytes that were actually copied
-	 * - ARG3 - number of bytes of the complete data
-	 *
-	 */
-	UDEBUG_M_THREAD_READ,
-	
-	/** Read the name of the debugged task.
-	 *
-	 * - ARG2 - destination address in the caller's address space
-	 * - ARG3 - size of receiving buffer in bytes
-	 *
-	 * The kernel fills the buffer with a non-terminated string.
-	 *
-	 * - ARG2 - number of bytes that were actually copied
-	 * - ARG3 - number of bytes of the complete data
-	 *
-	 */
-	UDEBUG_M_NAME_READ,
-	
-	/** Read the list of the debugged task's address space areas.
-	 *
-	 * - ARG2 - destination address in the caller's address space
-	 * - ARG3 - size of receiving buffer in bytes
-	 *
-	 * The kernel fills the buffer with a series of as_area_info_t structures.
-	 * Upon answer, the kernel will set:
-	 *
-	 * - ARG2 - number of bytes that were actually copied
-	 * - ARG3 - number of bytes of the complete data
-	 *
-	 */
-	UDEBUG_M_AREAS_READ,
-	
-	/** Read the debugged tasks's memory.
-	 *
-	 * - ARG2 - destination address in the caller's address space
-	 * - ARG3 - source address in the recipient's address space
-	 * - ARG4 - size of receiving buffer in bytes
-	 *
-	 */
-	UDEBUG_M_MEM_READ
-} udebug_method_t;
-
-typedef enum {
-	UDEBUG_EVENT_FINISHED = 1,  /**< Debuging session has finished */
-	UDEBUG_EVENT_STOP,          /**< Stopped on DEBUG_STOP request */
-	UDEBUG_EVENT_SYSCALL_B,     /**< Before beginning syscall execution */
-	UDEBUG_EVENT_SYSCALL_E,     /**< After finishing syscall execution */
-	UDEBUG_EVENT_THREAD_B,      /**< The task created a new thread */
-	UDEBUG_EVENT_THREAD_E       /**< A thread exited */
-} udebug_event_t;
-
-typedef enum {
-	UDEBUG_EM_FINISHED = UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED),
-	UDEBUG_EM_STOP = UDEBUG_EVMASK(UDEBUG_EVENT_STOP),
-	UDEBUG_EM_SYSCALL_B = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B),
-	UDEBUG_EM_SYSCALL_E = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E),
-	UDEBUG_EM_THREAD_B = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B),
-	UDEBUG_EM_THREAD_E = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E),
-	UDEBUG_EM_ALL =
-	    (UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED) |
-	    UDEBUG_EVMASK(UDEBUG_EVENT_STOP) |
-	    UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B) |
-	    UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E) |
-	    UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B) |
-	    UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E))
-} udebug_evmask_t;
-
-#ifdef KERNEL
-
+#include <abi/udebug.h>
 #include <ipc/ipc.h>
 #include <synch/mutex.h>
@@ -251,6 +107,4 @@
 #endif
 
-#endif
-
 /** @}
  */
Index: kernel/generic/src/console/console.c
===================================================================
--- kernel/generic/src/console/console.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/console/console.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -248,5 +248,5 @@
 }
 
-void klog_update(void)
+void klog_update(void *event)
 {
 	if (!atomic_get(&klog_inited))
@@ -327,5 +327,5 @@
 	/* Force notification on newline */
 	if (ch == '\n')
-		klog_update();
+		klog_update(NULL);
 }
 
@@ -358,5 +358,5 @@
 		free(data);
 	} else
-		klog_update();
+		klog_update(NULL);
 	
 	return size;
Index: kernel/generic/src/ddi/ddi.c
===================================================================
--- kernel/generic/src/ddi/ddi.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/ddi/ddi.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,5 +41,4 @@
 
 #include <ddi/ddi.h>
-#include <ddi/ddi_arg.h>
 #include <proc/task.h>
 #include <security/cap.h>
Index: kernel/generic/src/ipc/event.c
===================================================================
--- kernel/generic/src/ipc/event.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/ipc/event.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,9 +36,9 @@
 
 #include <ipc/event.h>
-#include <ipc/event_types.h>
 #include <mm/slab.h>
 #include <typedefs.h>
 #include <synch/spinlock.h>
 #include <console/console.h>
+#include <proc/task.h>
 #include <memstr.h>
 #include <errno.h>
@@ -48,4 +48,28 @@
 static event_t events[EVENT_END];
 
+static void event_initialize(event_t *event)
+{
+	spinlock_initialize(&event->lock, "event.lock");
+	event->answerbox = NULL;
+	event->counter = 0;
+	event->imethod = 0;
+	event->masked = false;
+	event->unmask_callback = NULL;
+}
+
+static event_t *evno2event(int evno, task_t *t)
+{
+	ASSERT(evno < EVENT_TASK_END);
+
+	event_t *event;
+
+	if (evno < EVENT_END)
+		event = &events[(event_type_t) evno];
+	else
+		event = &t->events[(event_task_type_t) evno - EVENT_END];
+
+	return event;
+}
+
 /** Initialize kernel events.
  *
@@ -53,13 +77,14 @@
 void event_init(void)
 {
-	for (unsigned int i = 0; i < EVENT_END; i++) {
-		spinlock_initialize(&events[i].lock, "event.lock");
-		events[i].answerbox = NULL;
-		events[i].counter = 0;
-		events[i].imethod = 0;
-		events[i].masked = false;
-		events[i].unmask_callback = NULL;
-	}
-}
+	for (unsigned int i = 0; i < EVENT_END; i++)
+		event_initialize(evno2event(i, NULL));
+}
+
+void event_task_init(task_t *task)
+{
+	for (unsigned int i = EVENT_END; i < EVENT_TASK_END; i++)
+		event_initialize(evno2event(i, task));
+}
+
 
 /** Unsubscribe kernel events associated with an answerbox
@@ -84,4 +109,11 @@
 }
 
+static void _event_set_unmask_callback(event_t *event, event_callback_t callback)
+{
+	spinlock_lock(&event->lock);
+	event->unmask_callback = callback;
+	spinlock_unlock(&event->lock);
+}
+
 /** Define a callback function for the event unmask event.
  *
@@ -95,7 +127,59 @@
 	ASSERT(evno < EVENT_END);
 	
-	spinlock_lock(&events[evno].lock);
-	events[evno].unmask_callback = callback;
-	spinlock_unlock(&events[evno].lock);
+	_event_set_unmask_callback(evno2event(evno, NULL), callback);
+}
+
+void event_task_set_unmask_callback(task_t *task, event_task_type_t evno,
+    event_callback_t callback)
+{
+	ASSERT(evno >= (int) EVENT_END);
+	ASSERT(evno < EVENT_TASK_END);
+		
+	_event_set_unmask_callback(evno2event(evno, task), callback);
+}
+
+static int event_enqueue(event_t *event, bool mask, sysarg_t a1, sysarg_t a2,
+    sysarg_t a3, sysarg_t a4, sysarg_t a5)
+{
+	int res;
+
+	spinlock_lock(&event->lock);
+	
+	if (event->answerbox != NULL) {
+		if (!event->masked) {
+			call_t *call = ipc_call_alloc(FRAME_ATOMIC);
+			
+			if (call) {
+				call->flags |= IPC_CALL_NOTIF;
+				call->priv = ++event->counter;
+				
+				IPC_SET_IMETHOD(call->data, event->imethod);
+				IPC_SET_ARG1(call->data, a1);
+				IPC_SET_ARG2(call->data, a2);
+				IPC_SET_ARG3(call->data, a3);
+				IPC_SET_ARG4(call->data, a4);
+				IPC_SET_ARG5(call->data, a5);
+				
+				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);
+				
+				if (mask)
+					event->masked = true;
+				
+				res = EOK;
+			} else
+				res = ENOMEM;
+		} else
+			res = EBUSY;
+	} else
+		res = ENOENT;
+	
+	spinlock_unlock(&event->lock);
+	return res;
 }
 
@@ -124,43 +208,34 @@
 	ASSERT(evno < EVENT_END);
 	
-	spinlock_lock(&events[evno].lock);
-	
-	int ret;
-	
-	if (events[evno].answerbox != NULL) {
-		if (!events[evno].masked) {
-			call_t *call = ipc_call_alloc(FRAME_ATOMIC);
-			
-			if (call) {
-				call->flags |= IPC_CALL_NOTIF;
-				call->priv = ++events[evno].counter;
-				
-				IPC_SET_IMETHOD(call->data, events[evno].imethod);
-				IPC_SET_ARG1(call->data, a1);
-				IPC_SET_ARG2(call->data, a2);
-				IPC_SET_ARG3(call->data, a3);
-				IPC_SET_ARG4(call->data, a4);
-				IPC_SET_ARG5(call->data, a5);
-				
-				irq_spinlock_lock(&events[evno].answerbox->irq_lock, true);
-				list_append(&call->link, &events[evno].answerbox->irq_notifs);
-				irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true);
-				
-				waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST);
-				
-				if (mask)
-					events[evno].masked = true;
-				
-				ret = EOK;
-			} else
-				ret = ENOMEM;
-		} else
-			ret = EBUSY;
-	} else
-		ret = ENOENT;
-	
-	spinlock_unlock(&events[evno].lock);
-	
-	return ret;
+	return event_enqueue(evno2event(evno, NULL), mask, a1, a2, a3, a4, a5);
+}
+
+/** Send per-task kernel notification event
+ *
+ * @param task Destination task.
+ * @param evno Event type.
+ * @param mask Mask further notifications after a successful
+ *             sending.
+ * @param a1   First argument.
+ * @param a2   Second argument.
+ * @param a3   Third argument.
+ * @param a4   Fourth argument.
+ * @param a5   Fifth argument.
+ *
+ * @return EOK if notification was successfully sent.
+ * @return ENOMEM if the notification IPC message failed to allocate.
+ * @return EBUSY if the notifications of the given type are
+ *         currently masked.
+ * @return ENOENT if the notifications of the given type are
+ *         currently not subscribed.
+ *
+ */
+int event_task_notify(task_t *task, event_task_type_t evno, bool mask,
+    sysarg_t a1, sysarg_t a2, sysarg_t a3, sysarg_t a4, sysarg_t a5)
+{
+	ASSERT(evno >= (int) EVENT_END);
+	ASSERT(evno < EVENT_TASK_END);
+	
+	return event_enqueue(evno2event(evno, task), mask, a1, a2, a3, a4, a5);
 }
 
@@ -177,23 +252,21 @@
  *
  */
-static int event_subscribe(event_type_t evno, sysarg_t imethod,
+static int event_subscribe(event_t *event, sysarg_t imethod,
     answerbox_t *answerbox)
 {
-	ASSERT(evno < EVENT_END);
-	
-	spinlock_lock(&events[evno].lock);
-	
 	int res;
-	
-	if (events[evno].answerbox == NULL) {
-		events[evno].answerbox = answerbox;
-		events[evno].imethod = imethod;
-		events[evno].counter = 0;
-		events[evno].masked = false;
+
+	spinlock_lock(&event->lock);
+	
+	if (event->answerbox == NULL) {
+		event->answerbox = answerbox;
+		event->imethod = imethod;
+		event->counter = 0;
+		event->masked = false;
 		res = EOK;
 	} else
 		res = EEXISTS;
 	
-	spinlock_unlock(&events[evno].lock);
+	spinlock_unlock(&event->lock);
 	
 	return res;
@@ -205,12 +278,10 @@
  *
  */
-static void event_unmask(event_type_t evno)
-{
-	ASSERT(evno < EVENT_END);
-	
-	spinlock_lock(&events[evno].lock);
-	events[evno].masked = false;
-	event_callback_t callback = events[evno].unmask_callback;
-	spinlock_unlock(&events[evno].lock);
+static void event_unmask(event_t *event)
+{
+	spinlock_lock(&event->lock);
+	event->masked = false;
+	event_callback_t callback = event->unmask_callback;
+	spinlock_unlock(&event->lock);
 	
 	/*
@@ -219,5 +290,5 @@
 	 */
 	if (callback != NULL)
-		callback();
+		callback(event);
 }
 
@@ -236,9 +307,9 @@
 sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
 {
-	if (evno >= EVENT_END)
+	if (evno >= EVENT_TASK_END)
 		return ELIMIT;
 	
-	return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)
-	    imethod, &TASK->answerbox);
+	return (sysarg_t) event_subscribe(evno2event(evno, TASK),
+	    (sysarg_t) imethod, &TASK->answerbox);
 }
 
@@ -258,8 +329,9 @@
 sysarg_t sys_event_unmask(sysarg_t evno)
 {
-	if (evno >= EVENT_END)
+	if (evno >= EVENT_TASK_END)
 		return ELIMIT;
 	
-	event_unmask((event_type_t) evno);
+	event_unmask(evno2event(evno, TASK));
+
 	return EOK;
 }
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/ipc/ipc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,11 +38,9 @@
  */
 
-#include <synch/synch.h>
 #include <synch/spinlock.h>
 #include <synch/mutex.h>
 #include <synch/waitq.h>
-#include <synch/synch.h>
 #include <ipc/ipc.h>
-#include <ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 #include <ipc/kbox.h>
 #include <ipc/event.h>
@@ -232,4 +230,6 @@
 		}
 	}
+
+	call->data.task_id = TASK->taskid;
 	
 	if (do_lock)
@@ -296,5 +296,5 @@
 		atomic_inc(&phone->active_calls);
 		call->data.phone = phone;
-		call->data.task = TASK;
+		call->data.task_id = TASK->taskid;
 	}
 	
@@ -408,5 +408,5 @@
 			call->caller_phone = call->data.phone;
 		call->data.phone = newphone;
-		call->data.task = TASK;
+		call->data.task_id = TASK->taskid;
 	}
 	
Index: kernel/generic/src/ipc/kbox.c
===================================================================
--- kernel/generic/src/ipc/kbox.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/ipc/kbox.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -33,9 +33,8 @@
  */
 
-#include <synch/synch.h>
 #include <synch/spinlock.h>
 #include <synch/mutex.h>
 #include <ipc/ipc.h>
-#include <ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 #include <ipc/ipcrsc.h>
 #include <arch.h>
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/ipc/sysipc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -40,8 +40,9 @@
 #include <debug.h>
 #include <ipc/ipc.h>
-#include <ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 #include <ipc/sysipc.h>
 #include <ipc/irq.h>
 #include <ipc/ipcrsc.h>
+#include <ipc/event.h>
 #include <ipc/kbox.h>
 #include <synch/waitq.h>
@@ -53,4 +54,5 @@
 #include <mm/as.h>
 #include <print.h>
+#include <macros.h>
 
 /**
@@ -134,4 +136,5 @@
 	case IPC_M_DATA_WRITE:
 	case IPC_M_DATA_READ:
+	case IPC_M_STATE_CHANGE_AUTHORIZE:
 		return true;
 	default:
@@ -164,4 +167,5 @@
 	case IPC_M_DATA_WRITE:
 	case IPC_M_DATA_READ:
+	case IPC_M_STATE_CHANGE_AUTHORIZE:
 		return true;
 	default:
@@ -249,6 +253,4 @@
 			/* The connection was accepted */
 			phone_connect(phoneid, &answer->sender->answerbox);
-			/* Set 'task hash' as arg4 of response */
-			IPC_SET_ARG4(answer->data, (sysarg_t) TASK);
 			/* Set 'phone hash' as arg5 of response */
 			IPC_SET_ARG5(answer->data,
@@ -334,4 +336,50 @@
 		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;
+		}
 	}
 	
@@ -427,6 +475,4 @@
 	case IPC_M_DATA_READ: {
 		size_t size = IPC_GET_ARG2(call->data);
-		if (size <= 0)
-			return ELIMIT;
 		if (size > DATA_XFER_LIMIT) {
 			int flags = IPC_GET_ARG3(call->data);
@@ -458,4 +504,25 @@
 		}
 		
+		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;
 	}
Index: kernel/generic/src/lib/elf.c
===================================================================
--- kernel/generic/src/lib/elf.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/lib/elf.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -47,4 +47,6 @@
 #include <macros.h>
 #include <arch.h>
+
+#include <lib/elf_load.h>
 
 static const char *error_codes[] = {
Index: kernel/generic/src/proc/program.c
===================================================================
--- kernel/generic/src/proc/program.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/proc/program.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -40,5 +40,4 @@
 #include <proc/thread.h>
 #include <proc/task.h>
-#include <proc/uarg.h>
 #include <mm/as.h>
 #include <mm/slab.h>
@@ -48,5 +47,5 @@
 #include <ipc/ipcrsc.h>
 #include <security/cap.h>
-#include <lib/elf.h>
+#include <lib/elf_load.h>
 #include <errno.h>
 #include <print.h>
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/proc/task.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -50,4 +50,5 @@
 #include <ipc/ipc.h>
 #include <ipc/ipcrsc.h>
+#include <ipc/event.h>
 #include <print.h>
 #include <errno.h>
@@ -57,5 +58,4 @@
 #include <syscall/copy.h>
 #include <macros.h>
-#include <ipc/event.h>
 
 /** Spinlock protecting the tasks_tree AVL tree. */
@@ -201,4 +201,6 @@
 	task->ipc_info.irq_notif_received = 0;
 	task->ipc_info.forwarded = 0;
+
+	event_task_init(task);
 	
 #ifdef CONFIG_UDEBUG
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/proc/thread.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,4 @@
 #include <proc/thread.h>
 #include <proc/task.h>
-#include <proc/uarg.h>
 #include <mm/frame.h>
 #include <mm/page.h>
@@ -45,5 +44,4 @@
 #include <arch/cycle.h>
 #include <arch.h>
-#include <synch/synch.h>
 #include <synch/spinlock.h>
 #include <synch/waitq.h>
Index: kernel/generic/src/synch/condvar.c
===================================================================
--- kernel/generic/src/synch/condvar.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/synch/condvar.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,4 @@
 #include <synch/mutex.h>
 #include <synch/waitq.h>
-#include <synch/synch.h>
 #include <arch.h>
 
Index: kernel/generic/src/synch/futex.c
===================================================================
--- kernel/generic/src/synch/futex.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/synch/futex.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,4 @@
 #include <synch/mutex.h>
 #include <synch/spinlock.h>
-#include <synch/synch.h>
 #include <mm/frame.h>
 #include <mm/page.h>
Index: kernel/generic/src/synch/mutex.c
===================================================================
--- kernel/generic/src/synch/mutex.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/synch/mutex.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,4 @@
 #include <synch/mutex.h>
 #include <synch/semaphore.h>
-#include <synch/synch.h>
 #include <debug.h>
 #include <arch.h>
Index: kernel/generic/src/synch/semaphore.c
===================================================================
--- kernel/generic/src/synch/semaphore.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/synch/semaphore.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,4 @@
 #include <synch/waitq.h>
 #include <synch/spinlock.h>
-#include <synch/synch.h>
 #include <arch/asm.h>
 #include <arch.h>
Index: kernel/generic/src/synch/waitq.c
===================================================================
--- kernel/generic/src/synch/waitq.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/synch/waitq.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -45,5 +45,4 @@
 
 #include <synch/waitq.h>
-#include <synch/synch.h>
 #include <synch/spinlock.h>
 #include <proc/thread.h>
Index: kernel/generic/src/sysinfo/stats.c
===================================================================
--- kernel/generic/src/sysinfo/stats.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/generic/src/sysinfo/stats.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -35,5 +35,5 @@
 
 #include <typedefs.h>
-#include <sysinfo/abi.h>
+#include <abi/sysinfo.h>
 #include <sysinfo/stats.h>
 #include <sysinfo/sysinfo.h>
Index: kernel/test/synch/semaphore2.c
===================================================================
--- kernel/test/synch/semaphore2.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ kernel/test/synch/semaphore2.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,5 +37,4 @@
 #include <synch/waitq.h>
 #include <synch/semaphore.h>
-#include <synch/synch.h>
 #include <synch/spinlock.h>
 
Index: tools/imgutil.py
===================================================================
--- tools/imgutil.py	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ tools/imgutil.py	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+"""
+Utilities for filesystem image creators
+"""
+
+import os
+import stat
+
+exclude_names = set(['.svn', '.bzr'])
+
+def align_up(size, alignment):
+	"Return size aligned up to alignment"
+	
+	if (size % alignment == 0):
+		return size
+	
+	return ((size // alignment) + 1) * alignment
+
+def count_up(size, alignment):
+	"Return units necessary to fit the size"
+	
+	if (size % alignment == 0):
+		return (size // alignment)
+	
+	return ((size // alignment) + 1)
+
+def num_of_trailing_bin_zeros(num):
+	"Return number of trailing zeros in binary representation"
+	
+	i = 0
+	if (num == 0): raise ValueError()
+	while num & 1 == 0:
+		i += 1
+		num = num >> 1
+	return i
+
+def get_bit(number, n):
+	"Return True if n-th least-significant bit is set in the given number"
+	
+	return bool((number >> n) & 1)
+
+def set_bit(number, n):
+	"Return the number with n-th least-significant bit set"
+	
+	return number | (1 << n)
+
+class ItemToPack:
+	"Stores information about one directory item to be added to the image"
+	
+	def __init__(self, parent, name):
+		self.parent = parent
+		self.name = name
+		self.path = os.path.join(parent, name)
+		self.stat = os.stat(self.path)
+		self.is_dir = stat.S_ISDIR(self.stat.st_mode)
+		self.is_file = stat.S_ISREG(self.stat.st_mode)
+		self.size = self.stat.st_size
+
+def listdir_items(path):
+	"Return a list of items to be packed inside a fs image"
+	
+	for name in os.listdir(path):
+		if name in exclude_names:
+			continue
+		item = ItemToPack(path, name)
+		if not (item.is_dir or item.is_file):
+			continue
+		yield item
+
+def chunks(item, chunk_size):
+	"Iterate contents of a file in chunks of a given size"
+	
+	inf = open(item.path, 'rb')
+	rd = 0
+	while (rd < item.size):
+		data = bytes(inf.read(chunk_size))
+		yield data
+		rd += len(data)
+	inf.close()
Index: tools/mkarray.py
===================================================================
--- tools/mkarray.py	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ tools/mkarray.py	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+"""
+C structure creator
+"""
+
+import sys
+import os
+import struct
+
+def usage(prname):
+	"Print usage syntax"
+	print("%s <DESTINATION> <LABEL> [SOURCE ...]" % prname)
+
+def main():
+	if (len(sys.argv) < 3):
+		usage(sys.argv[0])
+		return
+	
+	dest = sys.argv[1]
+	label = sys.argv[2]
+	
+	header_ctx = []
+	data_ctx = []
+	for src in sys.argv[3:]:
+		basename = os.path.basename(src)
+		symbol = basename.replace(".", "_")
+		
+		print("%s -> %s" % (src, symbol))
+		
+		src_in = open(src, "rb")
+		src_data = src_in.read()
+		src_in.close()
+		
+		header_rec = "extern uint8_t %s[];" % symbol
+		header_ctx.append(header_rec)
+		
+		data_rec = "uint8_t %s[] = {\n\t" % symbol
+		
+		fmt = 'B'
+		item_size = struct.calcsize(fmt)
+		offset = 0
+		cnt = 0
+		
+		while (len(src_data[offset:]) >= item_size):
+			byte = struct.unpack_from(fmt, src_data, offset)
+			
+			if (offset > 0):
+				if ((cnt % 15) == 0):
+					data_rec += ",\n\t"
+				else:
+					data_rec += ", "
+			
+			data_rec += "0x%x" % byte
+			offset += item_size
+			cnt += 1
+		
+		data_rec += "\n};\n"
+		data_ctx.append(data_rec)
+		
+		header_rec = "extern size_t %s_size;" % symbol
+		header_ctx.append(header_rec)
+		
+		data_rec = "size_t %s_size = %u;\n" % (symbol, offset)
+		data_ctx.append(data_rec)
+	
+	header = open("%s.h" % dest, "w")
+	
+	header.write('/***************************************\n')
+	header.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
+	header.write(' ***************************************/\n\n')
+	header.write("#ifndef %s_H_\n" % label)
+	header.write("#define %s_H_\n\n" % label)
+	header.write("#include <sys/types.h>\n\n")
+	header.write("\n".join(header_ctx))
+	header.write("\n\n")
+	header.write("#endif\n")
+	
+	header.close()
+	
+	data = open("%s.c" % dest, "w")
+	
+	data.write('/***************************************\n')
+	data.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
+	data.write(' ***************************************/\n\n')
+	data.write("#include \"%s.h\"\n\n" % dest)
+	data.write("\n".join(data_ctx))
+	
+	data.close()
+
+if __name__ == '__main__':
+	main()
Index: tools/mkext2.py
===================================================================
--- tools/mkext2.py	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ tools/mkext2.py	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,676 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+"""
+EXT2 creator
+"""
+
+import sys
+import os
+import xstruct
+import array
+import time
+import uuid
+from imgutil import *
+
+GDE_SIZE = 32
+
+STRUCT_DIR_ENTRY_HEAD = """little:
+	uint32_t inode       /* inode number */
+	uint16_t skip        /* byte offset to the next record */
+	uint8_t  name_length /* file attributes */
+	uint8_t  inode_type  /* type of the referenced inode */
+"""
+
+STRUCT_SUPERBLOCK = """little:
+	uint32_t total_inode_count    /* Total number of inodes */
+	uint32_t total_block_count    /* Total number of blocks */
+	uint32_t reserved_block_count /* Total number of reserved blocks */
+	uint32_t free_block_count     /* Total number of free blocks */
+	uint32_t free_inode_count     /* Total number of free inodes */
+	uint32_t first_block          /* Block containing the superblock */
+	uint32_t block_size_log2      /* log_2(block_size) */
+	int32_t  fragment_size_log2   /* log_2(fragment size) */
+	uint32_t blocks_per_group     /* Number of blocks in one block group */
+	uint32_t fragments_per_group  /* Number of fragments per block group */
+	uint32_t inodes_per_group     /* Number of inodes per block group */
+	uint32_t mount_time           /* Time when the filesystem was last mounted */
+	uint32_t write_time           /* Time when the filesystem was last written */
+	uint16_t mount_count          /* Mount count since last full filesystem check */
+	uint16_t max_mount_count      /* Number of mounts after which the fs must be checked */
+	uint16_t magic                /* Magic value */
+	uint16_t state                /* State (mounted/unmounted) */
+	uint16_t error_behavior       /* What to do when errors are encountered */
+	uint16_t rev_minor            /* Minor revision level */
+	uint32_t last_check_time      /* Unix time of last fs check */
+	uint32_t max_check_interval   /* Max unix time interval between checks */
+	uint32_t os                   /* OS that created the filesystem */
+	uint32_t rev_major            /* Major revision level */
+	padding[4] /* default reserved uid and gid */
+	
+	/* Following is for ext2 revision 1 only */
+	uint32_t first_inode
+	uint16_t inode_size
+	uint16_t block_group_number /* Block group where this SB is stored */
+	uint32_t features_compatible
+	uint32_t features_incompatible
+	uint32_t features_read_only
+	char     uuid[16]
+	char     volume_name[16]
+"""
+
+STRUCT_BLOCK_GROUP_DESCRIPTOR = """little:
+	uint32_t block_bitmap_block      /* Block ID for block bitmap */
+	uint32_t inode_bitmap_block      /* Block ID for inode bitmap */
+	uint32_t inode_table_first_block /* Block ID of first block of inode table */
+	uint16_t free_block_count        /* Count of free blocks */
+	uint16_t free_inode_count        /* Count of free inodes */
+	uint16_t directory_inode_count   /* Number of inodes allocated to directories */
+"""
+
+STRUCT_INODE = """little:
+	uint16_t mode
+	uint16_t user_id
+	uint32_t size
+	uint32_t access_time
+	uint32_t creation_time
+	uint32_t modification_time
+	uint32_t deletion_time
+	uint16_t group_id
+	uint16_t usage_count /* Hard link count, when 0 the inode is to be freed */
+	uint32_t reserved_512_blocks /* Size of this inode in 512-byte blocks */
+	uint32_t flags
+	padding[4]
+	uint32_t direct_blocks[12] /* Direct block ids stored in this inode */
+	uint32_t indirect_blocks[3]
+	uint32_t version
+	uint32_t file_acl
+	uint32_t size_high /* For regular files in version >= 1, dir_acl if dir */
+	padding[6]
+	uint16_t mode_high /* Hurd only */
+	uint16_t user_id_high /* Linux/Hurd only */
+	uint16_t group_id_high /* Linux/Hurd only */
+"""
+
+# The following is here to handle byte-order conversion in indirect block lookups
+STRUCT_BLOCK_REFERENCE = """little:
+	uint32_t block_id /* Referenced block ID */
+"""
+
+class Filesystem:	
+	def __init__(self, filename, block_groups, blocks_per_group, inodes_per_group, block_size, inode_size, reserved_inode_count):
+		"Initialize the filesystem writer"
+		
+		outf = open(filename, "w+b")
+		# Set the correct size of the image, so that we can read arbitrary position
+		outf.truncate(block_size * blocks_per_group * block_groups)
+		self.outf = outf
+		self.uuid = uuid.uuid4()
+		self.block_size = block_size
+		self.inode_size = inode_size
+		self.block_groups = block_groups
+		self.blocks_per_group = blocks_per_group
+		self.inodes_per_group = inodes_per_group
+		self.reserved_inode_count = reserved_inode_count
+		self.gdt_blocks = count_up(block_groups * GDE_SIZE, block_size)
+		self.inode_table_blocks_per_group = (inodes_per_group * inode_size) // block_size
+		self.inode_bitmap_blocks_per_group = count_up(inodes_per_group // 8, block_size)
+		self.block_bitmap_blocks_per_group = count_up(blocks_per_group // 8, block_size)
+		self.total_block_count = self.blocks_per_group * self.block_groups
+		self.total_inode_count = self.inodes_per_group * self.block_groups
+		self.inode_table_blocks = count_up(self.total_inode_count * inode_size, block_size)
+		self.inodes = {}
+		self.superblock_at_block = 2047 // block_size
+		self.block_ids_per_block = self.block_size // 4
+		self.indirect_limits = [12, None, None, None]
+		self.indirect_blocks_per_level = [1, None, None, None]
+		for i in range(1,4):
+			self.indirect_blocks_per_level[i] = self.indirect_blocks_per_level[i-1] * self.block_ids_per_block
+			self.indirect_limits[i] = self.indirect_limits[i-1] + self.indirect_blocks_per_level[i]
+		self.block_allocator = Allocator(0, self.total_block_count)
+		self.inode_allocator = Allocator(1, self.total_inode_count)
+		self.init_gdt()
+		# Set the callbacks after GDT has been initialized
+		self.block_allocator.mark_cb = self.mark_block_cb
+		self.inode_allocator.mark_cb = self.mark_inode_cb
+		self.block_allocator.mark_used_all(range(self.superblock_at_block))
+		self.inode_allocator.mark_used_all(range(1, self.reserved_inode_count + 1))
+		self.root_inode = Inode(self, 2, Inode.TYPE_DIR)
+		self.gdt[0].directory_inode_count += 1
+		self.lost_plus_found = Inode(self, self.inode_allocator.alloc(directory=True), Inode.TYPE_DIR)
+		lpf_dir = DirWriter(self.lost_plus_found)
+		lpf_dir.add(self.lost_plus_found.as_dirent('.'))
+		lpf_dir.add(self.root_inode.as_dirent('..'))
+		lpf_dir.finish()
+	
+	def init_gdt(self):
+		"Initialize block group descriptor table"
+		
+		self.superblock_positions = []
+		self.gdt = []
+		consumed_blocks_per_group = (1 + self.gdt_blocks +
+			    self.inode_bitmap_blocks_per_group +
+			    self.block_bitmap_blocks_per_group +
+			    self.inode_table_blocks_per_group)
+		initial_free_blocks = self.blocks_per_group - consumed_blocks_per_group
+		for bg in range(self.block_groups):
+			base = bg * self.blocks_per_group
+			if (bg == 0):
+				base = self.superblock_at_block
+				self.superblock_positions.append(1024)
+			else:
+				self.superblock_positions.append(base * self.block_size)
+			self.block_allocator.mark_used_all(range(base, base+consumed_blocks_per_group))
+			pos = base + 1 + self.gdt_blocks
+			gde = xstruct.create(STRUCT_BLOCK_GROUP_DESCRIPTOR)
+			gde.block_bitmap_block = pos
+			pos += self.block_bitmap_blocks_per_group
+			gde.inode_bitmap_block = pos
+			pos += self.inode_bitmap_blocks_per_group
+			gde.inode_table_first_block = pos
+			gde.free_block_count = initial_free_blocks
+			gde.free_inode_count = self.inodes_per_group
+			gde.directory_inode_count = 0
+			self.gdt.append(gde)
+	
+	def mark_block_cb(self, block):
+		"Called after a block has been allocated"
+		
+		self.gdt[block // self.blocks_per_group].free_block_count -= 1
+	
+	def mark_inode_cb(self, index, directory=False):
+		"Called after an inode has been allocated"
+		
+		index -= 1
+		gde = self.gdt[index // self.inodes_per_group]
+		gde.free_inode_count -= 1
+		if directory:
+			gde.directory_inode_count += 1		
+	
+	def seek_to_block(self, block, offset=0):
+		"Seek to offset bytes after the start of the given block"
+		
+		if offset < 0 or offset > self.block_size:
+			raise Exception("Invalid in-block offset")
+		self.outf.seek(block * self.block_size + offset)
+	
+	def seek_to_inode(self, index):
+		"Seek to the start of the inode structure for the inode number index"
+		
+		index -= 1
+		if index < 0:
+			raise Exception("Invalid inode number")
+		gde = self.gdt[index // self.inodes_per_group]
+		base_block = gde.inode_table_first_block
+		offset = (index % self.inodes_per_group) * self.inode_size
+		block = base_block + (offset // self.block_size)
+		self.seek_to_block(block, offset % self.block_size)	
+	
+	def subtree_add(self, inode, parent_inode, dirpath, is_root=False):
+		"Recursively add files to the filesystem"
+		
+		dir_writer = DirWriter(inode)	
+		dir_writer.add(inode.as_dirent('.'))
+		dir_writer.add(parent_inode.as_dirent('..'))
+		
+		if is_root:
+			dir_writer.add(self.lost_plus_found.as_dirent('lost+found'))
+
+		for item in listdir_items(dirpath):
+			newidx = self.inode_allocator.alloc(directory = item.is_dir)
+			if item.is_file:
+				child_inode = Inode(self, newidx, Inode.TYPE_FILE)
+				for data in chunks(item, self.block_size):
+					child_inode.write(data)
+			elif item.is_dir:
+				child_inode = Inode(self, newidx, Inode.TYPE_DIR)
+				self.subtree_add(child_inode, inode, item.path)
+		
+			dir_writer.add(child_inode.as_dirent(item.name))
+			self.write_inode(child_inode)
+
+		dir_writer.finish()
+	
+	def write_inode(self, inode):
+		"Write inode information into the inode table"
+		
+		self.seek_to_inode(inode.index)
+		self.outf.write(inode.pack())
+
+	def write_gdt(self):
+		"Write group descriptor table at the current file position"
+		
+		for gde in self.gdt:
+			data = bytes(gde.pack())
+			self.outf.write(data)
+			self.outf.seek(GDE_SIZE-len(data), os.SEEK_CUR)
+	
+	def write_superblock(self, block_group):
+		"Write superblock at the current position"
+		
+		sb = xstruct.create(STRUCT_SUPERBLOCK)
+		sb.total_inode_count = self.total_inode_count
+		sb.total_block_count = self.total_block_count
+		sb.reserved_block_count = 0
+		sb.free_block_count = self.block_allocator.free
+		sb.free_inode_count = self.inode_allocator.free
+		sb.first_block = self.superblock_at_block
+		sb.block_size_log2 = num_of_trailing_bin_zeros(self.block_size) - 10
+		sb.fragment_size_log2 = sb.block_size_log2
+		sb.blocks_per_group = self.blocks_per_group
+		sb.fragments_per_group = self.blocks_per_group
+		sb.inodes_per_group = self.inodes_per_group
+		curtime = int(time.time())
+		sb.mount_time = curtime
+		sb.write_time = curtime
+		sb.mount_count = 0
+		sb.max_mount_count = 21
+		sb.magic = 0xEF53
+		sb.state = 5 # clean
+		sb.error_behavior = 1 # continue on errors
+		sb.rev_minor = 0
+		sb.last_check_time = curtime
+		sb.max_check_interval = 15552000 # 6 months
+		sb.os = 0 # Linux
+		sb.rev_major = 1
+		sb.first_inode = self.reserved_inode_count + 1
+		sb.inode_size = self.inode_size
+		sb.block_group_number = block_group
+		sb.features_compatible = 0
+		sb.features_incompatible = 2 # filetype
+		sb.features_read_only = 0
+		sb.uuid = self.uuid.bytes_le
+		sb.volume_name = 'HelenOS rdimage\0'
+		self.outf.write(bytes(sb.pack()))
+	
+	def write_all_metadata(self):
+		"Write superblocks, block group tables, block and inode bitmaps"
+		
+		bbpg = self.blocks_per_group // 8
+		bipg = self.inodes_per_group // 8
+		def window(arr, index, size):
+			return arr[index * size:(index + 1) * size]
+		
+		for bg_index in xrange(len(self.gdt)):
+			sbpos = self.superblock_positions[bg_index]
+			sbblock = (sbpos + 1023) // self.block_size
+			gde = self.gdt[bg_index]
+			
+			self.outf.seek(sbpos)
+			self.write_superblock(bg_index)
+			
+			self.seek_to_block(sbblock+1)
+			self.write_gdt()
+			
+			self.seek_to_block(gde.block_bitmap_block)
+			self.outf.write(window(self.block_allocator.bitmap, bg_index, bbpg))
+			
+			self.seek_to_block(gde.inode_bitmap_block)
+			self.outf.write(window(self.inode_allocator.bitmap, bg_index, bipg))
+	
+	def close(self):
+		"Write all remaining data to the filesystem and close the file"
+		
+		self.write_inode(self.root_inode)
+		self.write_inode(self.lost_plus_found)
+		self.write_all_metadata()
+		self.outf.close()
+
+class Allocator:
+	def __init__(self, base, count):
+		self.count = count
+		self.base = base
+		self.free = count
+		self.nextidx = 0
+		self.bitmap = array.array('B', [0] * (count // 8))
+		self.mark_cb = None
+	
+	def __contains__(self, item):
+		"Check if the item is already used"
+		
+		bitidx = item - self.base
+		return get_bit(self.bitmap[bitidx // 8], bitidx % 8)
+	
+	def alloc(self, **options):
+		"Allocate a new item"
+		
+		while self.nextidx < self.count and (self.base + self.nextidx) in self:
+			self.nextidx += 1
+		if self.nextidx == self.count:
+			raise Exception("No free item available")
+		item = self.base + self.nextidx
+		self.nextidx += 1
+		self.mark_used(item, **options)
+		return item
+	
+	def mark_used(self, item, **options):
+		"Mark the specified item as used"
+		
+		bitidx = item - self.base
+		if item in self:
+			raise Exception("Item already used: " + str(item))
+		self.free -= 1
+		index = bitidx // 8
+		self.bitmap[index] = set_bit(self.bitmap[index], bitidx % 8)
+		if self.mark_cb:
+			self.mark_cb(item, **options)
+	
+	def mark_used_all(self, items, **options):
+		"Mark all specified items as used"
+		
+		for item in items:
+			self.mark_used(item, **options)
+
+class Inode:
+	TYPE_FILE = 1
+	TYPE_DIR = 2
+	TYPE2MODE = {TYPE_FILE: 8, TYPE_DIR: 4}
+	
+	def __init__(self, fs, index, typ):
+		self.fs = fs
+		self.direct = [None] * 12
+		self.indirect = [None] * 3
+		self.pos = 0
+		self.size = 0
+		self.blocks = 0
+		self.index = index
+		self.type = typ
+		self.refcount = 0
+	
+	def as_dirent(self, name):
+		"Return a DirEntry corresponding to this inode"
+		self.refcount += 1
+		return DirEntry(name, self.index, self.type)
+	
+	def new_block(self, data=True):
+		"Get a new block index from allocator and count it here as belonging to the file"
+		
+		block = self.fs.block_allocator.alloc()
+		self.blocks += 1
+		return block
+	
+	def get_or_add_block(self, block):
+		"Get or add a real block to the file"
+		
+		if block < 12:
+			return self.get_or_add_block_direct(block)
+		return self.get_or_add_block_indirect(block)
+	
+	def get_or_add_block_direct(self, block):
+		"Get or add a real block to the file (direct blocks)"
+		
+		if self.direct[block] == None:
+			self.direct[block] = self.new_block()
+		return self.direct[block]
+	
+	def get_or_add_block_indirect(self, block):
+		"Get or add a real block to the file (indirect blocks)"
+		
+		# Determine the indirection level for the desired block
+		level = None
+		for i in range(4):
+			if block < self.fs.indirect_limits[i]:
+				level = i
+				break
+
+		assert level != None
+	
+		# Compute offsets for the topmost level
+		block_offset_in_level = block - self.fs.indirect_limits[level-1];
+		if self.indirect[level-1] == None:
+			self.indirect[level-1] = self.new_block(data = False)
+		current_block = xstruct.create(STRUCT_BLOCK_REFERENCE)
+		current_block.block_id = self.indirect[level-1]
+		offset_in_block = block_offset_in_level // self.fs.indirect_blocks_per_level[level-1]
+	
+		# Navigate through other levels
+		while level > 0:		
+			assert offset_in_block < self.fs.block_ids_per_block
+			
+			level -= 1
+			
+			self.fs.seek_to_block(current_block.block_id, offset_in_block*4)
+			current_block.unpack(self.fs.outf.read(4))
+			
+			if current_block.block_id == 0:
+				# The block does not exist, so alloc one and write it there
+				self.fs.outf.seek(-4, os.SEEK_CUR)
+				current_block.block_id = self.new_block(data=(level==0))
+				self.fs.outf.write(current_block.pack())
+		
+			# 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 %= self.fs.indirect_blocks_per_level[level];
+			offset_in_block = block_offset_in_level // self.fs.indirect_blocks_per_level[level-1]
+
+		return current_block.block_id
+	
+	def do_seek(self):
+		"Perform a seek to the position indicated by self.pos"
+		
+		block = self.pos // self.fs.block_size
+		real_block = self.get_or_add_block(block)
+		offset = self.pos % self.fs.block_size
+		self.fs.seek_to_block(real_block, offset)
+		
+	def write(self, data):
+		"Write a piece of data (arbitrarily long) as the contents of the inode"
+		
+		data_pos = 0		
+		while data_pos < len(data):
+			bytes_remaining_in_block = self.fs.block_size - (self.pos % self.fs.block_size)
+			bytes_to_write = min(bytes_remaining_in_block, len(data)-data_pos)
+			self.do_seek()
+			self.fs.outf.write(data[data_pos:data_pos + bytes_to_write])
+			self.pos += bytes_to_write
+			data_pos += bytes_to_write
+			self.size = max(self.pos, self.size)
+	
+	def align_size_to_block(self):
+		"Align the size of the inode up to block size"
+		
+		self.size = align_up(self.size, self.fs.block_size)
+	
+	def align_pos(self, bytes):
+		"Align the current position up to bytes boundary"
+		
+		self.pos = align_up(self.pos, bytes)
+	
+	def pack(self):
+		"Pack the inode structure and return the result"
+		
+		data = xstruct.create(STRUCT_INODE)
+		data.mode = (Inode.TYPE2MODE[self.type] << 12)
+		data.mode |= 0x1ff # ugo+rwx
+		data.user_id = 0
+		data.size = self.size & 0xFFFFFFFF
+		data.group_id = 0
+		curtime = int(time.time())
+		data.access_time = curtime
+		data.modification_time = curtime
+		data.creation_time = curtime
+		data.deletion_time = 0
+		data.usage_count = self.refcount
+		data.reserved_512_blocks = self.blocks * (self.fs.block_size // 512)
+		data.flags = 0
+		blockconv = lambda x: 0 if x == None else x
+		data.direct_blocks = map(blockconv, self.direct)
+		data.indirect_blocks = map(blockconv, self.indirect)
+		data.version = 0
+		data.file_acl = 0
+		if self.type == Inode.TYPE_FILE:
+			data.size_high = (self.size >> 32)
+		else:
+			# size_high represents dir_acl in this case
+			data.size_high = 0
+		data.mode_high = 0
+		data.user_id_high = 0
+		data.group_id_high = 0
+		return data.pack()
+		
+class DirEntry:
+	"Represents a linked list directory entry"
+	
+	def __init__(self, name, inode, typ):
+		self.name = name.encode('UTF-8')
+		self.inode = inode
+		self.skip = None
+		self.type = typ
+	
+	def size(self):
+		"Return size of the entry in bytes"
+		
+		return align_up(8 + len(self.name)+1, 4)
+	
+	def write(self, inode):
+		"Write the directory entry into the inode"
+		
+		head = xstruct.create(STRUCT_DIR_ENTRY_HEAD)
+		head.inode = self.inode
+		head.skip = self.skip
+		head.name_length = len(self.name)
+		head.inode_type = self.type
+		inode.write(head.pack())
+		inode.write(self.name+'\0')
+		inode.align_pos(4)
+
+class DirWriter:
+	"Manages writing directory entries into an inode (alignment, etc.)"
+	
+	def __init__(self, inode):
+		self.pos = 0
+		self.inode = inode
+		self.prev_entry = None
+		self.prev_pos = None
+	
+	def prev_write(self):
+		"Write a previously remembered entry"
+		
+		if self.prev_entry:
+			self.prev_entry.skip = self.pos - self.prev_pos
+			if self.inode:
+				self.prev_entry.write(self.inode)
+	
+	def add(self, entry):
+		"Add a directory entry to the directory"
+		
+		size = entry.size()
+		block_size = self.inode.fs.block_size
+		if align_up(self.pos, block_size) < align_up(self.pos + size, block_size):
+			self.pos = align_up(self.pos, block_size)
+		self.prev_write()
+		self.prev_entry = entry
+		self.prev_pos = self.pos
+		self.pos += size
+	
+	def finish(self):
+		"Write the last entry and finish writing the directory contents"
+		
+		if not self.inode:
+			return
+		self.pos = align_up(self.pos, self.inode.fs.block_size)
+		self.prev_write()
+		self.inode.align_size_to_block()
+
+def subtree_stats(root, block_size):
+	"Recursively calculate statistics"
+	
+	blocks = 0
+	inodes = 1
+	dir_writer = DirWriter(None)
+	
+	for item in listdir_items(root):
+		inodes += 1
+		if item.is_file:
+			blocks += count_up(item.size, block_size)
+		elif item.is_dir:
+			subtree_blocks, subtree_inodes = subtree_stats(item.path, block_size)
+			blocks += subtree_blocks
+			inodes += subtree_inodes
+	
+	dir_writer.finish()
+	blocks += count_up(dir_writer.pos, block_size)
+	return (blocks, inodes)
+
+def usage(prname):
+	"Print usage syntax"
+	print(prname + " <EXTRA_BYTES> <PATH> <IMAGE>")
+
+def main():
+	if (len(sys.argv) < 4):
+		usage(sys.argv[0])
+		return
+	
+	if (not sys.argv[1].isdigit()):
+		print("<EXTRA_BYTES> must be a number")
+		return
+	
+	extra_bytes = int(sys.argv[1])
+	
+	path = os.path.abspath(sys.argv[2])
+	if (not os.path.isdir(path)):
+		print("<PATH> must be a directory")
+		return
+	
+	block_size = 4096
+	inode_size = 128
+	reserved_inode_count = 10
+	blocks_per_group = 1024
+	inodes_per_group = 512
+	
+	blocks, inodes = subtree_stats(path, block_size)
+	blocks += count_up(extra_bytes, block_size)
+	inodes += reserved_inode_count
+	
+	inodes_per_group = align_up(inodes_per_group, 8)
+	blocks_per_group = align_up(blocks_per_group, 8)
+	
+	inode_table_blocks_per_group = (inodes_per_group * inode_size) // block_size
+	inode_bitmap_blocks_per_group = count_up(inodes_per_group // 8, block_size)
+	block_bitmap_blocks_per_group = count_up(blocks_per_group // 8, block_size)
+	free_blocks_per_group = blocks_per_group
+	free_blocks_per_group -= inode_table_blocks_per_group
+	free_blocks_per_group -= inode_bitmap_blocks_per_group
+	free_blocks_per_group -= block_bitmap_blocks_per_group
+	free_blocks_per_group -= 10 # one for SB and some reserve for GDT
+	
+	block_groups = max(count_up(inodes, inodes_per_group), count_up(blocks, free_blocks_per_group))
+	
+	fs = Filesystem(sys.argv[3], block_groups, blocks_per_group, inodes_per_group,
+	                        block_size, inode_size, reserved_inode_count)
+	
+	fs.subtree_add(fs.root_inode, fs.root_inode, path, is_root=True)
+	fs.close()
+	
+if __name__ == '__main__':
+	main()
Index: tools/mkfat.py
===================================================================
--- tools/mkfat.py	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ tools/mkfat.py	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,14 +37,5 @@
 import xstruct
 import array
-
-exclude_names = set(['.svn', '.bzr'])
-
-def align_up(size, alignment):
-	"Return size aligned up to alignment"
-	
-	if (size % alignment == 0):
-		return size
-	
-	return ((size // alignment) + 1) * alignment
+from imgutil import *
 
 def subtree_size(root, cluster_size, dirent_size):
@@ -54,13 +45,10 @@
 	files = 2
 	
-	for name in os.listdir(root):
-		canon = os.path.join(root, name)
-		
-		if (os.path.isfile(canon) and (not name in exclude_names)):
-			size += align_up(os.path.getsize(canon), cluster_size)
+	for item in listdir_items(root):
+		if item.is_file:
+			size += align_up(item.size, cluster_size)
 			files += 1
-		
-		if (os.path.isdir(canon) and (not name in exclude_names)):
-			size += subtree_size(canon, cluster_size, dirent_size)
+		elif item.is_dir:
+			size += subtree_size(item.path, cluster_size, dirent_size)
 			files += 1
 	
@@ -72,14 +60,11 @@
 	return len(os.listdir(root))
 
-def write_file(path, outf, cluster_size, data_start, fat, reserved_clusters):
+def write_file(item, outf, cluster_size, data_start, fat, reserved_clusters):
 	"Store the contents of a file"
 	
-	size = os.path.getsize(path)
 	prev = -1
 	first = 0
 	
-	inf = open(path, "rb")
-	rd = 0;
-	while (rd < size):
+	for data in chunks(item, cluster_size):
 		empty_cluster = fat.index(0)
 		fat[empty_cluster] = 0xffff
@@ -92,11 +77,8 @@
 		prev = empty_cluster
 		
-		data = bytes(inf.read(cluster_size));
 		outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size)
 		outf.write(data)
-		rd += len(data)
-	inf.close()
-	
-	return first, size
+	
+	return first, item.size
 
 def write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster):
@@ -303,14 +285,11 @@
 		empty_cluster = 0
 	
-	for name in os.listdir(root):
-		canon = os.path.join(root, name)
-		
-		if (os.path.isfile(canon) and (not name in exclude_names)):
-			rv = write_file(canon, outf, cluster_size, data_start, fat, reserved_clusters)
-			directory.append(create_dirent(name, False, rv[0], rv[1]))
-		
-		if (os.path.isdir(canon) and (not name in exclude_names)):
-			rv = recursion(False, canon, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
-			directory.append(create_dirent(name, True, rv[0], rv[1]))
+	for item in listdir_items(root):		
+		if item.is_file:
+			rv = write_file(item, outf, cluster_size, data_start, fat, reserved_clusters)
+			directory.append(create_dirent(item.name, False, rv[0], rv[1]))
+		elif item.is_dir:
+			rv = recursion(False, item.path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
+			directory.append(create_dirent(item.name, True, rv[0], rv[1]))
 	
 	if (head):
Index: tools/mktmpfs.py
===================================================================
--- tools/mktmpfs.py	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ tools/mktmpfs.py	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -35,6 +35,5 @@
 import os
 import xstruct
-
-exclude_names = set(['.svn', '.bzr'])
+from imgutil import listdir_items, chunks
 
 HEADER = """little:
@@ -71,35 +70,26 @@
 	"Recursive directory walk"
 	
-	for name in os.listdir(root):
-		canon = os.path.join(root, name)
-		
-		if (os.path.isfile(canon) and (not name in exclude_names)):
-			size = os.path.getsize(canon)
-			
-			dentry = xstruct.create(DENTRY_FILE % len(name))
+	for item in listdir_items(root):		
+		if item.is_file:			
+			dentry = xstruct.create(DENTRY_FILE % len(item.name))
 			dentry.kind = TMPFS_FILE
-			dentry.fname_len = len(name)
-			dentry.fname = name.encode('ascii')
-			dentry.flen = size
+			dentry.fname_len = len(item.name)
+			dentry.fname = item.name.encode('ascii')
+			dentry.flen = item.size
 			
 			outf.write(dentry.pack())
 			
-			inf = open(canon, "rb")
-			rd = 0;
-			while (rd < size):
-				data = inf.read(4096);
+			for data in chunks(item, 4096):
 				outf.write(data)
-				rd += len(data)
-			inf.close()
 		
-		if (os.path.isdir(canon) and (not name in exclude_names)):
-			dentry = xstruct.create(DENTRY_DIRECTORY % len(name))
+		elif item.is_dir:
+			dentry = xstruct.create(DENTRY_DIRECTORY % len(item.name))
 			dentry.kind = TMPFS_DIRECTORY
-			dentry.fname_len = len(name)
-			dentry.fname = name.encode('ascii')
+			dentry.fname_len = len(item.name)
+			dentry.fname = item.name.encode('ascii')
 			
 			outf.write(dentry.pack())
 			
-			recursion(canon, outf)
+			recursion(item.path, outf)
 			
 			dentry = xstruct.create(DENTRY_NONE)
Index: tools/toolchain.sh
===================================================================
--- tools/toolchain.sh	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ tools/toolchain.sh	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -325,5 +325,5 @@
 	
 	change_title "binutils: configure (${PLATFORM})"
-	./configure "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --disable-nls
+	CFLAGS=-Wno-error ./configure "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --disable-nls
 	check_error $? "Error configuring binutils."
 	
Index: tools/xstruct.py
===================================================================
--- tools/xstruct.py	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ tools/xstruct.py	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,4 +1,5 @@
 #
 # Copyright (c) 2008 Martin Decky
+# Copyright (c) 2011 Martin Sucha
 # All rights reserved.
 #
@@ -31,4 +32,29 @@
 
 import struct
+import types
+
+ranges = {
+	'B': ((int, long), 0x00, 0xff),
+	'H': ((int, long), 0x0000, 0xffff),
+	'L': ((int, long), 0x00000000, 0xffffffff),
+	'Q': ((int, long), 0x0000000000000000, 0xffffffffffffffff),
+	'b': ((int, long), -0x80, 0x7f),
+	'h': ((int, long), -0x8000, 0x7fff),
+	'l': ((int, long), -0x80000000, 0x7fffffff) ,
+	'q': ((int, long), -0x8000000000000000, 0x7fffffffffffffff),
+}
+
+def check_range(varname, fmt, value):
+	if value == None:
+		raise ValueError('Variable "%s" not set' % varname)
+	if not fmt in ranges:
+		return
+	vartype, varmin, varmax = ranges[fmt]
+	if not isinstance(value, vartype):
+		raise ValueError('Variable "%s" is %s but should be %s' %
+		                 (varname, str(type(value)), str(vartype)))
+	if value < varmin or value > varmax:
+		raise ValueError('Variable "%s" value %s out of range %s..%s' % 
+		                 (varname, repr(value), repr(varmin), repr(varmax)))
 
 class Struct:
@@ -38,12 +64,24 @@
 	def pack(self):
 		args = []
-		for variable in self._args_:
-			if (isinstance(self.__dict__[variable], list)):
-				for item in self.__dict__[variable]:
+		for variable, fmt, length in self._args_:
+			value = self.__dict__[variable]
+			if isinstance(value, list):
+				if length != None and length != len(value):
+					raise ValueError('Variable "%s" length %u does not match %u' %
+				                      (variable, len(value), length))
+				for index, item in enumerate(value):
+					check_range(variable + '[' + repr(index) + ']', fmt, item)
 					args.append(item)
 			else:
-				args.append(self.__dict__[variable])
-		
+				check_range(variable, fmt, value)
+				args.append(value)		
 		return struct.pack(self._format_, *args)
+	
+	def unpack(self, data):
+		values = struct.unpack(self._format_, data)
+		i = 0
+		for variable, fmt, length in self._args_:
+			self.__dict__[variable] = values[i]
+			i += 1
 
 def create(definition):
@@ -77,11 +115,13 @@
 			subtokens = token.split("[")
 			
+			length = None
 			if (len(subtokens) > 1):
-				format += "%d" % int(subtokens[1].split("]")[0])
+				length = int(subtokens[1].split("]")[0])
+				format += "%d" % length
 			
 			format += variable
 			
 			inst.__dict__[subtokens[0]] = None
-			args.append(subtokens[0])
+			args.append((subtokens[0], variable, length))
 			
 			variable = None
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,4 +37,5 @@
 	app/blkdump \
 	app/bnchmark \
+	app/devctl \
 	app/edit \
 	app/ext2info \
@@ -44,4 +45,5 @@
 	app/killall \
 	app/klog \
+	app/locinfo \
 	app/lsusb \
 	app/mkfat \
@@ -65,5 +67,5 @@
 	app/mkbd \
 	srv/clip \
-	srv/devmap \
+	srv/loc \
 	srv/devman \
 	srv/loader \
@@ -79,6 +81,7 @@
 	srv/fs/fat \
 	srv/fs/tmpfs \
-	srv/fs/devfs \
+	srv/fs/locfs \
 	srv/fs/ext2fs \
+	srv/hid/console \
 	srv/hid/s3c24xx_ts \
 	srv/hid/fb \
@@ -121,8 +124,4 @@
 #
 
-ifneq ($(UARCH),abs32le)
-	DIRS += srv/hid/console
-endif
-
 ifeq ($(UARCH),amd64)
 	DIRS += \
@@ -164,4 +163,5 @@
 	lib/block \
 	lib/clui \
+	lib/fmtutil \
 	lib/scsi \
 	lib/softint \
@@ -169,4 +169,5 @@
 	lib/drv \
 	lib/packet \
+	lib/imgmap \
 	lib/net \
 	lib/ext2 \
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/Makefile.common	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -106,5 +106,7 @@
 LIBBLOCK_PREFIX = $(LIB_PREFIX)/block
 LIBFS_PREFIX = $(LIB_PREFIX)/fs
+LIBIMGMAP_PREFIX = $(LIB_PREFIX)/imgmap
 LIBCLUI_PREFIX = $(LIB_PREFIX)/clui
+LIBFMTUTIL_PREFIX = $(LIB_PREFIX)/fmtutil
 
 LIBEXT2_PREFIX = $(LIB_PREFIX)/ext2
Index: uspace/app/bdsh/Makefile
===================================================================
--- uspace/app/bdsh/Makefile	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bdsh/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -29,7 +29,8 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBCLUI_PREFIX)/libclui.a
-EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBCLUI_PREFIX) -I. -Icmds/ \
-	-Icmds/builtins -Icmds/modules
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBCLUI_PREFIX)/libclui.a \
+	$(LIBFMTUTIL_PREFIX)/libfmtutil.a
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBCLUI_PREFIX) -I$(LIBFMTUTIL_PREFIX)\
+	-I. -Icmds/ -Icmds/builtins -Icmds/modules
 BINARY = bdsh
 
@@ -54,4 +55,5 @@
 	cmds/mod_cmds.c \
 	cmds/builtin_cmds.c \
+	compl.c \
 	errors.c \
 	input.c \
Index: uspace/app/bdsh/cmds/modules/bdd/bdd.c
===================================================================
--- uspace/app/bdsh/cmds/modules/bdd/bdd.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bdsh/cmds/modules/bdd/bdd.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,5 @@
 
 #include <libblock.h>
-#include <devmap.h>
+#include <loc.h>
 #include <errno.h>
 #include <assert.h>
@@ -69,5 +69,5 @@
 	unsigned int argc;
 	unsigned int i, j;
-	devmap_handle_t handle;
+	service_id_t service_id;
 	aoff64_t offset;
 	uint8_t *blk;
@@ -96,5 +96,5 @@
 		size = 256;
 
-	rc = devmap_device_get_handle(argv[1], &handle, 0);
+	rc = loc_service_get_id(argv[1], &service_id, 0);
 	if (rc != EOK) {
 		printf("%s: Error resolving device `%s'.\n", cmdname, argv[1]);
@@ -102,5 +102,5 @@
 	}
 
-	rc = block_init(EXCHANGE_SERIALIZE, handle, 2048);
+	rc = block_init(EXCHANGE_SERIALIZE, service_id, 2048);
 	if (rc != EOK)  {
 		printf("%s: Error initializing libblock.\n", cmdname);
@@ -108,5 +108,5 @@
 	}
 
-	rc = block_get_bsize(handle, &block_size);
+	rc = block_get_bsize(service_id, &block_size);
 	if (rc != EOK) {
 		printf("%s: Error determining device block size.\n", cmdname);
@@ -117,5 +117,5 @@
 	if (blk == NULL) {
 		printf("%s: Error allocating memory.\n", cmdname);
-		block_fini(handle);
+		block_fini(service_id);
 		return CMD_FAILURE;
 	}
@@ -124,9 +124,9 @@
 
 	while (size > 0) {
-		rc = block_read_direct(handle, ba, 1, blk);
+		rc = block_read_direct(service_id, ba, 1, blk);
 		if (rc != EOK) {
 			printf("%s: Error reading block %" PRIuOFF64 "\n", cmdname, ba);
 			free(blk);
-			block_fini(handle);
+			block_fini(service_id);
 			return CMD_FAILURE;
 		}
@@ -170,5 +170,5 @@
 
 	free(blk);
-	block_fini(handle);
+	block_fini(service_id);
 
 	return CMD_SUCCESS;
Index: uspace/app/bdsh/cmds/modules/cp/cp.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cp/cp.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bdsh/cmds/modules/cp/cp.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -71,6 +71,6 @@
 	size_t blen, int vb)
 {
-	int fd1, fd2, bytes = 0;
-	off64_t total = 0;
+	int fd1, fd2, bytes;
+	off64_t total;
 	int64_t copied = 0;
 	char *buff = NULL;
@@ -104,37 +104,11 @@
 	}
 
-	for (;;) {
-		ssize_t res;
-		size_t written = 0;
-
-		bytes = read(fd1, buff, blen);
-		if (bytes <= 0)
+	while ((bytes = read_all(fd1, buff, blen)) > 0) {
+		if ((bytes = write_all(fd2, buff, bytes)) < 0)
 			break;
 		copied += bytes;
-		res = bytes;
-		do {
-			/*
-			 * Theoretically, it may not be enough to call write()
-			 * only once. Also the previous read() may have
-			 * returned less data than requested.
-			 */
-			bytes = write(fd2, buff + written, res);
-			if (bytes < 0)
-				goto err;
-			written += bytes;
-			res -= bytes;
-		} while (res > 0);
-
-		/* TODO: re-insert assert() once this is stand alone,
-		 * removed as abort() exits the entire shell
-		 */
-		if (res != 0) {
-			printf("\n%zd more bytes than actually exist were copied\n", res);
-			goto err;
-		}
 	}
 
 	if (bytes < 0) {
-err:
 		printf("\nError copying %s, (%d)\n", src, bytes);
 		copied = bytes;
Index: uspace/app/bdsh/cmds/modules/help/help.c
===================================================================
--- uspace/app/bdsh/cmds/modules/help/help.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bdsh/cmds/modules/help/help.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2008 Tim Post
+ * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
  *
@@ -30,4 +31,5 @@
 #include <stdlib.h>
 #include <str.h>
+#include <fmtutil.h>
 
 #include "config.h"
@@ -128,26 +130,28 @@
 static void help_survival(void)
 {
-	printf("Don't panic!\n\n");
-
-	printf("This is Bdsh, the Brain dead shell, currently "
+	print_wrapped_console(
+	    "Don't panic!\n\n"
+
+	    "This is Bdsh, the Brain dead shell, currently "
 	    "the primary user interface to HelenOS. Bdsh allows you to enter "
 	    "commands and supports history (Up, Down arrow keys), "
 	    "line editing (Left Arrow, Right Arrow, Home, End, Backspace), "
 	    "selection (Shift + movement keys), copy and paste (Ctrl-C, "
-	    "Ctrl-V), similar to common desktop environments.\n\n");
-
-	printf("The most basic filesystem commands are Bdsh builtins. Type "
+	    "Ctrl-V), similar to common desktop environments.\n\n"
+
+	    "The most basic filesystem commands are Bdsh builtins. Type "
 	    "'help commands' [Enter] to see the list of Bdsh builtin commands. "
 	    "Other commands are external executables located in the /app and "
 	    "/srv directories. Type 'ls /app' [Enter] and 'ls /srv' [Enter] "
 	    "to see their list. You can execute an external command simply "
-	    "by entering its name (e.g. type 'tetris' [Enter]).\n\n");
-
-	printf("HelenOS has virtual consoles (VCs). You can switch between "
-	    "these using the F1-F11 keys.\n\n");
-
-	printf("This is but a small glimpse of what you can do with HelenOS. "
+	    "by entering its name (e.g. type 'tetris' [Enter]).\n\n"
+
+	    "HelenOS has virtual consoles (VCs). You can switch between "
+	    "these using the F1-F11 keys.\n\n"
+
+	    "This is but a small glimpse of what you can do with HelenOS. "
 	    "To learn more please point your browser to the HelenOS User's "
-	    "Guide: http://trac.helenos.org/trac.fcgi/wiki/UsersGuide\n\n");
+	    "Guide: http://trac.helenos.org/trac.fcgi/wiki/UsersGuide\n\n",
+	    ALIGN_LEFT);
 }
 
Index: uspace/app/bdsh/cmds/modules/ls/ls.c
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bdsh/cmds/modules/ls/ls.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -169,11 +169,11 @@
 		
 		/* fill the name field */
-		tosort[nbdirs].name = (char *) malloc(str_length(dp->d_name) + 1);
+		tosort[nbdirs].name = (char *) malloc(str_size(dp->d_name) + 1);
 		if (!tosort[nbdirs].name) {
 			cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
 			goto out;
 		}
-		
-		str_cpy(tosort[nbdirs].name, str_length(dp->d_name) + 1, dp->d_name);
+
+		str_cpy(tosort[nbdirs].name, str_size(dp->d_name) + 1, dp->d_name);
 		len = snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[nbdirs].name);
 		buff[len] = '\0';
Index: uspace/app/bdsh/compl.c
===================================================================
--- uspace/app/bdsh/compl.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/app/bdsh/compl.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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 <bool.h>
+#include <dirent.h>
+#include <errno.h>
+#include <macros.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "cmds/cmds.h"
+#include "compl.h"
+#include "exec.h"
+#include "tok.h"
+
+static int compl_init(wchar_t *text, size_t pos, size_t *cstart, void **state);
+static int compl_get_next(void *state, char **compl);
+static void compl_fini(void *state);
+
+/** Bdsh implementation of completion ops. */
+tinput_compl_ops_t compl_ops = {
+	.init = compl_init,
+	.get_next = compl_get_next,
+	.fini = compl_fini
+};
+
+/** Completion state object.
+ *
+ * The state object contains 'iterators' for modules, builtins and
+ * executables in directories.
+ */
+typedef struct {
+	/** String prefix which we are trying to complete. */
+	char *prefix;
+	/** Length of string prefix (number of characters) */
+	size_t prefix_len;
+
+	/** Pointer inside list of modules */
+	module_t *module;
+	/** Pointer inside list of builtins */
+	builtin_t *builtin;
+
+	/** Pointer inside list of directories */
+	const char **path;
+	/** If not @c NULL, should be freed in the end. */
+	const char **path_list;
+	/** Current open directory */
+	DIR *dir;
+
+	char *last_compl;
+
+	/**
+	 * @c true if we are completing a command, @c false if we are
+	 * completing an argument
+	 */
+	bool is_command;
+} compl_t;
+
+/** Init completion.
+ *
+ * Set up iterators in completion object, based on current token.
+ */
+static int compl_init(wchar_t *text, size_t pos, size_t *cstart, void **state)
+{
+	compl_t *cs = NULL;
+	size_t pref_size;
+	char *stext = NULL;
+	char *prefix = NULL;
+	char *dirname = NULL;
+	char *rpath_sep;
+	static const char *dirlist_arg[] = { ".", NULL };
+	int retval;
+	tokenizer_t tok;
+	token_t tokens[WORD_MAX];
+	int current_token;
+	size_t tokens_length;
+
+	cs = calloc(1, sizeof(compl_t));
+	if (!cs) {
+		retval = ENOMEM;
+		goto error;
+	}
+
+	/* Convert text buffer to string */
+	stext = wstr_to_astr(text);
+	if (stext == NULL) {
+		retval = ENOMEM;
+		goto error;
+	}
+	
+	/* Tokenize the input string */
+	retval = tok_init(&tok, stext, tokens, WORD_MAX);
+	if (retval != EOK) {
+		goto error;
+	}
+	
+	retval = tok_tokenize(&tok, &tokens_length);
+	if (retval != EOK) {
+		goto error;
+	}
+	
+	/* Find the current token */
+	for (current_token = 0; current_token < (int) tokens_length;
+	    current_token++) {
+		token_t *t = &tokens[current_token];
+		size_t end = t->char_start + t->char_length;
+		/* Check if the caret lies inside the token or immediately
+		 * after it
+		 */
+		if (t->char_start <= pos && pos <= end) {
+			break;
+		}
+	}
+	if (tokens_length == 0) current_token = -1;
+	
+	if (current_token >= 0 && tokens[current_token].type != TOKTYPE_SPACE) {
+		*cstart = tokens[current_token].char_start;
+	}
+	else {
+		*cstart = pos;
+	}
+	
+	/* Extract the prefix being completed
+	 * XXX: handle strings, etc.
+	 */
+	pref_size = str_lsize(stext, pos - *cstart);
+	prefix = malloc(pref_size + 1);
+	if (prefix == NULL) {
+		retval = ENOMEM;
+		goto error;
+	}
+	prefix[pref_size] = 0;
+
+	if (current_token >= 0) {
+		str_ncpy(prefix, pref_size + 1, stext +
+		    tokens[current_token].byte_start, pref_size);
+	}
+
+	/*
+	 * Determine if the token being completed is a command or argument.
+	 * We look at the previous token. If there is none or it is a pipe
+	 * ('|'), it is a command, otherwise it is an argument.
+	 */
+
+	/* Skip any whitespace before current token */
+	int prev_token = current_token - 1;
+	if (prev_token >= 0 && tokens[prev_token].type == TOKTYPE_SPACE) {
+		prev_token--;
+	}
+
+	/*
+	 * It is a command if it is the first token or if it immediately
+	 * follows a pipe token.
+	 */
+	if (prev_token < 0 || tokens[prev_token].type == TOKTYPE_SPACE)
+		cs->is_command = true;
+	else
+		cs->is_command = false;
+
+	rpath_sep = str_rchr(prefix, '/');
+	if (rpath_sep != NULL) {
+		/* Extract path. For path beginning with '/' keep the '/'. */
+		dirname = str_ndup(prefix, max(1, rpath_sep - prefix));
+		if (dirname == NULL) {
+			retval = ENOMEM;
+			goto error;
+		}
+
+		/* Extract name prefix */
+		cs->prefix = str_dup(rpath_sep + 1);
+		if (cs->prefix == NULL) {
+			retval = ENOMEM;
+			goto error;
+		}
+		*cstart += rpath_sep + 1 - prefix;
+		free(prefix);
+
+		cs->path_list = malloc(sizeof(char *) * 2);
+		if (cs->path_list == NULL) {
+			retval = ENOMEM;
+			goto error;
+		}
+		cs->path_list[0] = dirname;
+		cs->path_list[1] = NULL;
+		cs->path = cs->path_list;
+
+	} else if (cs->is_command) {
+		/* Command without path */
+		cs->module = modules;
+		cs->builtin = builtins;
+		cs->prefix = prefix;
+		cs->path = &search_dir[0];
+	} else {
+		/* Argument without path */
+		cs->prefix = prefix;
+		cs->path = &dirlist_arg[0];
+	}
+
+	cs->prefix_len = str_length(cs->prefix);
+	
+	tok_fini(&tok);
+
+	*state = cs;
+	return EOK;
+
+error:
+	/* Error cleanup */
+	
+	tok_fini(&tok);
+
+	if (cs != NULL && cs->path_list != NULL) {
+		size_t i = 0;
+		while (cs->path_list[i] != NULL) {
+			free(cs->path_list[i]);
+			++i;
+		}
+		free(cs->path_list);
+	}
+
+	if (cs != NULL && cs->prefix != NULL)
+		free(cs->prefix);
+	if (dirname != NULL)
+		free(dirname);
+	if (prefix != NULL)
+		free(prefix);
+	if (stext != NULL)
+		free(stext);
+	if (cs != NULL)
+		free(cs);
+
+	return retval;
+}
+
+/** Determine if completion matches the required prefix.
+ *
+ * Required prefix is stored in @a cs->prefix.
+ *
+ * @param cs	Completion state object
+ * @param compl	Completion string
+ * @return	@c true when @a compl matches, @c false otherwise
+ */
+static bool compl_match_prefix(compl_t *cs, const char *compl)
+{
+	return str_lcmp(compl, cs->prefix, cs->prefix_len) == 0;
+}
+
+/** Get next match. */
+static int compl_get_next(void *state, char **compl)
+{
+	compl_t *cs = (compl_t *) state;
+	struct dirent *dent;
+
+	*compl = NULL;
+
+	if (cs->last_compl != NULL) {
+		free(cs->last_compl);
+		cs->last_compl = NULL;
+	}
+
+	/* Modules */
+	if (cs->module != NULL) {
+		while (*compl == NULL && cs->module->name != NULL) {
+			if (compl_match_prefix(cs, cs->module->name)) {
+				asprintf(compl, "%s ", cs->module->name);
+				cs->last_compl = *compl;
+				if (*compl == NULL)
+					return ENOMEM;
+			}
+			cs->module++;
+		}
+	}
+
+	/* Builtins */
+	if (cs->builtin != NULL) {
+		while (*compl == NULL && cs->builtin->name != NULL) {
+			if (compl_match_prefix(cs, cs->builtin->name)) {
+				asprintf(compl, "%s ", cs->builtin->name);
+				cs->last_compl = *compl;
+				if (*compl == NULL)
+					return ENOMEM;
+			}
+			cs->builtin++;
+		}
+	}
+
+	/* Files and directories. We scan entries from a set of directories. */
+	if (cs->path != NULL) {
+		while (*compl == NULL) {
+			/* Open next directory */
+			while (cs->dir == NULL) {
+				if (*cs->path == NULL)
+					break;
+
+				cs->dir = opendir(*cs->path);
+
+				/* Skip directories that we fail to open. */
+				if (cs->dir == NULL)
+					cs->path++;
+			}
+
+			/* If it was the last one, we are done */
+			if (cs->dir == NULL)
+				break;
+
+			/* Read next directory entry */
+			dent = readdir(cs->dir);
+			if (dent == NULL) {
+				/* Error. Close directory, go to next one */
+				closedir(cs->dir);
+				cs->dir = NULL;
+				cs->path++;
+				continue;
+			}
+
+			if (compl_match_prefix(cs, dent->d_name)) {
+				/* Construct pathname */
+				char *ent_path;
+				asprintf(&ent_path, "%s/%s", *cs->path, dent->d_name);
+				struct stat ent_stat;
+				if (stat(ent_path, &ent_stat) != EOK) {
+					/* Error */
+					free(ent_path);
+					continue;
+				}
+
+				free(ent_path);
+
+				/* If completing command, do not match directories. */
+				if (!ent_stat.is_directory || !cs->is_command) {
+					asprintf(compl, "%s%c", dent->d_name,
+					    ent_stat.is_directory ? '/' : ' ');
+					cs->last_compl = *compl;
+					if (*compl == NULL)
+						return ENOMEM;
+				}
+			}
+		}
+	}
+
+	if (*compl == NULL)
+		return ENOENT;
+
+	return EOK;
+}
+
+/** Finish completion operation. */
+static void compl_fini(void *state)
+{
+	compl_t *cs = (compl_t *) state;
+
+	if (cs->path_list != NULL) {
+		size_t i = 0;
+		while (cs->path_list[i] != NULL) {
+			free(cs->path_list[i]);
+			++i;
+		}
+		free(cs->path_list);
+	}
+
+	if (cs->last_compl != NULL)
+		free(cs->last_compl);
+	if (cs->dir != NULL)
+		closedir(cs->dir);
+
+	free(cs->prefix);
+	free(cs);
+}
Index: uspace/app/bdsh/compl.h
===================================================================
--- uspace/app/bdsh/compl.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/app/bdsh/compl.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2008 Tim Post
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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 COMPL_H
+#define COMPL_H
+
+#include <tinput.h>
+
+extern tinput_compl_ops_t compl_ops;
+
+#endif
Index: uspace/app/bdsh/config.h
===================================================================
--- uspace/app/bdsh/config.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bdsh/config.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -40,8 +40,4 @@
 #endif
 
-/* Work around for getenv() */
-#define PATH "/srv:/app"
-#define PATH_DELIM ":"
-
 /* Used in many places */
 #define SMALL_BUFLEN 256
Index: uspace/app/bdsh/exec.c
===================================================================
--- uspace/app/bdsh/exec.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bdsh/exec.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -40,4 +40,5 @@
 #include <str_error.h>
 #include <errno.h>
+#include <vfs/vfs.h>
 
 #include "config.h"
@@ -51,4 +52,6 @@
 static char *find_command(char *);
 static int try_access(const char *);
+
+const char *search_dir[] = { "/app", "/srv", NULL };
 
 /* work-around for access() */
@@ -69,8 +72,5 @@
 static char *find_command(char *cmd)
 {
-	char *path_tok;
-	char *path[PATH_MAX];
-	int n = 0, i = 0;
-	size_t x = str_size(cmd) + 2;
+	size_t i;
 
 	found = (char *)malloc(PATH_MAX);
@@ -81,24 +81,9 @@
 	}
 
-	path_tok = str_dup(PATH);
-
-	/* Extract the PATH env to a path[] array */
-	path[n] = strtok(path_tok, PATH_DELIM);
-	while (NULL != path[n]) {
-		if ((str_size(path[n]) + x ) > PATH_MAX) {
-			cli_error(CL_ENOTSUP,
-				"Segment %d of path is too large, search ends at segment %d",
-				n, n-1);
-			break;
-		}
-		path[++n] = strtok(NULL, PATH_DELIM);
-	}
-
 	/* We now have n places to look for the command */
-	for (i=0; path[i]; i++) {
+	for (i = 0; search_dir[i] != NULL; i++) {
 		memset(found, 0, sizeof(found));
-		snprintf(found, PATH_MAX, "%s/%s", path[i], cmd);
+		snprintf(found, PATH_MAX, "%s/%s", search_dir[i], cmd);
 		if (-1 != try_access(found)) {
-			free(path_tok);
 			return (char *) found;
 		}
@@ -106,5 +91,4 @@
 
 	/* We didn't find it, just give it back as-is. */
-	free(path_tok);
 	return (char *) cmd;
 }
@@ -116,6 +100,6 @@
 	char *tmp;
 	int rc, retval, i;
-	fdi_node_t file_nodes[3];
-	fdi_node_t *file_nodes_p[4];
+	int file_handles[3];
+	int *file_handles_p[4];
 	FILE *files[3];
 
@@ -128,14 +112,14 @@
 	
 	for (i = 0; i < 3 && files[i] != NULL; i++) {
-		if (fnode(files[i], &file_nodes[i]) == EOK) {
-			file_nodes_p[i] = &file_nodes[i];
+		if (fhandle(files[i], &file_handles[i]) == EOK) {
+			file_handles_p[i] = &file_handles[i];
 		}
 		else {
-			file_nodes_p[i] = NULL;
+			file_handles_p[i] = NULL;
 		}
 	}
-	file_nodes_p[i] = NULL;
+	file_handles_p[i] = NULL;
 
-	rc = task_spawnvf(&tid, tmp, (const char **) argv, file_nodes_p);
+	rc = task_spawnvf(&tid, tmp, (const char **) argv, file_handles_p);
 	free(tmp);
 
Index: uspace/app/bdsh/exec.h
===================================================================
--- uspace/app/bdsh/exec.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bdsh/exec.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -33,4 +33,6 @@
 #include "scli.h"
 
+extern const char *search_dir[];
+
 extern unsigned int try_exec(char *, char **, iostate_t *);
 
Index: uspace/app/bdsh/input.c
===================================================================
--- uspace/app/bdsh/input.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bdsh/input.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,4 +1,6 @@
 /*
  * Copyright (c) 2008 Tim Post
+ * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
  *
@@ -43,4 +45,5 @@
 
 #include "config.h"
+#include "compl.h"
 #include "util.h"
 #include "scli.h"
@@ -65,23 +68,37 @@
 {
 	char *cmd[WORD_MAX];
+	token_t *tokens = calloc(WORD_MAX, sizeof(token_t));
+	if (tokens == NULL)
+		return ENOMEM;
 	int rc = 0;
 	tokenizer_t tok;
-	int i, pipe_count, processed_pipes;
-	int pipe_pos[2];
-	char **actual_cmd;
+	unsigned int i, pipe_count, processed_pipes;
+	unsigned int pipe_pos[2];
 	char *redir_from = NULL;
 	char *redir_to = NULL;
 
-	if (NULL == usr->line)
+	if (NULL == usr->line) {
+		free(tokens);
 		return CL_EFAIL;
-
-	rc = tok_init(&tok, usr->line, cmd, WORD_MAX);
+	}
+
+	rc = tok_init(&tok, usr->line, tokens, WORD_MAX);
 	if (rc != EOK) {
 		goto finit;
 	}
 	
-	rc = tok_tokenize(&tok);
+	size_t tokens_length;
+	rc = tok_tokenize(&tok, &tokens_length);
 	if (rc != EOK) {
 		goto finit;
+	}
+	
+	if (tokens_length > 0 && tokens[0].type == TOKTYPE_SPACE) {
+		tokens++;
+		tokens_length--;
+	}
+	
+	if (tokens_length > 0 && tokens[tokens_length-1].type == TOKTYPE_SPACE) {
+		tokens_length--;
 	}
 	
@@ -91,7 +108,6 @@
 	 * First find the pipes and check that there are no more
 	 */
-	int cmd_length = 0;
-	for (i = 0, pipe_count = 0; cmd[i] != NULL; i++, cmd_length++) {
-		if (cmd[i][0] == '|') {
+	for (i = 0, pipe_count = 0; i < tokens_length; i++) {
+		if (tokens[i].type == TOKTYPE_PIPE) {
 			if (pipe_count >= 2) {
 				print_pipe_usage();
@@ -104,12 +120,14 @@
 	}
 	
-	actual_cmd = cmd;
+	unsigned int cmd_token_start = 0;
+	unsigned int cmd_token_end = tokens_length;
+	
 	processed_pipes = 0;
 	
 	/* Check if the first part (from <file> |) is present */
-	if (pipe_count > 0 && pipe_pos[0] == 2 && str_cmp(cmd[0], "from") == 0) {
+	if (pipe_count > 0 && (pipe_pos[0] == 3 || pipe_pos[0] == 4) && str_cmp(tokens[0].text, "from") == 0) {
 		/* Ignore the first three tokens (from, file, pipe) and set from */
-		redir_from = cmd[1];
-		actual_cmd = cmd + 3;
+		redir_from = tokens[2].text;
+		cmd_token_start = pipe_pos[0]+1;
 		processed_pipes++;
 	}
@@ -117,10 +135,11 @@
 	/* Check if the second part (| to <file>) is present */
 	if ((pipe_count - processed_pipes) > 0 &&
-	    pipe_pos[processed_pipes] == cmd_length - 3 &&
-	    str_cmp(cmd[cmd_length-2], "to") == 0) {
+	    (pipe_pos[processed_pipes] == tokens_length - 4 ||
+	    (pipe_pos[processed_pipes] == tokens_length - 5 &&
+	    tokens[tokens_length-4].type == TOKTYPE_SPACE )) &&
+	    str_cmp(tokens[tokens_length-3].text, "to") == 0) {
 		/* Ignore the last three tokens (pipe, to, file) and set to */
-		redir_to = cmd[cmd_length-1];
-		cmd[cmd_length-3] = NULL;
-		cmd_length -= 3;
+		redir_to = tokens[tokens_length-1].text;
+		cmd_token_end = pipe_pos[processed_pipes];
 		processed_pipes++;
 	}
@@ -132,5 +151,14 @@
 	}
 	
-	if (actual_cmd[0] == NULL) {
+	/* Convert tokens of the command to string array */
+	unsigned int cmd_pos = 0;
+	for (i = cmd_token_start; i < cmd_token_end; i++) {
+		if (tokens[i].type != TOKTYPE_SPACE) {
+			cmd[cmd_pos++] = tokens[i].text;
+		}
+	}
+	cmd[cmd_pos++] = NULL;
+	
+	if (cmd[0] == NULL) {
 		print_pipe_usage();
 		rc = ENOTSUP;
@@ -184,4 +212,5 @@
 	}
 	tok_fini(&tok);
+	free(tokens);
 
 	return rc;
@@ -226,9 +255,5 @@
 	int rc;
 	
-	console_flush(tinput->console);
-	console_set_style(tinput->console, STYLE_EMPHASIS);
-	printf("%s", usr->prompt);
-	console_flush(tinput->console);
-	console_set_style(tinput->console, STYLE_NORMAL);
+	tinput_set_prompt(tinput, usr->prompt);
 
 	rc = tinput_read(tinput, &str);
@@ -263,4 +288,6 @@
 	}
 
+	tinput_set_compl_ops(tinput, &compl_ops);
+
 	return 0;
 }
Index: uspace/app/bdsh/scli.h
===================================================================
--- uspace/app/bdsh/scli.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bdsh/scli.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -32,4 +32,5 @@
 #include "config.h"
 #include <stdint.h>
+#include <stdio.h>
 
 typedef struct {
Index: uspace/app/bdsh/tok.c
===================================================================
--- uspace/app/bdsh/tok.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bdsh/tok.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,4 +42,5 @@
 static bool tok_pending_chars(tokenizer_t *);
 static int tok_finish_string(tokenizer_t *);
+static void tok_start_token(tokenizer_t *, token_type_t);
 
 /** Initialize the token parser
@@ -50,15 +51,16 @@
  * @param max_tokens number of elements of the out_tokens array
  */
-int tok_init(tokenizer_t *tok, char *input, char **out_tokens,
+int tok_init(tokenizer_t *tok, char *input, token_t *out_tokens,
     size_t max_tokens)
 {	
 	tok->in = input;
 	tok->in_offset = 0;
+	tok->last_in_offset = 0;
+	tok->in_char_offset = 0;
+	tok->last_in_char_offset = 0;
 	
 	tok->outtok = out_tokens;
 	tok->outtok_offset = 0;
-	/* Leave one slot for a null terminator */
-	assert(max_tokens > 0);
-	tok->outtok_size = max_tokens - 1;
+	tok->outtok_size = max_tokens;
 	
 	/* Prepare a buffer where all the token strings will be stored */
@@ -87,14 +89,13 @@
 
 /** Tokenize the input string into the tokens */
-int tok_tokenize(tokenizer_t *tok)
+int tok_tokenize(tokenizer_t *tok, size_t *tokens_length)
 {
 	int rc;
-	wchar_t cur_char;
+	wchar_t next_char;
 	
 	/* Read the input line char by char and append tokens */
-	while ((cur_char = tok_get_char(tok)) != 0) {
-		if (cur_char == ' ') {
-			/* Spaces delimit tokens, but are not processed in any way
-			 * Push the token if there is any.
+	while ((next_char = tok_look_char(tok)) != 0) {
+		if (next_char == ' ') {
+			/* Push the token if there is any.
 			 * There may not be any pending char for a token in case
 			 * there are several spaces in the input.
@@ -106,8 +107,15 @@
 				}
 			}
-		}
-		else if (cur_char == '|') {
-			/* Pipes are tokens that are delimiters and should be output
-			 * as a separate token
+			tok_start_token(tok, TOKTYPE_SPACE);
+			/* Eat all the spaces */
+			while (tok_look_char(tok) == ' ') {
+				tok_push_char(tok, tok_get_char(tok));
+			}
+			tok_push_token(tok);
+			
+		}
+		else if (next_char == '|') {
+			/* Pipes are tokens that are delimiters and should be
+			 * output as a separate token
 			 */
 			if (tok_pending_chars(tok)) {
@@ -118,5 +126,7 @@
 			}
 			
-			rc = tok_push_char(tok, '|');
+			tok_start_token(tok, TOKTYPE_PIPE);
+			
+			rc = tok_push_char(tok, tok_get_char(tok));
 			if (rc != EOK) {
 				return rc;
@@ -128,8 +138,11 @@
 			}
 		}
-		else if (cur_char == '\'') {
+		else if (next_char == '\'') {
 			/* A string starts with a quote (') and ends again with a quote.
 			 * A literal quote is written as ''
 			 */
+			tok_start_token(tok, TOKTYPE_TEXT);
+			/* Eat the quote */
+			tok_get_char(tok);
 			rc = tok_finish_string(tok);
 			if (rc != EOK) {
@@ -138,8 +151,11 @@
 		}
 		else {
+			if (!tok_pending_chars(tok)) {
+				tok_start_token(tok, TOKTYPE_TEXT);
+			}
 			/* If we are handling any other character, just append it to
 			 * the current token.
 			 */
-			rc = tok_push_char(tok, cur_char);
+			rc = tok_push_char(tok, tok_get_char(tok));
 			if (rc != EOK) {
 				return rc;
@@ -156,7 +172,5 @@
 	}
 	
-	/* We always have a space for the terminator, as we
-	 * reserved it in tok_init */
-	tok->outtok[tok->outtok_offset] = 0;
+	*tokens_length = tok->outtok_offset;
 	
 	return EOK;
@@ -167,8 +181,10 @@
 {
 	int rc;
-	wchar_t cur_char;
-	
-	while ((cur_char = tok_get_char(tok)) != 0) {
-		if (cur_char == '\'') {
+	wchar_t next_char;
+	
+	while ((next_char = tok_look_char(tok)) != 0) {
+		if (next_char == '\'') {
+			/* Eat the quote */
+			tok_get_char(tok);
 			if (tok_look_char(tok) == '\'') {
 				/* Encode a single literal quote */
@@ -187,5 +203,5 @@
 		}
 		else {
-			rc = tok_push_char(tok, cur_char);
+			rc = tok_push_char(tok, tok_get_char(tok));
 			if (rc != EOK) {
 				return rc;
@@ -201,4 +217,5 @@
 wchar_t tok_get_char(tokenizer_t *tok)
 {
+	tok->in_char_offset++;
 	return str_decode(tok->in, &tok->in_offset, STR_NO_LIMIT);
 }
@@ -208,6 +225,8 @@
 {
 	size_t old_offset = tok->in_offset;
+	size_t old_char_offset = tok->in_char_offset;
 	wchar_t ret = tok_get_char(tok);
 	tok->in_offset = old_offset;
+	tok->in_char_offset = old_char_offset;
 	return ret;
 }
@@ -219,4 +238,9 @@
 }
 
+void tok_start_token(tokenizer_t *tok, token_type_t type)
+{
+	tok->current_type = type;
+}
+
 /** Push the current token to the output array */
 int tok_push_token(tokenizer_t *tok)
@@ -231,6 +255,16 @@
 	
 	tok->outbuf[tok->outbuf_offset++] = 0;
-	tok->outtok[tok->outtok_offset++] = tok->outbuf + tok->outbuf_last_start;
+	token_t *tokinfo = &tok->outtok[tok->outtok_offset++];
+	tokinfo->type = tok->current_type;
+	tokinfo->text = tok->outbuf + tok->outbuf_last_start;
+	tokinfo->byte_start = tok->last_in_offset;
+	tokinfo->byte_length = tok->in_offset - tok->last_in_offset;
+	tokinfo->char_start = tok->last_in_char_offset;
+	tokinfo->char_length = tok->in_char_offset - tok->last_in_char_offset;
 	tok->outbuf_last_start = tok->outbuf_offset;
+	
+	/* We have consumed the first char of the next token already */
+	tok->last_in_offset = tok->in_offset;
+	tok->last_in_char_offset = tok->in_char_offset;
 	
 	return EOK;
Index: uspace/app/bdsh/tok.h
===================================================================
--- uspace/app/bdsh/tok.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bdsh/tok.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -30,7 +30,25 @@
 #define TOK_H
 
+typedef enum {
+	TOKTYPE_TEXT,
+	TOKTYPE_PIPE,
+	TOKTYPE_SPACE
+} token_type_t;
+
+typedef struct {
+	char *text;
+	size_t byte_start;
+	size_t char_start;
+	size_t byte_length;
+	size_t char_length;
+ 	token_type_t type;
+} token_t;
+
 typedef struct {
 	char *in;
 	size_t in_offset;
+	size_t last_in_offset;
+	size_t in_char_offset;
+	size_t last_in_char_offset;
 	
 	char *outbuf;
@@ -39,12 +57,13 @@
 	size_t outbuf_last_start;
 	
-	char **outtok;
+	token_t *outtok;
+	token_type_t current_type;
 	size_t outtok_offset;
 	size_t outtok_size;
 } tokenizer_t;
 
-extern int tok_init(tokenizer_t *, char *, char **, size_t);
+extern int tok_init(tokenizer_t *, char *, token_t *, size_t);
 extern void tok_fini(tokenizer_t *);
-extern int tok_tokenize(tokenizer_t *);
+extern int tok_tokenize(tokenizer_t *, size_t *);
 
 #endif
Index: uspace/app/blkdump/blkdump.c
===================================================================
--- uspace/app/blkdump/blkdump.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/blkdump/blkdump.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,5 +42,5 @@
 #include <libblock.h>
 #include <mem.h>
-#include <devmap.h>
+#include <loc.h>
 #include <byteorder.h>
 #include <sys/types.h>
@@ -59,5 +59,5 @@
 	int rc;
 	char *dev_path;
-	devmap_handle_t handle;
+	service_id_t service_id;
 	size_t block_size;
 	char *endptr;
@@ -128,5 +128,5 @@
 	dev_path = *argv;
 
-	rc = devmap_device_get_handle(dev_path, &handle, 0);
+	rc = loc_service_get_id(dev_path, &service_id, 0);
 	if (rc != EOK) {
 		printf(NAME ": Error resolving device `%s'.\n", dev_path);
@@ -134,5 +134,5 @@
 	}
 
-	rc = block_init(EXCHANGE_SERIALIZE, handle, 2048);
+	rc = block_init(EXCHANGE_SERIALIZE, service_id, 2048);
 	if (rc != EOK)  {
 		printf(NAME ": Error initializing libblock.\n");
@@ -140,5 +140,5 @@
 	}
 
-	rc = block_get_bsize(handle, &block_size);
+	rc = block_get_bsize(service_id, &block_size);
 	if (rc != EOK) {
 		printf(NAME ": Error determining device block size.\n");
@@ -146,5 +146,5 @@
 	}
 
-	rc = block_get_nblocks(handle, &dev_nblocks);
+	rc = block_get_nblocks(service_id, &dev_nblocks);
 	if (rc != EOK) {
 		printf(NAME ": Warning, failed to obtain block device size.\n");
@@ -156,5 +156,5 @@
 	if (data == NULL) {
 		printf(NAME ": Error allocating data buffer of %" PRIuOFF64 " bytes", (aoff64_t) block_size);
-		block_fini(handle);
+		block_fini(service_id);
 		return 3;
 	}
@@ -162,5 +162,5 @@
 	limit = block_offset + block_count;
 	for (current = block_offset; current < limit; current++) {
-		rc = block_read_direct(handle, current, 1, data);
+		rc = block_read_direct(service_id, current, 1, data);
 		if (rc != EOK) {
 			printf(NAME ": Error reading block at %" PRIuOFF64 " \n", current);
@@ -186,5 +186,5 @@
 	free(data);
 
-	block_fini(handle);
+	block_fini(service_id);
 
 	return 0;
Index: uspace/app/bnchmark/bnchmark.c
===================================================================
--- uspace/app/bnchmark/bnchmark.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/bnchmark/bnchmark.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,5 +41,5 @@
 #include <stdlib.h>
 #include <mem.h>
-#include <devmap.h>
+#include <loc.h>
 #include <byteorder.h>
 #include <sys/types.h>
Index: uspace/app/devctl/Makefile
===================================================================
--- uspace/app/devctl/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/app/devctl/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../..
+BINARY = devctl
+
+SOURCES = \
+	devctl.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/devctl/devctl.c
===================================================================
--- uspace/app/devctl/devctl.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/app/devctl/devctl.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,111 @@
+/*
+ * 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 devctl
+ * @{
+ */
+/** @file Control device framework (devman server).
+ */
+
+#include <devman.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/typefmt.h>
+
+#define NAME "devctl"
+
+#define MAX_NAME_LENGTH 1024
+
+static int fun_tree_print(devman_handle_t funh, int lvl)
+{
+	char name[MAX_NAME_LENGTH];
+	devman_handle_t devh;
+	devman_handle_t *cfuns;
+	size_t count, i;
+	int rc;
+	int j;
+
+	for (j = 0; j < lvl; j++)
+		printf("    ");
+
+	rc = devman_fun_get_name(funh, name, MAX_NAME_LENGTH);
+	if (rc != EOK) {
+		str_cpy(name, MAX_NAME_LENGTH, "unknown");
+		return ENOMEM;
+	}
+
+	if (name[0] == '\0')
+		str_cpy(name, MAX_NAME_LENGTH, "/");
+
+	printf("%s (%" PRIun ")\n", name, funh);
+
+	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++)
+		fun_tree_print(cfuns[i], lvl + 1);
+
+	free(cfuns);
+	return EOK;
+}
+
+int main(int argc, char *argv[])
+{
+	devman_handle_t root_fun;
+	int rc;
+
+	rc = devman_fun_get_handle("/", &root_fun, 0);
+	if (rc != EOK) {
+		printf(NAME ": Error resolving root function.\n");
+		return 1;
+	}
+
+	rc = fun_tree_print(root_fun, 0);
+	if (rc != EOK)
+		return 1;
+
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/ext2info/ext2info.c
===================================================================
--- uspace/app/ext2info/ext2info.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/ext2info/ext2info.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,5 +42,5 @@
 #include <libblock.h>
 #include <mem.h>
-#include <devmap.h>
+#include <loc.h>
 #include <byteorder.h>
 #include <sys/types.h>
@@ -81,5 +81,5 @@
 	char *endptr;
 	char *dev_path;
-	devmap_handle_t handle;
+	service_id_t service_id;
 	ext2_filesystem_t filesystem;
 	int arg_flags;
@@ -178,5 +178,5 @@
 	dev_path = *argv;
 
-	rc = devmap_device_get_handle(dev_path, &handle, 0);
+	rc = loc_service_get_id(dev_path, &service_id, 0);
 	if (rc != EOK) {
 		printf(NAME ": Error resolving device `%s'.\n", dev_path);
@@ -184,5 +184,5 @@
 	}
 
-	rc = ext2_filesystem_init(&filesystem, handle);
+	rc = ext2_filesystem_init(&filesystem, service_id);
 	if (rc != EOK)  {
 		printf(NAME ": Error initializing libext2.\n");
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/init/init.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -46,5 +46,5 @@
 #include <macros.h>
 #include <str.h>
-#include <devmap.h>
+#include <loc.h>
 #include <str_error.h>
 #include "init.h"
@@ -53,6 +53,6 @@
 #define ROOT_MOUNT_POINT  "/"
 
-#define DEVFS_FS_TYPE      "devfs"
-#define DEVFS_MOUNT_POINT  "/dev"
+#define LOCFS_FS_TYPE      "locfs"
+#define LOCFS_MOUNT_POINT  "/loc"
 
 #define TMPFS_FS_TYPE      "tmpfs"
@@ -66,4 +66,5 @@
 #define APP_GETTERM  "/app/getterm"
 
+/** Print banner */
 static void info_print(void)
 {
@@ -71,4 +72,5 @@
 }
 
+/** Report mount operation success */
 static bool mount_report(const char *desc, const char *mntpt,
     const char *fstype, const char *dev, int rc)
@@ -100,4 +102,15 @@
 }
 
+/** Mount root filesystem
+ *
+ * The operation blocks until the root filesystem
+ * server is ready for mounting.
+ *
+ * @param[in] fstype Root filesystem type.
+ *
+ * @return True on success.
+ * @return False on failure.
+ *
+ */
 static bool mount_root(const char *fstype)
 {
@@ -113,10 +126,19 @@
 }
 
-static bool mount_devfs(void)
-{
-	int rc = mount(DEVFS_FS_TYPE, DEVFS_MOUNT_POINT, "", "",
+/** Mount locfs filesystem
+ *
+ * The operation blocks until the locfs filesystem
+ * server is ready for mounting.
+ *
+ * @return True on success.
+ * @return False on failure.
+ *
+ */
+static bool mount_locfs(void)
+{
+	int rc = mount(LOCFS_FS_TYPE, LOCFS_MOUNT_POINT, "", "",
 	    IPC_FLAG_BLOCKING);
-	return mount_report("Device filesystem", DEVFS_MOUNT_POINT, DEVFS_FS_TYPE,
-	    NULL, rc);
+	return mount_report("Location service filesystem", LOCFS_MOUNT_POINT,
+	    LOCFS_FS_TYPE, NULL, rc);
 }
 
@@ -157,5 +179,5 @@
 	rc = task_wait(id, &texit, &retval);
 	if (rc != EOK) {
-		printf("%s: Error waiting for %s (%s(\n", NAME, fname,
+		printf("%s: Error waiting for %s (%s)\n", NAME, fname,
 		    str_error(rc));
 		return;
@@ -174,36 +196,36 @@
 }
 
-static void console(const char *dev)
-{
-	printf("%s: Spawning %s %s\n", NAME, SRV_CONSOLE, dev);
-	
-	/* Wait for the input device to be ready */
-	devmap_handle_t handle;
-	int rc = devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		printf("%s: Error waiting on %s (%s)\n", NAME, dev,
-		    str_error(rc));
-		return;
-	}
-	
-	rc = task_spawnl(NULL, SRV_CONSOLE, SRV_CONSOLE, dev, NULL);
+static void console(const char *svc)
+{
+	printf("%s: Spawning %s %s\n", NAME, SRV_CONSOLE, svc);
+	
+	/* Wait for the input service to be ready */
+	service_id_t service_id;
+	int rc = loc_service_get_id(svc, &service_id, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		printf("%s: Error waiting on %s (%s)\n", NAME, svc,
+		    str_error(rc));
+		return;
+	}
+	
+	rc = task_spawnl(NULL, SRV_CONSOLE, SRV_CONSOLE, svc, NULL);
 	if (rc != EOK) {
 		printf("%s: Error spawning %s %s (%s)\n", NAME, SRV_CONSOLE,
-		    dev, str_error(rc));
-	}
-}
-
-static void getterm(const char *dev, const char *app, bool wmsg)
-{
-	char term[DEVMAP_NAME_MAXLEN];
+		    svc, str_error(rc));
+	}
+}
+
+static void getterm(const char *svc, const char *app, bool wmsg)
+{
+	char term[LOC_NAME_MAXLEN];
 	int rc;
 	
-	snprintf(term, DEVMAP_NAME_MAXLEN, "%s/%s", DEVFS_MOUNT_POINT, dev);
+	snprintf(term, LOC_NAME_MAXLEN, "%s/%s", LOCFS_MOUNT_POINT, svc);
 	
 	printf("%s: Spawning %s %s %s\n", NAME, APP_GETTERM, term, app);
 	
-	/* Wait for the terminal device to be ready */
-	devmap_handle_t handle;
-	rc = devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING);
+	/* Wait for the terminal service to be ready */
+	service_id_t service_id;
+	rc = loc_service_get_id(svc, &service_id, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
 		printf("%s: Error waiting on %s (%s)\n", NAME, term,
@@ -257,8 +279,8 @@
 	}
 	
-	spawn("/srv/devfs");
+	spawn("/srv/locfs");
 	spawn("/srv/taskmon");
 	
-	if (!mount_devfs()) {
+	if (!mount_locfs()) {
 		printf("%s: Exiting\n", NAME);
 		return -2;
@@ -294,4 +316,8 @@
 	
 #ifdef CONFIG_MOUNT_DATA
+	/* Make sure fat is running. */
+	if (str_cmp(STRING(RDFMT), "fat") != 0) {
+		srv_start("/srv/fat");
+	}
 	mount_data();
 #else
Index: uspace/app/locinfo/Makefile
===================================================================
--- uspace/app/locinfo/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/app/locinfo/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../..
+EXTRA_CFLAGS = -Iinclude
+BINARY = locinfo
+
+SOURCES = \
+	locinfo.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/locinfo/locinfo.c
===================================================================
--- uspace/app/locinfo/locinfo.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/app/locinfo/locinfo.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,102 @@
+/*
+ * 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 locinfo
+ * @{
+ */
+/** @file locinfo.c Print information from location service.
+ */
+
+#include <errno.h>
+#include <loc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <str.h>
+#include <sys/types.h>
+#include <sys/typefmt.h>
+
+#define NAME "locinfo"
+
+int main(int argc, char *argv[])
+{
+	category_id_t *cat_ids;
+	size_t cat_cnt;
+	service_id_t *svc_ids;
+	size_t svc_cnt;
+
+	size_t i, j;
+	char *cat_name;
+	char *svc_name;
+	int rc;
+
+	rc = loc_get_categories(&cat_ids, &cat_cnt);
+	if (rc != EOK) {
+		printf(NAME ": Error getting list of categories.\n");
+		return 1;
+	}
+
+	for (i = 0; i < cat_cnt; i++) {
+		rc = loc_category_get_name(cat_ids[i], &cat_name);
+		if (rc != EOK)
+			cat_name = str_dup("<unknown>");
+
+		if (cat_name == NULL) {
+			printf(NAME ": Error allocating memory.\n");
+			return 1;
+		}
+
+		printf("%s (%" PRIun "):\n", cat_name, cat_ids[i]);
+
+		rc = loc_category_get_svcs(cat_ids[i], &svc_ids, &svc_cnt);
+		if (rc != EOK) {
+			printf(NAME ": Failed getting list of services in "
+			    "category %s, skipping.\n", cat_name);
+			free(cat_name);
+			continue;
+		}
+
+		for (j = 0; j < svc_cnt; j++) {
+			rc = loc_service_get_name(svc_ids[j], &svc_name);
+			if (rc != EOK) {
+				printf(NAME ": Unknown service name (SID %"
+				    PRIun ").\n", svc_ids[j]);
+				continue;
+			}
+			printf("\t%s (%" PRIun ")\n", svc_name, svc_ids[j]);
+		}
+
+		free(svc_ids);
+		free(cat_name);
+	}
+
+	free(cat_ids);
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/lsusb/main.c
===================================================================
--- uspace/app/lsusb/main.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/lsusb/main.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -43,5 +43,5 @@
 #include <getopt.h>
 #include <devman.h>
-#include <devmap.h>
+#include <loc.h>
 #include <usb/dev/hub.h>
 #include <usb/hc.h>
@@ -50,15 +50,12 @@
 
 #define MAX_USB_ADDRESS USB11_ADDRESS_MAX
-#define MAX_FAILED_ATTEMPTS 10
 #define MAX_PATH_LENGTH 1024
 
-static void print_found_hc(size_t class_index, const char *path)
+static void print_found_hc(service_id_t sid, const char *path)
 {
-	// printf(NAME ": host controller %zu is `%s'.\n", class_index, path);
-	printf("Bus %02zu: %s\n", class_index, path);
+	printf("Bus %" PRIun ": %s\n", sid, path);
 }
 static void print_found_dev(usb_address_t addr, const char *path)
 {
-	// printf(NAME ":     device with address %d is `%s'.\n", addr, path);
 	printf("  Device %02d: %s\n", addr, path);
 }
@@ -84,5 +81,5 @@
 		}
 		char path[MAX_PATH_LENGTH];
-		rc = devman_get_device_path(dev_handle, path, MAX_PATH_LENGTH);
+		rc = devman_fun_get_path(dev_handle, path, MAX_PATH_LENGTH);
 		if (rc != EOK) {
 			continue;
@@ -95,23 +92,43 @@
 int main(int argc, char *argv[])
 {
-	size_t class_index = 0;
-	size_t failed_attempts = 0;
+	category_id_t usbhc_cat;
+	service_id_t *svcs;
+	size_t count;
+	size_t i;
+	int rc;
 
-	while (failed_attempts < MAX_FAILED_ATTEMPTS) {
-		class_index++;
+	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_class(class_index, &hc_handle);
+		int rc = usb_ddf_get_hc_handle_by_sid(svcs[i], &hc_handle);
 		if (rc != EOK) {
-			failed_attempts++;
+			printf(NAME ": Error resolving handle of HC with SID %"
+			    PRIun ", skipping.\n", svcs[i]);
 			continue;
 		}
 		char path[MAX_PATH_LENGTH];
-		rc = devman_get_device_path(hc_handle, 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(class_index, path);
+		print_found_hc(svcs[i], path);
 		print_hc_devices(hc_handle);
 	}
+
+	free(svcs);
 
 	return 0;
Index: uspace/app/mkbd/main.c
===================================================================
--- uspace/app/mkbd/main.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/mkbd/main.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -43,5 +43,5 @@
 #include <getopt.h>
 #include <devman.h>
-#include <devmap.h>
+#include <loc.h>
 #include <usb/dev/hub.h>
 #include <usb/hid/iface.h>
@@ -240,5 +240,5 @@
 	
 	char path[MAX_PATH_LENGTH];
-	rc = devman_get_device_path(dev_handle, path, MAX_PATH_LENGTH);
+	rc = devman_fun_get_path(dev_handle, path, MAX_PATH_LENGTH);
 	if (rc != EOK) {
 		return ENOMEM;
Index: uspace/app/mkfat/mkfat.c
===================================================================
--- uspace/app/mkfat/mkfat.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/mkfat/mkfat.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,5 +42,5 @@
 #include <libblock.h>
 #include <mem.h>
-#include <devmap.h>
+#include <loc.h>
 #include <byteorder.h>
 #include <sys/types.h>
@@ -85,5 +85,5 @@
     struct fat_params *par);
 static int fat_blocks_write(struct fat_params const *par,
-    devmap_handle_t handle);
+    service_id_t service_id);
 static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs);
 
@@ -95,5 +95,5 @@
 	int rc;
 	char *dev_path;
-	devmap_handle_t handle;
+	service_id_t service_id;
 	size_t block_size;
 	char *endptr;
@@ -138,5 +138,5 @@
 	dev_path = *argv;
 
-	rc = devmap_device_get_handle(dev_path, &handle, 0);
+	rc = loc_service_get_id(dev_path, &service_id, 0);
 	if (rc != EOK) {
 		printf(NAME ": Error resolving device `%s'.\n", dev_path);
@@ -144,5 +144,5 @@
 	}
 
-	rc = block_init(EXCHANGE_SERIALIZE, handle, 2048);
+	rc = block_init(EXCHANGE_SERIALIZE, service_id, 2048);
 	if (rc != EOK)  {
 		printf(NAME ": Error initializing libblock.\n");
@@ -150,5 +150,5 @@
 	}
 
-	rc = block_get_bsize(handle, &block_size);
+	rc = block_get_bsize(service_id, &block_size);
 	if (rc != EOK) {
 		printf(NAME ": Error determining device block size.\n");
@@ -156,5 +156,5 @@
 	}
 
-	rc = block_get_nblocks(handle, &dev_nblocks);
+	rc = block_get_nblocks(service_id, &dev_nblocks);
 	if (rc != EOK) {
 		printf(NAME ": Warning, failed to obtain block device size.\n");
@@ -183,5 +183,5 @@
 	}
 
-	rc = fat_blocks_write(&par, handle);
+	rc = fat_blocks_write(&par, service_id);
 	if (rc != EOK) {
 		printf(NAME ": Error writing device.\n");
@@ -189,5 +189,5 @@
 	}
 
-	block_fini(handle);
+	block_fini(service_id);
 	printf("Success.\n");
 
@@ -234,5 +234,5 @@
 
 /** Create file system with the given parameters. */
-static int fat_blocks_write(struct fat_params const *par, devmap_handle_t handle)
+static int fat_blocks_write(struct fat_params const *par, service_id_t service_id)
 {
 	aoff64_t addr;
@@ -245,5 +245,5 @@
 	fat_bootsec_create(par, &bs);
 
-	rc = block_write_direct(handle, BS_BLOCK, 1, &bs);
+	rc = block_write_direct(service_id, BS_BLOCK, 1, &bs);
 	if (rc != EOK)
 		return EIO;
@@ -257,5 +257,5 @@
 	/* Reserved sectors */
 	for (i = 0; i < par->reserved_sectors - 1; ++i) {
-		rc = block_write_direct(handle, addr, 1, buffer);
+		rc = block_write_direct(service_id, addr, 1, buffer);
 		if (rc != EOK)
 			return EIO;
@@ -277,5 +277,5 @@
 			}
 
-			rc = block_write_direct(handle, addr, 1, buffer);
+			rc = block_write_direct(service_id, addr, 1, buffer);
 			if (rc != EOK)
 				return EIO;
@@ -291,5 +291,5 @@
 	/* Root directory */
 	for (i = 0; i < par->rootdir_sectors; ++i) {
-		rc = block_write_direct(handle, addr, 1, buffer);
+		rc = block_write_direct(service_id, addr, 1, buffer);
 		if (rc != EOK)
 			return EIO;
Index: uspace/app/sbi/src/input.c
===================================================================
--- uspace/app/sbi/src/input.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/sbi/src/input.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -176,4 +176,5 @@
 int input_get_line(input_t *input, char **line)
 {
+	const char *prompt;
 	const char *sp;
 	char *dp;
@@ -212,10 +213,10 @@
 		/* Interactive mode */
 		if (input->line_no == 0)
-			printf("sbi> ");
+			prompt = "sbi> ";
 		else
-			printf("...  ");
+			prompt = "...  ";
 
 		fflush(stdout);
-		if (os_input_line(&line_p) != EOK)
+		if (os_input_line(prompt, &line_p) != EOK)
 			return EIO;
 
Index: uspace/app/sbi/src/os/helenos.c
===================================================================
--- uspace/app/sbi/src/os/helenos.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/sbi/src/os/helenos.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -210,5 +210,5 @@
  * @param ptr	Place to store pointer to new string.
  */
-int os_input_line(char **ptr)
+int os_input_line(const char *prompt, char **ptr)
 {
 	char *line;
@@ -219,4 +219,6 @@
 		if (tinput == NULL)
 			return EIO;
+
+		tinput_set_prompt(tinput, prompt);
 	}
 
Index: uspace/app/sbi/src/os/os.h
===================================================================
--- uspace/app/sbi/src/os/os.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/sbi/src/os/os.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,5 @@
 char *os_chr_to_astr(wchar_t chr);
 void os_input_disp_help(void);
-int os_input_line(char **ptr);
+int os_input_line(const char *prompt, char **ptr);
 int os_exec(char * const cmd[]);
 
Index: uspace/app/sbi/src/os/posix.c
===================================================================
--- uspace/app/sbi/src/os/posix.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/sbi/src/os/posix.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -193,6 +193,8 @@
  * @param ptr	Place to store pointer to new string.
  */
-int os_input_line(char **ptr)
-{
+int os_input_line(const char *prompt, char **ptr)
+{
+	printf("%s", prompt);
+
 	if (fgets(os_input_buffer, OS_INPUT_BUFFER_SIZE, stdin) == NULL)
 		os_input_buffer[0] = '\0';
Index: uspace/app/taskdump/elf_core.c
===================================================================
--- uspace/app/taskdump/elf_core.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/taskdump/elf_core.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -38,12 +38,16 @@
  * Looking at core files produced by Linux, these don't have section headers,
  * only program headers, although objdump shows them as having sections.
- * Basically at the beginning there should be a note segment (which we
- * do not write) and one loadable segment per memory area (which we do write).
- *
- * The note segment probably contains register state, etc. -- we don't
- * deal with these yet. Nevertheless you can use these core files with
- * objdump or gdb.
- */
-
+ * Basically at the beginning there should be a note segment followed
+ * by one loadable segment per memory area.
+ *
+ * The note segment contains a series of records with register state,
+ * process info etc. We only write one record NT_PRSTATUS which contains
+ * process/register state (anything which is not register state we fill
+ * with zeroes).
+ */
+
+#include <align.h>
+#include <elf/elf.h>
+#include <elf/elf_linux.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -58,10 +62,10 @@
 #include <udebug.h>
 #include <macros.h>
-
-#include <elf.h>
-#include "include/elf_core.h"
+#include <libarch/istate.h>
+
+#include "elf_core.h"
 
 static off64_t align_foff_up(off64_t, uintptr_t, size_t);
-static int write_all(int, void *, size_t);
+static int align_pos(int, size_t);
 static int write_mem_area(int, as_area_info_t *, async_sess_t *);
 
@@ -83,5 +87,5 @@
  */
 int elf_core_save(const char *file_name, as_area_info_t *ainfo, unsigned int n,
-    async_sess_t *sess)
+    async_sess_t *sess, istate_t *istate)
 {
 	elf_header_t elf_hdr;
@@ -90,12 +94,29 @@
 	elf_word flags;
 	elf_segment_header_t *p_hdr;
+	elf_prstatus_t pr_status;
+	elf_note_t note;
+	size_t word_size;
 
 	int fd;
-	int rc;
+	ssize_t rc;
 	unsigned int i;
 
-	n_ph = n;
-
-	p_hdr = malloc(sizeof(elf_segment_header_t) * n);
+#ifdef __32_BITS__
+	word_size = 4;
+#endif
+#ifdef __64_BITS__
+	/*
+	 * This should be 8 per the 64-bit ELF spec, but the Linux kernel
+	 * screws up and uses 4 anyway (and screws up elf_note_t as well)
+	 * and we are trying to be compatible with Linux GDB target. Sigh.
+	 */
+	word_size = 4;
+#endif
+	memset(&pr_status, 0, sizeof(pr_status));
+	istate_to_elf_regs(istate, &pr_status.regs);
+
+	n_ph = n + 1;
+
+	p_hdr = malloc(sizeof(elf_segment_header_t) * n_ph);
 	if (p_hdr == NULL) {
 		printf("Failed allocating memory.\n");
@@ -115,7 +136,8 @@
 	 * 	ELF header
 	 *	program headers
+	 *	note segment
 	 * repeat:
 	 *	(pad for alignment)
-	 *	segment data
+	 *	core segment
 	 * end repeat
 	 */
@@ -147,30 +169,44 @@
 	foff = elf_hdr.e_phoff + n_ph * sizeof(elf_segment_header_t);
 
-	for (i = 1; i <= n; ++i) {
-		foff = align_foff_up(foff, ainfo[i - 1].start_addr, PAGE_SIZE);
+	memset(&p_hdr[0], 0, sizeof(p_hdr[0]));
+	p_hdr[0].p_type = PT_NOTE;
+	p_hdr[0].p_offset = foff;
+	p_hdr[0].p_vaddr = 0;
+	p_hdr[0].p_paddr = 0;
+	p_hdr[0].p_filesz = sizeof(elf_note_t)
+	    + ALIGN_UP((str_size("CORE") + 1), word_size)
+	    + ALIGN_UP(sizeof(elf_prstatus_t), word_size);
+	p_hdr[0].p_memsz = 0;
+	p_hdr[0].p_flags = 0;
+	p_hdr[0].p_align = 1;
+
+	foff += p_hdr[0].p_filesz;
+
+	for (i = 0; i < n; ++i) {
+		foff = align_foff_up(foff, ainfo[i].start_addr, PAGE_SIZE);
 
 		flags = 0;
-		if (ainfo[i - 1].flags & AS_AREA_READ)
+		if (ainfo[i].flags & AS_AREA_READ)
 			flags |= PF_R;
-		if (ainfo[i - 1].flags & AS_AREA_WRITE)
+		if (ainfo[i].flags & AS_AREA_WRITE)
 			flags |= PF_W;
-		if (ainfo[i - 1].flags & AS_AREA_EXEC)
+		if (ainfo[i].flags & AS_AREA_EXEC)
 			flags |= PF_X;
 
-		memset(&p_hdr[i - 1], 0, sizeof(p_hdr[i - 1]));
-		p_hdr[i - 1].p_type = PT_LOAD;
-		p_hdr[i - 1].p_offset = foff;
-		p_hdr[i - 1].p_vaddr = ainfo[i - 1].start_addr;
-		p_hdr[i - 1].p_paddr = 0;
-		p_hdr[i - 1].p_filesz = ainfo[i - 1].size;
-		p_hdr[i - 1].p_memsz = ainfo[i - 1].size;
-		p_hdr[i - 1].p_flags = flags;
-		p_hdr[i - 1].p_align = PAGE_SIZE;
-
-		foff += ainfo[i - 1].size;
+		memset(&p_hdr[i + 1], 0, sizeof(p_hdr[i + 1]));
+		p_hdr[i + 1].p_type = PT_LOAD;
+		p_hdr[i + 1].p_offset = foff;
+		p_hdr[i + 1].p_vaddr = ainfo[i].start_addr;
+		p_hdr[i + 1].p_paddr = 0;
+		p_hdr[i + 1].p_filesz = ainfo[i].size;
+		p_hdr[i + 1].p_memsz = ainfo[i].size;
+		p_hdr[i + 1].p_flags = flags;
+		p_hdr[i + 1].p_align = PAGE_SIZE;
+
+		foff += ainfo[i].size;
 	}
 
 	rc = write_all(fd, &elf_hdr, sizeof(elf_hdr));
-	if (rc != EOK) {
+	if (rc != sizeof(elf_hdr)) {
 		printf("Failed writing ELF header.\n");
 		free(p_hdr);
@@ -180,5 +216,5 @@
 	for (i = 0; i < n_ph; ++i) {
 		rc = write_all(fd, &p_hdr[i], sizeof(p_hdr[i]));
-		if (rc != EOK) {
+		if (rc != sizeof(p_hdr[i])) {
 			printf("Failed writing program header.\n");
 			free(p_hdr);
@@ -187,5 +223,46 @@
 	}
 
-	for (i = 0; i < n_ph; ++i) {
+	if (lseek(fd, p_hdr[0].p_offset, SEEK_SET) == (off64_t) -1) {
+		printf("Failed writing memory data.\n");
+		free(p_hdr);
+		return EIO;
+	}
+
+	/*
+	 * Write note header
+	 */
+	note.namesz = str_size("CORE") + 1;
+	note.descsz = sizeof(elf_prstatus_t);
+	note.type = NT_PRSTATUS;
+
+	rc = write_all(fd, &note, sizeof(elf_note_t));
+	if (rc != sizeof(elf_note_t)) {
+		printf("Failed writing note header.\n");
+		free(p_hdr);
+		return EIO;
+	}
+
+	rc = write_all(fd, "CORE", note.namesz);
+	if (rc != (ssize_t) note.namesz) {
+		printf("Failed writing note header.\n");
+		free(p_hdr);
+		return EIO;
+	}
+
+	rc = align_pos(fd, word_size);
+	if (rc != EOK) {
+		printf("Failed writing note header.\n");
+		free(p_hdr);
+		return EIO;
+	}
+
+	rc = write_all(fd, &pr_status, sizeof(elf_prstatus_t));
+	if (rc != sizeof(elf_prstatus_t)) {
+		printf("Failed writing register data.\n");
+		free(p_hdr);
+		return EIO;
+	}
+
+	for (i = 1; i < n_ph; ++i) {
 		if (lseek(fd, p_hdr[i].p_offset, SEEK_SET) == (off64_t) -1) {
 			printf("Failed writing memory data.\n");
@@ -193,5 +270,5 @@
 			return EIO;
 		}
-		if (write_mem_area(fd, &ainfo[i], sess) != EOK) {
+		if (write_mem_area(fd, &ainfo[i - 1], sess) != EOK) {
 			printf("Failed writing memory data.\n");
 			free(p_hdr);
@@ -210,8 +287,8 @@
 	off64_t rva = vaddr % page_size;
 	off64_t rfo = foff % page_size;
-	
+
 	if (rva >= rfo)
 		return (foff + (rva - rfo));
-	
+
 	return (foff + (page_size + (rva - rfo)));
 }
@@ -231,5 +308,5 @@
 	size_t total;
 	uintptr_t addr;
-	int rc;
+	ssize_t rc;
 
 	addr = area->start_addr;
@@ -245,5 +322,5 @@
 
 		rc = write_all(fd, buffer, to_copy);
-		if (rc != EOK) {
+		if (rc != (ssize_t) to_copy) {
 			printf("Failed writing memory contents.\n");
 			return EIO;
@@ -257,35 +334,23 @@
 }
 
-/** Write until the buffer is written in its entirety.
- *
- * This function fails if it cannot write exactly @a len bytes to the file.
- *
- * @param fd		The file to write to.
- * @param buf		Data, @a len bytes long.
- * @param len		Number of bytes to write.
- *
- * @return		EOK on error, return value from write() if writing
- *			failed.
- */
-static int write_all(int fd, void *data, size_t len)
+static int align_pos(int fd, size_t align)
 {
-	int cnt = 0;
-
-	do {
-		data += cnt;
-		len -= cnt;
-		cnt = write(fd, data, len);
-	} while (cnt > 0 && (len - cnt) > 0);
-
-	if (cnt < 0)
-		return cnt;
-
-	if (len - cnt > 0)
-		return EIO;
+	off64_t cur_pos;
+	size_t rem, adv;
+
+	cur_pos = lseek(fd, 0, SEEK_CUR);
+	if (cur_pos < 0)
+		return -1;
+
+	rem = cur_pos % align;
+	adv = align - rem;
+
+	cur_pos = lseek(fd, adv, SEEK_CUR);
+	if (cur_pos < 0)
+		return -1;
 
 	return EOK;
 }
 
-
 /** @}
  */
Index: pace/app/taskdump/include/elf.h
===================================================================
--- uspace/app/taskdump/include/elf.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,349 +1,0 @@
-/*
- * Copyright (c) 2006 Sergey Bondari
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING 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 ELF_H_
-#define ELF_H_
-
-#include <arch/elf.h>
-#include <sys/types.h>
-
-/**
- * current ELF version
- */
-#define	EV_CURRENT	1
-
-/** 
- * ELF types 
- */
-#define ET_NONE		0	/* No type */
-#define ET_REL		1	/* Relocatable file */
-#define ET_EXEC		2	/* Executable */
-#define ET_DYN		3	/* Shared object */
-#define ET_CORE		4	/* Core */
-#define ET_LOPROC	0xff00	/* Processor specific */
-#define ET_HIPROC	0xffff	/* Processor specific */
-
-/** 
- * ELF machine types
- */
-#define EM_NO		0	/* No machine */
-#define EM_SPARC	2	/* SPARC */
-#define EM_386		3	/* i386 */
-#define EM_MIPS		8	/* MIPS RS3000 */
-#define EM_MIPS_RS3_LE	10	/* MIPS RS3000 LE */
-#define EM_PPC		20	/* PPC32 */
-#define EM_PPC64	21	/* PPC64 */
-#define EM_ARM		40	/* ARM */
-#define EM_SPARCV9	43	/* SPARC64 */
-#define EM_IA_64	50	/* IA-64 */
-#define EM_X86_64	62	/* AMD64/EMT64 */
-
-/**
- * ELF identification indexes
- */
-#define EI_MAG0		0
-#define EI_MAG1		1
-#define EI_MAG2		2
-#define EI_MAG3		3
-#define EI_CLASS	4		/* File class */
-#define EI_DATA		5		/* Data encoding */
-#define EI_VERSION	6		/* File version */
-#define EI_OSABI	7
-#define EI_ABIVERSION	8
-#define EI_PAD		9		/* Start of padding bytes */
-#define EI_NIDENT	16		/* ELF identification table size */
-
-/**
- * ELF magic number
- */
-#define ELFMAG0		0x7f
-#define ELFMAG1		'E'
-#define ELFMAG2		'L'
-#define ELFMAG3		'F'
-
-/**
- * ELF file classes
- */
-#define ELFCLASSNONE	0
-#define ELFCLASS32	1
-#define ELFCLASS64	2
-
-/**
- * ELF data encoding types
- */
-#define ELFDATANONE	0
-#define ELFDATA2LSB	1		/* Least significant byte first (little endian) */
-#define ELFDATA2MSB	2		/* Most signigicant byte first (big endian) */
-
-/**
- * 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_IRRECOVERABLE	5
-
-/**
- * ELF section types
- */
-#define SHT_NULL		0
-#define SHT_PROGBITS		1
-#define SHT_SYMTAB		2
-#define SHT_STRTAB		3
-#define SHT_RELA		4
-#define SHT_HASH		5
-#define SHT_DYNAMIC		6
-#define SHT_NOTE		7
-#define SHT_NOBITS		8
-#define SHT_REL			9
-#define SHT_SHLIB		10
-#define SHT_DYNSYM		11
-#define SHT_LOOS		0x60000000
-#define SHT_HIOS		0x6fffffff
-#define SHT_LOPROC		0x70000000
-#define SHT_HIPROC		0x7fffffff
-#define SHT_LOUSER		0x80000000
-#define SHT_HIUSER		0xffffffff
-
-/**
- * ELF section flags
- */
-#define SHF_WRITE		0x1 
-#define SHF_ALLOC		0x2
-#define SHF_EXECINSTR		0x4
-#define SHF_TLS			0x400
-#define SHF_MASKPROC		0xf0000000
-
-/** Macros for decomposing elf_symbol.st_info into binging and type */
-#define ELF_ST_BIND(i)		((i) >> 4)
-#define ELF_ST_TYPE(i)		((i) & 0x0f)
-#define ELF_ST_INFO(b, t)	(((b) << 4) + ((t) & 0x0f))
-
-/**
- * Symbol binding
- */
-#define STB_LOCAL		0
-#define STB_GLOBAL		1
-#define STB_WEAK		2
-#define STB_LOPROC		13
-#define STB_HIPROC		15
-
-/**
- * Symbol types
- */
-#define STT_NOTYPE		0
-#define STT_OBJECT		1
-#define STT_FUNC		2
-#define STT_SECTION		3
-#define STT_FILE		4
-#define STT_LOPROC		13
-#define STT_HIPROC		15
-
-/**
- * Program segment types
- */
-#define PT_NULL			0
-#define PT_LOAD			1
-#define PT_DYNAMIC		2
-#define PT_INTERP		3
-#define PT_NOTE			4
-#define PT_SHLIB		5
-#define PT_PHDR			6
-#define PT_LOPROC		0x70000000
-#define PT_HIPROC		0x7fffffff
-
-/**
- * Program segment attributes.
- */
-#define PF_X	1
-#define PF_W	2
-#define PF_R	4
-
-/**
- * ELF data types
- *
- * These types are found to be identical in both 32-bit and 64-bit
- * ELF object file specifications. They are the only types used
- * in ELF header.
- */
-typedef uint64_t elf_xword;
-typedef int64_t elf_sxword;
-typedef uint32_t elf_word;
-typedef int32_t elf_sword;
-typedef uint16_t elf_half;
-
-/**
- * 32-bit ELF data types.
- *
- * These types are specific for 32-bit format.
- */
-typedef uint32_t elf32_addr;
-typedef uint32_t elf32_off;
-
-/**
- * 64-bit ELF data types.
- *
- * These types are specific for 64-bit format.
- */
-typedef uint64_t elf64_addr;
-typedef uint64_t elf64_off;
-
-/** ELF header */
-struct elf32_header {
-	uint8_t e_ident[EI_NIDENT];
-	elf_half e_type;
-	elf_half e_machine;
-	elf_word e_version;
-	elf32_addr e_entry;
-	elf32_off e_phoff;
-	elf32_off e_shoff;
-	elf_word e_flags;
-	elf_half e_ehsize;
-	elf_half e_phentsize;
-	elf_half e_phnum;
-	elf_half e_shentsize;
-	elf_half e_shnum;
-	elf_half e_shstrndx;
-};
-struct elf64_header {
-	uint8_t e_ident[EI_NIDENT];
-	elf_half e_type;
-	elf_half e_machine;
-	elf_word e_version;
-	elf64_addr e_entry;
-	elf64_off e_phoff;
-	elf64_off e_shoff;
-	elf_word e_flags;
-	elf_half e_ehsize;
-	elf_half e_phentsize;
-	elf_half e_phnum;
-	elf_half e_shentsize;
-	elf_half e_shnum;
-	elf_half e_shstrndx;
-};
-
-/*
- * ELF segment header.
- * Segments headers are also known as program headers.
- */
-struct elf32_segment_header {
-	elf_word p_type;
-	elf32_off p_offset;
-	elf32_addr p_vaddr;
-	elf32_addr p_paddr;
-	elf_word p_filesz;
-	elf_word p_memsz;
-	elf_word p_flags;
-	elf_word p_align;
-};
-struct elf64_segment_header {
-	elf_word p_type;
-	elf_word p_flags;
-	elf64_off p_offset;
-	elf64_addr p_vaddr;
-	elf64_addr p_paddr;
-	elf_xword p_filesz;
-	elf_xword p_memsz;
-	elf_xword p_align;
-};
-
-/*
- * ELF section header
- */
-struct elf32_section_header {
-	elf_word sh_name;
-	elf_word sh_type;
-	elf_word sh_flags;
-	elf32_addr sh_addr;
-	elf32_off sh_offset;
-	elf_word sh_size;
-	elf_word sh_link;
-	elf_word sh_info;
-	elf_word sh_addralign;
-	elf_word sh_entsize;
-};
-struct elf64_section_header {
-	elf_word sh_name;
-	elf_word sh_type;
-	elf_xword sh_flags;
-	elf64_addr sh_addr;
-	elf64_off sh_offset;
-	elf_xword sh_size;
-	elf_word sh_link;
-	elf_word sh_info;
-	elf_xword sh_addralign;
-	elf_xword sh_entsize;
-};
-
-/*
- * ELF symbol table entry
- */
-struct elf32_symbol {
-	elf_word st_name;
-	elf32_addr st_value;
-	elf_word st_size;
-	uint8_t st_info;
-	uint8_t st_other;
-	elf_half st_shndx;
-};
-struct elf64_symbol {
-	elf_word st_name;
-	uint8_t st_info;
-	uint8_t st_other;
-	elf_half st_shndx;
-	elf64_addr st_value;
-	elf_xword st_size;
-};
-
-#ifdef __32_BITS__ 
-typedef struct elf32_header elf_header_t;
-typedef struct elf32_segment_header elf_segment_header_t;
-typedef struct elf32_section_header elf_section_header_t;
-typedef struct elf32_symbol elf_symbol_t;
-#endif
-#ifdef __64_BITS__
-typedef struct elf64_header elf_header_t;
-typedef struct elf64_segment_header elf_segment_header_t;
-typedef struct elf64_section_header elf_section_header_t;
-typedef struct elf64_symbol elf_symbol_t;
-#endif
-
-extern char *elf_error(unsigned int rc);
-
-#endif
-
-/** @}
- */
Index: uspace/app/taskdump/include/elf_core.h
===================================================================
--- uspace/app/taskdump/include/elf_core.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/taskdump/include/elf_core.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,7 +37,9 @@
 
 #include <async.h>
+#include <elf/elf_linux.h>
+#include <libarch/istate.h>
 
 extern int elf_core_save(const char *, as_area_info_t *, unsigned int,
-    async_sess_t *);
+    async_sess_t *, istate_t *);
 
 #endif
Index: uspace/app/taskdump/include/symtab.h
===================================================================
--- uspace/app/taskdump/include/symtab.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/taskdump/include/symtab.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,6 +36,6 @@
 #define SYMTAB_H_
 
+#include <elf/elf.h>
 #include <sys/types.h>
-#include <elf.h>
 
 typedef struct {
Index: uspace/app/taskdump/symtab.c
===================================================================
--- uspace/app/taskdump/symtab.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/taskdump/symtab.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,4 +36,5 @@
  */
 
+#include <elf/elf.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -43,5 +44,4 @@
 #include <fcntl.h>
 
-#include <elf.h>
 #include "include/symtab.h"
 
@@ -50,5 +50,4 @@
     elf_section_header_t *shdr);
 static int chunk_load(int fd, off64_t start, size_t size, void **ptr);
-static int read_all(int fd, void *buf, size_t len);
 
 /** Load symbol table from an ELF file.
@@ -90,5 +89,5 @@
 
 	rc = read_all(fd, &elf_hdr, sizeof(elf_header_t));
-	if (rc != EOK) {
+	if (rc != sizeof(elf_header_t)) {
 		printf("failed reading elf header\n");
 		free(stab);
@@ -312,5 +311,5 @@
 
 	rc = read_all(fd, sec_hdr, sizeof(elf_section_header_t));
-	if (rc != EOK)
+	if (rc != sizeof(elf_section_header_t))
 		return EIO;
 
@@ -331,8 +330,9 @@
 static int chunk_load(int fd, off64_t start, size_t size, void **ptr)
 {
-	int rc;
-
-	rc = lseek(fd, start, SEEK_SET);
-	if (rc == (off64_t) -1) {
+	ssize_t rc;
+	off64_t offs;
+
+	offs = lseek(fd, start, SEEK_SET);
+	if (offs == (off64_t) -1) {
 		printf("failed seeking chunk\n");
 		*ptr = NULL;
@@ -347,5 +347,5 @@
 
 	rc = read_all(fd, *ptr, size);
-	if (rc != EOK) {
+	if (rc != (ssize_t) size) {
 		printf("failed reading chunk\n");
 		free(*ptr);
@@ -357,34 +357,4 @@
 }
 
-/** Read until the buffer is read in its entirety.
- *
- * This function fails if it cannot read exactly @a len bytes from the file.
- *
- * @param fd		The file to read from.
- * @param buf		Buffer for storing data, @a len bytes long.
- * @param len		Number of bytes to read.
- *
- * @return		EOK on error, EIO if file is short or return value
- *			from read() if reading failed.
- */
-static int read_all(int fd, void *buf, size_t len)
-{
-	int cnt = 0;
-
-	do {
-		buf += cnt;
-		len -= cnt;
-		cnt = read(fd, buf, len);
-	} while (cnt > 0 && (len - cnt) > 0);
-
-	if (cnt < 0)
-		return cnt;
-
-	if (len - cnt > 0)
-		return EIO;
-
-	return EOK;
-}
-
 /** @}
  */
Index: uspace/app/taskdump/taskdump.c
===================================================================
--- uspace/app/taskdump/taskdump.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/taskdump/taskdump.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -34,4 +34,5 @@
 
 #include <async.h>
+#include <elf/elf_linux.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -72,4 +73,6 @@
 static char *get_app_task_name(void);
 static char *fmt_sym_address(uintptr_t addr);
+
+static istate_t reg_state;
 
 int main(int argc, char *argv[])
@@ -293,5 +296,8 @@
 	if (write_core_file) {
 		printf("Writing core file '%s'\n", core_file_name);
-		rc = elf_core_save(core_file_name, ainfo_buf, n_areas, sess);
+
+		rc = elf_core_save(core_file_name, ainfo_buf, n_areas, sess,
+		    &reg_state);
+
 		if (rc != EOK) {
 			printf("Failed writing core file.\n");
@@ -321,4 +327,7 @@
 	pc = istate_get_pc(&istate);
 	fp = istate_get_fp(&istate);
+
+	/* Save register state for dumping to core file later. */
+	reg_state = istate;
 
 	sym_pc = fmt_sym_address(pc);
Index: uspace/app/tester/Makefile
===================================================================
--- uspace/app/tester/Makefile	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/tester/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -56,6 +56,4 @@
 	mm/malloc3.c \
 	mm/mapping1.c \
-	devs/devman1.c \
-	devs/devman2.c \
 	hw/misc/virtchar1.c \
 	hw/serial/serial1.c \
Index: pace/app/tester/devs/devman1.c
===================================================================
--- uspace/app/tester/devs/devman1.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,89 +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.
- */
-
-/** @addtogroup tester
- * @brief Test devman service.
- * @{
- */
-/**
- * @file
- */
-
-#include <inttypes.h>
-#include <errno.h>
-#include <str_error.h>
-#include <sys/types.h>
-#include <async.h>
-#include <devman.h>
-#include <str.h>
-#include <vfs/vfs.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "../tester.h"
-
-#define DEVICE_PATH_NORMAL "/virt/null/a"
-#define DEVICE_CLASS "virt-null"
-#define DEVICE_CLASS_NAME "1"
-#define DEVICE_PATH_CLASSES DEVICE_CLASS "/" DEVICE_CLASS_NAME
-
-const char *test_devman1(void)
-{
-	devman_handle_t handle_primary;
-	devman_handle_t handle_class;
-	
-	int rc;
-	
-	TPRINTF("Asking for handle of `%s'...\n", DEVICE_PATH_NORMAL);
-	rc = devman_device_get_handle(DEVICE_PATH_NORMAL, &handle_primary, 0);
-	if (rc != EOK) {
-		TPRINTF(" ...failed: %s.\n", str_error(rc));
-		if (rc == ENOENT) {
-			TPRINTF("Have you compiled the test drivers?\n");
-		}
-		return "Failed getting device handle";
-	}
-
-	TPRINTF("Asking for handle of `%s' by class..\n", DEVICE_PATH_CLASSES);
-	rc = devman_device_get_handle_by_class(DEVICE_CLASS, DEVICE_CLASS_NAME,
-	    &handle_class, 0);
-	if (rc != EOK) {
-		TPRINTF(" ...failed: %s.\n", str_error(rc));
-		return "Failed getting device class handle";
-	}
-
-	TPRINTF("Received handles %" PRIun " and %" PRIun ".\n",
-	    handle_primary, handle_class);
-	if (handle_primary != handle_class) {
-		return "Retrieved different handles for the same device";
-	}
-
-	return NULL;
-}
-
-/** @}
- */
Index: pace/app/tester/devs/devman1.def
===================================================================
--- uspace/app/tester/devs/devman1.def	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,6 +1,0 @@
-{
-	"devman1",
-	"devman test",
-	&test_devman1,
-	false
-},
Index: pace/app/tester/devs/devman2.c
===================================================================
--- uspace/app/tester/devs/devman2.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,94 +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.
- */
-
-/** @addtogroup tester
- * @brief Test devman service.
- * @{
- */
-/**
- * @file
- */
-
-#include <inttypes.h>
-#include <errno.h>
-#include <str_error.h>
-#include <sys/types.h>
-#include <async.h>
-#include <devman.h>
-#include <str.h>
-#include <async.h>
-#include <vfs/vfs.h>
-#include <vfs/vfs_sess.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "../tester.h"
-
-#define DEVICE_CLASS "test3"
-
-const char *test_devman2(void)
-{
-	size_t idx = 1;
-	int rc = EOK;
-	const char *err_msg = NULL;
-	char *path = NULL;
-	while (rc == EOK) {
-		rc = asprintf(&path, "/dev/class/%s\\%zu", DEVICE_CLASS, idx);
-		if (rc < 0) {
-			continue;
-		}
-		int fd = open(path, O_RDONLY);
-		if (fd < 0) {
-			TPRINTF("Failed opening `%s': %s.\n",
-			    path, str_error(fd));
-			rc = fd;
-			err_msg = "Failed opening file";
-			continue;
-		}
-		async_sess_t *sess = fd_session(EXCHANGE_SERIALIZE, fd);
-		close(fd);
-		if (sess == NULL) {
-			TPRINTF("Failed opening phone: %s.\n", str_error(errno));
-			rc = errno;
-			err_msg = "Failed opening file descriptor phone";
-			continue;
-		}
-		async_hangup(sess);
-		TPRINTF("Path `%s' okay.\n", path);
-		free(path);
-		idx++;
-		rc = EOK;
-	}
-	
-	if (path != NULL)
-		free(path);
-	
-	return err_msg;
-}
-
-/** @}
- */
Index: pace/app/tester/devs/devman2.def
===================================================================
--- uspace/app/tester/devs/devman2.def	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,6 +1,0 @@
-{
-	"devman2",
-	"devman test",
-	&test_devman2,
-	false
-},
Index: uspace/app/tester/hw/misc/virtchar1.c
===================================================================
--- uspace/app/tester/hw/misc/virtchar1.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/tester/hw/misc/virtchar1.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -48,6 +48,5 @@
 #include "../../tester.h"
 
-#define DEVICE_PATH_NORMAL "/dev/devices/\\virt\\null\\a"
-#define DEVICE_PATH_CLASSES "/dev/class/virt-null\\1"
+#define DEVICE_PATH_NORMAL "/loc/devices/\\virt\\null\\a"
 #define BUFFER_SIZE 64
 
@@ -105,9 +104,4 @@
 	}
 
-	res = test_virtchar1_internal(DEVICE_PATH_CLASSES);
-	if (res != NULL) {
-		return res;
-	}
-
 	return NULL;
 }
Index: uspace/app/tester/hw/serial/serial1.c
===================================================================
--- uspace/app/tester/hw/serial/serial1.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/tester/hw/serial/serial1.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -72,5 +72,5 @@
 	
 	devman_handle_t handle;
-	int res = devman_device_get_handle("/hw/pci0/00:01.0/com1/a", &handle,
+	int res = devman_fun_get_handle("/hw/pci0/00:01.0/com1/a", &handle,
 	    IPC_FLAG_BLOCKING);
 	if (res != EOK)
Index: uspace/app/tester/stdio/stdio1.c
===================================================================
--- uspace/app/tester/stdio/stdio1.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/tester/stdio/stdio1.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,5 @@
 {
 	FILE *file;
-	const char *file_name = "/readme";
+	const char *file_name = "/textdemo";
 	
 	TPRINTF("Open file \"%s\"...", file_name);
Index: uspace/app/tester/tester.c
===================================================================
--- uspace/app/tester/tester.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/tester/tester.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -68,6 +68,4 @@
 #include "hw/misc/virtchar1.def"
 #include "libext2/libext2_1.def"
-#include "devs/devman1.def"
-#include "devs/devman2.def"
 	{NULL, NULL, NULL, false}
 };
Index: uspace/app/tester/vfs/vfs1.c
===================================================================
--- uspace/app/tester/vfs/vfs1.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/tester/vfs/vfs1.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -35,5 +35,5 @@
 #include <fcntl.h>
 #include <dirent.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sys/types.h>
 #include <sys/stat.h>
Index: uspace/app/testread/testread.c
===================================================================
--- uspace/app/testread/testread.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/testread/testread.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -50,5 +50,5 @@
 #include <stdlib.h>
 #include <mem.h>
-#include <devmap.h>
+#include <loc.h>
 #include <byteorder.h>
 #include <sys/types.h>
Index: uspace/app/top/top.c
===================================================================
--- uspace/app/top/top.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/top/top.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,5 +42,4 @@
 #include <thread.h>
 #include <sys/time.h>
-#include <arch/barrier.h>
 #include <errno.h>
 #include <sort.h>
Index: uspace/app/trace/ipc_desc.c
===================================================================
--- uspace/app/trace/ipc_desc.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/trace/ipc_desc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -33,6 +33,5 @@
  */
 
-#include <kernel/ipc/ipc.h>
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 #include <stdlib.h>
 #include "ipc_desc.h"
Index: uspace/app/trace/ipcp.c
===================================================================
--- uspace/app/trace/ipcp.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/trace/ipcp.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,5 +37,5 @@
 #include <adt/hash_table.h>
 #include <sys/typefmt.h>
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 #include "ipc_desc.h"
 #include "proto.h"
Index: uspace/app/trace/syscalls.c
===================================================================
--- uspace/app/trace/syscalls.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/trace/syscalls.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -33,5 +33,5 @@
  */
 
-#include <kernel/syscall/syscall.h>
+#include <abi/syscall.h>
 #include "syscalls.h"
 #include "trace.h"
Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/trace/trace.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -50,4 +50,5 @@
 #include <sys/types.h>
 #include <sys/typefmt.h>
+#include <vfs/vfs.h>
 
 #include <libc.h>
@@ -586,21 +587,21 @@
 
 	/* Send default files */
-	fdi_node_t *files[4];
-	fdi_node_t stdin_node;
-	fdi_node_t stdout_node;
-	fdi_node_t stderr_node;
-	
-	if ((stdin != NULL) && (fnode(stdin, &stdin_node) == EOK))
-		files[0] = &stdin_node;
+	int *files[4];
+	int fd_stdin;
+	int fd_stdout;
+	int fd_stderr;
+	
+	if ((stdin != NULL) && (fhandle(stdin, &fd_stdin) == EOK))
+		files[0] = &fd_stdin;
 	else
 		files[0] = NULL;
 	
-	if ((stdout != NULL) && (fnode(stdout, &stdout_node) == EOK))
-		files[1] = &stdout_node;
+	if ((stdout != NULL) && (fhandle(stdout, &fd_stdout) == EOK))
+		files[1] = &fd_stdout;
 	else
 		files[1] = NULL;
 	
-	if ((stderr != NULL) && (fnode(stderr, &stderr_node) == EOK))
-		files[2] = &stderr_node;
+	if ((stderr != NULL) && (fhandle(stderr, &fd_stderr) == EOK))
+		files[2] = &fd_stderr;
 	else
 		files[2] = NULL;
@@ -761,6 +762,4 @@
 	o = oper_new("open", 2, arg_def, V_INT_ERRNO, 0, resp_def);
 	proto_add_oper(p, VFS_IN_OPEN, o);
-	o = oper_new("open_node", 4, arg_def, V_INT_ERRNO, 0, resp_def);
-	proto_add_oper(p, VFS_IN_OPEN_NODE, o);
 	o = oper_new("read", 1, arg_def, V_ERRNO, 1, resp_def);
 	proto_add_oper(p, VFS_IN_READ, o);
Index: uspace/app/usbinfo/main.c
===================================================================
--- uspace/app/usbinfo/main.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/app/usbinfo/main.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,5 +42,5 @@
 #include <getopt.h>
 #include <devman.h>
-#include <devmap.h>
+#include <loc.h>
 #include <usb/hc.h>
 #include <usb/dev/pipes.h>
Index: pace/dist/readme
===================================================================
--- uspace/dist/readme	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,10 +1,0 @@
-Multilingual text test
-----------------------
-
-English:  Quick brown fox jumps over the lazy dog
-Czech:    Příliš žluťoučký kůň úpěl ďábelské ódy
-Greek:    Ὦ ξεῖν’, ἀγγέλλειν Λακεδαιμονίοις ὅτι τῇδε
-Hebrew:   משוואת ברנולי היא משוואה בהידרודינמיקה
-Arabic:   التوزيع الجغرافي للحمل العنقودي
-Russian:  Леннон познакомился с художницей-авангардисткой
-Armenian: Սկսեց հրատարակվել Երուսաղեմի հայկական
Index: uspace/dist/src/sysel/demos/htxtfile.sy
===================================================================
--- uspace/dist/src/sysel/demos/htxtfile.sy	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/dist/src/sysel/demos/htxtfile.sy	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -35,5 +35,5 @@
 		var out_file : TextFile;
 
-		name = "/readme";
+		name = "/textdemo";
 
 		in_file = new TextFile();
Index: uspace/dist/textdemo
===================================================================
--- uspace/dist/textdemo	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/dist/textdemo	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,10 @@
+Multilingual text test
+----------------------
+
+English:  Quick brown fox jumps over the lazy dog
+Czech:    Příliš žluťoučký kůň úpěl ďábelské ódy
+Greek:    Ὦ ξεῖν’, ἀγγέλλειν Λακεδαιμονίοις ὅτι τῇδε
+Hebrew:   משוואת ברנולי היא משוואה בהידרודינמיקה
+Arabic:   التوزيع الجغرافي للحمل العنقودي
+Russian:  Леннон познакомился с художницей-авангардисткой
+Armenian: Սկսեց հրատարակվել Երուսաղեմի հայկական
Index: uspace/doc/doxygroups.h
===================================================================
--- uspace/doc/doxygroups.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/doc/doxygroups.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -322,6 +322,6 @@
 	 * The purpose of this driver is to simplify querying of unknown
 	 * devices from within HelenOS (without a driver, no node at all
-	 * may appear under /dev/devices).
-	 */
-
-
+	 * may appear under /loc/devices).
+	 */
+
+
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/isa/isa.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -352,4 +352,6 @@
 		    str_error(rc));
 	}
+
+	free(id);
 }
 
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -342,4 +342,6 @@
 	}
 	
+	free(match_id_str);
+	
 	/* TODO add more ids (with subsys ids, using class id etc.) */
 }
Index: uspace/drv/bus/usb/ehci/main.c
===================================================================
--- uspace/drv/bus/usb/ehci/main.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/ehci/main.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -101,5 +101,5 @@
 	    "Failed to bind EHCI function: %s.\n",
 	    str_error(ret));
-	ret = ddf_fun_add_to_class(hc_fun, USB_HC_DDF_CLASS_NAME);
+	ret = ddf_fun_add_to_category(hc_fun, USB_HC_CATEGORY);
 	CHECK_RET_RETURN(ret,
 	    "Failed to add EHCI to HC class: %s.\n",
Index: uspace/drv/bus/usb/ohci/endpoint_list.c
===================================================================
--- uspace/drv/bus/usb/ohci/endpoint_list.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/ohci/endpoint_list.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -26,4 +26,5 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 /** @addtogroup drvusbohci
  * @{
@@ -32,8 +33,8 @@
  * @brief OHCI driver transfer list implementation
  */
+
 #include <errno.h>
 #include <usb/debug.h>
-#include <arch/barrier.h>
-
+#include <libarch/barrier.h>
 #include "endpoint_list.h"
 
Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -46,8 +46,73 @@
 #define OHCI_USED_INTERRUPTS \
     (I_SO | I_WDH | I_UE | I_RHSC)
-static int interrupt_emulator(hc_t *instance);
+
+static const irq_cmd_t ohci_irq_commands[] =
+{
+	{ .cmd = CMD_MEM_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_MEM_WRITE_A_32, .srcarg = 1, .addr = NULL /*filled later*/ },
+	{ .cmd = CMD_ACCEPT },
+};
+
 static void hc_gain_control(hc_t *instance);
+static void hc_start(hc_t *instance);
 static int hc_init_transfer_lists(hc_t *instance);
 static int hc_init_memory(hc_t *instance);
+static int interrupt_emulator(hc_t *instance);
+
+/*----------------------------------------------------------------------------*/
+/** Get number of commands used in IRQ code.
+ * @return Number of commands.
+ */
+size_t hc_irq_cmd_count(void)
+{
+	return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);
+}
+/*----------------------------------------------------------------------------*/
+/** Generate IRQ code commands.
+ * @param[out] cmds Place to store the commands.
+ * @param[in] cmd_size Size of the place (bytes).
+ * @param[in] regs Physical address of device's registers.
+ * @param[in] reg_size Size of the register area (bytes).
+ *
+ * @return Error code.
+ */
+int hc_get_irq_commands(
+    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
+{
+	if (cmd_size < sizeof(ohci_irq_commands)
+	    || reg_size < sizeof(ohci_regs_t))
+		return EOVERFLOW;
+
+	/* Create register mapping to use in IRQ handler.
+	 * This mapping should be present in kernel only.
+	 * Remove it from here when kernel knows how to create mappings
+	 * and accepts physical addresses in IRQ code.
+	 * TODO: remove */
+	ohci_regs_t *registers;
+	const int ret = pio_enable((void*)regs, reg_size, (void**)&registers);
+	if (ret != EOK)
+		return ret;
+
+	/* Some bogus access to force create mapping. DO NOT remove,
+	 * unless whole virtual addresses in irq is replaced
+	 * NOTE: Compiler won't remove this as ohci_regs_t members
+	 * are declared volatile.
+	 *
+	 * Introducing CMD_MEM set of IRQ code commands broke
+	 * assumption that IRQ code does not cause page faults.
+	 * If this happens during idling (THREAD == NULL)
+	 * it causes kernel panic.
+	 */
+	registers->revision;
+
+	memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
+
+	void *address = (void*)&registers->interrupt_status;
+	cmds[0].addr = address;
+	cmds[3].addr = address;
+	return EOK;
+}
 /*----------------------------------------------------------------------------*/
 /** Announce OHCI root hub to the DDF
@@ -83,17 +148,14 @@
 	int ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
 	    USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
-	CHECK_RET_RELEASE(ret, "Failed(%d) to add OHCI rh endpoint 0.\n", ret);
-
-	char *match_str = NULL;
-	/* DDF needs heap allocated string */
-	ret = asprintf(&match_str, "usb&class=hub");
-	ret = ret > 0 ? 0 : ret;
-	CHECK_RET_RELEASE(ret, "Failed(%d) to create match-id string.\n", ret);
-
-	ret = ddf_fun_add_match_id(hub_fun, match_str, 100);
-	CHECK_RET_RELEASE(ret, "Failed(%d) add root hub match-id.\n", ret);
+	CHECK_RET_RELEASE(ret,
+	    "Failed to add OHCI root hub endpoint 0: %s.\n", str_error(ret));
+
+	ret = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100);
+	CHECK_RET_RELEASE(ret,
+	    "Failed to add root hub match-id: %s.\n", str_error(ret));
 
 	ret = ddf_fun_bind(hub_fun);
-	CHECK_RET_RELEASE(ret, "Failed(%d) to bind root hub function.\n", ret);
+	CHECK_RET_RELEASE(ret,
+	    "Failed to bind root hub function: %s.\n", str_error(ret));
 
 	return EOK;
@@ -112,5 +174,5 @@
 {
 	assert(instance);
-	int ret = EOK;
+
 #define CHECK_RET_RETURN(ret, message...) \
 if (ret != EOK) { \
@@ -119,11 +181,12 @@
 } else (void)0
 
-	ret = pio_enable((void*)regs, reg_size, (void**)&instance->registers);
+	int ret =
+	    pio_enable((void*)regs, reg_size, (void**)&instance->registers);
 	CHECK_RET_RETURN(ret,
-	    "Failed(%d) to gain access to device registers: %s.\n",
-	    ret, str_error(ret));
+	    "Failed to gain access to device registers: %s.\n", str_error(ret));
 
 	list_initialize(&instance->pending_batches);
 	usb_device_keeper_init(&instance->manager);
+
 	ret = usb_endpoint_manager_init(&instance->ep_manager,
 	    BANDWIDTH_AVAILABLE_USB11);
@@ -137,7 +200,6 @@
 
 	fibril_mutex_initialize(&instance->guard);
+
 	hc_gain_control(instance);
-
-	rh_init(&instance->rh, instance->registers);
 
 	if (!interrupts) {
@@ -147,8 +209,11 @@
 	}
 
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Create end register endpoint structures
+	rh_init(&instance->rh, instance->registers);
+	hc_start(instance);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Create and register endpoint structures.
  *
  * @param[in] instance OHCI driver structure.
@@ -168,13 +233,8 @@
     size_t mps, size_t size, unsigned interval)
 {
-	endpoint_t *ep = malloc(sizeof(endpoint_t));
+	endpoint_t *ep =
+	    endpoint_get(address, endpoint, direction, type, speed, mps);
 	if (ep == NULL)
 		return ENOMEM;
-	int ret =
-	    endpoint_init(ep, address, endpoint, direction, type, speed, mps);
-	if (ret != EOK) {
-		free(ep);
-		return ret;
-	}
 
 	hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
@@ -184,5 +244,6 @@
 	}
 
-	ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
+	int ret =
+	    usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
 	if (ret != EOK) {
 		hcd_endpoint_clear(ep);
@@ -212,6 +273,4 @@
 		    &instance->lists[ep->transfer_type], hcd_ep);
 		instance->registers->control |= C_PLE | C_IE;
-		break;
-	default:
 		break;
 	}
@@ -312,5 +371,6 @@
 	/* Check for root hub communication */
 	if (batch->ep->address == instance->rh.address) {
-		return rh_request(&instance->rh, batch);
+		rh_request(&instance->rh, batch);
+		return EOK;
 	}
 
@@ -374,5 +434,5 @@
 
 	if (status & I_UE) {
-		hc_start_hw(instance);
+		hc_start(instance);
 	}
 
@@ -399,4 +459,7 @@
 /** Turn off any (BIOS)driver that might be in control of the device.
  *
+ * This function implements routines described in chapter 5.1.1.3 of the OHCI
+ * specification (page 40, pdf page 54).
+ *
  * @param[in] instance OHCI hc driver structure.
  */
@@ -404,14 +467,22 @@
 {
 	assert(instance);
+
 	usb_log_debug("Requesting OHCI control.\n");
-	/* Turn off legacy emulation */
-	volatile uint32_t *ohci_emulation_reg =
-	    (uint32_t*)((char*)instance->registers + 0x100);
-	usb_log_debug("OHCI legacy register %p: %x.\n",
-	    ohci_emulation_reg, *ohci_emulation_reg);
-	/* Do not change A20 state */
-	*ohci_emulation_reg &= 0x100;
-	usb_log_debug("OHCI legacy register %p: %x.\n",
-	    ohci_emulation_reg, *ohci_emulation_reg);
+	if (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
+		 * except GateA20 (causes restart on some hw).
+		 * See page 145 of the specs for details.
+		 */
+		volatile uint32_t *ohci_emulation_reg =
+		(uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
+		usb_log_debug("OHCI legacy register %p: %x.\n",
+		    ohci_emulation_reg, *ohci_emulation_reg);
+		/* Zero everything but A20State */
+		*ohci_emulation_reg &= 0x100;
+		usb_log_debug(
+		    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
+		    ohci_emulation_reg, *ohci_emulation_reg);
+	}
 
 	/* Interrupt routing enabled => smm driver is active */
@@ -419,15 +490,15 @@
 		usb_log_debug("SMM driver: request ownership change.\n");
 		instance->registers->command_status |= CS_OCR;
+		/* Hope that SMM actually knows its stuff or we can hang here */
 		while (instance->registers->control & C_IR) {
 			async_usleep(1000);
 		}
 		usb_log_info("SMM driver: Ownership taken.\n");
-		instance->registers->control &= (C_HCFS_RESET << C_HCFS_SHIFT);
+		C_HCFS_SET(instance->registers->control, C_HCFS_RESET);
 		async_usleep(50000);
 		return;
 	}
 
-	const unsigned hc_status =
-	    (instance->registers->control >> C_HCFS_SHIFT) & C_HCFS_MASK;
+	const unsigned hc_status = C_HCFS_GET(instance->registers->control);
 	/* Interrupt routing disabled && status != USB_RESET => BIOS active */
 	if (hc_status != C_HCFS_RESET) {
@@ -437,6 +508,6 @@
 			return;
 		}
-		/* HC is suspended assert resume for 20ms */
-		instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
+		/* HC is suspended assert resume for 20ms, */
+		C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
 		async_usleep(20000);
 		usb_log_info("BIOS driver: HC resumed.\n");
@@ -454,5 +525,5 @@
  * @param[in] instance OHCI hc driver structure.
  */
-void hc_start_hw(hc_t *instance)
+void hc_start(hc_t *instance)
 {
 	/* OHCI guide page 42 */
@@ -516,5 +587,5 @@
 	    instance->registers->periodic_start, frame_length);
 
-	instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
+	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);
@@ -534,6 +605,6 @@
 	int ret = endpoint_list_init(&instance->lists[type], name); \
 	if (ret != EOK) { \
-		usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
-		    ret, name); \
+		usb_log_error("Failed to setup %s endpoint list: %s.\n", \
+		    name, str_error(ret)); \
 		endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\
 		endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
@@ -587,38 +658,7 @@
 	    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
 
-	/* Init interrupt code */
-	instance->interrupt_code.cmds = instance->interrupt_commands;
-	instance->interrupt_code.cmdcount = OHCI_NEEDED_IRQ_COMMANDS;
-	{
-		/* Read status register */
-		instance->interrupt_commands[0].cmd = CMD_MEM_READ_32;
-		instance->interrupt_commands[0].dstarg = 1;
-		instance->interrupt_commands[0].addr =
-		    (void*)&instance->registers->interrupt_status;
-
-		/* Test whether we are the interrupt cause */
-		instance->interrupt_commands[1].cmd = CMD_BTEST;
-		instance->interrupt_commands[1].value =
-		    OHCI_USED_INTERRUPTS;
-		instance->interrupt_commands[1].srcarg = 1;
-		instance->interrupt_commands[1].dstarg = 2;
-
-		/* Predicate cleaning and accepting */
-		instance->interrupt_commands[2].cmd = CMD_PREDICATE;
-		instance->interrupt_commands[2].value = 2;
-		instance->interrupt_commands[2].srcarg = 2;
-
-		/* Write-clean status register */
-		instance->interrupt_commands[3].cmd = CMD_MEM_WRITE_A_32;
-		instance->interrupt_commands[3].srcarg = 1;
-		instance->interrupt_commands[3].addr =
-		    (void*)&instance->registers->interrupt_status;
-
-		/* Accept interrupt */
-		instance->interrupt_commands[4].cmd = CMD_ACCEPT;
-	}
-
-	return EOK;
-}
+	return EOK;
+}
+
 /**
  * @}
Index: uspace/drv/bus/usb/ohci/hc.h
===================================================================
--- uspace/drv/bus/usb/ohci/hc.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/ohci/hc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -51,7 +51,5 @@
 #include "hw_struct/hcca.h"
 
-#define OHCI_NEEDED_IRQ_COMMANDS 5
-
-/** Main OHCI drier structure */
+/** Main OHCI driver structure */
 typedef struct hc {
 	/** USB bus driver, devices and addresses */
@@ -76,17 +74,13 @@
 	fibril_mutex_t guard;
 
-	/** Code to be executed in kernel interrupt handler */
-	irq_code_t interrupt_code;
-
-	/** Commands that form interrupt code */
-	irq_cmd_t interrupt_commands[OHCI_NEEDED_IRQ_COMMANDS];
-
 	/** USB hub emulation structure */
 	rh_t rh;
 } hc_t;
 
+size_t hc_irq_cmd_count(void);
+int hc_get_irq_commands(
+    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
+int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
-int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
-void hc_start_hw(hc_t *instance);
 
 /** Safely dispose host controller internal structures
Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -58,8 +58,6 @@
 {
 	assert(dev);
-	assert(dev->driver_data);
 	return dev->driver_data;
 }
-
 /** IRQ handling callback, identifies device
  *
@@ -70,8 +68,13 @@
 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
 {
-	hc_t *hc = &dev_to_ohci(dev)->hc;
-	assert(hc);
+	assert(dev);
+
+	ohci_t *ohci = dev_to_ohci(dev);
+	if (!ohci) {
+		usb_log_warning("Interrupt on device that is not ready.\n");
+		return;
+	}
 	const uint16_t status = IPC_GET_ARG1(*call);
-	hc_interrupt(hc, status);
+	hc_interrupt(&ohci->hc, status);
 }
 /*----------------------------------------------------------------------------*/
@@ -166,4 +169,5 @@
 	} \
 	free(instance); \
+	device->driver_data = NULL; \
 	usb_log_error(message); \
 	return ret; \
@@ -173,5 +177,6 @@
 	instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc");
 	int ret = instance->hc_fun ? EOK : ENOMEM;
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI HC function.\n");
+	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;
@@ -179,5 +184,6 @@
 	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh");
 	ret = instance->rh_fun ? EOK : ENOMEM;
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI RH function.\n");
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to create OHCI RH function: %s.\n", str_error(ret));
 	instance->rh_fun->ops = &rh_ops;
 
@@ -193,48 +199,53 @@
 	    (void *) reg_base, reg_size, irq);
 
+	const size_t cmd_count = hc_irq_cmd_count();
+	irq_cmd_t irq_cmds[cmd_count];
+	ret =
+	    hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to generate IRQ commands: %s.\n", str_error(ret));
+
+	irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
+
+	/* Register handler to avoid interrupt lockup */
+	ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to register interrupt handler: %s.\n", str_error(ret));
+
+	/* Try to enable interrupts */
 	bool interrupts = false;
-#ifdef CONFIG_USBHC_NO_INTERRUPTS
-	usb_log_warning("Interrupts disabled in OS config, "
-	    "falling back to polling.\n");
-#else
 	ret = pci_enable_interrupts(device);
 	if (ret != EOK) {
-		usb_log_warning("Failed to enable interrupts: %s.\n",
-		    str_error(ret));
-		usb_log_info("HW interrupts not available, "
-		    "falling back to polling.\n");
+		usb_log_warning("Failed to enable interrupts: %s."
+		    " Falling back to polling\n", str_error(ret));
+		/* We don't need that handler */
+		unregister_interrupt_handler(device, irq);
 	} else {
 		usb_log_debug("Hw interrupts enabled.\n");
 		interrupts = true;
 	}
-#endif
 
 	ret = hc_init(&instance->hc, reg_base, reg_size, interrupts);
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed(%d) to init ohci_hcd.\n", ret);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to init ohci_hcd: %s.\n", str_error(ret));
+
+	device->driver_data = instance;
 
 #define CHECK_RET_FINI_RETURN(ret, message...) \
 if (ret != EOK) { \
+	unregister_interrupt_handler(device, irq); \
 	hc_fini(&instance->hc); \
 	CHECK_RET_DEST_FREE_RETURN(ret, message); \
 } else (void)0
 
-	/* It does no harm if we register this on polling */
-	ret = register_interrupt_handler(device, irq, irq_handler,
-	    &instance->hc.interrupt_code);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to register interrupt handler.\n", ret);
 
 	ret = ddf_fun_bind(instance->hc_fun);
 	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to bind OHCI device function: %s.\n",
-	    ret, str_error(ret));
-
-	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
+	    "Failed to bind OHCI device function: %s.\n", str_error(ret));
+
+	ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY);
 	CHECK_RET_FINI_RETURN(ret,
 	    "Failed to add OHCI to HC class: %s.\n", str_error(ret));
 
-	device->driver_data = instance;
-
-	hc_start_hw(&instance->hc);
 	hc_register_hub(&instance->hc, instance->rh_fun);
 	return EOK;
Index: uspace/drv/bus/usb/ohci/ohci_regs.h
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_regs.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/ohci/ohci_regs.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -34,16 +34,22 @@
 #ifndef DRV_OHCI_OHCI_REGS_H
 #define DRV_OHCI_OHCI_REGS_H
-#include <stdint.h>
+#include <sys/types.h>
+
+#define LEGACY_REGS_OFFSET 0x100
 
 /** OHCI memory mapped registers structure */
 typedef struct ohci_regs {
-	const volatile uint32_t revision;
-	volatile uint32_t control;
-#define C_CSBR_MASK (0x3) /* Control-bulk service ratio */
-#define C_CSBR_1_1  (0x0)
-#define C_CSBR_1_2  (0x1)
-#define C_CSBR_1_3  (0x2)
-#define C_CSBR_1_4  (0x3)
-#define C_CSBR_SHIFT (0)
+	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 */
+#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_PLE (1 << 2)   /* Periodic list enable */
@@ -59,9 +65,18 @@
 #define C_HCFS_SHIFT       (6)
 
+#define C_HCFS_GET(reg) \
+	((reg >> C_HCFS_SHIFT) & C_HCFS_MASK)
+#define C_HCFS_SET(reg, hcfs_state) \
+do { \
+	reg = (reg & ~(C_HCFS_MASK << C_HCFS_SHIFT)) \
+	    | ((hcfs_state & C_HCFS_MASK) << C_HCFS_SHIFT); \
+} 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_RWE (1 << 10)  /* Remote wakeup enable */
 
-	volatile uint32_t command_status;
+	ioport32_t command_status;
 #define CS_HCR (1 << 0)   /* Host controller reset */
 #define CS_CLF (1 << 1)   /* Control list filled */
@@ -75,7 +90,7 @@
 	 * writing causes enable/disable,
 	 * status is write-clean (writing 1 clears the bit*/
-	volatile uint32_t interrupt_status;
-	volatile uint32_t interrupt_enable;
-	volatile uint32_t interrupt_disable;
+	ioport32_t interrupt_status;
+	ioport32_t interrupt_enable;
+	ioport32_t interrupt_disable;
 #define I_SO   (1 << 0)   /* Scheduling overrun */
 #define I_WDH  (1 << 1)   /* Done head write-back */
@@ -89,27 +104,27 @@
 
 	/** HCCA pointer (see hw_struct hcca.h) */
-	volatile uint32_t hcca;
+	ioport32_t hcca;
 #define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */
 
 	/** Currently executed periodic endpoint */
-	const volatile uint32_t periodic_current;
+	const ioport32_t periodic_current;
 
 	/** The first control endpoint */
-	volatile uint32_t control_head;
+	ioport32_t control_head;
 
 	/** Currently executed control endpoint */
-	volatile uint32_t control_current;
+	ioport32_t control_current;
 
 	/** The first bulk endpoint */
-	volatile uint32_t bulk_head;
+	ioport32_t bulk_head;
 
 	/** Currently executed bulk endpoint */
-	volatile uint32_t bulk_current;
+	ioport32_t bulk_current;
 
 	/** Done TD list, this value is periodically written to HCCA */
-	const volatile uint32_t done_head;
+	const ioport32_t done_head;
 
 	/** Frame time and max packet size for all transfers */
-	volatile uint32_t fm_interval;
+	ioport32_t fm_interval;
 #define FMI_FI_MASK (0x3fff) /* Frame interval in bit times (should be 11999)*/
 #define FMI_FI_SHIFT (0)
@@ -119,5 +134,5 @@
 
 	/** Bit times remaining in current frame */
-	const volatile uint32_t fm_remaining;
+	const ioport32_t fm_remaining;
 #define FMR_FR_MASK FMI_FI_MASK
 #define FMR_FR_SHIFT FMI_FI_SHIFT
@@ -125,17 +140,17 @@
 
 	/** Frame number */
-	const volatile uint32_t fm_number;
+	const ioport32_t fm_number;
 #define FMN_NUMBER_MASK (0xffff)
 
 	/** Remaining bit time in frame to start periodic transfers */
-	volatile uint32_t periodic_start;
+	ioport32_t periodic_start;
 #define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */
 
 	/** Threshold for starting LS transaction */
-	volatile uint32_t ls_threshold;
+	ioport32_t ls_threshold;
 #define LST_LST_MASK (0x7fff)
 
 	/** The first root hub control register */
-	volatile uint32_t rh_desc_a;
+	ioport32_t rh_desc_a;
 #define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */
 #define RHDA_NDS_SHIFT (0)
@@ -144,10 +159,10 @@
 #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      (1 << 12) /* OC control: 0-use OCPM, 1-OC off */
+#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)
 
 	/** The other root hub control register */
-	volatile uint32_t rh_desc_b;
+	ioport32_t rh_desc_b;
 #define RHDB_DR_MASK (0xffff) /* Device removable mask */
 #define RHDB_DR_SHIFT (0)
@@ -161,5 +176,5 @@
 
 	/** Root hub status register */
-	volatile uint32_t rh_status;
+	ioport32_t rh_status;
 #define RHS_LPS_FLAG  (1 <<  0)/* read: 0,
                                 * write: 0-no effect,
@@ -167,5 +182,5 @@
                                 *        specified in PPCM(RHDB), or all ports,
                                 *        if power is set globally */
-#define RHS_CLEAR_PORT_POWER RHS_LPS_FLAG /* synonym for the above */
+#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
@@ -178,10 +193,10 @@
                                 *        specified in PPCM(RHDB), or all ports,
                                 *        if power is set globally */
-#define RHS_SET_PORT_POWER RHS_LPSC_FLAG /* synonym for the above */
+#define RHS_SET_GLOBAL_POWER RHS_LPSC_FLAG /* synonym for the above */
 #define RHS_OCIC_FLAG (1 << 17)/* Over-current indicator change   */
 #define RHS_CLEAR_DRWE (1 << 31)
 
 	/** Root hub per port status */
-	volatile uint32_t rh_port_status[];
+	ioport32_t rh_port_status[];
 #define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,
                                 * w: 1-clear port enable, 0-nothing */
Index: uspace/drv/bus/usb/ohci/root_hub.c
===================================================================
--- uspace/drv/bus/usb/ohci/root_hub.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/ohci/root_hub.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -40,4 +40,5 @@
 #include "root_hub.h"
 #include <usb/classes/classes.h>
+#include <usb/classes/hub.h>
 #include <usb/dev/driver.h>
 #include "ohci_regs.h"
@@ -56,7 +57,7 @@
 	.device_subclass = 0,
 	.device_version = 0,
-	.length = sizeof (usb_standard_device_descriptor_t),
-	.max_packet_size = 8,
-	.vendor_id = 0x16db,
+	.length = sizeof(usb_standard_device_descriptor_t),
+	.max_packet_size = 64,
+	.vendor_id = 0x16db, /* HelenOS does not have USB vendor ID assigned.*/
 	.product_id = 0x0001,
 	.str_serial_number = 0,
@@ -73,6 +74,6 @@
 	.descriptor_type = USB_DESCTYPE_CONFIGURATION,
 	.interface_count = 1,
-	.length = sizeof (usb_standard_configuration_descriptor_t),
-	.max_power = 100,
+	.length = sizeof(usb_standard_configuration_descriptor_t),
+	.max_power = 0, /* root hubs don't need no power */
 	.str_configuration = 0,
 };
@@ -89,5 +90,5 @@
 	.interface_protocol = 0,
 	.interface_subclass = 0,
-	.length = sizeof (usb_standard_interface_descriptor_t),
+	.length = sizeof(usb_standard_interface_descriptor_t),
 	.str_interface = 0,
 };
@@ -100,345 +101,268 @@
 	.descriptor_type = USB_DESCTYPE_ENDPOINT,
 	.endpoint_address = 1 + (1 << 7),
-	.length = sizeof (usb_standard_endpoint_descriptor_t),
-	.max_packet_size = 8,
+	.length = sizeof(usb_standard_endpoint_descriptor_t),
+	.max_packet_size = 2,
 	.poll_interval = 255,
 };
 
-/**
- * bitmask of hub features that are valid to be cleared
- */
-static const uint32_t hub_clear_feature_valid_mask =
-    RHS_OCIC_FLAG |
-    RHS_CLEAR_PORT_POWER;
-
-/**
- * bitmask of hub features that are cleared by writing 1 (and not 0)
- */
-static const uint32_t hub_clear_feature_by_writing_one_mask =
-    RHS_CLEAR_PORT_POWER;
-
-/**
- * bitmask of hub features that are valid to be set
- */
-static const uint32_t hub_set_feature_valid_mask =
-    RHS_LPSC_FLAG |
-    RHS_OCIC_FLAG;
-
-/**
- * bitmask of hub features that are set by writing 1 and cleared by writing 0
- */
-static const uint32_t hub_set_feature_direct_mask =
-    RHS_SET_PORT_POWER;
-
-/**
- * bitmask of port features that are valid to be set
- */
-static const uint32_t port_set_feature_valid_mask =
-    RHPS_SET_PORT_ENABLE |
-    RHPS_SET_PORT_SUSPEND |
-    RHPS_SET_PORT_RESET |
-    RHPS_SET_PORT_POWER;
-
-/**
- * bitmask of port features that can be cleared
- */
-static const uint32_t port_clear_feature_valid_mask =
-    RHPS_CCS_FLAG |
-    RHPS_SET_PORT_SUSPEND |
-    RHPS_POCI_FLAG |
-    RHPS_SET_PORT_POWER |
-    RHPS_CSC_FLAG |
-    RHPS_PESC_FLAG |
-    RHPS_PSSC_FLAG |
-    RHPS_OCIC_FLAG |
-    RHPS_PRSC_FLAG;
-
-//note that USB_HUB_FEATURE_PORT_POWER bit is translated into
-//USB_HUB_FEATURE_PORT_LOW_SPEED for port set feature request
-
-/**
- * bitmask with port status changes
- */
-static const uint32_t port_status_change_mask = RHPS_CHANGE_WC_MASK;
-
-static int create_serialized_hub_descriptor(rh_t *instance);
-
-static int rh_init_descriptors(rh_t *instance);
-
-static int process_get_port_status_request(rh_t *instance, uint16_t port,
-    usb_transfer_batch_t * request);
-
-static int process_get_hub_status_request(rh_t *instance,
-    usb_transfer_batch_t * request);
-
-static int process_get_status_request(rh_t *instance,
-    usb_transfer_batch_t * request);
-
-static void create_interrupt_mask_in_instance(rh_t *instance);
-
-static int process_get_descriptor_request(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_get_configuration_request(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_hub_feature_set_request(rh_t *instance, uint16_t feature);
-
-static int process_hub_feature_clear_request(rh_t *instance,
-    uint16_t feature);
-
-static int process_port_feature_set_request(rh_t *instance,
-    uint16_t feature, uint16_t port);
-
-static int process_port_feature_clear_request(rh_t *instance,
-    uint16_t feature, uint16_t port);
-
-static int process_address_set_request(rh_t *instance,
-    uint16_t address);
-
-static int process_request_with_output(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_request_with_input(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_request_without_data(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
-
-static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
-
-static bool is_zeros(void * buffer, size_t size);
-
-/** Root hub initialization
- * @return Error code.
- */
-int rh_init(rh_t *instance, ohci_regs_t *regs) {
-	assert(instance);
+static void create_serialized_hub_descriptor(rh_t *instance);
+static void rh_init_descriptors(rh_t *instance);
+static uint16_t create_interrupt_mask(rh_t *instance);
+static int get_status(rh_t *instance, usb_transfer_batch_t *request);
+static int get_descriptor(rh_t *instance, usb_transfer_batch_t *request);
+static int set_feature(rh_t *instance, usb_transfer_batch_t *request);
+static int clear_feature(rh_t *instance, usb_transfer_batch_t *request);
+static int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port);
+static int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port);
+static int control_request(rh_t *instance, usb_transfer_batch_t *request);
+static inline void interrupt_request(
+    usb_transfer_batch_t *request, uint16_t mask, size_t size)
+{
+	assert(request);
+
+	memcpy(request->data_buffer, &mask, size);
+	request->transfered_size = size;
+	usb_transfer_batch_finish_error(request, EOK);
+}
+
+#define TRANSFER_OK(bytes) \
+do { \
+	request->transfered_size = bytes; \
+	return EOK; \
+} while (0)
+
+/** Root Hub driver structure initialization.
+ *
+ * Reads info registers and prepares descriptors. Sets power mode.
+ */
+void rh_init(rh_t *instance, ohci_regs_t *regs)
+{
+	assert(instance);
+	assert(regs);
+
 	instance->registers = regs;
 	instance->port_count =
 	    (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
-	int opResult = rh_init_descriptors(instance);
-	if (opResult != EOK) {
-		return opResult;
-	}
-	// set port power mode to no-power-switching
+	if (instance->port_count > 15) {
+		usb_log_warning("OHCI specification does not allow more than 15"
+		    " ports. Max 15 ports will be used");
+		instance->port_count = 15;
+	}
+
+	/* Don't forget the hub status bit and round up */
+	instance->interrupt_mask_size = 1 + (instance->port_count / 8);
+	instance->unfinished_interrupt_transfer = NULL;
+
+#ifdef OHCI_POWER_SWITCH_no
+	/* Set port power mode to no power-switching. (always on) */
 	instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
-	instance->unfinished_interrupt_transfer = NULL;
-	instance->interrupt_mask_size = (instance->port_count + 8) / 8;
-	instance->interrupt_buffer = malloc(instance->interrupt_mask_size);
-	if (!instance->interrupt_buffer)
-		return ENOMEM;
+	/* Set to no over-current reporting */
+	instance->registers->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;
+	/* Set to global over-current */
+	instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
+	instance->registers->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;
+
+	/* 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;
+	/* Return control to per port state */
+	instance->registers->rh_desc_b |=
+		((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT;
+	/* Set per port over-current */
+	instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
+	instance->registers->rh_desc_a |= RHDA_OCPM_FLAG;
+#endif
+
+	rh_init_descriptors(instance);
 
 	usb_log_info("Root hub (%zu ports) initialized.\n",
 	    instance->port_count);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process root hub request
- *
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-int rh_request(rh_t *instance, usb_transfer_batch_t *request) {
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Process root hub request.
+ *
+ * @param instance Root hub instance
+ * @param request Structure containing both request and response information
+ * @return Error code
+ */
+void rh_request(rh_t *instance, usb_transfer_batch_t *request)
+{
 	assert(instance);
 	assert(request);
-	int opResult;
-	if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
+
+	switch (request->ep->transfer_type)
+	{
+	case USB_TRANSFER_CONTROL:
 		usb_log_debug("Root hub got CONTROL packet\n");
-		opResult = process_ctrl_request(instance, request);
-		usb_transfer_batch_finish_error(request, opResult);
-	} else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
+		const int ret = control_request(instance, request);
+		usb_transfer_batch_finish_error(request, ret);
+		break;
+	case USB_TRANSFER_INTERRUPT:
 		usb_log_debug("Root hub got INTERRUPT packet\n");
-		create_interrupt_mask_in_instance(instance);
-		if (is_zeros(instance->interrupt_buffer,
-		    instance->interrupt_mask_size)) {
+		const uint16_t mask = create_interrupt_mask(instance);
+		if (mask == 0) {
 			usb_log_debug("No changes..\n");
+			assert(instance->unfinished_interrupt_transfer == NULL);
 			instance->unfinished_interrupt_transfer = request;
-			//will be finished later
-		} else {
-			usb_log_debug("Processing changes..\n");
-			process_interrupt_mask_in_instance(instance, request);
+			break;
 		}
-		opResult = EOK;
-	} else {
-
-		opResult = EINVAL;
-		usb_transfer_batch_finish_error(request, opResult);
-	}
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * process interrupt on a hub
+		usb_log_debug("Processing changes...\n");
+		interrupt_request(request, mask, instance->interrupt_mask_size);
+		break;
+
+	default:
+		usb_log_error("Root hub got unsupported request.\n");
+		usb_transfer_batch_finish_error(request, EINVAL);
+	}
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Process interrupt on a hub device.
  *
  * If there is no pending interrupt transfer, nothing happens.
  * @param instance
  */
-void rh_interrupt(rh_t *instance) {
-	if (!instance->unfinished_interrupt_transfer) {
+void rh_interrupt(rh_t *instance)
+{
+	assert(instance);
+
+	if (!instance->unfinished_interrupt_transfer)
 		return;
-	}
+
 	usb_log_debug("Finalizing interrupt transfer\n");
-	create_interrupt_mask_in_instance(instance);
-	process_interrupt_mask_in_instance(instance,
-	    instance->unfinished_interrupt_transfer);
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * Create hub descriptor used in hub-driver <-> hub communication
- *
- * This means creating byt array from data in root hub registers. For more
- * info see usb hub specification.
- *
+	const uint16_t mask = create_interrupt_mask(instance);
+	interrupt_request(instance->unfinished_interrupt_transfer,
+	    mask, instance->interrupt_mask_size);
+
+	instance->unfinished_interrupt_transfer = NULL;
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Create hub descriptor.
+ *
+ * For descriptor format see USB hub specification (chapter 11.15.2.1, pg. 263)
+ *
+ * @param instance Root hub instance
+ * @return Error code
+ */
+void create_serialized_hub_descriptor(rh_t *instance)
+{
+	assert(instance);
+
+	/* 7 bytes + 2 port bit fields (port count + global bit) */
+	const size_t size = 7 + (instance->interrupt_mask_size * 2);
+	assert(size <= HUB_DESCRIPTOR_MAX_SIZE);
+	instance->hub_descriptor_size = size;
+
+	const uint32_t hub_desc = instance->registers->rh_desc_a;
+	const uint32_t port_desc = instance->registers->rh_desc_b;
+
+	/* bDescLength */
+	instance->descriptors.hub[0] = size;
+	/* bDescriptorType */
+	instance->descriptors.hub[1] = USB_DESCTYPE_HUB;
+	/* bNmbrPorts */
+	instance->descriptors.hub[2] = instance->port_count;
+	/* wHubCharacteristics */
+	instance->descriptors.hub[3] = 0 |
+	    /* The lowest 2 bits indicate power switching mode */
+	    (((hub_desc & RHDA_PSM_FLAG)  ? 1 : 0) << 0) |
+	    (((hub_desc & RHDA_NPS_FLAG)  ? 1 : 0) << 1) |
+	    /* Bit 3 indicates device type (compound device) */
+	    (((hub_desc & RHDA_DT_FLAG)   ? 1 : 0) << 2) |
+	    /* Bits 4,5 indicate over-current protection mode */
+	    (((hub_desc & RHDA_OCPM_FLAG) ? 1 : 0) << 3) |
+	    (((hub_desc & RHDA_NOCP_FLAG) ? 1 : 0) << 4);
+
+	/* Reserved */
+	instance->descriptors.hub[4] = 0;
+	/* bPwrOn2PwrGood */
+	instance->descriptors.hub[5] =
+	    (hub_desc >> RHDA_POTPGT_SHIFT) & RHDA_POTPGT_MASK;
+	/* 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[8] = 0xff;
+	if (instance->interrupt_mask_size == 2) {
+		instance->descriptors.hub[8] =
+		    (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK >> 8;
+		instance->descriptors.hub[9]  = 0xff;
+		instance->descriptors.hub[10] = 0xff;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize hub descriptors.
+ *
+ * A full configuration descriptor is assembled. The configuration and endpoint
+ * descriptors have local modifications.
+ * @param instance Root hub instance
+ * @return Error code
+ */
+void rh_init_descriptors(rh_t *instance)
+{
+	assert(instance);
+
+	instance->descriptors.configuration = ohci_rh_conf_descriptor;
+	instance->descriptors.interface = ohci_rh_iface_descriptor;
+	instance->descriptors.endpoint = ohci_rh_ep_descriptor;
+	create_serialized_hub_descriptor(instance);
+
+	instance->descriptors.endpoint.max_packet_size =
+	    instance->interrupt_mask_size;
+
+	instance->descriptors.configuration.total_length =
+	    sizeof(usb_standard_configuration_descriptor_t) +
+	    sizeof(usb_standard_endpoint_descriptor_t) +
+	    sizeof(usb_standard_interface_descriptor_t) +
+	    instance->hub_descriptor_size;
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Create bitmap of changes to answer status interrupt.
+ *
+ * Result contains bitmap where bit 0 indicates change on hub and
+ * bit i indicates change on i`th port (i>0). For more info see
+ * Hub and Port status bitmap specification in USB specification
+ * (chapter 11.13.4).
  * @param instance root hub instance
- * @return error code
- */
-static int create_serialized_hub_descriptor(rh_t *instance) {
-	size_t size = 7 +
-	    ((instance->port_count + 7) / 8) * 2;
-	size_t var_size = (instance->port_count + 7) / 8;
-	uint8_t * result = (uint8_t*) malloc(size);
-	if (!result) return ENOMEM;
-
-	bzero(result, size);
-	//size
-	result[0] = size;
-	//descriptor type
-	result[1] = USB_DESCTYPE_HUB;
-	result[2] = instance->port_count;
-	uint32_t hub_desc_reg = instance->registers->rh_desc_a;
-	result[3] =
-	    ((hub_desc_reg >> 8) % 2) +
-	    (((hub_desc_reg >> 9) % 2) << 1) +
-	    (((hub_desc_reg >> 10) % 2) << 2) +
-	    (((hub_desc_reg >> 11) % 2) << 3) +
-	    (((hub_desc_reg >> 12) % 2) << 4);
-	result[4] = 0;
-	result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
-	result[6] = 50;
-
-	size_t port;
-	for (port = 1; port <= instance->port_count; ++port) {
-		uint8_t is_non_removable =
-		    instance->registers->rh_desc_b >> port % 2;
-		result[7 + port / 8] +=
-		    is_non_removable << (port % 8);
-	}
-	size_t i;
-	for (i = 0; i < var_size; ++i) {
-		result[7 + var_size + i] = 255;
-	}
-	instance->hub_descriptor = result;
-	instance->descriptor_size = size;
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/** initialize hub descriptors
- *
- * Initialized are device and full configuration descriptor. These need to
- * be initialized only once per hub.
- * @instance root hub instance
- * @return error code
- */
-static int rh_init_descriptors(rh_t *instance) {
-	memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
-	    sizeof (ohci_rh_device_descriptor)
-	    );
-	usb_standard_configuration_descriptor_t descriptor;
-	memcpy(&descriptor, &ohci_rh_conf_descriptor,
-	    sizeof (ohci_rh_conf_descriptor));
-
-	int opResult = create_serialized_hub_descriptor(instance);
-	if (opResult != EOK) {
-		return opResult;
-	}
-	descriptor.total_length =
-	    sizeof (usb_standard_configuration_descriptor_t) +
-	    sizeof (usb_standard_endpoint_descriptor_t) +
-	    sizeof (usb_standard_interface_descriptor_t) +
-	    instance->descriptor_size;
-
-	uint8_t * full_config_descriptor =
-	    (uint8_t*) malloc(descriptor.total_length);
-	if (!full_config_descriptor) {
-		return ENOMEM;
-	}
-	memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
-	memcpy(full_config_descriptor + sizeof (descriptor),
-	    &ohci_rh_iface_descriptor, sizeof (ohci_rh_iface_descriptor));
-	memcpy(full_config_descriptor + sizeof (descriptor) +
-	    sizeof (ohci_rh_iface_descriptor),
-	    &ohci_rh_ep_descriptor, sizeof (ohci_rh_ep_descriptor));
-	memcpy(full_config_descriptor + sizeof (descriptor) +
-	    sizeof (ohci_rh_iface_descriptor) +
-	    sizeof (ohci_rh_ep_descriptor),
-	    instance->hub_descriptor, instance->descriptor_size);
-
-	instance->descriptors.configuration = full_config_descriptor;
-	instance->descriptors.configuration_size = descriptor.total_length;
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to port status_request
- *
- * Copy content of corresponding port status register to answer buffer. The
- * format of the port status register and port status data is the same (
- * see OHCI root hub and USB hub documentation).
- *
- * @param instance root hub instance
- * @param port port number, counted from 1
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_get_port_status_request(rh_t *instance, uint16_t port,
-    usb_transfer_batch_t * request) {
-	if (port < 1 || port > instance->port_count)
-		return EINVAL;
-	request->transfered_size = 4;
-	uint32_t data = instance->registers->rh_port_status[port - 1];
-	memcpy(request->data_buffer, &data, 4);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to port status_request
- *
- * This copies flags in hub status register into the buffer. The format of the
- * status register and status message is the same, according to USB hub
- * specification and OHCI root hub specification.
- *
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_get_hub_status_request(rh_t *instance,
-    usb_transfer_batch_t * request) {
-	request->transfered_size = 4;
-	//bits, 0,1,16,17
-	uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17);
-	uint32_t data = mask & instance->registers->rh_status;
-	memcpy(request->data_buffer, &data, 4);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to status request
+ * @return Mask of changes.
+ */
+uint16_t create_interrupt_mask(rh_t *instance)
+{
+	assert(instance);
+	uint16_t mask = 0;
+
+	/* Only local power source change and over-current change can happen */
+	if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
+		mask |= 1;
+	}
+	size_t port = 1;
+	for (; 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]) {
+
+			mask |= (1 << port);
+		}
+	}
+	/* USB is little endian */
+	return host2uint32_t_le(mask);
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Create answer to status request.
  *
  * This might be either hub status or port status request. If neither,
@@ -448,204 +372,119 @@
  * @return error code
  */
-static int process_get_status_request(rh_t *instance,
-    usb_transfer_batch_t * request) {
-	size_t buffer_size = request->buffer_size;
-	usb_device_request_setup_packet_t * request_packet =
-	    (usb_device_request_setup_packet_t*)
-	    request->setup_buffer;
-
-	usb_hub_bm_request_type_t request_type = request_packet->request_type;
-	if (buffer_size < 4) {
-		usb_log_warning("Requested more data than buffer size\n");
-		return EINVAL;
-	}
-
-	if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
-		return process_get_hub_status_request(instance, request);
-	if (request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
-		return process_get_port_status_request(instance,
-	    request_packet->index,
-	    request);
+int get_status(rh_t *instance, usb_transfer_batch_t *request)
+{
+	assert(instance);
+	assert(request);
+
+	const usb_device_request_setup_packet_t *request_packet =
+	    (usb_device_request_setup_packet_t*)request->setup_buffer;
+
+	if (request->buffer_size < 4) {
+		usb_log_error("Buffer too small for get status request.\n");
+		return EOVERFLOW;
+	}
+
+	/* Hub status: just filter relevant info from rh_status reg */
+	if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) {
+		const uint32_t data = instance->registers->rh_status &
+		    (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG);
+		memcpy(request->data_buffer, &data, 4);
+		TRANSFER_OK(4);
+	}
+
+	/* Copy appropriate rh_port_status register, OHCI designers were
+	 * kind enough to make those bit values match USB specification */
+	if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) {
+		const unsigned port = request_packet->index;
+		if (port < 1 || port > instance->port_count)
+			return EINVAL;
+
+		const uint32_t data =
+		    instance->registers->rh_port_status[port - 1];
+		memcpy(request->data_buffer, &data, 4);
+		TRANSFER_OK(4);
+	}
 
 	return ENOTSUP;
 }
 /*----------------------------------------------------------------------------*/
-
-/**
- * create answer to status interrupt consisting of change bitmap
- *
- * Result contains bitmap where bit 0 indicates change on hub and
- * bit i indicates change on i`th port (i>0). For more info see
- * Hub and Port status bitmap specification in USB specification
- * (chapter 11.13.4).
- * Uses instance`s interrupt buffer to store the interrupt information.
- * @param instance root hub instance
- */
-static void create_interrupt_mask_in_instance(rh_t * instance) {
-	uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
-	uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
-	    | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
-	bzero(bitmap, instance->interrupt_mask_size);
-	if ((instance->registers->rh_status & mask) != 0) {
-		bitmap[0] = 1;
-	}
-	size_t port;
-	mask = port_status_change_mask;
-	for (port = 1; port <= instance->port_count; ++port) {
-		if ((mask & instance->registers->rh_port_status[port - 1]) != 0) {
-
-			bitmap[(port) / 8] += 1 << (port % 8);
-		}
-	}
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to a descriptor request
+/**
+ * Create answer to a descriptor request.
  *
  * This might be a request for standard (configuration, device, endpoint or
  * interface) or device specific (hub) descriptor.
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_get_descriptor_request(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*) request->setup_buffer;
+ * @param instance Root hub instance
+ * @param request Structure containing both request and response information
+ * @return Error code
+ */
+int get_descriptor(rh_t *instance, usb_transfer_batch_t *request)
+{
+	assert(instance);
+	assert(request);
+
+	const usb_device_request_setup_packet_t *setup_request =
+	    (usb_device_request_setup_packet_t *) request->setup_buffer;
 	size_t size;
-	const void * result_descriptor = NULL;
+	const void *descriptor = NULL;
 	const uint16_t setup_request_value = setup_request->value_high;
 	//(setup_request->value_low << 8);
-	switch (setup_request_value) {
-		case USB_DESCTYPE_HUB:
-		{
-			usb_log_debug2("USB_DESCTYPE_HUB\n");
-			result_descriptor = instance->hub_descriptor;
-			size = instance->descriptor_size;
-			break;
-		}
-		case USB_DESCTYPE_DEVICE:
-		{
-			usb_log_debug2("USB_DESCTYPE_DEVICE\n");
-			result_descriptor = &ohci_rh_device_descriptor;
-			size = sizeof (ohci_rh_device_descriptor);
-			break;
-		}
-		case USB_DESCTYPE_CONFIGURATION:
-		{
-			usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n");
-			result_descriptor = instance->descriptors.configuration;
-			size = instance->descriptors.configuration_size;
-			break;
-		}
-		case USB_DESCTYPE_INTERFACE:
-		{
-			usb_log_debug2("USB_DESCTYPE_INTERFACE\n");
-			result_descriptor = &ohci_rh_iface_descriptor;
-			size = sizeof (ohci_rh_iface_descriptor);
-			break;
-		}
-		case USB_DESCTYPE_ENDPOINT:
-		{
-			usb_log_debug2("USB_DESCTYPE_ENDPOINT\n");
-			result_descriptor = &ohci_rh_ep_descriptor;
-			size = sizeof (ohci_rh_ep_descriptor);
-			break;
-		}
-		default:
-		{
-			usb_log_debug2("USB_DESCTYPE_EINVAL %d \n",
-			    setup_request->value);
-			usb_log_debug2("\ttype %d\n\trequest %d\n\tvalue "
-			    "%d\n\tindex %d\n\tlen %d\n ",
-			    setup_request->request_type,
-			    setup_request->request,
-			    setup_request_value,
-			    setup_request->index,
-			    setup_request->length
-			    );
-			return EINVAL;
-		}
+	switch (setup_request_value)
+	{
+	case USB_DESCTYPE_HUB:
+		usb_log_debug2("USB_DESCTYPE_HUB\n");
+		/* Hub descriptor was generated locally */
+		descriptor = instance->descriptors.hub;
+		size = instance->hub_descriptor_size;
+		break;
+
+	case USB_DESCTYPE_DEVICE:
+		usb_log_debug2("USB_DESCTYPE_DEVICE\n");
+		/* Device descriptor is shared (No one should ask for it)*/
+		descriptor = &ohci_rh_device_descriptor;
+		size = sizeof(ohci_rh_device_descriptor);
+		break;
+
+	case USB_DESCTYPE_CONFIGURATION:
+		usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n");
+		/* Start with configuration and add others depending on
+		 * request size */
+		descriptor = &instance->descriptors;
+		size = instance->descriptors.configuration.total_length;
+		break;
+
+	case USB_DESCTYPE_INTERFACE:
+		usb_log_debug2("USB_DESCTYPE_INTERFACE\n");
+		/* Use local interface descriptor. There is one and it
+		 * might be modified */
+		descriptor = &instance->descriptors.interface;
+		size = sizeof(instance->descriptors.interface);
+		break;
+
+	case USB_DESCTYPE_ENDPOINT:
+		/* Use local endpoint descriptor. There is one
+		 * it might have max_packet_size field modified*/
+		usb_log_debug2("USB_DESCTYPE_ENDPOINT\n");
+		descriptor = &instance->descriptors.endpoint;
+		size = sizeof(instance->descriptors.endpoint);
+		break;
+
+	default:
+		usb_log_debug2("USB_DESCTYPE_EINVAL %d \n"
+		    "\ttype %d\n\trequest %d\n\tvalue "
+		    "%d\n\tindex %d\n\tlen %d\n ",
+		    setup_request->value,
+		    setup_request->request_type, setup_request->request,
+		    setup_request_value, setup_request->index,
+		    setup_request->length);
+		return EINVAL;
 	}
 	if (request->buffer_size < size) {
 		size = request->buffer_size;
 	}
-	request->transfered_size = size;
-	memcpy(request->data_buffer, result_descriptor, size);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * answer to get configuration request
- *
- * Root hub works independently on the configuration.
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_get_configuration_request(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	//set and get configuration requests do not have any meaning, only dummy
-	//values are returned
-	if (request->buffer_size != 1)
-		return EINVAL;
-	request->data_buffer[0] = 1;
-	request->transfered_size = 1;
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process feature-enabling request on hub
- *
- * @param instance root hub instance
- * @param feature feature selector
- * @return error code
- */
-static int process_hub_feature_set_request(rh_t *instance,
-    uint16_t feature) {
-	if (!((1 << feature) & hub_set_feature_valid_mask))
-		return EINVAL;
-	if (feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)
-		feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16;
-	instance->registers->rh_status =
-	    (instance->registers->rh_status | (1 << feature))
-	    & (~hub_clear_feature_by_writing_one_mask);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process feature-disabling request on hub
- *
- * @param instance root hub instance
- * @param feature feature selector
- * @return error code
- */
-static int process_hub_feature_clear_request(rh_t *instance,
-    uint16_t feature) {
-	if (!((1 << feature) & hub_clear_feature_valid_mask))
-		return EINVAL;
-	//is the feature cleared directly?
-	if ((1 << feature) & hub_set_feature_direct_mask) {
-		instance->registers->rh_status =
-		    (instance->registers->rh_status & (~(1 << feature)))
-		    & (~hub_clear_feature_by_writing_one_mask);
-	} else {//the feature is cleared by writing '1'
-
-		instance->registers->rh_status =
-		    (instance->registers->rh_status
-		    & (~hub_clear_feature_by_writing_one_mask))
-		    | (1 << feature);
-	}
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
+
+	memcpy(request->data_buffer, descriptor, size);
+	TRANSFER_OK(size);
+}
+/*----------------------------------------------------------------------------*/
 /**
  * process feature-enabling request on hub
@@ -657,19 +496,36 @@
  * @return error code
  */
-static int process_port_feature_set_request(rh_t *instance,
-    uint16_t feature, uint16_t port) {
-	if (!((1 << feature) & port_set_feature_valid_mask))
-		return EINVAL;
+int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
+{
+	assert(instance);
+
 	if (port < 1 || port > instance->port_count)
 		return EINVAL;
-	instance->registers->rh_port_status[port - 1] =
-	    (instance->registers->rh_port_status[port - 1] | (1 << feature))
-	    & (~port_clear_feature_valid_mask);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process feature-disabling request on hub
+
+	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;
+		}
+	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);
+		return EOK;
+	default:
+		return ENOTSUP;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Process feature clear request.
  *
  * @param instance root hub instance
@@ -679,93 +535,52 @@
  * @return error code
  */
-static int process_port_feature_clear_request(rh_t *instance,
-    uint16_t feature, uint16_t port) {
-	if (!((1 << feature) & port_clear_feature_valid_mask))
-		return EINVAL;
+int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
+{
+	assert(instance);
+
 	if (port < 1 || port > instance->port_count)
 		return EINVAL;
-	if (feature == USB_HUB_FEATURE_PORT_POWER)
-		feature = USB_HUB_FEATURE_PORT_LOW_SPEED;
-	if (feature == USB_HUB_FEATURE_PORT_SUSPEND)
-		feature = USB_HUB_FEATURE_PORT_OVER_CURRENT;
-	instance->registers->rh_port_status[port - 1] =
-	    (instance->registers->rh_port_status[port - 1]
-	    & (~port_clear_feature_valid_mask))
-	    | (1 << feature);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * register address to this device
- *
- * @param instance root hub instance
- * @param address new address
- * @return error code
- */
-static int process_address_set_request(rh_t *instance,
-    uint16_t address) {
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process one of requests that requere output data
- *
- * Request can be one of USB_DEVREQ_GET_STATUS, USB_DEVREQ_GET_DESCRIPTOR or
- * USB_DEVREQ_GET_CONFIGURATION.
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_request_with_output(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*) request->setup_buffer;
-	if (setup_request->request == USB_DEVREQ_GET_STATUS) {
-		usb_log_debug("USB_DEVREQ_GET_STATUS\n");
-		return process_get_status_request(instance, request);
-	}
-	if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR) {
-		usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
-		return process_get_descriptor_request(instance, request);
-	}
-	if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) {
-		usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
-
-		return process_get_configuration_request(instance, request);
-	}
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process one of requests that carry input data
- *
- * Request can be one of USB_DEVREQ_SET_DESCRIPTOR or
- * USB_DEVREQ_SET_CONFIGURATION.
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_request_with_input(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*) request->setup_buffer;
-	request->transfered_size = 0;
-	if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) {
+
+	/* Enabled features to clear: see page 269 of USB specs */
+	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;
+			return EOK;
+		}
+		instance->registers->rh_port_status[port - 1] =
+			RHPS_CLEAR_PORT_POWER;
+		return EOK;
+
+	case USB_HUB_FEATURE_PORT_ENABLE:         //1
+		instance->registers->rh_port_status[port - 1] =
+			RHPS_CLEAR_PORT_ENABLE;
+		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);
+		return EOK;
+
+	default:
 		return ENOTSUP;
 	}
-	if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION) {
-		//set and get configuration requests do not have any meaning,
-		//only dummy values are returned
-
-		return EOK;
-	}
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
+}
+/*----------------------------------------------------------------------------*/
 /**
  * process one of requests that do not request nor carry additional data
@@ -777,55 +592,76 @@
  * @return error code
  */
-static int process_request_without_data(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*) request->setup_buffer;
-	request->transfered_size = 0;
-	if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) {
-		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
-			usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
-			return process_hub_feature_clear_request(instance,
-			    setup_request->value);
-		}
-		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
-			usb_log_debug2("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
-			return process_port_feature_clear_request(instance,
-			    setup_request->value,
-			    setup_request->index);
-		}
-		usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
+int set_feature(rh_t *instance, usb_transfer_batch_t *request)
+{
+	assert(instance);
+	assert(request);
+
+	const usb_device_request_setup_packet_t *setup_request =
+	    (usb_device_request_setup_packet_t *) request->setup_buffer;
+	switch (setup_request->request_type)
+	{
+	case USB_HUB_REQ_TYPE_SET_PORT_FEATURE:
+		usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
+		return set_feature_port(instance,
+		    setup_request->value, setup_request->index);
+
+	case USB_HUB_REQ_TYPE_SET_HUB_FEATURE:
+		/* Chapter 11.16.2 specifies that hub can be recipient
+		 * only for C_HUB_LOCAL_POWER and C_HUB_OVER_CURRENT
+		 * features. It makes no sense to SET either. */
+		usb_log_error("Invalid HUB set feature request.\n");
+		return ENOTSUP;
+	default:
+		usb_log_error("Invalid set feature request type: %d\n",
 		    setup_request->request_type);
 		return EINVAL;
 	}
-	if (setup_request->request == USB_DEVREQ_SET_FEATURE) {
-		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
-			usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
-			return process_hub_feature_set_request(instance,
-			    setup_request->value);
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * process one of requests that do not request nor carry additional data
+ *
+ * Request can be one of USB_DEVREQ_CLEAR_FEATURE, USB_DEVREQ_SET_FEATURE or
+ * USB_DEVREQ_SET_ADDRESS.
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+int clear_feature(rh_t *instance, usb_transfer_batch_t *request)
+{
+	assert(instance);
+	assert(request);
+
+	const usb_device_request_setup_packet_t *setup_request =
+	    (usb_device_request_setup_packet_t *) request->setup_buffer;
+	request->transfered_size = 0;
+	switch (setup_request->request_type)
+	{
+	case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE:
+		usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n");
+		return clear_feature_port(instance,
+		    setup_request->value, setup_request->index);
+
+	case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE:
+		usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE\n");
+		/*
+		 * Chapter 11.16.2 specifies that only C_HUB_LOCAL_POWER and
+		 * C_HUB_OVER_CURRENT are supported. C_HUB_OVER_CURRENT is represented
+		 * by OHCI RHS_OCIC_FLAG. C_HUB_LOCAL_POWER is not supported
+		 * 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;
+			TRANSFER_OK(0);
 		}
-		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
-			usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
-			return process_port_feature_set_request(instance,
-			    setup_request->value,
-			    setup_request->index);
-		}
-		usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
+	default:
+		usb_log_error("Invalid clear feature request type: %d\n",
 		    setup_request->request_type);
 		return EINVAL;
 	}
-	if (setup_request->request == USB_DEVREQ_SET_ADDRESS) {
-		usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
-		return process_address_set_request(instance,
-		    setup_request->value);
-	}
-	usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",
-	    setup_request->request_type);
-
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process hub control request
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Process hub control request.
  *
  * If needed, writes answer into the request structure.
@@ -844,95 +680,65 @@
  * @return error code
  */
-static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) {
+int control_request(rh_t *instance, usb_transfer_batch_t *request)
+{
+	assert(instance);
+	assert(request);
+
 	if (!request->setup_buffer) {
-		usb_log_error("root hub received empty transaction?");
+		usb_log_error("Root hub received empty transaction!");
 		return EINVAL;
 	}
-	int opResult;
-	if (sizeof (usb_device_request_setup_packet_t) > request->setup_size) {
+
+	if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) {
 		usb_log_error("Setup packet too small\n");
-		return EINVAL;
-	}
-	usb_log_debug("CTRL packet: %s.\n",
-	    usb_debug_str_buffer(
-	    (const uint8_t *) request->setup_buffer, 8, 8));
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*)
-	    request->setup_buffer;
-	switch (setup_request->request) {
-		case USB_DEVREQ_GET_STATUS:
-		case USB_DEVREQ_GET_DESCRIPTOR:
-		case USB_DEVREQ_GET_CONFIGURATION:
-			usb_log_debug2("Processing request with output\n");
-			opResult = process_request_with_output(
-			    instance, request);
-			break;
-		case USB_DEVREQ_CLEAR_FEATURE:
-		case USB_DEVREQ_SET_FEATURE:
-		case USB_DEVREQ_SET_ADDRESS:
-			usb_log_debug2("Processing request without "
-			    "additional data\n");
-			opResult = process_request_without_data(
-			    instance, request);
-			break;
-		case USB_DEVREQ_SET_DESCRIPTOR:
-		case USB_DEVREQ_SET_CONFIGURATION:
-			usb_log_debug2("Processing request with input\n");
-			opResult = process_request_with_input(
-			    instance, request);
-
-			break;
-		default:
-			usb_log_warning("Received unsupported request: %d.\n",
-			    setup_request->request);
-			opResult = ENOTSUP;
-	}
-	return opResult;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process hanging interrupt request
- *
- * If an interrupt transfer has been received and there was no change,
- * the driver stores the transfer information and waits for change to occcur.
- * This routine is called when that happens and it finalizes the interrupt
- * transfer.
- *
- * @param instance hub instance
- * @param request batch request to be processed
- *
- * @return
- */
-static int process_interrupt_mask_in_instance(rh_t *instance,
-    usb_transfer_batch_t * request) {
-	memcpy(request->data_buffer, instance->interrupt_buffer,
-	    instance->interrupt_mask_size);
-	request->transfered_size = instance->interrupt_mask_size;
-	instance->unfinished_interrupt_transfer = NULL;
-	usb_transfer_batch_finish_error(request, EOK);
-
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * return whether the buffer is full of zeros
- *
- * Convenience function.
- * @param buffer
- * @param size
- * @return
- */
-static bool is_zeros(void *buffer, size_t size) {
-	if (!buffer) return true;
-	if (!size) return true;
-	size_t i;
-	for (i = 0; i < size; ++i) {
-		if (((char*) buffer)[i])
-			return false;
-	}
-	return true;
+		return EOVERFLOW;
+	}
+
+	usb_log_debug2("CTRL packet: %s.\n",
+	    usb_debug_str_buffer((uint8_t *) request->setup_buffer, 8, 8));
+	const usb_device_request_setup_packet_t *setup_request =
+	    (usb_device_request_setup_packet_t *) request->setup_buffer;
+	switch (setup_request->request)
+	{
+	case USB_DEVREQ_GET_STATUS:
+		usb_log_debug("USB_DEVREQ_GET_STATUS\n");
+		return get_status(instance, request);
+
+	case USB_DEVREQ_GET_DESCRIPTOR:
+		usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
+		return get_descriptor(instance, request);
+
+	case USB_DEVREQ_GET_CONFIGURATION:
+		usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
+		if (request->buffer_size != 1)
+			return EINVAL;
+		request->data_buffer[0] = 1;
+		TRANSFER_OK(1);
+
+	case USB_DEVREQ_CLEAR_FEATURE:
+		usb_log_debug2("Processing request without "
+		    "additional data\n");
+		return clear_feature(instance, request);
+	case USB_DEVREQ_SET_FEATURE:
+		usb_log_debug2("Processing request without "
+		    "additional data\n");
+		return set_feature(instance, request);
+
+	case USB_DEVREQ_SET_ADDRESS:
+		usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
+		instance->address = setup_request->value;
+		TRANSFER_OK(0);
+
+	case USB_DEVREQ_SET_CONFIGURATION:
+		usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n");
+		/* We don't need to do anything */
+		TRANSFER_OK(0);
+
+	case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */
+	default:
+		usb_log_error("Received unsupported request: %d.\n",
+		    setup_request->request);
+		return ENOTSUP;
+	}
 }
 
Index: uspace/drv/bus/usb/ohci/root_hub.h
===================================================================
--- uspace/drv/bus/usb/ohci/root_hub.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/ohci/root_hub.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,4 +41,6 @@
 #include "batch.h"
 
+#define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2)
+
 /**
  * ohci root hub representation
@@ -51,28 +53,23 @@
 	/** hub port count */
 	size_t port_count;
-	/** hubs descriptors */
-	usb_device_descriptors_t descriptors;
 	/** interrupt transfer waiting for an actual interrupt to occur */
-	usb_transfer_batch_t * unfinished_interrupt_transfer;
-	/** pre-allocated interrupt mask
-	 *
-	 * This is allocated when initializing instance, so that memory
-	 * allocation is not needed when processing request. Buffer is used for
-	 * interrupt bitmask.
-	 */
-	uint8_t * interrupt_buffer;
+	usb_transfer_batch_t *unfinished_interrupt_transfer;
 	/** size of interrupt buffer */
 	size_t interrupt_mask_size;
-	/** instance`s descriptor*/
-	uint8_t * hub_descriptor;
+	/** Descriptors */
+	struct {
+		usb_standard_configuration_descriptor_t configuration;
+		usb_standard_interface_descriptor_t interface;
+		usb_standard_endpoint_descriptor_t endpoint;
+		uint8_t hub[HUB_DESCRIPTOR_MAX_SIZE];
+	} __attribute__ ((packed)) descriptors;
 	/** size of hub descriptor */
-	size_t descriptor_size;
-
+	size_t hub_descriptor_size;
 
 } rh_t;
 
-int rh_init(rh_t *instance, ohci_regs_t *regs);
+void rh_init(rh_t *instance, ohci_regs_t *regs);
 
-int rh_request(rh_t *instance, usb_transfer_batch_t *request);
+void rh_request(rh_t *instance, usb_transfer_batch_t *request);
 
 void rh_interrupt(rh_t *instance);
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -47,4 +47,13 @@
     (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
 
+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 },
+};
 
 static int hc_init_transfer_lists(hc_t *instance);
@@ -54,4 +63,37 @@
 static int hc_interrupt_emulator(void *arg);
 static int hc_debug_checker(void *arg);
+
+/*----------------------------------------------------------------------------*/
+/** Get number of commands used in IRQ code.
+ * @return Number of commands.
+ */
+size_t hc_irq_cmd_count(void)
+{
+	return sizeof(uhci_irq_commands) / sizeof(irq_cmd_t);
+}
+/*----------------------------------------------------------------------------*/
+/** Generate IRQ code commands.
+ * @param[out] cmds Place to store the commands.
+ * @param[in] cmd_size Size of the place (bytes).
+ * @param[in] regs Physical address of device's registers.
+ * @param[in] reg_size Size of the register area (bytes).
+ *
+ * @return Error code.
+ */
+int hc_get_irq_commands(
+    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
+{
+	if (cmd_size < sizeof(uhci_irq_commands)
+	    || reg_size < sizeof(uhci_regs_t))
+		return EOVERFLOW;
+
+	uhci_regs_t *registers = (uhci_regs_t*)regs;
+
+	memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands));
+
+	cmds[0].addr = (void*)&registers->usbsts;
+	cmds[3].addr = (void*)&registers->usbsts;
+	return EOK;
+}
 /*----------------------------------------------------------------------------*/
 /** Initialize UHCI hc driver structure
@@ -69,5 +111,5 @@
 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
 {
-	assert(reg_size >= sizeof(regs_t));
+	assert(reg_size >= sizeof(uhci_regs_t));
 	int ret;
 
@@ -82,17 +124,16 @@
 
 	/* allow access to hc control registers */
-	regs_t *io;
+	uhci_regs_t *io;
 	ret = pio_enable(regs, reg_size, (void **)&io);
-	CHECK_RET_RETURN(ret,
-	    "Failed(%d) to gain access to registers at %p: %s.\n",
-	    ret, io, str_error(ret));
+	CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p: %s.\n",
+	    io, str_error(ret));
 	instance->registers = io;
-	usb_log_debug("Device registers at %p (%zuB) accessible.\n",
-	    io, reg_size);
+	usb_log_debug(
+	    "Device registers at %p (%zuB) accessible.\n", io, reg_size);
 
 	ret = hc_init_mem_structures(instance);
 	CHECK_RET_RETURN(ret,
-	    "Failed(%d) to initialize UHCI memory structures: %s.\n",
-	    ret, str_error(ret));
+	    "Failed to initialize UHCI memory structures: %s.\n",
+	    str_error(ret));
 
 	hc_init_hw(instance);
@@ -116,12 +157,12 @@
 {
 	assert(instance);
-	regs_t *registers = instance->registers;
+	uhci_regs_t *registers = instance->registers;
 
 	/* Reset everything, who knows what touched it before us */
 	pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
-	async_usleep(10000); /* 10ms according to USB spec */
+	async_usleep(50000); /* 50ms according to USB spec(root hub reset) */
 	pio_write_16(&registers->usbcmd, 0);
 
-	/* Reset hc, all states and counters */
+	/* Reset hc, all states and counters. Hope that hw is not broken */
 	pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
 	do { async_usleep(10); }
@@ -141,7 +182,7 @@
 	}
 
-	const uint16_t status = pio_read_16(&registers->usbcmd);
-	if (status != 0)
-		usb_log_warning("Previous command value: %x.\n", status);
+	const uint16_t cmd = pio_read_16(&registers->usbcmd);
+	if (cmd != 0)
+		usb_log_warning("Previous command value: %x.\n", cmd);
 
 	/* Start the hc with large(64B) packet FSBR */
@@ -170,60 +211,12 @@
 	} else (void) 0
 
-	/* Init interrupt code */
-	instance->interrupt_code.cmds = instance->interrupt_commands;
-	{
-		/* Read status register */
-		instance->interrupt_commands[0].cmd = CMD_PIO_READ_16;
-		instance->interrupt_commands[0].dstarg = 1;
-		instance->interrupt_commands[0].addr =
-		    &instance->registers->usbsts;
-
-		/* Test whether we are the interrupt cause */
-		instance->interrupt_commands[1].cmd = CMD_BTEST;
-		instance->interrupt_commands[1].value =
-		    UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS;
-		instance->interrupt_commands[1].srcarg = 1;
-		instance->interrupt_commands[1].dstarg = 2;
-
-		/* Predicate cleaning and accepting */
-		instance->interrupt_commands[2].cmd = CMD_PREDICATE;
-		instance->interrupt_commands[2].value = 2;
-		instance->interrupt_commands[2].srcarg = 2;
-
-		/* Write clean status register */
-		instance->interrupt_commands[3].cmd = CMD_PIO_WRITE_A_16;
-		instance->interrupt_commands[3].srcarg = 1;
-		instance->interrupt_commands[3].addr =
-		    &instance->registers->usbsts;
-
-		/* Accept interrupt */
-		instance->interrupt_commands[4].cmd = CMD_ACCEPT;
-
-		instance->interrupt_code.cmdcount = UHCI_NEEDED_IRQ_COMMANDS;
-	}
-
 	/* Init transfer lists */
 	int ret = hc_init_transfer_lists(instance);
-	CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n");
+	CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
 	usb_log_debug("Initialized transfer lists.\n");
-
-	/* Init USB frame list page*/
-	instance->frame_list = get_page();
-	ret = instance->frame_list ? EOK : ENOMEM;
-	CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
-	usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
-
-	/* Set all frames to point to the first queue head */
-	const uint32_t queue = LINK_POINTER_QH(
-	        addr_to_phys(instance->transfers_interrupt.queue_head));
-
-	unsigned i = 0;
-	for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
-		instance->frame_list[i] = queue;
-	}
 
 	/* Init device keeper */
 	usb_device_keeper_init(&instance->manager);
-	usb_log_debug("Initialized device manager.\n");
+	usb_log_debug("Initialized device keeper.\n");
 
 	ret = usb_endpoint_manager_init(&instance->ep_manager,
@@ -232,4 +225,21 @@
 	    str_error(ret));
 
+	/* Init USB frame list page*/
+	instance->frame_list = get_page();
+	if (!instance->frame_list) {
+		usb_log_error("Failed to get frame list page.\n");
+		usb_endpoint_manager_destroy(&instance->ep_manager);
+		return ENOMEM;
+	}
+	usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
+
+	/* Set all frames to point to the first queue head */
+	const uint32_t queue = LINK_POINTER_QH(
+	        addr_to_phys(instance->transfers_interrupt.queue_head));
+	unsigned i = 0;
+	for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
+		instance->frame_list[i] = queue;
+	}
+
 	return EOK;
 #undef CHECK_RET_RETURN
@@ -252,6 +262,6 @@
 	int ret = transfer_list_init(&instance->transfers_##type, name); \
 	if (ret != EOK) { \
-		usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \
-		    ret, name, str_error(ret)); \
+		usb_log_error("Failed to setup %s transfer list: %s.\n", \
+		    name, str_error(ret)); \
 		transfer_list_fini(&instance->transfers_bulk_full); \
 		transfer_list_fini(&instance->transfers_control_full); \
Index: uspace/drv/bus/usb/uhci/hc.h
===================================================================
--- uspace/drv/bus/usb/uhci/hc.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/uhci/hc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -84,5 +84,5 @@
 	/** SOF modification to match external timers */
 	uint8_t sofmod;
-} regs_t;
+} uhci_regs_t;
 
 #define UHCI_FRAME_LIST_COUNT 1024
@@ -100,5 +100,5 @@
 
 	/** Addresses of I/O registers */
-	regs_t *registers;
+	uhci_regs_t *registers;
 
 	/** Frame List contains 1024 link pointers */
@@ -116,14 +116,6 @@
 	/** Pointer table to the above lists, helps during scheduling */
 	transfer_list_t *transfers[2][4];
-
-	/** Code to be executed in kernel interrupt handler */
-	irq_code_t interrupt_code;
-
-	/** Commands that form interrupt code */
-	irq_cmd_t interrupt_commands[UHCI_NEEDED_IRQ_COMMANDS];
-
 	/** Fibril periodically checking status register*/
 	fid_t interrupt_emulator;
-
 	/** Indicator of hw interrupts availability */
 	bool hw_interrupts;
@@ -132,9 +124,9 @@
 	unsigned hw_failures;
 } hc_t;
-
+size_t hc_irq_cmd_count(void);
+int hc_get_irq_commands(
+    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
-
 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
-
 void hc_interrupt(hc_t *instance, uint16_t status);
 
Index: uspace/drv/bus/usb/uhci/root_hub.c
===================================================================
--- uspace/drv/bus/usb/uhci/root_hub.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/uhci/root_hub.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -50,21 +50,12 @@
 int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
 {
+	int ret;
+
 	assert(fun);
 
-	char *match_str = NULL;
-	int ret = asprintf(&match_str, "usb&uhci&root-hub");
-	if (ret < 0) {
-		usb_log_error(
-		    "Failed(%d) to create root hub match string: %s.\n",
-		    ret, str_error(ret));
-		return ret;
-	}
-	assert(match_str);
-
-	ret = ddf_fun_add_match_id(fun, match_str, 100);
+	ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
 	if (ret != EOK) {
-		free(match_str);
-		usb_log_error("Failed(%d) to add root hub match id: %s\n",
-		    ret, str_error(ret));
+		usb_log_error("Failed to add root hub match id: %s\n",
+		    str_error(ret));
 		return ret;
 	}
Index: uspace/drv/bus/usb/uhci/transfer_list.c
===================================================================
--- uspace/drv/bus/usb/uhci/transfer_list.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/uhci/transfer_list.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -26,4 +26,5 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 /** @addtogroup drvusbuhcihc
  * @{
@@ -32,9 +33,8 @@
  * @brief UHCI driver transfer list implementation
  */
+
 #include <errno.h>
 #include <usb/debug.h>
-#include <arch/barrier.h>
-
-
+#include <libarch/barrier.h>
 #include "transfer_list.h"
 #include "batch.h"
@@ -141,5 +141,5 @@
 	list_append(&batch->link, &instance->batch_list);
 
-	usb_log_debug("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",
 	    batch, USB_TRANSFER_BATCH_ARGS(*batch), instance->name);
 	fibril_mutex_unlock(&instance->guard);
Index: uspace/drv/bus/usb/uhci/uhci.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -64,5 +64,4 @@
 {
 	assert(dev);
-	assert(dev->driver_data);
 	return dev->driver_data;
 }
@@ -78,8 +77,10 @@
 	assert(dev);
 	uhci_t *uhci = dev_to_uhci(dev);
-	hc_t *hc = &uhci->hc;
+	if (!uhci) {
+		usb_log_error("Interrupt on not yet initialized device.\n");
+		return;
+	}
 	const uint16_t status = IPC_GET_ARG1(*call);
-	assert(hc);
-	hc_interrupt(hc, status);
+	hc_interrupt(&uhci->hc, status);
 }
 /*----------------------------------------------------------------------------*/
@@ -192,4 +193,5 @@
 	} \
 	free(instance); \
+	device->driver_data = NULL; \
 	usb_log_error(message); \
 	return ret; \
@@ -222,27 +224,35 @@
 	ret = pci_disable_legacy(device);
 	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
+	    "Failed to disable legacy USB: %s.\n", str_error(ret));
+
+	const size_t cmd_count = hc_irq_cmd_count();
+	irq_cmd_t irq_cmds[cmd_count];
+	ret =
+	    hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to generate IRQ commands: %s.\n", str_error(ret));
+
+	irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
+
+        /* Register handler to avoid interrupt lockup */
+        ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);
+        CHECK_RET_DEST_FREE_RETURN(ret,
+            "Failed to register interrupt handler: %s.\n", str_error(ret));
 
 	bool interrupts = false;
-#ifdef CONFIG_USBHC_NO_INTERRUPTS
-	usb_log_warning("Interrupts disabled in OS config, " \
-	    "falling back to polling.\n");
-#else
 	ret = pci_enable_interrupts(device);
 	if (ret != EOK) {
-		usb_log_warning("Failed to enable interrupts: %s.\n",
-		    str_error(ret));
-		usb_log_info("HW interrupts not available, " \
-		    "falling back to polling.\n");
+		usb_log_warning("Failed to enable interrupts: %s."
+		    " Falling back to polling.\n", str_error(ret));
 	} else {
 		usb_log_debug("Hw interrupts enabled.\n");
 		interrupts = true;
 	}
-#endif
-
 
 	ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
 	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed(%d) to init uhci_hcd: %s.\n", ret, str_error(ret));
+	    "Failed to init uhci_hcd: %s.\n", str_error(ret));
+
+	device->driver_data = instance;
 
 #define CHECK_RET_FINI_RETURN(ret, message...) \
@@ -253,17 +263,9 @@
 } else (void)0
 
-	/* It does no harm if we register this on polling */
-	ret = register_interrupt_handler(device, irq, irq_handler,
-	    &instance->hc.interrupt_code);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to register interrupt handler: %s.\n",
-	    ret, str_error(ret));
-
 	ret = ddf_fun_bind(instance->hc_fun);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to bind UHCI device function: %s.\n",
-	    ret, str_error(ret));
-
-	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
+	CHECK_RET_FINI_RETURN(ret, "Failed to bind UHCI device function: %s.\n",
+	    str_error(ret));
+
+	ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY);
 	CHECK_RET_FINI_RETURN(ret,
 	    "Failed to add UHCI to HC class: %s.\n", str_error(ret));
@@ -272,11 +274,10 @@
 	    (uintptr_t)instance->hc.registers + 0x10, 4);
 	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret));
+	    "Failed to setup UHCI root hub: %s.\n", str_error(ret));
 
 	ret = ddf_fun_bind(instance->rh_fun);
 	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
-
-	device->driver_data = instance;
+	    "Failed to register UHCI root hub: %s.\n", str_error(ret));
+
 	return EOK;
 #undef CHECK_RET_FINI_RETURN
Index: uspace/drv/bus/usb/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -192,5 +192,5 @@
 static int usb_generic_hid_create_function(usb_hid_dev_t *hid_dev)
 {	
-	/* Create the function exposed under /dev/devices. */
+	/* Create the exposed function. */
 	/** @todo Generate numbers for the devices? */
 	usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME);
Index: uspace/drv/bus/usb/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -72,5 +72,5 @@
 
 // FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 
 /*----------------------------------------------------------------------------*/
@@ -102,5 +102,5 @@
 
 const char *HID_KBD_FUN_NAME = "keyboard";
-const char *HID_KBD_CLASS_NAME = "keyboard";
+const char *HID_KBD_CATEGORY_NAME = "keyboard";
 
 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
@@ -524,5 +524,5 @@
 	assert(kbd_dev != NULL);
 	
-	/* Create the function exposed under /dev/devices. */
+	/* Create the exposed function. */
 	usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
 	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
@@ -551,10 +551,10 @@
 	    HID_KBD_FUN_NAME, fun->handle);
 	
-	usb_log_debug("Adding DDF function to class %s...\n", 
+	usb_log_debug("Adding DDF function to category %s...\n", 
 	    HID_KBD_CLASS_NAME);
-	rc = ddf_fun_add_to_class(fun, HID_KBD_CLASS_NAME);
+	rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
 	if (rc != EOK) {
 		usb_log_error(
-		    "Could not add DDF function to class %s: %s.\n",
+		    "Could not add DDF function to category %s: %s.\n",
 		    HID_KBD_CLASS_NAME, str_error(rc));
 		ddf_fun_destroy(fun);
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -57,5 +57,5 @@
 
 // FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 
 #define NAME "mouse"
@@ -74,6 +74,6 @@
 const char *HID_MOUSE_FUN_NAME = "mouse";
 const char *HID_MOUSE_WHEEL_FUN_NAME = "mouse-wheel";
-const char *HID_MOUSE_CLASS_NAME = "mouse";
-const char *HID_MOUSE_WHEEL_CLASS_NAME = "keyboard";
+const char *HID_MOUSE_CATEGORY = "mouse";
+const char *HID_MOUSE_WHEEL_CATEGORY = "keyboard";
 
 /** Default idle rate for mouses. */
@@ -325,5 +325,5 @@
 	assert(mouse != NULL);
 	
-	/* Create the function exposed under /dev/devices. */
+	/* Create the exposed function. */
 	usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
 	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
@@ -345,11 +345,11 @@
 	}
 	
-	usb_log_debug("Adding DDF function to class %s...\n", 
-	    HID_MOUSE_CLASS_NAME);
-	rc = ddf_fun_add_to_class(fun, HID_MOUSE_CLASS_NAME);
+	usb_log_debug("Adding DDF function to category %s...\n", 
+	    HID_MOUSE_CATEGORY);
+	rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
 	if (rc != EOK) {
 		usb_log_error(
-		    "Could not add DDF function to class %s: %s.\n",
-		    HID_MOUSE_CLASS_NAME, str_error(rc));
+		    "Could not add DDF function to category %s: %s.\n",
+		    HID_MOUSE_CATEGORY, str_error(rc));
 		ddf_fun_destroy(fun);
 		return rc;
@@ -383,11 +383,11 @@
 	}
 	
-	usb_log_debug("Adding DDF function to class %s...\n", 
-	    HID_MOUSE_WHEEL_CLASS_NAME);
-	rc = ddf_fun_add_to_class(fun, HID_MOUSE_WHEEL_CLASS_NAME);
+	usb_log_debug("Adding DDF function to category %s...\n", 
+	    HID_MOUSE_WHEEL_CATEGORY);
+	rc = ddf_fun_add_to_category(fun, HID_MOUSE_WHEEL_CATEGORY);
 	if (rc != EOK) {
 		usb_log_error(
-		    "Could not add DDF function to class %s: %s.\n",
-		    HID_MOUSE_WHEEL_CLASS_NAME, str_error(rc));
+		    "Could not add DDF function to category %s: %s.\n",
+		    HID_MOUSE_WHEEL_CATEGORY, str_error(rc));
 		ddf_fun_destroy(fun);
 		return rc;
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -59,5 +59,5 @@
 
 const char *HID_MOUSE_FUN_NAME;
-const char *HID_MOUSE_CLASS_NAME;
+const char *HID_MOUSE_CATEGORY;
 
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/bus/usb/usbhid/multimedia/multimedia.c
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -54,5 +54,5 @@
 
 // FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 
 #define NAME "multimedia-keys"
@@ -185,5 +185,5 @@
     usb_multimedia_t *multim_dev)
 {
-	/* Create the function exposed under /dev/devices. */
+	/* Create the exposed function. */
 	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
 	    NAME);
@@ -205,11 +205,11 @@
 	}
 	
-	usb_log_debug("%s function created (jandle: %" PRIun ").\n",
+	usb_log_debug("%s function created (handle: %" PRIun ").\n",
 	    NAME, fun->handle);
 	
-	rc = ddf_fun_add_to_class(fun, "keyboard");
+	rc = ddf_fun_add_to_category(fun, "keyboard");
 	if (rc != EOK) {
 		usb_log_error(
-		    "Could not add DDF function to class 'keyboard': %s.\n",
+		    "Could not add DDF function to category 'keyboard': %s.\n",
 		    str_error(rc));
 		// TODO: Can / should I destroy the DDF function?
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -131,5 +131,5 @@
 	opResult = ddf_fun_bind(hub_fun);
 	assert(opResult == EOK);
-	opResult = ddf_fun_add_to_class(hub_fun, "hub");
+	opResult = ddf_fun_add_to_category(hub_fun, "hub");
 	assert(opResult == EOK);
 
@@ -220,9 +220,9 @@
  * @return error code
  */
-static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) {
+int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info)
+{
 	// get hub descriptor
-	usb_log_debug("Creating serialized descriptor\n");
+	usb_log_debug("Retrieving descriptor\n");
 	uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE];
-	usb_hub_descriptor_t * descriptor;
 	int opResult;
 
@@ -234,47 +234,53 @@
 
 	if (opResult != EOK) {
-		usb_log_error("Failed when receiving hub descriptor, "
-		    "%s\n",
-		    str_error(opResult));
-		free(serialized_descriptor);
+		usb_log_error("Failed to receive hub descriptor: %s.\n",
+		    str_error(opResult));
 		return opResult;
 	}
-	usb_log_debug2("Deserializing descriptor\n");
-	descriptor = usb_create_deserialized_hub_desriptor(
-	    serialized_descriptor);
-	if (descriptor == NULL) {
-		usb_log_warning("could not deserialize descriptor \n");
-		return ENOMEM;
-	}
-	usb_log_debug("setting port count to %d\n", descriptor->ports_count);
-	hub_info->port_count = descriptor->ports_count;
-	bool is_power_switched =
-	    ((descriptor->hub_characteristics & 1) == 0);
-	bool has_individual_port_powering =
-	    ((descriptor->hub_characteristics & 1) != 0);
-	hub_info->ports = malloc(
-	    sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
+	usb_log_debug2("Parsing descriptor\n");
+	usb_hub_descriptor_t descriptor;
+	opResult = usb_deserialize_hub_desriptor(
+	        serialized_descriptor, received_size, &descriptor);
+	if (opResult != EOK) {
+		usb_log_error("Could not parse descriptor: %s\n",
+		    str_error(opResult));
+		return opResult;
+	}
+	usb_log_debug("Setting port count to %d.\n", descriptor.ports_count);
+	hub_info->port_count = descriptor.ports_count;
+
+	hub_info->ports =
+	    malloc(sizeof(usb_hub_port_t) * (hub_info->port_count + 1));
 	if (!hub_info->ports) {
 		return ENOMEM;
 	}
+
 	size_t port;
 	for (port = 0; port < hub_info->port_count + 1; ++port) {
 		usb_hub_port_init(&hub_info->ports[port]);
 	}
+
+	const bool is_power_switched =
+	    !(descriptor.hub_characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);
 	if (is_power_switched) {
 		usb_log_debug("Hub power switched\n");
-
-		if (!has_individual_port_powering) {
-			//this setting actually makes no difference
-			usb_log_debug("Hub has global powering\n");
-		}
+		const bool per_port_power = descriptor.hub_characteristics
+		    & HUB_CHAR_POWER_PER_PORT_FLAG;
 
 		for (port = 1; port <= hub_info->port_count; ++port) {
 			usb_log_debug("Powering port %zu.\n", port);
-			opResult = usb_hub_set_port_feature(hub_info->control_pipe,
+			opResult = usb_hub_set_port_feature(
+			    hub_info->control_pipe,
 			    port, USB_HUB_FEATURE_PORT_POWER);
 			if (opResult != EOK) {
 				usb_log_error("Cannot power on port %zu: %s.\n",
 				    port, str_error(opResult));
+			} else {
+				if (!per_port_power) {
+					usb_log_debug(
+					    "Ganged power switching mode, "
+					    "one port is enough.\n");
+					break;
+				}
 			}
 		}
@@ -283,6 +289,4 @@
 		usb_log_debug("Power not switched, not going to be powered\n");
 	}
-	usb_log_debug2("Freeing data\n");
-	free(descriptor);
 	return EOK;
 }
Index: uspace/drv/bus/usb/usbhub/usbhub_private.h
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub_private.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbhub/usbhub_private.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -171,9 +171,6 @@
     void * serialized_descriptor);
 
-usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
-    void * serialized_descriptor);
-
-void usb_deserialize_hub_desriptor(void * serialized_descriptor,
-    usb_hub_descriptor_t * descriptor);
+int usb_deserialize_hub_desriptor(
+    void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor);
 
 
Index: uspace/drv/bus/usb/usbhub/utils.c
===================================================================
--- uspace/drv/bus/usb/usbhub/utils.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbhub/utils.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -110,53 +110,45 @@
 }
 
+/*----------------------------------------------------------------------------*/
 /**
- * create deserialized desriptor structure out of serialized descriptor
+ * Deserialize descriptor into given pointer
  *
- * The serialized descriptor must be proper usb hub descriptor,
- * otherwise an eerror might occur.
- *
- * @param sdescriptor serialized descriptor
- * @return newly created deserialized descriptor pointer
- */
-usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
-    void *serialized_descriptor) {
-	uint8_t * sdescriptor = serialized_descriptor;
-
-	if (sdescriptor[1] != USB_DESCTYPE_HUB) {
-		usb_log_warning("trying to deserialize wrong descriptor %x\n",
-		    sdescriptor[1]);
-		return NULL;
-	}
-
-	usb_hub_descriptor_t * result = malloc(sizeof (usb_hub_descriptor_t));
-	if (result)
-		usb_deserialize_hub_desriptor(serialized_descriptor, result);
-	return result;
-}
-
-/**
- * deserialize descriptor into given pointer
- * 
  * @param serialized_descriptor
  * @param descriptor
  * @return
  */
-void usb_deserialize_hub_desriptor(
-    void * serialized_descriptor, usb_hub_descriptor_t *descriptor) {
+int usb_deserialize_hub_desriptor(
+    void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor)
+{
 	uint8_t * sdescriptor = serialized_descriptor;
+
+	if (sdescriptor[1] != USB_DESCTYPE_HUB) {
+		usb_log_error("Trying to deserialize wrong descriptor %x\n",
+		    sdescriptor[1]);
+		return EINVAL;
+	}
+	if (size < 7) {
+		usb_log_error("Serialized descriptor too small.\n");
+		return EOVERFLOW;
+	}
+
 	descriptor->ports_count = sdescriptor[2];
-	/// @fixme handling of endianness??
-	descriptor->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3];
+	descriptor->hub_characteristics = sdescriptor[3] + 256 * sdescriptor[4];
 	descriptor->pwr_on_2_good_time = sdescriptor[5];
 	descriptor->current_requirement = sdescriptor[6];
-	size_t var_size = (descriptor->ports_count + 7) / 8;
+	const size_t var_size = (descriptor->ports_count + 7) / 8;
 	//descriptor->devices_removable = (uint8_t*) malloc(var_size);
 
-	size_t i;
-	for (i = 0; i < var_size; ++i) {
+	if (size < (7 + var_size)) {
+		usb_log_error("Serialized descriptor too small.\n");
+		return EOVERFLOW;
+	}
+	size_t i = 0;
+	for (; i < var_size; ++i) {
 		descriptor->devices_removable[i] = sdescriptor[7 + i];
 	}
+	return EOK;
 }
-
+/*----------------------------------------------------------------------------*/
 /**
  * @}
Index: uspace/drv/bus/usb/usbmast/Makefile
===================================================================
--- uspace/drv/bus/usb/usbmast/Makefile	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbmast/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -44,7 +44,7 @@
 
 SOURCES = \
-	cmds.c \
+	bo_trans.c \
+	cmdw.c \
 	main.c \
-	mast.c \
 	scsi_ms.c
 
Index: uspace/drv/bus/usb/usbmast/bo_trans.c
===================================================================
--- uspace/drv/bus/usb/usbmast/bo_trans.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/drv/bus/usb/usbmast/bo_trans.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,272 @@
+/*
+ * 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.
+ */
+
+/** @addtogroup drvusbmast
+ * @{
+ */
+/**
+ * @file
+ * USB mass storage bulk-only transport.
+ */
+#include <bool.h>
+#include <errno.h>
+#include <str_error.h>
+#include <usb/debug.h>
+#include <usb/dev/request.h>
+
+#include "bo_trans.h"
+#include "cmdw.h"
+#include "usbmast.h"
+
+bool usb_mast_verbose = false;
+
+#define MASTLOG(format, ...) \
+	do { \
+		if (usb_mast_verbose) { \
+			usb_log_debug2("USB cl08: " format, ##__VA_ARGS__); \
+		} \
+	} while (false)
+
+/** Send command via bulk-only transport.
+ *
+ * @param mfun		Mass storage function
+ * @param tag		Command block wrapper tag (automatically compared
+ *			with answer)
+ * @param cmd		SCSI command
+ *
+ * @return		Error code
+ */
+int usb_massstor_cmd(usbmast_fun_t *mfun, uint32_t tag, scsi_cmd_t *cmd)
+{
+	int rc;
+	int retval = EOK;
+	size_t act_size;
+	usb_pipe_t *bulk_in_pipe = mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe;
+	usb_pipe_t *bulk_out_pipe = mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe;
+	usb_direction_t ddir;
+	void *dbuf;
+	size_t dbuf_size;
+
+	if (cmd->data_out != NULL && cmd->data_in == NULL) {
+		ddir = USB_DIRECTION_OUT;
+		dbuf = (void *)cmd->data_out;
+		dbuf_size = cmd->data_out_size;
+	} else if (cmd->data_out == NULL && cmd->data_in != NULL) {
+		ddir = USB_DIRECTION_IN;
+		dbuf = cmd->data_in;
+		dbuf_size = cmd->data_in_size;
+	} else {
+		assert(false);
+	}
+
+	/* Prepare CBW - command block wrapper */
+	usb_massstor_cbw_t cbw;
+	usb_massstor_cbw_prepare(&cbw, tag, dbuf_size, ddir, mfun->lun,
+	    cmd->cdb_size, cmd->cdb);
+
+	/* Send the CBW. */
+	MASTLOG("Sending CBW.\n");
+	rc = usb_pipe_write(bulk_out_pipe, &cbw, sizeof(cbw));
+	MASTLOG("CBW '%s' sent: %s.\n",
+	    usb_debug_str_buffer((uint8_t *) &cbw, sizeof(cbw), 0),
+	    str_error(rc));
+	if (rc != EOK)
+		return EIO;
+
+	MASTLOG("Transferring data.\n");
+	if (ddir == USB_DIRECTION_IN) {
+		/* Recieve data from the device. */
+		rc = usb_pipe_read(bulk_in_pipe, dbuf, dbuf_size, &act_size);
+		MASTLOG("Received %zu bytes (%s): %s.\n", act_size,
+		    usb_debug_str_buffer((uint8_t *) dbuf, act_size, 0),
+		    str_error(rc));
+	} else {
+		/* Send data to the device. */
+		rc = usb_pipe_write(bulk_out_pipe, dbuf, dbuf_size);
+		MASTLOG("Sent %zu bytes (%s): %s.\n", act_size,
+		    usb_debug_str_buffer((uint8_t *) dbuf, act_size, 0),
+		    str_error(rc));
+	}
+
+	if (rc == ESTALL) {
+		/* Clear stall condition and continue below to read CSW. */
+		if (ddir == USB_DIRECTION_IN) {
+			usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
+			    mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe);
+		} else {
+			usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
+			    mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
+		}
+        } else if (rc != EOK) {
+		return EIO;
+	}
+
+	/* Read CSW. */
+	usb_massstor_csw_t csw;
+	size_t csw_size;
+	MASTLOG("Reading CSW.\n");
+	rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size);
+	MASTLOG("CSW '%s' received (%zu bytes): %s.\n",
+	    usb_debug_str_buffer((uint8_t *) &csw, csw_size, 0), csw_size,
+	    str_error(rc));
+	if (rc != EOK) {
+		MASTLOG("rc != EOK\n");
+		return EIO;
+	}
+
+	if (csw_size != sizeof(csw)) {
+		MASTLOG("csw_size != sizeof(csw)\n");
+		return EIO;
+	}
+
+	if (csw.dCSWTag != tag) {
+		MASTLOG("csw.dCSWTag != tag\n");
+		return EIO;
+	}
+
+	/*
+	 * Determine the actual return value from the CSW.
+	 */
+	switch (csw.dCSWStatus) {
+	case cbs_passed:
+		cmd->status = CMDS_GOOD;
+		break;
+	case cbs_failed:
+		MASTLOG("Command failed\n");
+		cmd->status = CMDS_FAILED;
+		break;
+	case cbs_phase_error:
+		MASTLOG("Phase error\n");
+		retval = EIO;
+		break;
+	default:
+		retval = EIO;
+		break;
+	}
+
+	size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue);
+	if (residue > dbuf_size) {
+		MASTLOG("residue > dbuf_size\n");
+		return EIO;
+	}
+
+	/*
+	 * When the device has less data to send than requested (or cannot
+	 * receive moredata), it can either stall the pipe or send garbage
+	 * (ignore data) and indicate that via the residue field in CSW.
+	 * That means dbuf_size - residue is the authoritative size of data
+	 * received (sent).
+	 */
+
+	if (ddir == USB_DIRECTION_IN)
+		cmd->rcvd_size = dbuf_size - residue;
+
+	return retval;
+}
+
+/** Perform bulk-only mass storage reset.
+ *
+ * @param mfun		Mass storage function
+ * @return		Error code
+ */
+int usb_massstor_reset(usbmast_dev_t *mdev)
+{
+	return usb_control_request_set(&mdev->usb_dev->ctrl_pipe,
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
+	    0xFF, 0, mdev->usb_dev->interface_no, NULL, 0);
+}
+
+/** Perform complete reset recovery of bulk-only mass storage.
+ *
+ * Notice that no error is reported because if this fails, the error
+ * would reappear on next transaction somehow.
+ *
+ * @param mfun		Mass storage function
+ */
+void usb_massstor_reset_recovery(usbmast_dev_t *mdev)
+{
+	/* We would ignore errors here because if this fails
+	 * we are doomed anyway and any following transaction would fail.
+	 */
+	usb_massstor_reset(mdev);
+	usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe,
+	    mdev->usb_dev->pipes[BULK_IN_EP].pipe);
+	usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe,
+	    mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
+}
+
+/** Get max LUN of a mass storage device.
+ *
+ * @see usb_masstor_get_lun_count
+ *
+ * @warning Error from this command does not necessarily indicate malfunction
+ * of the device. Device does not need to support this request.
+ * You shall rather use usb_masstor_get_lun_count.
+ *
+ * @param mfun		Mass storage function
+ * @return		Error code of maximum LUN (index, not count)
+ */
+int usb_massstor_get_max_lun(usbmast_dev_t *mdev)
+{
+	uint8_t max_lun;
+	size_t data_recv_len;
+	int rc = usb_control_request_get(&mdev->usb_dev->ctrl_pipe,
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
+	    0xFE, 0, mdev->usb_dev->interface_no, &max_lun, 1, &data_recv_len);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (data_recv_len != 1) {
+		return EEMPTY;
+	}
+	return (int) max_lun;
+}
+
+/** Get number of LUNs supported by mass storage device.
+ *
+ * @warning This function hides any error during the request
+ * (typically that shall not be a problem).
+ *
+ * @param mfun		Mass storage function
+ * @return		Number of LUNs
+ */
+size_t usb_masstor_get_lun_count(usbmast_dev_t *mdev)
+{
+	int max_lun = usb_massstor_get_max_lun(mdev);
+	if (max_lun < 0) {
+		max_lun = 1;
+	} else {
+		max_lun++;
+	}
+
+	return (size_t) max_lun;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/bo_trans.h
===================================================================
--- uspace/drv/bus/usb/usbmast/bo_trans.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/drv/bus/usb/usbmast/bo_trans.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+/** @addtogroup drvusbmast
+ * @{
+ */
+/** @file
+ * USB mass storage bulk-only transport.
+ */
+
+#ifndef BO_TRANS_H_
+#define BO_TRANS_H_
+
+#include <scsi/spc.h>
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/driver.h>
+#include "usbmast.h"
+
+#define BULK_IN_EP 0
+#define BULK_OUT_EP 1
+
+typedef enum cmd_status {
+	CMDS_GOOD,
+	CMDS_FAILED
+} cmd_status_t;
+
+/** SCSI command.
+ *
+ * Contains (a subset of) the input and output arguments of SCSI
+ * Execute Command procedure call (see SAM-4 chapter 5.1)
+ */
+typedef struct {
+	/*
+	 * Related to IN fields
+	 */
+
+	/** Command Descriptor Block */
+	void *cdb;
+	/** CDB size in bytes */
+	size_t cdb_size;
+
+	/** Outgoing data */
+	const void *data_out;
+	/** Size of outgoing data in bytes */
+	size_t data_out_size;
+
+	/*
+	 * Related to OUT fields
+	 */
+
+	/** Buffer for incoming data */
+	void *data_in;
+	/** Size of input buffer in bytes */
+	size_t data_in_size;
+
+	/** Number of bytes actually received */
+	size_t rcvd_size;
+
+	/** Status */
+	cmd_status_t status;
+} scsi_cmd_t;
+
+extern int usb_massstor_cmd(usbmast_fun_t *, uint32_t, scsi_cmd_t *);
+extern int usb_massstor_reset(usbmast_dev_t *);
+extern void usb_massstor_reset_recovery(usbmast_dev_t *);
+extern int usb_massstor_get_max_lun(usbmast_dev_t *);
+extern size_t usb_masstor_get_lun_count(usbmast_dev_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: pace/drv/bus/usb/usbmast/cmds.c
===================================================================
--- uspace/drv/bus/usb/usbmast/cmds.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,66 +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.
- */
-
-/** @addtogroup drvusbmast
- * @{
- */
-/** @file
- * USB mass storage commands.
- */
-
-#include <byteorder.h>
-#include <mem.h>
-#include <sys/types.h>
-#include <usb/usb.h>
-#include "cmds.h"
-
-void usb_massstor_cbw_prepare(usb_massstor_cbw_t *cbw,
-    uint32_t tag, uint32_t transfer_length, usb_direction_t dir,
-    uint8_t lun, uint8_t cmd_len, uint8_t *cmd)
-{
-	cbw->dCBWSignature = uint32_host2usb(0x43425355);
-	cbw->dCBWTag = tag;
-	cbw->dCBWDataTransferLength = transfer_length;
-
-	cbw->bmCBWFlags = 0;
-	if (dir == USB_DIRECTION_IN) {
-		cbw->bmCBWFlags |= (1 << 7);
-	}
-
-	/* Only lowest 4 bits. */
-	cbw->bCBWLUN = lun & 0x0F;
-
-	/* Only lowest 5 bits. */
-	cbw->bCBWBLength = cmd_len & 0x1F;
-
-	memcpy(cbw->CBWCB, cmd, cbw->bCBWBLength);
-}
-
-/**
- * @}
- */
Index: pace/drv/bus/usb/usbmast/cmds.h
===================================================================
--- uspace/drv/bus/usb/usbmast/cmds.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,66 +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.
- */
-
-/** @addtogroup drvusbmast
- * @{
- */
-/** @file
- * USB mass storage commands.
- */
-
-#ifndef USB_USBMAST_CMDS_H_
-#define USB_USBMAST_CMDS_H_
-
-#include <sys/types.h>
-#include <usb/usb.h>
-
-typedef struct {
-	uint32_t dCBWSignature;
-	uint32_t dCBWTag;
-	uint32_t dCBWDataTransferLength;
-	uint8_t bmCBWFlags;
-	uint8_t bCBWLUN;
-	uint8_t bCBWBLength;
-	uint8_t CBWCB[16];
-} __attribute__((packed)) usb_massstor_cbw_t;
-
-typedef struct {
-	uint32_t dCSWSignature;
-	uint32_t dCSWTag;
-	uint32_t dCSWDataResidue;
-	uint8_t dCSWStatus;
-} __attribute__((packed)) usb_massstor_csw_t;
-
-extern void usb_massstor_cbw_prepare(usb_massstor_cbw_t *, uint32_t, uint32_t,
-    usb_direction_t, uint8_t, uint8_t, uint8_t *);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/drv/bus/usb/usbmast/cmdw.c
===================================================================
--- uspace/drv/bus/usb/usbmast/cmdw.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/drv/bus/usb/usbmast/cmdw.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+/** @addtogroup drvusbmast
+ * @{
+ */
+/** @file
+ * USB mass storage commands.
+ */
+
+#include <byteorder.h>
+#include <mem.h>
+#include <sys/types.h>
+#include <usb/usb.h>
+#include "cmdw.h"
+
+void usb_massstor_cbw_prepare(usb_massstor_cbw_t *cbw,
+    uint32_t tag, uint32_t transfer_length, usb_direction_t dir,
+    uint8_t lun, uint8_t cmd_len, const uint8_t *cmd)
+{
+	cbw->dCBWSignature = uint32_host2usb(0x43425355);
+	cbw->dCBWTag = tag;
+	cbw->dCBWDataTransferLength = transfer_length;
+
+	cbw->bmCBWFlags = 0;
+	if (dir == USB_DIRECTION_IN) {
+		cbw->bmCBWFlags |= (1 << 7);
+	}
+
+	/* Only lowest 4 bits. */
+	cbw->bCBWLUN = lun & 0x0F;
+
+	/* Only lowest 5 bits. */
+	cbw->bCBWBLength = cmd_len & 0x1F;
+
+	memcpy(cbw->CBWCB, cmd, cbw->bCBWBLength);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/cmdw.h
===================================================================
--- uspace/drv/bus/usb/usbmast/cmdw.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/drv/bus/usb/usbmast/cmdw.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+/** @addtogroup drvusbmast
+ * @{
+ */
+/** @file
+ * USB mass storage commands.
+ */
+
+#ifndef CMDW_H_
+#define CMDW_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+
+typedef struct {
+	uint32_t dCBWSignature;
+	uint32_t dCBWTag;
+	uint32_t dCBWDataTransferLength;
+	uint8_t bmCBWFlags;
+	uint8_t bCBWLUN;
+	uint8_t bCBWBLength;
+	uint8_t CBWCB[16];
+} __attribute__((packed)) usb_massstor_cbw_t;
+
+typedef struct {
+	uint32_t dCSWSignature;
+	uint32_t dCSWTag;
+	uint32_t dCSWDataResidue;
+	uint8_t dCSWStatus;
+} __attribute__((packed)) usb_massstor_csw_t;
+
+enum cmd_block_status {
+	cbs_passed	= 0x00,
+	cbs_failed	= 0x01,
+	cbs_phase_error = 0x02
+};
+
+extern void usb_massstor_cbw_prepare(usb_massstor_cbw_t *, uint32_t, uint32_t,
+    usb_direction_t, uint8_t, uint8_t, const uint8_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/main.c
===================================================================
--- uspace/drv/bus/usb/usbmast/main.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbmast/main.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -34,4 +35,8 @@
  * Main routines of USB mass storage driver.
  */
+#include <as.h>
+#include <async.h>
+#include <ipc/bd.h>
+#include <macros.h>
 #include <usb/dev/driver.h>
 #include <usb/debug.h>
@@ -40,7 +45,8 @@
 #include <errno.h>
 #include <str_error.h>
-#include "cmds.h"
-#include "mast.h"
+#include "cmdw.h"
+#include "bo_trans.h"
 #include "scsi_ms.h"
+#include "usbmast.h"
 
 #define NAME "usbmast"
@@ -72,4 +78,8 @@
 };
 
+static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun);
+static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg);
+
 /** Callback when new device is attached and recognized as a mass storage.
  *
@@ -80,20 +90,19 @@
 {
 	int rc;
-	const char *fun_name = "ctl";
-
-	ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
-	    fun_name);
-	if (ctl_fun == NULL) {
-		usb_log_error("Failed to create control function.\n");
-		return ENOMEM;
-	}
-	rc = ddf_fun_bind(ctl_fun);
-	if (rc != EOK) {
-		usb_log_error("Failed to bind control function: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-
-	usb_log_info("Pretending to control mass storage `%s'.\n",
+	usbmast_dev_t *mdev = NULL;
+	unsigned i;
+
+	/* Allocate softstate */
+	mdev = calloc(1, sizeof(usbmast_dev_t));
+	if (mdev == NULL) {
+		usb_log_error("Failed allocating softstate.\n");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	mdev->ddf_dev = dev->ddf_dev;
+	mdev->usb_dev = dev;
+
+	usb_log_info("Initializing mass storage `%s'.\n",
 	    dev->ddf_dev->name);
 	usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
@@ -105,32 +114,94 @@
 
 	usb_log_debug("Get LUN count...\n");
-	size_t lun_count = usb_masstor_get_lun_count(dev);
+	mdev->luns = usb_masstor_get_lun_count(mdev);
+
+	for (i = 0; i < mdev->luns; i++) {
+		rc = usbmast_fun_create(mdev, i);
+		if (rc != EOK)
+			goto error;
+	}
+
+	return EOK;
+error:
+	/* XXX Destroy functions */
+	if (mdev != NULL)
+		free(mdev);
+	return rc;
+}
+
+/** Create mass storage function.
+ *
+ * Called once for each LUN.
+ *
+ * @param mdev		Mass storage device
+ * @param lun		LUN
+ * @return		EOK on success or negative error code.
+ */
+static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun)
+{
+	int rc;
+	char *fun_name = NULL;
+	ddf_fun_t *fun = NULL;
+	usbmast_fun_t *mfun = NULL;
+
+	/* Allocate softstate */
+	mfun = calloc(1, sizeof(usbmast_fun_t));
+	if (mfun == NULL) {
+		usb_log_error("Failed allocating softstate.\n");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	mfun->mdev = mdev;
+	mfun->lun = lun;
+
+	if (asprintf(&fun_name, "l%u", lun) < 0) {
+		usb_log_error("Out of memory.\n");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	fun = ddf_fun_create(mdev->ddf_dev, fun_exposed, fun_name);
+	if (fun == NULL) {
+		usb_log_error("Failed to create DDF function %s.\n", fun_name);
+		rc = ENOMEM;
+		goto error;
+	}
+
+	free(fun_name);
+	fun_name = NULL;
+
+	/* Set up a connection handler. */
+	fun->conn_handler = usbmast_bd_connection;
+	fun->driver_data = mfun;
 
 	usb_log_debug("Inquire...\n");
 	usbmast_inquiry_data_t inquiry;
-	rc = usbmast_inquiry(dev, &inquiry);
+	rc = usbmast_inquiry(mfun, &inquiry);
 	if (rc != EOK) {
 		usb_log_warning("Failed to inquire device `%s': %s.\n",
-		    dev->ddf_dev->name, str_error(rc));
-		return EOK;
-	}
-
-	usb_log_info("Mass storage `%s': " \
-	    "%s by %s rev. %s is %s (%s), %zu LUN(s).\n",
-	    dev->ddf_dev->name,
+		    mdev->ddf_dev->name, str_error(rc));
+		rc = EIO;
+		goto error;
+	}
+
+	usb_log_info("Mass storage `%s' LUN %u: " \
+	    "%s by %s rev. %s is %s (%s).\n",
+	    mdev->ddf_dev->name,
+	    lun,
 	    inquiry.product,
 	    inquiry.vendor,
 	    inquiry.revision,
 	    usbmast_scsi_dev_type_str(inquiry.device_type),
-	    inquiry.removable ? "removable" : "non-removable",
-	    lun_count);
+	    inquiry.removable ? "removable" : "non-removable");
 
 	uint32_t nblocks, block_size;
 
-	rc = usbmast_read_capacity(dev, &nblocks, &block_size);
+	rc = usbmast_read_capacity(mfun, &nblocks, &block_size);
 	if (rc != EOK) {
 		usb_log_warning("Failed to read capacity, device `%s': %s.\n",
-		    dev->ddf_dev->name, str_error(rc));
-		return EOK;
+		    mdev->ddf_dev->name, str_error(rc));
+		rc = EIO;
+		goto error;
 	}
 
@@ -138,25 +209,93 @@
 	    "block_size=%" PRIu32 "\n", nblocks, block_size);
 
-	usb_log_info("Doing test read of block 0.\n");
-	static uint8_t bdata[512];
-
-	rc = usbmast_read(dev, 0, 1, 512, &bdata);
+	mfun->nblocks = nblocks;
+	mfun->block_size = block_size;
+
+	rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
-		usb_log_warning("Failed to read block 0, device `%s': %s.\n",
-		    dev->ddf_dev->name, str_error(rc));
-		return EOK;
-	}
-
-	usb_log_info("Requesting sense data.\n");
-	static scsi_sense_data_t sdata;
-
-	rc = usbmast_request_sense(dev, &sdata, sizeof(sdata));
-	if (rc != EOK) {
-		usb_log_warning("Failed to get sense data, device `%s': %s.\n",
-		    dev->ddf_dev->name, str_error(rc));
-		return EOK;
+		usb_log_error("Failed to bind DDF function %s: %s.\n",
+		    fun_name, str_error(rc));
+		goto error;
 	}
 
 	return EOK;
+
+	/* Error cleanup */
+error:
+	if (fun != NULL)
+		ddf_fun_destroy(fun);
+	if (fun_name != NULL)
+		free(fun_name);
+	if (mfun != NULL)
+		free(mfun);
+	return rc;
+}
+
+/** Blockdev client connection handler. */
+static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
+{
+	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;
+	}
+
+	comm_buf = as_get_mappable_page(comm_size);
+	if (comm_buf == NULL) {
+		async_answer_0(callid, EHANGUP);
+		return;
+	}
+
+	(void) async_share_out_finalize(callid, comm_buf);
+
+	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);
+		}
+	}
 }
 
Index: pace/drv/bus/usb/usbmast/mast.c
===================================================================
--- uspace/drv/bus/usb/usbmast/mast.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,231 +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.
- */
-
-/** @addtogroup drvusbmast
- * @{
- */
-/**
- * @file
- * Generic functions for USB mass storage (implementation).
- */
-#include "mast.h"
-#include "cmds.h"
-#include <bool.h>
-#include <errno.h>
-#include <str_error.h>
-#include <usb/debug.h>
-#include <usb/dev/request.h>
-
-bool usb_mast_verbose = true;
-
-#define MASTLOG(format, ...) \
-	do { \
-		if (usb_mast_verbose) { \
-			usb_log_debug("USB cl08: " format, ##__VA_ARGS__); \
-		} \
-	} while (false)
-
-/** Request data from mass storage device.
- *
- * @param tag Command block wrapper tag (automatically compared with answer).
- * @param lun LUN index.
- * @param cmd SCSI command buffer (in SCSI endianness).
- * @param cmd_size Length of SCSI command @p cmd in bytes.
- * @param in_buffer Buffer where to store the answer (CSW is not returned).
- * @param in_buffer_size Size of the buffer (size of the request to the device).
- * @param received_size Number of actually received bytes.
- * @return Error code.
- */
-int usb_massstor_data_in(usb_device_t *dev,
-    uint32_t tag, uint8_t lun, void *cmd, size_t cmd_size,
-    void *in_buffer, size_t in_buffer_size, size_t *received_size)
-{
-	int rc;
-	size_t act_size;
-	usb_pipe_t *bulk_in_pipe = dev->pipes[BULK_IN_EP].pipe;
-	usb_pipe_t *bulk_out_pipe = dev->pipes[BULK_OUT_EP].pipe;
-
-	/* Prepare CBW - command block wrapper */
-	usb_massstor_cbw_t cbw;
-	usb_massstor_cbw_prepare(&cbw, tag, in_buffer_size,
-	    USB_DIRECTION_IN, lun, cmd_size, cmd);
-
-	/* First, send the CBW. */
-	rc = usb_pipe_write(bulk_out_pipe, &cbw, sizeof(cbw));
-	MASTLOG("CBW '%s' sent: %s.\n",
-	    usb_debug_str_buffer((uint8_t *) &cbw, sizeof(cbw), 0),
-	    str_error(rc));
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/* Try to retrieve the data from the device. */
-	act_size = 0;
-	rc = usb_pipe_read(bulk_in_pipe, in_buffer, in_buffer_size, &act_size);
-	MASTLOG("Received %zuB (%s): %s.\n", act_size,
-	    usb_debug_str_buffer((uint8_t *) in_buffer, act_size, 0),
-	    str_error(rc));
-	if (rc != EOK) {
-		/*
-		 * XXX If the pipe is stalled, we should clear it
-		 * and read CSW.
-		 */
-		return rc;
-	}
-
-	/* Read CSW. */
-	usb_massstor_csw_t csw;
-	size_t csw_size;
-	rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size);
-	MASTLOG("CSW '%s' received (%zuB): %s.\n",
-	    usb_debug_str_buffer((uint8_t *) &csw, csw_size, 0), csw_size,
-	    str_error(rc));
-	if (rc != EOK) {
-		MASTLOG("rc != EOK\n");
-		return rc;
-	}
-
-	if (csw_size != sizeof(csw)) {
-		MASTLOG("csw_size != sizeof(csw)\n");
-		return ERANGE;
-	}
-
-	if (csw.dCSWTag != tag) {
-		MASTLOG("csw.dCSWTag != tag\n");
-		return EBADCHECKSUM;
-	}
-
-	/*
-	 * Determine the actual return value from the CSW.
-	 */
-	if (csw.dCSWStatus != 0) {
-		MASTLOG("csw.dCSWStatus != 0\n");
-		// FIXME: better error code
-		// FIXME: distinguish 0x01 and 0x02
-		return EXDEV;
-	}
-
-	size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue);
-	if (residue > in_buffer_size) {
-		MASTLOG("residue > in_buffer_size\n");
-		return ERANGE;
-	}
-
-	/*
-	 * When the device has less data to send than requested, it can
-	 * either stall the pipe or send garbage and indicate that via
-	 * the residue field in CSW. That means in_buffer_size - residue
-	 * is the authoritative size of data received.
-	 */
-
-	if (received_size != NULL) {
-		*received_size = in_buffer_size - residue;
-	}
-
-	return EOK;
-}
-
-/** Perform bulk-only mass storage reset.
- *
- * @param dev Device to be reseted.
- * @return Error code.
- */
-int usb_massstor_reset(usb_device_t *dev)
-{
-	return usb_control_request_set(&dev->ctrl_pipe,
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
-	    0xFF, 0, dev->interface_no, NULL, 0);
-}
-
-/** Perform complete reset recovery of bulk-only mass storage.
- *
- * Notice that no error is reported because if this fails, the error
- * would reappear on next transaction somehow.
- *
- * @param dev Device to be reseted.
- */
-void usb_massstor_reset_recovery(usb_device_t *dev)
-{
-	/* We would ignore errors here because if this fails
-	 * we are doomed anyway and any following transaction would fail.
-	 */
-	usb_massstor_reset(dev);
-	usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[BULK_IN_EP].pipe);
-	usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[BULK_OUT_EP].pipe);
-}
-
-/** Get max LUN of a mass storage device.
- *
- * @see usb_masstor_get_lun_count
- *
- * @warning Error from this command does not necessarily indicate malfunction
- * of the device. Device does not need to support this request.
- * You shall rather use usb_masstor_get_lun_count.
- *
- * @param dev Mass storage device.
- * @return Error code of maximum LUN (index, not count).
- */
-int usb_massstor_get_max_lun(usb_device_t *dev)
-{
-	uint8_t max_lun;
-	size_t data_recv_len;
-	int rc = usb_control_request_get(&dev->ctrl_pipe,
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
-	    0xFE, 0, dev->interface_no, &max_lun, 1, &data_recv_len);
-	if (rc != EOK) {
-		return rc;
-	}
-	if (data_recv_len != 1) {
-		return EEMPTY;
-	}
-	return (int) max_lun;
-}
-
-/** Get number of LUNs supported by mass storage device.
- *
- * @warning This function hides any error during the request
- * (typically that shall not be a problem).
- *
- * @param dev Mass storage device.
- * @return Number of LUNs.
- */
-size_t usb_masstor_get_lun_count(usb_device_t *dev)
-{
-	int max_lun = usb_massstor_get_max_lun(dev);
-	if (max_lun < 0) {
-		max_lun = 1;
-	} else {
-		max_lun++;
-	}
-
-	return (size_t) max_lun;
-}
-
-/**
- * @}
- */
Index: pace/drv/bus/usb/usbmast/mast.h
===================================================================
--- uspace/drv/bus/usb/usbmast/mast.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,59 +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.
- */
-
-/** @addtogroup drvusbmast
- * @{
- */
-/** @file
- * Generic functions for USB mass storage.
- */
-
-#ifndef USB_USBMAST_MAST_H_
-#define USB_USBMAST_MAST_H_
-
-#include <scsi/spc.h>
-#include <sys/types.h>
-#include <usb/usb.h>
-#include <usb/dev/pipes.h>
-#include <usb/dev/driver.h>
-
-#define BULK_IN_EP 0
-#define BULK_OUT_EP 1
-
-int usb_massstor_data_in(usb_device_t *dev, uint32_t, uint8_t, void *,
-    size_t, void *, size_t, size_t *);
-int usb_massstor_reset(usb_device_t *);
-void usb_massstor_reset_recovery(usb_device_t *);
-int usb_massstor_get_max_lun(usb_device_t *);
-size_t usb_masstor_get_lun_count(usb_device_t *);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/drv/bus/usb/usbmast/scsi_ms.c
===================================================================
--- uspace/drv/bus/usb/usbmast/scsi_ms.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbmast/scsi_ms.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -46,7 +46,8 @@
 #include <scsi/sbc.h>
 #include <scsi/spc.h>
-#include "cmds.h"
-#include "mast.h"
+#include "cmdw.h"
+#include "bo_trans.h"
 #include "scsi_ms.h"
+#include "usbmast.h"
 
 /** Get string representation for SCSI peripheral device type.
@@ -60,14 +61,73 @@
 }
 
+static void usbmast_dump_sense(scsi_sense_data_t *sense_buf)
+{
+	unsigned sense_key;
+
+	sense_key = sense_buf->flags_key & 0x0f;
+	printf("Got sense data. Sense key: 0x%x (%s), ASC 0x%02x, "
+	    "ASCQ 0x%02x.\n", sense_key,
+	    scsi_get_sense_key_str(sense_key),
+	    sense_buf->additional_code,
+	    sense_buf->additional_cqual);
+}
+
+/** Run SCSI command.
+ *
+ * Run command and repeat in case of unit attention.
+ * XXX This is too simplified.
+ */
+static int usbmast_run_cmd(usbmast_fun_t *mfun, scsi_cmd_t *cmd)
+{
+	uint8_t sense_key;
+	scsi_sense_data_t sense_buf;
+	int rc;
+
+	do {
+		rc = usb_massstor_cmd(mfun, 0xDEADBEEF, cmd);
+		if (rc != EOK) {
+			usb_log_error("Inquiry transport failed, device %s: %s.\n",
+			   mfun->mdev->ddf_dev->name, str_error(rc));
+			return rc;
+		}
+
+		if (cmd->status == CMDS_GOOD)
+			return EOK;
+
+		usb_log_error("SCSI command failed, device %s.\n",
+		    mfun->mdev->ddf_dev->name);
+
+		rc = usbmast_request_sense(mfun, &sense_buf, sizeof(sense_buf));
+		if (rc != EOK) {
+			usb_log_error("Failed to read sense data.\n");
+			return EIO;
+		}
+
+		/* Dump sense data to log */
+		usbmast_dump_sense(&sense_buf);
+
+		/* Get sense key */
+		sense_key = sense_buf.flags_key & 0x0f;
+
+		if (sense_key == SCSI_SK_UNIT_ATTENTION) {
+			printf("Got unit attention. Re-trying command.\n");
+		}
+
+	} while (sense_key == SCSI_SK_UNIT_ATTENTION);
+
+	/* Command status is not good, nevertheless transport succeeded. */
+	return EOK;
+}
+
 /** Perform SCSI Inquiry command on USB mass storage device.
  *
- * @param dev		USB device.
- * @param inquiry_result Where to store parsed inquiry result.
- * @return		Error code.
- */
-int usbmast_inquiry(usb_device_t *dev, usbmast_inquiry_data_t *inq_res)
+ * @param mfun		Mass storage function
+ * @param inquiry_result Where to store parsed inquiry result
+ * @return		Error code
+ */
+int usbmast_inquiry(usbmast_fun_t *mfun, usbmast_inquiry_data_t *inq_res)
 {
 	scsi_std_inquiry_data_t inq_data;
-	size_t response_len;
+	scsi_cmd_t cmd;
 	scsi_cdb_inquiry_t cdb;
 	int rc;
@@ -77,16 +137,27 @@
 	cdb.alloc_len = host2uint16_t_be(sizeof(inq_data));
 
-	rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
-	    sizeof(cdb), &inq_data, sizeof(inq_data), &response_len);
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.cdb = &cdb;
+	cmd.cdb_size = sizeof(cdb);
+	cmd.data_in = &inq_data;
+	cmd.data_in_size = sizeof(inq_data);
+
+	rc = usb_massstor_cmd(mfun, 0xDEADBEEF, &cmd);
 
 	if (rc != EOK) {
-		usb_log_error("Inquiry failed, device %s: %s.\n",
-		   dev->ddf_dev->name, str_error(rc));
-		return rc;
-	}
-
-	if (response_len < SCSI_STD_INQUIRY_DATA_MIN_SIZE) {
+		usb_log_error("Inquiry transport failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (cmd.status != CMDS_GOOD) {
+		usb_log_error("Inquiry command failed, device %s.\n",
+		   mfun->mdev->ddf_dev->name);
+		return EIO;
+	}
+
+	if (cmd.rcvd_size < SCSI_STD_INQUIRY_DATA_MIN_SIZE) {
 		usb_log_error("SCSI Inquiry response too short (%zu).\n",
-		    response_len);
+		    cmd.rcvd_size);
 		return EIO;
 	}
@@ -118,5 +189,5 @@
 /** Perform SCSI Request Sense command on USB mass storage device.
  *
- * @param dev		USB device
+ * @param mfun		Mass storage function
  * @param buf		Destination buffer
  * @param size		Size of @a buf
@@ -124,8 +195,8 @@
  * @return		Error code.
  */
-int usbmast_request_sense(usb_device_t *dev, void *buf, size_t size)
-{
+int usbmast_request_sense(usbmast_fun_t *mfun, void *buf, size_t size)
+{
+	scsi_cmd_t cmd;
 	scsi_cdb_request_sense_t cdb;
-	size_t data_len;
 	int rc;
 
@@ -134,17 +205,22 @@
 	cdb.alloc_len = min(size, SCSI_SENSE_DATA_MAX_SIZE);
 
-	rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
-	    sizeof(cdb), buf, size, &data_len);
-
-        if (rc != EOK) {
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.cdb = &cdb;
+	cmd.cdb_size = sizeof(cdb);
+	cmd.data_in = buf;
+	cmd.data_in_size = size;
+
+	rc = usb_massstor_cmd(mfun, 0xDEADBEEF, &cmd);
+
+        if (rc != EOK || cmd.status != CMDS_GOOD) {
 		usb_log_error("Request Sense failed, device %s: %s.\n",
-		   dev->ddf_dev->name, str_error(rc));
-		return rc;
-	}
-
-	if (data_len < SCSI_SENSE_DATA_MIN_SIZE) {
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (cmd.rcvd_size < SCSI_SENSE_DATA_MIN_SIZE) {
 		/* The missing bytes should be considered to be zeroes. */
-		memset((uint8_t *)buf + data_len, 0,
-		    SCSI_SENSE_DATA_MIN_SIZE - data_len);
+		memset((uint8_t *)buf + cmd.rcvd_size, 0,
+		    SCSI_SENSE_DATA_MIN_SIZE - cmd.rcvd_size);
 	}
 
@@ -154,16 +230,16 @@
 /** Perform SCSI Read Capacity command on USB mass storage device.
  *
- * @param dev		USB device.
- * @param nblocks	Output, number of blocks.
- * @param block_size	Output, block size in bytes.
+ * @param mfun		Mass storage function
+ * @param nblocks	Output, number of blocks
+ * @param block_size	Output, block size in bytes
  *
  * @return		Error code.
  */
-int usbmast_read_capacity(usb_device_t *dev, uint32_t *nblocks,
+int usbmast_read_capacity(usbmast_fun_t *mfun, uint32_t *nblocks,
     uint32_t *block_size)
 {
+	scsi_cmd_t cmd;
 	scsi_cdb_read_capacity_10_t cdb;
 	scsi_read_capacity_10_data_t data;
-	size_t data_len;
 	int rc;
 
@@ -171,16 +247,27 @@
 	cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
 
-	rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
-	    sizeof(cdb), &data, sizeof(data), &data_len);
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.cdb = &cdb;
+	cmd.cdb_size = sizeof(cdb);
+	cmd.data_in = &data;
+	cmd.data_in_size = sizeof(data);
+
+	rc = usbmast_run_cmd(mfun, &cmd);
 
         if (rc != EOK) {
-		usb_log_error("Read Capacity (10) failed, device %s: %s.\n",
-		   dev->ddf_dev->name, str_error(rc));
-		return rc;
-	}
-
-	if (data_len < sizeof(data)) {
+		usb_log_error("Read Capacity (10) transport failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (cmd.status != CMDS_GOOD) {
+		usb_log_error("Read Capacity (10) command failed, device %s.\n",
+		   mfun->mdev->ddf_dev->name);
+		return EIO;
+	}
+
+	if (cmd.rcvd_size < sizeof(data)) {
 		usb_log_error("SCSI Read Capacity response too short (%zu).\n",
-		    data_len);
+		    cmd.rcvd_size);
 		return EIO;
 	}
@@ -194,43 +281,100 @@
 /** Perform SCSI Read command on USB mass storage device.
  *
- * @param dev		USB device.
- * @param ba		Address of first block.
- * @param nblocks	Number of blocks to read.
- * @param bsize		Block size.
- *
- * @return		Error code.
- */
-int usbmast_read(usb_device_t *dev, uint64_t ba, size_t nblocks, size_t bsize,
-    void *buf)
-{
-	scsi_cdb_read_12_t cdb;
-	size_t data_len;
-	int rc;
-
-	/* XXX Need softstate to store block size. */
+ * @param mfun		Mass storage function
+ * @param ba		Address of first block
+ * @param nblocks	Number of blocks to read
+ *
+ * @return		Error code
+ */
+int usbmast_read(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks, void *buf)
+{
+	scsi_cmd_t cmd;
+	scsi_cdb_read_10_t cdb;
+	int rc;
 
 	if (ba > UINT32_MAX)
 		return ELIMIT;
 
-	if ((uint64_t)nblocks * bsize > UINT32_MAX)
+	if (nblocks > UINT16_MAX)
 		return ELIMIT;
 
 	memset(&cdb, 0, sizeof(cdb));
-	cdb.op_code = SCSI_CMD_READ_12;
+	cdb.op_code = SCSI_CMD_READ_10;
 	cdb.lba = host2uint32_t_be(ba);
-	cdb.xfer_len = host2uint32_t_be(nblocks);
-
-	rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
-	    sizeof(cdb), buf, nblocks * bsize, &data_len);
+	cdb.xfer_len = host2uint16_t_be(nblocks);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.cdb = &cdb;
+	cmd.cdb_size = sizeof(cdb);
+	cmd.data_in = buf;
+	cmd.data_in_size = nblocks * mfun->block_size;
+
+	rc = usbmast_run_cmd(mfun, &cmd);
 
         if (rc != EOK) {
-		usb_log_error("Read (12) failed, device %s: %s.\n",
-		   dev->ddf_dev->name, str_error(rc));
-		return rc;
-	}
-
-	if (data_len < nblocks * bsize) {
+		usb_log_error("Read (10) transport failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (cmd.status != CMDS_GOOD) {
+		usb_log_error("Read (10) command failed, device %s.\n",
+		   mfun->mdev->ddf_dev->name);
+		return EIO;
+	}
+
+	if (cmd.rcvd_size < nblocks * mfun->block_size) {
 		usb_log_error("SCSI Read response too short (%zu).\n",
-		    data_len);
+		    cmd.rcvd_size);
+		return EIO;
+	}
+
+	return EOK;
+}
+
+/** Perform SCSI Write command on USB mass storage device.
+ *
+ * @param mfun		Mass storage function
+ * @param ba		Address of first block
+ * @param nblocks	Number of blocks to read
+ * @param data		Data to write
+ *
+ * @return		Error code
+ */
+int usbmast_write(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks,
+    const void *data)
+{
+	scsi_cmd_t cmd;
+	scsi_cdb_write_10_t cdb;
+	int rc;
+
+	if (ba > UINT32_MAX)
+		return ELIMIT;
+
+	if (nblocks > UINT16_MAX)
+		return ELIMIT;
+
+	memset(&cdb, 0, sizeof(cdb));
+	cdb.op_code = SCSI_CMD_WRITE_10;
+	cdb.lba = host2uint32_t_be(ba);
+	cdb.xfer_len = host2uint16_t_be(nblocks);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.cdb = &cdb;
+	cmd.cdb_size = sizeof(cdb);
+	cmd.data_out = data;
+	cmd.data_out_size = nblocks * mfun->block_size;
+
+	rc = usbmast_run_cmd(mfun, &cmd);
+
+        if (rc != EOK) {
+		usb_log_error("Write (10) transport failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (cmd.status != CMDS_GOOD) {
+		usb_log_error("Write (10) command failed, device %s.\n",
+		   mfun->mdev->ddf_dev->name);
 		return EIO;
 	}
Index: uspace/drv/bus/usb/usbmast/scsi_ms.h
===================================================================
--- uspace/drv/bus/usb/usbmast/scsi_ms.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbmast/scsi_ms.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -59,8 +59,9 @@
 } usbmast_inquiry_data_t;
 
-extern int usbmast_inquiry(usb_device_t *, usbmast_inquiry_data_t *);
-extern int usbmast_request_sense(usb_device_t *, void *, size_t);
-extern int usbmast_read_capacity(usb_device_t *, uint32_t *, uint32_t *);
-extern int usbmast_read(usb_device_t *, uint64_t, size_t, size_t, void *);
+extern int usbmast_inquiry(usbmast_fun_t *, usbmast_inquiry_data_t *);
+extern int usbmast_request_sense(usbmast_fun_t *, void *, size_t);
+extern int usbmast_read_capacity(usbmast_fun_t *, uint32_t *, uint32_t *);
+extern int usbmast_read(usbmast_fun_t *, uint64_t, size_t, void *);
+extern int usbmast_write(usbmast_fun_t *, uint64_t, size_t, const void *);
 extern const char *usbmast_scsi_dev_type_str(unsigned);
 
Index: uspace/drv/bus/usb/usbmast/usbmast.h
===================================================================
--- uspace/drv/bus/usb/usbmast/usbmast.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/drv/bus/usb/usbmast/usbmast.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -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 drvusbmast
+ * @{
+ */
+/** @file
+ * USB mass storage commands.
+ */
+
+#ifndef USBMAST_H_
+#define USBMAST_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+
+/** Mass storage device. */
+typedef struct {
+	/** DDF device */
+	ddf_dev_t *ddf_dev;
+	/** USB device */
+	usb_device_t *usb_dev;
+	/** Number of LUNs */
+	unsigned luns;
+} usbmast_dev_t;
+
+/** Mass storage function.
+ *
+ * Serves as soft state for function/LUN.
+ */
+typedef struct {
+	/** Mass storage device the function belongs to */
+	usbmast_dev_t *mdev;
+	/** DDF function */
+	ddf_fun_t *ddf_fun;
+	/** LUN */
+	unsigned lun;
+	/** Total number of blocks */
+	uint64_t nblocks;
+	/** Block size in bytes */
+	size_t block_size;
+} usbmast_fun_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmouse/init.c
===================================================================
--- uspace/drv/bus/usb/usbmouse/init.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/usbmouse/init.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -116,5 +116,5 @@
 	
 	/* Add the function to mouse class. */
-	rc = ddf_fun_add_to_class(mouse->mouse_fun, "mouse");
+	rc = ddf_fun_add_to_category(mouse->mouse_fun, "mouse");
 	if (rc != EOK)
 		goto leave;
Index: uspace/drv/bus/usb/vhc/connhost.c
===================================================================
--- uspace/drv/bus/usb/vhc/connhost.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/vhc/connhost.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -141,19 +141,14 @@
     size_t max_packet_size, unsigned int interval)
 {
-	VHC_DATA(vhc, fun);
-
-	endpoint_t *ep = malloc(sizeof(endpoint_t));
+	/* TODO: Use usb_endpoint_manager_add_ep */
+	VHC_DATA(vhc, fun);
+
+	endpoint_t *ep = endpoint_get(
+	    address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1);
 	if (ep == NULL) {
 		return ENOMEM;
 	}
 
-	int rc = endpoint_init(ep, address, endpoint, direction, transfer_type,
-	    USB_SPEED_FULL, 1);
-	if (rc != EOK) {
-		free(ep);
-		return rc;
-	}
-
-	rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
+	int rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
 	if (rc != EOK) {
 		endpoint_destroy(ep);
Index: uspace/drv/bus/usb/vhc/main.c
===================================================================
--- uspace/drv/bus/usb/vhc/main.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/bus/usb/vhc/main.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -34,5 +34,5 @@
  */
 
-#include <devmap.h>
+#include <loc.h>
 #include <async.h>
 #include <unistd.h>
@@ -104,5 +104,5 @@
 	}
 
-	rc = ddf_fun_add_to_class(hc, USB_HC_DDF_CLASS_NAME);
+	rc = ddf_fun_add_to_category(hc, USB_HC_CATEGORY);
 	if (rc != EOK) {
 		usb_log_fatal("Failed to add function to HC class: %s.\n",
Index: uspace/drv/char/ns8250/ns8250.c
===================================================================
--- uspace/drv/char/ns8250/ns8250.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/char/ns8250/ns8250.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -781,5 +781,5 @@
 	ns->fun = fun;
 	
-	ddf_fun_add_to_class(fun, "serial");
+	ddf_fun_add_to_category(fun, "serial");
 	
 	ddf_msg(LVL_NOTE, "Device %s successfully initialized.",
Index: uspace/drv/infrastructure/root/root.c
===================================================================
--- uspace/drv/infrastructure/root/root.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/infrastructure/root/root.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -176,4 +176,6 @@
 	}
 
+	free(match_id);
+
 	rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
Index: uspace/drv/test/test1/test1.c
===================================================================
--- uspace/drv/test/test1/test1.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/test/test1/test1.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -74,5 +74,5 @@
 	}
 
-	rc = ddf_fun_add_match_id(fun, str_dup(match_id), match_score);
+	rc = ddf_fun_add_match_id(fun, match_id, match_score);
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
@@ -143,9 +143,9 @@
 	}
 
-	ddf_fun_add_to_class(fun_a, "virtual");
+	ddf_fun_add_to_category(fun_a, "virtual");
 
 	if (str_cmp(dev->name, "null") == 0) {
 		fun_a->ops = &char_device_ops;
-		ddf_fun_add_to_class(fun_a, "virt-null");
+		ddf_fun_add_to_category(fun_a, "virt-null");
 	} else if (str_cmp(dev->name, "test1") == 0) {
 		(void) register_fun_verbose(dev,
Index: uspace/drv/test/test2/test2.c
===================================================================
--- uspace/drv/test/test2/test2.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/test/test2/test2.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -123,5 +123,5 @@
 	}
 
-	ddf_fun_add_to_class(fun_a, "virtual");
+	ddf_fun_add_to_category(fun_a, "virtual");
 
 	return EOK;
Index: uspace/drv/test/test3/test3.c
===================================================================
--- uspace/drv/test/test3/test3.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/drv/test/test3/test3.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -50,5 +50,5 @@
 };
 
-static int register_fun_and_add_to_class(ddf_dev_t *parent,
+static int register_fun_and_add_to_category(ddf_dev_t *parent,
      const char *base_name, size_t index, const char *class_name)
 {
@@ -77,5 +77,5 @@
 	}
 	
-	ddf_fun_add_to_class(fun, class_name);
+	ddf_fun_add_to_category(fun, class_name);
 
 	ddf_msg(LVL_NOTE, "Registered exposed function `%s'.", fun_name);
@@ -100,5 +100,5 @@
 	size_t i;
 	for (i = 0; i < 20; i++) {
-		rc = register_fun_and_add_to_class(dev,
+		rc = register_fun_and_add_to_category(dev,
 		    "test3_", i, "test3");
 		if (rc != EOK) {
Index: uspace/lib/block/libblock.c
===================================================================
--- uspace/lib/block/libblock.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/block/libblock.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,5 @@
 #include "libblock.h"
 #include "../../srv/vfs/vfs.h"
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 #include <ipc/bd.h>
 #include <ipc/services.h>
@@ -78,5 +78,5 @@
 typedef struct {
 	link_t link;
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 	async_sess_t *sess;
 	fibril_mutex_t comm_area_lock;
@@ -95,5 +95,5 @@
 static aoff64_t ba_ltop(devcon_t *, aoff64_t);
 
-static devcon_t *devcon_search(devmap_handle_t devmap_handle)
+static devcon_t *devcon_search(service_id_t service_id)
 {
 	fibril_mutex_lock(&dcl_lock);
@@ -101,5 +101,5 @@
 	list_foreach(dcl, cur) {
 		devcon_t *devcon = list_get_instance(cur, devcon_t, link);
-		if (devcon->devmap_handle == devmap_handle) {
+		if (devcon->service_id == service_id) {
 			fibril_mutex_unlock(&dcl_lock);
 			return devcon;
@@ -111,5 +111,5 @@
 }
 
-static int devcon_add(devmap_handle_t devmap_handle, async_sess_t *sess,
+static int devcon_add(service_id_t service_id, async_sess_t *sess,
     size_t bsize, void *comm_area, size_t comm_size)
 {
@@ -124,5 +124,5 @@
 	
 	link_initialize(&devcon->link);
-	devcon->devmap_handle = devmap_handle;
+	devcon->service_id = service_id;
 	devcon->sess = sess;
 	fibril_mutex_initialize(&devcon->comm_area_lock);
@@ -137,5 +137,5 @@
 	list_foreach(dcl, cur) {
 		devcon_t *d = list_get_instance(cur, devcon_t, link);
-		if (d->devmap_handle == devmap_handle) {
+		if (d->service_id == service_id) {
 			fibril_mutex_unlock(&dcl_lock);
 			free(devcon);
@@ -155,5 +155,5 @@
 }
 
-int block_init(exch_mgmt_t mgmt, devmap_handle_t devmap_handle,
+int block_init(exch_mgmt_t mgmt, service_id_t service_id,
     size_t comm_size)
 {
@@ -163,5 +163,5 @@
 		return ENOMEM;
 	
-	async_sess_t *sess = devmap_device_connect(mgmt, devmap_handle,
+	async_sess_t *sess = loc_service_connect(mgmt, service_id,
 	    IPC_FLAG_BLOCKING);
 	if (!sess) {
@@ -190,5 +190,5 @@
 	}
 	
-	rc = devcon_add(devmap_handle, sess, bsize, comm_area, comm_size);
+	rc = devcon_add(service_id, sess, bsize, comm_area, comm_size);
 	if (rc != EOK) {
 		munmap(comm_area, comm_size);
@@ -200,11 +200,11 @@
 }
 
-void block_fini(devmap_handle_t devmap_handle)
-{
-	devcon_t *devcon = devcon_search(devmap_handle);
+void block_fini(service_id_t service_id)
+{
+	devcon_t *devcon = devcon_search(service_id);
 	assert(devcon);
 	
 	if (devcon->cache)
-		(void) block_cache_fini(devmap_handle);
+		(void) block_cache_fini(service_id);
 	
 	devcon_remove(devcon);
@@ -219,10 +219,10 @@
 }
 
-int block_bb_read(devmap_handle_t devmap_handle, aoff64_t ba)
+int block_bb_read(service_id_t service_id, aoff64_t ba)
 {
 	void *bb_buf;
 	int rc;
 
-	devcon_t *devcon = devcon_search(devmap_handle);
+	devcon_t *devcon = devcon_search(service_id);
 	if (!devcon)
 		return ENOENT;
@@ -249,7 +249,7 @@
 }
 
-void *block_bb_get(devmap_handle_t devmap_handle)
-{
-	devcon_t *devcon = devcon_search(devmap_handle);
+void *block_bb_get(service_id_t service_id)
+{
+	devcon_t *devcon = devcon_search(service_id);
 	assert(devcon);
 	return devcon->bb_buf;
@@ -258,5 +258,5 @@
 static hash_index_t cache_hash(unsigned long *key)
 {
-	return *key & (CACHE_BUCKETS - 1);
+	return MERGE_LOUP32(key[0], key[1]) & (CACHE_BUCKETS - 1);
 }
 
@@ -264,5 +264,5 @@
 {
 	block_t *b = hash_table_get_instance(item, block_t, hash_link);
-	return b->lba == *key;
+	return b->lba == MERGE_LOUP32(key[0], key[1]);
 }
 
@@ -277,8 +277,8 @@
 };
 
-int block_cache_init(devmap_handle_t devmap_handle, size_t size, unsigned blocks,
+int block_cache_init(service_id_t service_id, size_t size, unsigned blocks,
     enum cache_mode mode)
 {
-	devcon_t *devcon = devcon_search(devmap_handle);
+	devcon_t *devcon = devcon_search(service_id);
 	cache_t *cache;
 	if (!devcon)
@@ -305,5 +305,5 @@
 	cache->blocks_cluster = cache->lblock_size / devcon->pblock_size;
 
-	if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
+	if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 2,
 	    &cache_ops)) {
 		free(cache);
@@ -315,7 +315,7 @@
 }
 
-int block_cache_fini(devmap_handle_t devmap_handle)
-{
-	devcon_t *devcon = devcon_search(devmap_handle);
+int block_cache_fini(service_id_t service_id)
+{
+	devcon_t *devcon = devcon_search(service_id);
 	cache_t *cache;
 	int rc;
@@ -344,6 +344,9 @@
 		}
 
-		unsigned long key = b->lba;
-		hash_table_remove(&cache->block_hash, &key, 1);
+		unsigned long key[2] = {
+			LOWER32(b->lba),
+			UPPER32(b->lba)
+		};
+		hash_table_remove(&cache->block_hash, key, 2);
 		
 		free(b->data);
@@ -384,5 +387,5 @@
  * @param block			Pointer to where the function will store the
  * 				block pointer on success.
- * @param devmap_handle		Device handle of the block device.
+ * @param service_id		Service ID of the block device.
  * @param ba			Block address (logical).
  * @param flags			If BLOCK_FLAGS_NOREAD is specified, block_get()
@@ -392,5 +395,5 @@
  * @return			EOK on success or a negative error code.
  */
-int block_get(block_t **block, devmap_handle_t devmap_handle, aoff64_t ba, int flags)
+int block_get(block_t **block, service_id_t service_id, aoff64_t ba, int flags)
 {
 	devcon_t *devcon;
@@ -398,8 +401,12 @@
 	block_t *b;
 	link_t *l;
-	unsigned long key = ba;
+	unsigned long key[2] = {
+		LOWER32(ba),
+		UPPER32(ba)
+	};
+
 	int rc;
 	
-	devcon = devcon_search(devmap_handle);
+	devcon = devcon_search(service_id);
 
 	assert(devcon);
@@ -413,5 +420,5 @@
 
 	fibril_mutex_lock(&cache->lock);
-	l = hash_table_find(&cache->block_hash, &key);
+	l = hash_table_find(&cache->block_hash, key);
 	if (l) {
 found:
@@ -451,5 +458,4 @@
 			 * Try to recycle a block from the free list.
 			 */
-			unsigned long temp_key;
 recycle:
 			if (list_empty(&cache->free_list)) {
@@ -499,5 +505,5 @@
 					goto retry;
 				}
-				l = hash_table_find(&cache->block_hash, &key);
+				l = hash_table_find(&cache->block_hash, key);
 				if (l) {
 					/*
@@ -522,14 +528,17 @@
 			 */
 			list_remove(&b->free_link);
-			temp_key = b->lba;
-			hash_table_remove(&cache->block_hash, &temp_key, 1);
+			unsigned long temp_key[2] = {
+				LOWER32(b->lba),
+				UPPER32(b->lba)
+			};
+			hash_table_remove(&cache->block_hash, temp_key, 2);
 		}
 
 		block_initialize(b);
-		b->devmap_handle = devmap_handle;
+		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);
+		hash_table_insert(&cache->block_hash, key, &b->hash_link);
 
 		/*
@@ -577,5 +586,5 @@
 int block_put(block_t *block)
 {
-	devcon_t *devcon = devcon_search(block->devmap_handle);
+	devcon_t *devcon = devcon_search(block->service_id);
 	cache_t *cache;
 	unsigned blocks_cached;
@@ -643,6 +652,9 @@
 			 * Take the block out of the cache and free it.
 			 */
-			unsigned long key = block->lba;
-			hash_table_remove(&cache->block_hash, &key, 1);
+			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);
@@ -675,5 +687,5 @@
 /** Read sequential data from a block device.
  *
- * @param devmap_handle	Device handle of the block device.
+ * @param service_id	Service ID of the block device.
  * @param bufpos	Pointer to the first unread valid offset within the
  * 			communication buffer.
@@ -687,5 +699,5 @@
  * @return		EOK on success or a negative return code on failure.
  */
-int block_seqread(devmap_handle_t devmap_handle, size_t *bufpos, size_t *buflen,
+int block_seqread(service_id_t service_id, size_t *bufpos, size_t *buflen,
     aoff64_t *pos, void *dst, size_t size)
 {
@@ -695,5 +707,5 @@
 	devcon_t *devcon;
 
-	devcon = devcon_search(devmap_handle);
+	devcon = devcon_search(service_id);
 	assert(devcon);
 	block_size = devcon->pblock_size;
@@ -741,5 +753,5 @@
 /** Read blocks directly from device (bypass cache).
  *
- * @param devmap_handle	Device handle of the block device.
+ * @param service_id	Service ID of the block device.
  * @param ba		Address of first block (physical).
  * @param cnt		Number of blocks.
@@ -748,10 +760,10 @@
  * @return		EOK on success or negative error code on failure.
  */
-int block_read_direct(devmap_handle_t devmap_handle, aoff64_t ba, size_t cnt, void *buf)
+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(devmap_handle);
+	devcon = devcon_search(service_id);
 	assert(devcon);
 	
@@ -769,5 +781,5 @@
 /** Write blocks directly to device (bypass cache).
  *
- * @param devmap_handle	Device handle of the block device.
+ * @param service_id	Service ID of the block device.
  * @param ba		Address of first block (physical).
  * @param cnt		Number of blocks.
@@ -776,5 +788,5 @@
  * @return		EOK on success or negative error code on failure.
  */
-int block_write_direct(devmap_handle_t devmap_handle, aoff64_t ba, size_t cnt,
+int block_write_direct(service_id_t service_id, aoff64_t ba, size_t cnt,
     const void *data)
 {
@@ -782,5 +794,5 @@
 	int rc;
 
-	devcon = devcon_search(devmap_handle);
+	devcon = devcon_search(service_id);
 	assert(devcon);
 	
@@ -797,14 +809,14 @@
 /** Get device block size.
  *
- * @param devmap_handle	Device handle of the block device.
+ * @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(devmap_handle_t devmap_handle, size_t *bsize)
+int block_get_bsize(service_id_t service_id, size_t *bsize)
 {
 	devcon_t *devcon;
 
-	devcon = devcon_search(devmap_handle);
+	devcon = devcon_search(service_id);
 	assert(devcon);
 	
@@ -814,12 +826,12 @@
 /** Get number of blocks on device.
  *
- * @param devmap_handle	Device handle of the block 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(devmap_handle_t devmap_handle, aoff64_t *nblocks)
-{
-	devcon_t *devcon = devcon_search(devmap_handle);
+int block_get_nblocks(service_id_t service_id, aoff64_t *nblocks)
+{
+	devcon_t *devcon = devcon_search(service_id);
 	assert(devcon);
 	
@@ -829,5 +841,5 @@
 /** Read bytes directly from the device (bypass cache)
  * 
- * @param devmap_handle	Device handle of the block device.
+ * @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
@@ -836,5 +848,5 @@
  * @return		EOK on success or negative error code on failure.
  */
-int block_read_bytes_direct(devmap_handle_t devmap_handle, aoff64_t abs_offset,
+int block_read_bytes_direct(service_id_t service_id, aoff64_t abs_offset,
     size_t bytes, void *data)
 {
@@ -848,5 +860,5 @@
 	size_t offset;
 	
-	rc = block_get_bsize(devmap_handle, &phys_block_size);
+	rc = block_get_bsize(service_id, &phys_block_size);
 	if (rc != EOK) {
 		return rc;
@@ -866,5 +878,5 @@
 	}
 	
-	rc = block_read_direct(devmap_handle, first_block, blocks, buffer);
+	rc = block_read_direct(service_id, first_block, blocks, buffer);
 	if (rc != EOK) {
 		free(buffer);
@@ -900,5 +912,5 @@
 		printf("Error %d reading %zu blocks starting at block %" PRIuOFF64
 		    " from device handle %" PRIun "\n", rc, cnt, ba,
-		    devcon->devmap_handle);
+		    devcon->service_id);
 #ifndef NDEBUG
 		stacktrace_print();
@@ -929,5 +941,5 @@
 	if (rc != EOK) {
 		printf("Error %d writing %zu blocks starting at block %" PRIuOFF64
-		    " to device handle %" PRIun "\n", rc, cnt, ba, devcon->devmap_handle);
+		    " to device handle %" PRIun "\n", rc, cnt, ba, devcon->service_id);
 #ifndef NDEBUG
 		stacktrace_print();
Index: uspace/lib/block/libblock.h
===================================================================
--- uspace/lib/block/libblock.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/block/libblock.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2008 Jakub Jermar
- * Copyright (c) 2008 Martin Decky 
- * Copyright (c) 2011 Martin Sucha 
+ * Copyright (c) 2008 Martin Decky
+ * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
  *
@@ -73,6 +73,6 @@
 	/** Readers / Writer lock protecting the contents of the block. */
 	fibril_rwlock_t contents_lock;
-	/** Handle of the device where the block resides. */
-	devmap_handle_t devmap_handle;
+	/** Service ID of service providing the block device. */
+	service_id_t service_id;
 	/** Logical block address */
 	aoff64_t lba;
@@ -97,24 +97,24 @@
 };
 
-extern int block_init(exch_mgmt_t, devmap_handle_t, size_t);
-extern void block_fini(devmap_handle_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(devmap_handle_t, aoff64_t);
-extern void *block_bb_get(devmap_handle_t);
+extern int block_bb_read(service_id_t, aoff64_t);
+extern void *block_bb_get(service_id_t);
 
-extern int block_cache_init(devmap_handle_t, size_t, unsigned, enum cache_mode);
-extern int block_cache_fini(devmap_handle_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 **, devmap_handle_t, aoff64_t, int);
+extern int block_get(block_t **, service_id_t, aoff64_t, int);
 extern int block_put(block_t *);
 
-extern int block_seqread(devmap_handle_t, size_t *, size_t *, aoff64_t *, void *,
+extern int block_seqread(service_id_t, size_t *, size_t *, aoff64_t *, void *,
     size_t);
 
-extern int block_get_bsize(devmap_handle_t, size_t *);
-extern int block_get_nblocks(devmap_handle_t, aoff64_t *);
-extern int block_read_direct(devmap_handle_t, aoff64_t, size_t, void *);
-extern int block_read_bytes_direct(devmap_handle_t, aoff64_t, size_t, void *);
-extern int block_write_direct(devmap_handle_t, aoff64_t, size_t, const void *);
+extern int block_get_bsize(service_id_t, size_t *);
+extern int block_get_nblocks(service_id_t, aoff64_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 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -31,6 +31,5 @@
 ROOT_PATH = $(USPACE_PREFIX)/..
 
-INCLUDE_KERNEL = include/kernel
-INCLUDE_ARCH = include/arch
+INCLUDE_ABI = include/abi
 INCLUDE_LIBARCH = include/libarch
 
@@ -47,7 +46,7 @@
 	$(LIBC_PREFIX)/arch/$(UARCH)/_link-dlexe.ld
 
-PRE_DEPEND = $(INCLUDE_KERNEL) $(INCLUDE_ARCH) $(INCLUDE_LIBARCH) $(COMMON_HEADER_ARCH)
+PRE_DEPEND = $(INCLUDE_ABI) $(INCLUDE_LIBARCH) $(COMMON_HEADER_ARCH)
 EXTRA_OUTPUT = $(LINKER_SCRIPTS)
-EXTRA_CLEAN = $(INCLUDE_KERNEL) $(INCLUDE_ARCH) $(INCLUDE_LIBARCH) $(COMMON_HEADER_ARCH) $(LINKER_SCRIPTS)
+EXTRA_CLEAN = $(INCLUDE_ABI) $(INCLUDE_LIBARCH) $(COMMON_HEADER_ARCH) $(LINKER_SCRIPTS)
 LIBRARY = libc
 SLIBRARY = libc.so.0.0
@@ -59,6 +58,4 @@
 -include arch/$(UARCH)/Makefile.inc
 
-EXTRA_CFLAGS += -I../../srv/loader/include
-
 GENERIC_SOURCES = \
 	generic/libc.c \
@@ -67,10 +64,11 @@
 	generic/cap.c \
 	generic/clipboard.c \
-	generic/devmap.c \
 	generic/devman.c \
 	generic/device/hw_res.c \
 	generic/device/char_dev.c \
+	generic/elf/elf_load.c \
 	generic/event.c \
 	generic/errno.c \
+	generic/loc.c \
 	generic/mem.c \
 	generic/str.c \
@@ -134,5 +132,4 @@
 		generic/dlfcn.c \
 		generic/rtld/rtld.c \
-		generic/rtld/elf_load.c \
 		generic/rtld/dynamic.c \
 		generic/rtld/module.c \
@@ -146,13 +143,8 @@
 include $(USPACE_PREFIX)/Makefile.common
 
-$(INCLUDE_ARCH): $(INCLUDE_KERNEL) $(INCLUDE_KERNEL)/arch
-	ln -sfn kernel/arch $@
-
 $(INCLUDE_LIBARCH): arch/$(UARCH)/include
 	ln -sfn ../$< $@
 
-$(INCLUDE_KERNEL)/arch: ../../../kernel/generic/include/arch $(INCLUDE_KERNEL)
-
-$(INCLUDE_KERNEL): ../../../kernel/generic/include/
+$(INCLUDE_ABI): ../../../abi/include/
 	ln -sfn ../$< $@
 
Index: uspace/lib/c/arch/abs32le/include/barrier.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/abs32le/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/abs32le/include/barrier.h
Index: uspace/lib/c/arch/abs32le/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/abs32le/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/abs32le/include/context_offset.h
Index: uspace/lib/c/arch/abs32le/include/elf.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/abs32le/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/abs32le/include/elf.h
Index: uspace/lib/c/arch/abs32le/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/abs32le/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,52 @@
+/*
+ * 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 libcabs32le
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_abs32le_ELF_LINUX_H_
+#define LBIC_abs32le_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+typedef struct {
+} elf_regs_t;
+
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	(void) istate; (void) elf_regs;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/abs32le/include/istate.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/abs32le/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 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 debug
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_abs32le__ISTATE_H_
-#define LIBC_abs32le__ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/abs32le/include/istate.h
Index: uspace/lib/c/arch/abs32le/include/syscall.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/syscall.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/abs32le/include/syscall.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,5 @@
 
 #include <sys/types.h>
-#include <kernel/syscall/syscall.h>
+#include <abi/syscall.h>
 
 #define __syscall0  __syscall
Index: uspace/lib/c/arch/amd64/include/barrier.h
===================================================================
--- uspace/lib/c/arch/amd64/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/amd64/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/amd64/include/barrier.h
Index: uspace/lib/c/arch/amd64/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/amd64/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/amd64/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/amd64/include/context_offset.h
Index: uspace/lib/c/arch/amd64/include/elf.h
===================================================================
--- uspace/lib/c/arch/amd64/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/amd64/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/amd64/include/elf.h
Index: uspace/lib/c/arch/amd64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/amd64/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/amd64/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,98 @@
+/*
+ * 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 libcamd64
+ * @{
+ */
+/** @file Definitions needed to write core files in Linux-ELF format.
+ */
+
+#ifndef LIBC_amd64_ELF_LINUX_H_
+#define LBIC_amd64_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+/** Linux kernel struct pt_regs structure.
+ *
+ * We need this to save register state to a core file in Linux format
+ * (readable by GDB configured for Linux target).
+ */
+typedef struct {
+	uint64_t r15;
+	uint64_t r14;
+	uint64_t r13;
+	uint64_t r12;
+	uint64_t rbp;
+	uint64_t rbx;
+	uint64_t r11;
+	uint64_t r10;
+	uint64_t r9;
+	uint64_t r8;
+	uint64_t rax;
+	uint64_t rcx;
+	uint64_t rdx;
+	uint64_t rsi;
+	uint64_t rdi;
+	uint64_t old_rax;
+	uint64_t rip;
+	uint64_t cs;
+	uint64_t rflags;
+	uint64_t rsp;
+	uint64_t ss;
+} elf_regs_t;
+
+/** Convert istate_t to elf_regs_t. */
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	elf_regs->r15 = istate->r15;
+	elf_regs->r14 = istate->r14;
+	elf_regs->r13 = istate->r13;
+	elf_regs->r12 = istate->r12;
+	elf_regs->rbp = istate->rbp;
+	elf_regs->rbx = istate->rbx;
+	elf_regs->r11 = istate->r11;
+	elf_regs->r10 = istate->r10;
+	elf_regs->r9 = istate->r9;
+	elf_regs->r8 = istate->r8;
+	elf_regs->rax = istate->rax;
+	elf_regs->rcx = istate->rcx;
+	elf_regs->rdx = istate->rdx;
+	elf_regs->rsi = istate->rsi;
+	elf_regs->rdi = istate->rdi;
+	elf_regs->rip = istate->rip;
+	elf_regs->cs = istate->cs;
+	elf_regs->rflags = istate->rflags;
+	elf_regs->rsp = istate->rsp;
+	elf_regs->ss = istate->ss;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/amd64/include/istate.h
===================================================================
--- uspace/lib/c/arch/amd64/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/amd64/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 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 libcamd64
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_amd64_ISTATE_H_
-#define LIBC_amd64_ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/amd64/include/istate.h
Index: uspace/lib/c/arch/amd64/src/fibril.S
===================================================================
--- uspace/lib/c/arch/amd64/src/fibril.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/amd64/src/fibril.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -32,5 +32,5 @@
 .global context_restore
 
-#include <kernel/arch/context_offset.h>
+#include <libarch/context_offset.h>
 
 ## Save current CPU context
Index: uspace/lib/c/arch/arm32/include/barrier.h
===================================================================
--- uspace/lib/c/arch/arm32/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/arm32/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/arm32/include/barrier.h
Index: uspace/lib/c/arch/arm32/include/elf.h
===================================================================
--- uspace/lib/c/arch/arm32/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/arm32/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/arm32/include/elf.h
Index: uspace/lib/c/arch/arm32/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/arm32/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/arm32/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,94 @@
+/*
+ * 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 libcarm32
+ * @{
+ */
+/** @file Definitions needed to write core files in Linux-ELF format.
+ */
+
+#ifndef LIBC_arm32_ELF_LINUX_H_
+#define LBIC_arm32_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+/** Linux kernel struct pt_regs structure.
+ *
+ * We need this to save register state to a core file in Linux format
+ * (readable by GDB configured for Linux target).
+ */
+typedef struct {
+	uint32_t r0;
+	uint32_t r1;
+	uint32_t r2;
+	uint32_t r3;
+	uint32_t r4;
+	uint32_t r5;
+	uint32_t r6;
+	uint32_t r7;
+	uint32_t r8;
+	uint32_t r9;
+	uint32_t r10;
+	uint32_t fp;
+	uint32_t r12;
+	uint32_t sp;
+	uint32_t lr;
+	uint32_t pc;
+	uint32_t cpsr;
+	uint32_t old_r0;
+} elf_regs_t;
+
+/** Convert istate_t to elf_regs_t. */
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	elf_regs->r0 = istate->r0;
+	elf_regs->r1 = istate->r1;
+	elf_regs->r2 = istate->r2;
+	elf_regs->r3 = istate->r3;
+	elf_regs->r4 = istate->r4;
+	elf_regs->r5 = istate->r5;
+	elf_regs->r6 = istate->r6;
+	elf_regs->r7 = istate->r7;
+	elf_regs->r8 = istate->r8;
+	elf_regs->r9 = istate->r9;
+	elf_regs->r10 = istate->r10;
+
+	elf_regs->fp = istate->fp;
+	elf_regs->r12 = istate->r12;
+	elf_regs->sp = istate->sp;
+	elf_regs->lr = istate->lr;
+	elf_regs->pc = istate->pc;
+	elf_regs->cpsr = istate->spsr;
+	elf_regs->old_r0 = 0;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/arm32/include/istate.h
===================================================================
--- uspace/lib/c/arch/arm32/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/arm32/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 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 libcarm32
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_arm32__ISTATE_H_
-#define LIBC_arm32__ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/arm32/include/istate.h
Index: uspace/lib/c/arch/arm32/include/regutils.h
===================================================================
--- uspace/lib/c/arch/arm32/include/regutils.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/arm32/include/regutils.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/arm32/include/regutils.h
Index: uspace/lib/c/arch/ia32/Makefile.common
===================================================================
--- uspace/lib/c/arch/ia32/Makefile.common	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/ia32/Makefile.common	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -28,5 +28,10 @@
 
 CLANG_ARCH = i386
-GCC_CFLAGS += -march=pentium -fno-omit-frame-pointer
+
+ifeq ($(PROCESSOR),i486)
+	GCC_CFLAGS += -march=i486 -fno-omit-frame-pointer
+else
+	GCC_CFLAGS += -march=pentium -fno-omit-frame-pointer
+endif
 
 ENDIANESS = LE
Index: uspace/lib/c/arch/ia32/Makefile.inc
===================================================================
--- uspace/lib/c/arch/ia32/Makefile.inc	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/ia32/Makefile.inc	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -28,5 +28,5 @@
 
 ARCH_SOURCES = \
-	arch/$(UARCH)/src/entry.s \
+	arch/$(UARCH)/src/entry.S \
 	arch/$(UARCH)/src/entryjmp.s \
 	arch/$(UARCH)/src/thread_entry.s \
Index: uspace/lib/c/arch/ia32/include/barrier.h
===================================================================
--- uspace/lib/c/arch/ia32/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ia32/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ia32/include/barrier.h
Index: uspace/lib/c/arch/ia32/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/ia32/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ia32/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ia32/include/context_offset.h
Index: uspace/lib/c/arch/ia32/include/ddi.h
===================================================================
--- uspace/lib/c/arch/ia32/include/ddi.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/ia32/include/ddi.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,63 +41,81 @@
 static inline uint8_t pio_read_8(ioport8_t *port)
 {
-	uint8_t val;
-	
-	asm volatile (
-		"inb %w[port], %b[val]\n"
-		: [val] "=a" (val)
-		: [port] "d" (port)
-	);
-	
-	return val;
+	if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
+		uint8_t val;
+		
+		asm volatile (
+			"inb %w[port], %b[val]\n"
+			: [val] "=a" (val)
+			: [port] "d" (port)
+		);
+		
+		return val;
+	} else
+		return (uint8_t) *port;
 }
 
 static inline uint16_t pio_read_16(ioport16_t *port)
 {
-	uint16_t val;
-	
-	asm volatile (
-		"inw %w[port], %w[val]\n"
-		: [val] "=a" (val)
-		: [port] "d" (port)
-	);
-	
-	return val;
+	if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
+		uint16_t val;
+		
+		asm volatile (
+			"inw %w[port], %w[val]\n"
+			: [val] "=a" (val)
+			: [port] "d" (port)
+		);
+		
+		return val;
+	} else
+		return (uint16_t) *port;
 }
 
 static inline uint32_t pio_read_32(ioport32_t *port)
 {
-	uint32_t val;
-	
-	asm volatile (
-		"inl %w[port], %[val]\n"
-		: [val] "=a" (val)
-		: [port] "d" (port)
-	);
-	
-	return val;
+	if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
+		uint32_t val;
+		
+		asm volatile (
+			"inl %w[port], %[val]\n"
+			: [val] "=a" (val)
+			: [port] "d" (port)
+		);
+		
+		return val;
+	} else
+		return (uint32_t) *port;
 }
 
 static inline void pio_write_8(ioport8_t *port, uint8_t val)
 {
-	asm volatile (
-		"outb %b[val], %w[port]\n"
-		:: [val] "a" (val), [port] "d" (port)
-	);
+	if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
+		asm volatile (
+			"outb %b[val], %w[port]\n"
+			:: [val] "a" (val), [port] "d" (port)
+		);	
+	} else
+		*port = val;
 }
 
 static inline void pio_write_16(ioport16_t *port, uint16_t val)
 {
-	asm volatile (
-		"outw %w[val], %w[port]\n"
-		:: [val] "a" (val), [port] "d" (port)
-	);
+	if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
+		asm volatile (
+			"outw %w[val], %w[port]\n"
+			:: [val] "a" (val), [port] "d" (port)
+		);
+	} else
+		*port = val;
 }
 
 static inline void pio_write_32(ioport32_t *port, uint32_t val)
 {
-	asm volatile (
-		"outl %[val], %w[port]\n"
-		:: [val] "a" (val), [port] "d" (port)
-	);
+	if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
+		asm volatile (
+			"outl %[val], %w[port]\n"
+			:: [val] "a" (val), [port] "d" (port)
+		);
+	} else
+		*port = val;
 }
 
Index: uspace/lib/c/arch/ia32/include/elf.h
===================================================================
--- uspace/lib/c/arch/ia32/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ia32/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ia32/include/elf.h
Index: uspace/lib/c/arch/ia32/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/ia32/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ia32/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,93 @@
+/*
+ * 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 libcia32
+ * @{
+ */
+/** @file Definitions needed to write core files in Linux-ELF format.
+ */
+
+#ifndef LIBC_ia32_ELF_LINUX_H_
+#define LBIC_ia32_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+/** Linux kernel struct pt_regs structure.
+ *
+ * We need this to save register state to a core file in Linux format
+ * (readable by GDB configured for Linux target).
+ */
+typedef struct {
+	uint32_t ebx;
+	uint32_t ecx;
+	uint32_t edx;
+	uint32_t esi;
+	uint32_t edi;
+	uint32_t ebp;
+	uint32_t eax;
+	uint32_t ds;
+	uint32_t es;
+	uint32_t fs;
+	uint32_t gs;
+	uint32_t old_eax;
+	uint32_t eip;
+	uint32_t cs;
+	uint32_t eflags;
+	uint32_t esp;
+	uint32_t ss;
+} elf_regs_t;
+
+/** Convert istate_t to elf_regs_t. */
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	elf_regs->ebx = istate->ebx;
+	elf_regs->ecx = istate->ecx;
+	elf_regs->edx = istate->edx;
+	elf_regs->esi = istate->esi;
+	elf_regs->edi = istate->edi;
+	elf_regs->ebp = istate->ebp;
+	elf_regs->eax = istate->eax;
+
+	elf_regs->ds = istate->ds;
+	elf_regs->es = istate->es;
+	elf_regs->fs = istate->fs;
+	elf_regs->gs = istate->gs;
+
+	elf_regs->old_eax = 0;
+	elf_regs->eip = istate->eip;
+	elf_regs->cs = istate->cs;
+	elf_regs->eflags = istate->eflags;
+	elf_regs->esp = istate->esp;
+	elf_regs->ss = istate->ss;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/ia32/include/istate.h
===================================================================
--- uspace/lib/c/arch/ia32/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/ia32/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 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 debug
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ia32__ISTATE_H_
-#define LIBC_ia32__ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/ia32/include/istate.h
Index: uspace/lib/c/arch/ia32/include/syscall.h
===================================================================
--- uspace/lib/c/arch/ia32/include/syscall.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/ia32/include/syscall.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,5 @@
 
 #include <sys/types.h>
-#include <kernel/syscall/syscall.h>
+#include <abi/syscall.h>
 
 #define __syscall0  __syscall_fast_func
Index: uspace/lib/c/arch/ia32/src/entry.S
===================================================================
--- uspace/lib/c/arch/ia32/src/entry.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ia32/src/entry.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,68 @@
+#
+# 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.
+#
+
+INTEL_CPUID_STANDARD = 1
+INTEL_SEP = 11
+
+.section .init, "ax"
+
+.org 0
+
+.globl __entry
+
+## User-space task entry point
+#
+# %edi contains the PCB pointer
+#
+__entry:
+	mov %ss, %ax
+	mov %ax, %ds
+	mov %ax, %es
+	mov %ax, %fs
+	# Do not set %gs, it contains descriptor that can see TLS
+	
+#ifndef PROCESSOR_i486	
+	# Detect the mechanism used for making syscalls
+	movl $(INTEL_CPUID_STANDARD), %eax
+	cpuid
+	bt $(INTEL_SEP), %edx
+	jnc 0f
+		leal __syscall_fast_func, %eax
+		movl $__syscall_fast, (%eax)
+	0:
+#endif
+	
+	#
+	# Create the first stack frame.
+	#
+	pushl $0
+	movl %esp, %ebp
+	
+	# Pass the PCB pointer to __main as the first argument
+	pushl %edi
+	call __main
Index: pace/lib/c/arch/ia32/src/entry.s
===================================================================
--- uspace/lib/c/arch/ia32/src/entry.s	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,65 +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.
-#
-
-INTEL_CPUID_STANDARD = 1
-INTEL_SEP = 11
-
-.section .init, "ax"
-
-.org 0
-
-.globl __entry
-
-## User-space task entry point
-#
-# %edi contains the PCB pointer
-#
-__entry:
-	mov %ss, %ax
-	mov %ax, %ds
-	mov %ax, %es
-	mov %ax, %fs
-	# Do not set %gs, it contains descriptor that can see TLS
-	
-	# Detect the mechanism used for making syscalls
-	movl $(INTEL_CPUID_STANDARD), %eax
-	cpuid
-	bt $(INTEL_SEP), %edx
-	jnc 0f
-	leal __syscall_fast_func, %eax
-	movl $__syscall_fast, (%eax)
-0:
-	#
-	# Create the first stack frame.
-	#
-	pushl $0
-	movl %esp, %ebp
-	
-	# Pass the PCB pointer to __main as the first argument
-	pushl %edi
-	call __main
Index: uspace/lib/c/arch/ia32/src/fibril.S
===================================================================
--- uspace/lib/c/arch/ia32/src/fibril.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/ia32/src/fibril.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -27,5 +27,5 @@
 #
 
-#include <kernel/arch/context_offset.h>
+#include <libarch/context_offset.h>
 
 .text
Index: uspace/lib/c/arch/ia32/src/setjmp.S
===================================================================
--- uspace/lib/c/arch/ia32/src/setjmp.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/ia32/src/setjmp.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -27,5 +27,5 @@
 #
 
-#include <kernel/arch/context_offset.h>
+#include <libarch/context_offset.h>
 
 .text
Index: uspace/lib/c/arch/ia64/include/barrier.h
===================================================================
--- uspace/lib/c/arch/ia64/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ia64/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ia64/include/barrier.h
Index: uspace/lib/c/arch/ia64/include/elf.h
===================================================================
--- uspace/lib/c/arch/ia64/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ia64/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ia64/include/elf.h
Index: uspace/lib/c/arch/ia64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/ia64/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ia64/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,55 @@
+/*
+ * 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 libcia64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_ia64_ELF_LINUX_H_
+#define LBIC_ia64_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+typedef struct {
+	/* TODO */
+	uint64_t pad[16];
+} elf_regs_t;
+
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	/* TODO */
+	(void) istate; (void) elf_regs;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/ia64/include/istate.h
===================================================================
--- uspace/lib/c/arch/ia64/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/ia64/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 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 libcsparc64
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ia64_ISTATE_H_
-#define LIBC_ia64_ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/ia64/include/istate.h
Index: uspace/lib/c/arch/ia64/include/register.h
===================================================================
--- uspace/lib/c/arch/ia64/include/register.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ia64/include/register.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ia64/include/register.h
Index: uspace/lib/c/arch/mips32/include/barrier.h
===================================================================
--- uspace/lib/c/arch/mips32/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips32/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips32/include/barrier.h
Index: uspace/lib/c/arch/mips32/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/mips32/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips32/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips32/include/context_offset.h
Index: uspace/lib/c/arch/mips32/include/cp0.h
===================================================================
--- uspace/lib/c/arch/mips32/include/cp0.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips32/include/cp0.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips32/include/cp0.h
Index: uspace/lib/c/arch/mips32/include/elf.h
===================================================================
--- uspace/lib/c/arch/mips32/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips32/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips32/include/elf.h
Index: uspace/lib/c/arch/mips32/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/mips32/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips32/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,134 @@
+/*
+ * 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 libcmips32
+ * @{
+ */
+/** @file Definitions needed to write core files in Linux-ELF format.
+ */
+
+#ifndef LIBC_mips32_ELF_LINUX_H_
+#define LBIC_mips32_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+/** Linux kernel struct pt_regs structure.
+ *
+ * We need this to save register state to a core file in Linux format
+ * (readable by GDB configured for Linux target).
+ */
+typedef struct {
+	uint32_t pad0[6];
+
+	uint32_t r0;
+	uint32_t r1;
+	uint32_t r2;
+	uint32_t r3;
+	uint32_t r4;
+	uint32_t r5;
+	uint32_t r6;
+	uint32_t r7;
+	uint32_t r8;
+	uint32_t r9;
+	uint32_t r10;
+	uint32_t r11;
+	uint32_t r12;
+	uint32_t r13;
+	uint32_t r14;
+	uint32_t r15;
+	uint32_t r16;
+	uint32_t r17;
+	uint32_t r18;
+	uint32_t r19;
+	uint32_t r20;
+	uint32_t r21;
+	uint32_t r22;
+	uint32_t r23;
+	uint32_t r24;
+	uint32_t r25;
+	uint32_t r26;
+	uint32_t r27;
+	uint32_t r28;
+	uint32_t r29;
+	uint32_t r30;
+	uint32_t r31;
+
+	uint32_t cp0_status;
+	uint32_t hi;
+	uint32_t lo;
+	uint32_t cp0_badvaddr;
+	uint32_t cp0_cause;
+	uint32_t cp0_epc;
+} elf_regs_t;
+
+/** Convert istate_t to elf_regs_t. */
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	elf_regs->r1 = istate->at;
+	elf_regs->r2 = istate->v0;
+	elf_regs->r3 = istate->v1;
+	elf_regs->r4 = istate->a0;
+	elf_regs->r5 = istate->a1;
+	elf_regs->r6 = istate->a2;
+	elf_regs->r7 = istate->a3;
+	elf_regs->r8 = istate->t0;
+	elf_regs->r9 = istate->t1;
+	elf_regs->r10 = istate->t2;
+	elf_regs->r11 = istate->t3;
+	elf_regs->r12 = istate->t4;
+	elf_regs->r13 = istate->t5;
+	elf_regs->r14 = istate->t6;
+	elf_regs->r15 = istate->t7;
+	elf_regs->r16 = istate->s0;
+	elf_regs->r17 = istate->s1;
+	elf_regs->r18 = istate->s2;
+	elf_regs->r19 = istate->s3;
+	elf_regs->r20 = istate->s4;
+	elf_regs->r21 = istate->s5;
+	elf_regs->r22 = istate->s6;
+	elf_regs->r23 = istate->s7;
+	elf_regs->r24 = istate->t8;
+	elf_regs->r25 = istate->t9;
+	elf_regs->r26 = istate->kt0;
+	elf_regs->r27 = istate->kt1;
+	elf_regs->r28 = istate->gp;
+	elf_regs->r29 = istate->sp;
+	elf_regs->r30 = istate->s8;
+	elf_regs->r31 = istate->ra;
+
+	elf_regs->cp0_status = istate->status;
+	elf_regs->hi = istate->hi;
+	elf_regs->lo = istate->lo;
+	elf_regs->cp0_epc = istate->epc;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips32/include/istate.h
===================================================================
--- uspace/lib/c/arch/mips32/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/mips32/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 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 libcmips32
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_mips32__ISTATE_H_
-#define LIBC_mips32__ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/mips32/include/istate.h
Index: uspace/lib/c/arch/mips32/include/regname.h
===================================================================
--- uspace/lib/c/arch/mips32/include/regname.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips32/include/regname.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips32/include/asm/regname.h
Index: uspace/lib/c/arch/mips32/src/fibril.S
===================================================================
--- uspace/lib/c/arch/mips32/src/fibril.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/mips32/src/fibril.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -32,5 +32,5 @@
 .set noreorder
 
-#include <arch/context_offset.h>
+#include <libarch/context_offset.h>
 	
 .global context_save
Index: uspace/lib/c/arch/mips32eb/include/barrier.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips32eb/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../mips32/include/barrier.h
Index: uspace/lib/c/arch/mips32eb/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips32eb/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../mips32/include/context_offset.h
Index: uspace/lib/c/arch/mips32eb/include/cp0.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/cp0.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips32eb/include/cp0.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../mips32/include/cp0.h
Index: uspace/lib/c/arch/mips32eb/include/elf.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips32eb/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../mips32/include/elf.h
Index: uspace/lib/c/arch/mips32eb/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips32eb/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../mips32/include/elf_linux.h
Index: uspace/lib/c/arch/mips32eb/include/regname.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/regname.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips32eb/include/regname.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../mips32/include/regname.h
Index: uspace/lib/c/arch/mips64/include/barrier.h
===================================================================
--- uspace/lib/c/arch/mips64/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips64/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips64/include/barrier.h
Index: uspace/lib/c/arch/mips64/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/mips64/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips64/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips64/include/context_offset.h
Index: uspace/lib/c/arch/mips64/include/cp0.h
===================================================================
--- uspace/lib/c/arch/mips64/include/cp0.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips64/include/cp0.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips64/include/cp0.h
Index: uspace/lib/c/arch/mips64/include/elf.h
===================================================================
--- uspace/lib/c/arch/mips64/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips64/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips64/include/elf.h
Index: uspace/lib/c/arch/mips64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/mips64/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips64/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,55 @@
+/*
+ * 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 libcmips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_mips64_ELF_LINUX_H_
+#define LBIC_mips64_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+typedef struct {
+	/* TODO */
+	uint64_t pad[16];
+} elf_regs_t;
+
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	/* TODO */
+	(void) istate; (void) elf_regs;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/include/istate.h
===================================================================
--- uspace/lib/c/arch/mips64/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/mips64/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 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 libcmips64
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_mips64__ISTATE_H_
-#define LIBC_mips64__ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/mips64/include/istate.h
Index: uspace/lib/c/arch/mips64/include/regname.h
===================================================================
--- uspace/lib/c/arch/mips64/include/regname.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/mips64/include/regname.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips64/include/asm/regname.h
Index: uspace/lib/c/arch/mips64/src/fibril.S
===================================================================
--- uspace/lib/c/arch/mips64/src/fibril.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/mips64/src/fibril.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -32,5 +32,5 @@
 .set noreorder
 
-#include <arch/context_offset.h>
+#include <libarch/context_offset.h>
 
 .global context_save
Index: uspace/lib/c/arch/ppc32/include/barrier.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ppc32/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ppc32/include/barrier.h
Index: uspace/lib/c/arch/ppc32/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ppc32/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ppc32/include/context_offset.h
Index: uspace/lib/c/arch/ppc32/include/elf.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ppc32/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ppc32/include/elf.h
Index: uspace/lib/c/arch/ppc32/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ppc32/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,140 @@
+/*
+ * 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 libcppc32
+ * @{
+ */
+/** @file Definitions needed to write core files in Linux-ELF format.
+ */
+
+#ifndef LIBC_ppc32_ELF_LINUX_H_
+#define LBIC_ppc32_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+/** Linux kernel struct pt_regs structure.
+ *
+ * We need this to save register state to a core file in Linux format
+ * (readable by GDB configured for Linux target).
+ */
+typedef struct {
+	uint32_t r0;
+	uint32_t r1;
+	uint32_t r2;
+	uint32_t r3;
+	uint32_t r4;
+	uint32_t r5;
+	uint32_t r6;
+	uint32_t r7;
+	uint32_t r8;
+	uint32_t r9;
+	uint32_t r10;
+	uint32_t r11;
+	uint32_t r12;
+	uint32_t r13;
+	uint32_t r14;
+	uint32_t r15;
+	uint32_t r16;
+	uint32_t r17;
+	uint32_t r18;
+	uint32_t r19;
+	uint32_t r20;
+	uint32_t r21;
+	uint32_t r22;
+	uint32_t r23;
+	uint32_t r24;
+	uint32_t r25;
+	uint32_t r26;
+	uint32_t r27;
+	uint32_t r28;
+	uint32_t r29;
+	uint32_t r30;
+	uint32_t r31;
+
+	uint32_t nip;
+	uint32_t msr;
+	uint32_t old_r3;
+	uint32_t ctr;
+	uint32_t link;
+	uint32_t xer;
+	uint32_t ccr;
+	uint32_t mq;
+	uint32_t trap;
+	uint32_t dar;
+	uint32_t dsisr;
+	uint32_t result;
+} elf_regs_t;
+
+/** Convert istate_t to elf_regs_t. */
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	elf_regs->r0 = istate->r0;
+	elf_regs->r1 = istate->sp;
+	elf_regs->r2 = istate->r2;
+	elf_regs->r3 = istate->r3;
+	elf_regs->r4 = istate->r4;
+	elf_regs->r5 = istate->r5;
+	elf_regs->r6 = istate->r6;
+	elf_regs->r7 = istate->r7;
+	elf_regs->r8 = istate->r8;
+	elf_regs->r9 = istate->r9;
+	elf_regs->r10 = istate->r10;
+	elf_regs->r11 = istate->r11;
+	elf_regs->r12 = istate->r12;
+	elf_regs->r13 = istate->r13;
+	elf_regs->r14 = istate->r14;
+	elf_regs->r15 = istate->r15;
+	elf_regs->r16 = istate->r16;
+	elf_regs->r17 = istate->r17;
+	elf_regs->r18 = istate->r18;
+	elf_regs->r19 = istate->r19;
+	elf_regs->r20 = istate->r20;
+	elf_regs->r21 = istate->r21;
+	elf_regs->r22 = istate->r22;
+	elf_regs->r23 = istate->r23;
+	elf_regs->r24 = istate->r24;
+	elf_regs->r25 = istate->r25;
+	elf_regs->r26 = istate->r26;
+	elf_regs->r27 = istate->r27;
+	elf_regs->r28 = istate->r28;
+	elf_regs->r29 = istate->r29;
+	elf_regs->r30 = istate->r30;
+	elf_regs->r31 = istate->r31;
+
+	elf_regs->ctr = istate->ctr;
+	elf_regs->link = istate->lr;
+	elf_regs->xer = istate->xer;
+	elf_regs->ccr = istate->cr;
+	elf_regs->dar = istate->dar;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/ppc32/include/istate.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/ppc32/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,99 +1,1 @@
-/*
- * Copyright (c) 2010 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 libcppc32
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ppc32_ISTATE_H_
-#define LIBC_ppc32_ISTATE_H_
-
-#include <sys/types.h>
-
-/** Interrupt context.
- *
- * This is a copy of the kernel definition with which it must be kept in sync.
- */
-typedef struct istate {
-	uint32_t r0;
-	uint32_t r2;
-	uint32_t r3;
-	uint32_t r4;
-	uint32_t r5;
-	uint32_t r6;
-	uint32_t r7;
-	uint32_t r8;
-	uint32_t r9;
-	uint32_t r10;
-	uint32_t r11;
-	uint32_t r13;
-	uint32_t r14;
-	uint32_t r15;
-	uint32_t r16;
-	uint32_t r17;
-	uint32_t r18;
-	uint32_t r19;
-	uint32_t r20;
-	uint32_t r21;
-	uint32_t r22;
-	uint32_t r23;
-	uint32_t r24;
-	uint32_t r25;
-	uint32_t r26;
-	uint32_t r27;
-	uint32_t r28;
-	uint32_t r29;
-	uint32_t r30;
-	uint32_t r31;
-	uint32_t cr;
-	uint32_t pc;
-	uint32_t srr1;
-	uint32_t lr;
-	uint32_t ctr;
-	uint32_t xer;
-	uint32_t dar;
-	uint32_t r12;
-	uint32_t sp;
-} istate_t;
-
-static inline uintptr_t istate_get_pc(istate_t *istate)
-{
-	return istate->pc;
-}
-
-static inline uintptr_t istate_get_fp(istate_t *istate)
-{
-	return istate->sp;
-}
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/ppc32/include/istate.h
Index: uspace/lib/c/arch/ppc32/include/msr.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/msr.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/ppc32/include/msr.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ppc32/include/msr.h
Index: uspace/lib/c/arch/ppc32/src/fibril.S
===================================================================
--- uspace/lib/c/arch/ppc32/src/fibril.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/ppc32/src/fibril.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -33,5 +33,5 @@
 
 #include <libarch/regname.h>
-#include <arch/context_offset.h>
+#include <libarch/context_offset.h>
 
 context_save:
Index: uspace/lib/c/arch/sparc64/include/barrier.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/sparc64/include/barrier.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/sparc64/include/barrier.h
Index: uspace/lib/c/arch/sparc64/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/sparc64/include/context_offset.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/sparc64/include/context_offset.h
Index: uspace/lib/c/arch/sparc64/include/elf.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/sparc64/include/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/sparc64/include/elf.h
Index: uspace/lib/c/arch/sparc64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/sparc64/include/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,55 @@
+/*
+ * 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 libcsparc64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_sparc64_ELF_LINUX_H_
+#define LBIC_sparc64_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+typedef struct {
+	/* TODO */
+	uint64_t pad[16];
+} elf_regs_t;
+
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	/* TODO */
+	(void) istate; (void) elf_regs;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/sparc64/include/istate.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/istate.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/sparc64/include/istate.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 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 libcsparc64
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_sparc64_ISTATE_H_
-#define LIBC_sparc64_ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/sparc64/include/istate.h
Index: uspace/lib/c/arch/sparc64/include/regdef.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/regdef.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/arch/sparc64/include/regdef.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/sparc64/include/regdef.h
Index: uspace/lib/c/arch/sparc64/include/syscall.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/syscall.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/sparc64/include/syscall.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,5 +37,5 @@
 
 #include <sys/types.h>
-#include <kernel/syscall/syscall.h>
+#include <abi/syscall.h>
 
 #define __syscall0	__syscall
Index: uspace/lib/c/arch/sparc64/src/fibril.S
===================================================================
--- uspace/lib/c/arch/sparc64/src/fibril.S	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/arch/sparc64/src/fibril.S	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -27,7 +27,7 @@
 #
 
-#include <kernel/arch/context_offset.h>
+#include <libarch/context_offset.h>
 
-.text   
+.text
 
 .global context_save
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/async.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -98,4 +98,5 @@
 #include <ipc/ipc.h>
 #include <async.h>
+#include "private/async.h"
 #undef LIBC_ASYNC_C_
 
@@ -107,10 +108,10 @@
 #include <errno.h>
 #include <sys/time.h>
-#include <arch/barrier.h>
+#include <libarch/barrier.h>
 #include <bool.h>
 #include <malloc.h>
 #include <mem.h>
 #include <stdlib.h>
-#include "private/async.h"
+#include <macros.h>
 
 #define CLIENT_HASH_TABLE_BUCKETS  32
@@ -138,5 +139,5 @@
 	link_t link;
 	
-	sysarg_t in_task_hash;
+	task_id_t in_task_id;
 	atomic_t refcnt;
 	void *data;
@@ -150,6 +151,6 @@
 	link_t link;
 	
-	/** Incoming client task hash. */
-	sysarg_t in_task_hash;
+	/** Incoming client task ID. */
+	task_id_t in_task_id;
 	
 	/** Incoming phone hash. */
@@ -203,10 +204,4 @@
 }
 
-void *async_get_client_data(void)
-{
-	assert(fibril_connection);
-	return fibril_connection->client->data;
-}
-
 /** Default fibril function that gets called to handle new connection.
  *
@@ -289,8 +284,10 @@
 {
 	assert(key);
+	assert(keys == 2);
 	assert(item);
 	
 	client_t *client = hash_table_get_instance(item, client_t, link);
-	return (key[0] == client->in_task_hash);
+	return (key[0] == LOWER32(client->in_task_id) &&
+	    (key[1] == UPPER32(client->in_task_id)));
 }
 
@@ -580,4 +577,91 @@
 }
 
+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);
+	if (lnk) {
+		client = hash_table_get_instance(lnk, client_t, link);
+		atomic_inc(&client->refcnt);
+	} else if (create) {
+		client = malloc(sizeof(client_t));
+		if (client) {
+			client->in_task_id = client_id;
+			client->data = async_client_data_create();
+		
+			atomic_set(&client->refcnt, 1);
+			hash_table_insert(&client_hash_table, key, &client->link);
+		}
+	}
+
+	futex_up(&async_futex);
+	return client;
+}
+
+static void async_client_put(client_t *client)
+{
+	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);
+		destroy = true;
+	} else
+		destroy = false;
+	
+	futex_up(&async_futex);
+	
+	if (destroy) {
+		if (client->data)
+			async_client_data_destroy(client->data);
+		
+		free(client);
+	}
+}
+
+void *async_get_client_data(void)
+{
+	assert(fibril_connection);
+	return fibril_connection->client->data;
+}
+
+void *async_get_client_data_by_id(task_id_t client_id)
+{
+	client_t *client = async_client_get(client_id, false);
+	if (!client)
+		return NULL;
+	if (!client->data) {
+		async_client_put(client);
+		return NULL;
+	}
+
+	return client->data;
+}
+
+void async_put_client_data_by_id(task_id_t client_id)
+{
+	client_t *client = async_client_get(client_id, false);
+
+	assert(client);
+	assert(client->data);
+
+	/* Drop the reference we got in async_get_client_data_by_hash(). */
+	async_client_put(client);
+
+	/* Drop our own reference we got at the beginning of this function. */
+	async_client_put(client);
+}
+
 /** Wrapper for client connection fibril.
  *
@@ -598,6 +682,4 @@
 	 */
 	fibril_connection = (connection_t *) arg;
-	
-	futex_down(&async_futex);
 	
 	/*
@@ -606,30 +688,11 @@
 	 * hash in a new tracking structure.
 	 */
-	
-	unsigned long key = fibril_connection->in_task_hash;
-	link_t *lnk = hash_table_find(&client_hash_table, &key);
-	
-	client_t *client;
-	
-	if (lnk) {
-		client = hash_table_get_instance(lnk, client_t, link);
-		atomic_inc(&client->refcnt);
-	} else {
-		client = malloc(sizeof(client_t));
-		if (!client) {
-			ipc_answer_0(fibril_connection->callid, ENOMEM);
-			futex_up(&async_futex);
-			return 0;
-		}
-		
-		client->in_task_hash = fibril_connection->in_task_hash;
-		client->data = async_client_data_create();
-		
-		atomic_set(&client->refcnt, 1);
-		hash_table_insert(&client_hash_table, &key, &client->link);
-	}
-	
-	futex_up(&async_futex);
-	
+
+	client_t *client = async_client_get(fibril_connection->in_task_id, true);
+	if (!client) {
+		ipc_answer_0(fibril_connection->callid, ENOMEM);
+		return 0;
+	}
+
 	fibril_connection->client = client;
 	
@@ -643,22 +706,5 @@
 	 * Remove the reference for this client task connection.
 	 */
-	bool destroy;
-	
-	futex_down(&async_futex);
-	
-	if (atomic_predec(&client->refcnt) == 0) {
-		hash_table_remove(&client_hash_table, &key, 1);
-		destroy = true;
-	} else
-		destroy = false;
-	
-	futex_up(&async_futex);
-	
-	if (destroy) {
-		if (client->data)
-			async_client_data_destroy(client->data);
-		
-		free(client);
-	}
+	async_client_put(client);
 	
 	/*
@@ -666,5 +712,5 @@
 	 */
 	futex_down(&async_futex);
-	key = fibril_connection->in_phone_hash;
+	unsigned long key = fibril_connection->in_phone_hash;
 	hash_table_remove(&conn_hash_table, &key, 1);
 	futex_up(&async_futex);
@@ -700,5 +746,5 @@
  * particular fibrils.
  *
- * @param in_task_hash  Identification of the incoming connection.
+ * @param in_task_id    Identification of the incoming connection.
  * @param in_phone_hash Identification of the incoming connection.
  * @param callid        Hash of the opening IPC_M_CONNECT_ME_TO call.
@@ -714,5 +760,5 @@
  *
  */
-fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash,
+fid_t async_new_connection(task_id_t in_task_id, sysarg_t in_phone_hash,
     ipc_callid_t callid, ipc_call_t *call,
     async_client_conn_t cfibril, void *carg)
@@ -726,5 +772,5 @@
 	}
 	
-	conn->in_task_hash = in_task_hash;
+	conn->in_task_id = in_task_id;
 	conn->in_phone_hash = in_phone_hash;
 	list_initialize(&conn->msg_queue);
@@ -785,5 +831,5 @@
 	case IPC_M_CONNECT_ME_TO:
 		/* Open new connection with fibril, etc. */
-		async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call),
+		async_new_connection(call->in_task_id, IPC_GET_ARG5(*call),
 		    callid, call, client_connection, NULL);
 		return;
@@ -933,5 +979,5 @@
 {
 	if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS,
-	    1, &client_hash_table_ops))
+	    2, &client_hash_table_ops))
 		abort();
 	
@@ -949,4 +995,7 @@
 	session_ns->arg2 = 0;
 	session_ns->arg3 = 0;
+	
+	fibril_mutex_initialize(&session_ns->remote_state_mtx);
+	session_ns->remote_state_data = NULL;
 	
 	list_initialize(&session_ns->exch_list);
@@ -1426,13 +1475,19 @@
 		return ENOENT;
 	
-	sysarg_t task_hash;
 	sysarg_t phone_hash;
-	int rc = async_req_3_5(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
-	    NULL, NULL, NULL, &task_hash, &phone_hash);
+	sysarg_t rc;
+
+	aid_t req;
+	ipc_call_t answer;
+	req = async_send_3(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
+	    &answer);
+	async_wait_for(req, &rc);
 	if (rc != EOK)
-		return rc;
-	
+		return (int) rc;
+
+	phone_hash = IPC_GET_ARG5(answer);
+
 	if (client_receiver != NULL)
-		async_new_connection(task_hash, phone_hash, 0, NULL,
+		async_new_connection(answer.in_task_id, phone_hash, 0, NULL,
 		    client_receiver, carg);
 	
@@ -1509,4 +1564,7 @@
 	sess->arg3 = 0;
 	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
 	list_initialize(&sess->exch_list);
 	fibril_mutex_initialize(&sess->mutex);
@@ -1590,4 +1648,7 @@
 	sess->arg3 = arg3;
 	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
 	list_initialize(&sess->exch_list);
 	fibril_mutex_initialize(&sess->mutex);
@@ -1595,4 +1656,22 @@
 	
 	return sess;
+}
+
+/** Set arguments for new connections.
+ *
+ * FIXME This is an ugly hack to work around the problem that parallel
+ * exchanges are implemented using parallel connections. When we create
+ * a callback session, the framework does not know arguments for the new
+ * connections.
+ *
+ * The proper solution seems to be to implement parallel exchanges using
+ * tagging.
+ */
+void async_sess_args_set(async_sess_t *sess, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3)
+{
+	sess->arg1 = arg1;
+	sess->arg2 = arg2;
+	sess->arg3 = arg3;
 }
 
@@ -1640,4 +1719,7 @@
 	sess->arg3 = arg3;
 	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
 	list_initialize(&sess->exch_list);
 	fibril_mutex_initialize(&sess->mutex);
@@ -1670,4 +1752,7 @@
 	sess->arg2 = 0;
 	sess->arg3 = 0;
+	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
 	
 	list_initialize(&sess->exch_list);
@@ -2334,4 +2419,7 @@
 	sess->arg3 = 0;
 	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
 	list_initialize(&sess->exch_list);
 	fibril_mutex_initialize(&sess->mutex);
@@ -2380,4 +2468,7 @@
 	sess->arg3 = 0;
 	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
 	list_initialize(&sess->exch_list);
 	fibril_mutex_initialize(&sess->mutex);
@@ -2422,4 +2513,7 @@
 	sess->arg3 = 0;
 	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
 	list_initialize(&sess->exch_list);
 	fibril_mutex_initialize(&sess->mutex);
@@ -2429,4 +2523,107 @@
 }
 
+int async_state_change_start(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, async_exch_t *other_exch)
+{
+	return async_req_5_0(exch, IPC_M_STATE_CHANGE_AUTHORIZE,
+	    arg1, arg2, arg3, 0, other_exch->phone);
+}
+
+bool async_state_change_receive(ipc_callid_t *callid, sysarg_t *arg1,
+    sysarg_t *arg2, sysarg_t *arg3)
+{
+	assert(callid);
+
+	ipc_call_t call;
+	*callid = async_get_call(&call);
+
+	if (IPC_GET_IMETHOD(call) != IPC_M_STATE_CHANGE_AUTHORIZE)
+		return false;
+	
+	if (arg1)
+		*arg1 = IPC_GET_ARG1(call);
+	if (arg2)
+		*arg2 = IPC_GET_ARG2(call);
+	if (arg3)
+		*arg3 = IPC_GET_ARG3(call);
+
+	return true;
+}
+
+int async_state_change_finalize(ipc_callid_t callid, async_exch_t *other_exch)
+{
+	return ipc_answer_1(callid, EOK, other_exch->phone);
+}
+
+/** Lock and get session remote state
+ *
+ * Lock and get the local replica of the remote state
+ * in stateful sessions. The call should be paired
+ * with async_remote_state_release*().
+ *
+ * @param[in] sess Stateful session.
+ *
+ * @return Local replica of the remote state.
+ *
+ */
+void *async_remote_state_acquire(async_sess_t *sess)
+{
+	fibril_mutex_lock(&sess->remote_state_mtx);
+	return sess->remote_state_data;
+}
+
+/** Update the session remote state
+ *
+ * Update the local replica of the remote state
+ * in stateful sessions. The remote state must
+ * be already locked.
+ *
+ * @param[in] sess  Stateful session.
+ * @param[in] state New local replica of the remote state.
+ *
+ */
+void async_remote_state_update(async_sess_t *sess, void *state)
+{
+	assert(fibril_mutex_is_locked(&sess->remote_state_mtx));
+	sess->remote_state_data = state;
+}
+
+/** Release the session remote state
+ *
+ * Unlock the local replica of the remote state
+ * in stateful sessions.
+ *
+ * @param[in] sess Stateful session.
+ *
+ */
+void async_remote_state_release(async_sess_t *sess)
+{
+	assert(fibril_mutex_is_locked(&sess->remote_state_mtx));
+	
+	fibril_mutex_unlock(&sess->remote_state_mtx);
+}
+
+/** Release the session remote state and end an exchange
+ *
+ * Unlock the local replica of the remote state
+ * in stateful sessions. This is convenience function
+ * which gets the session pointer from the exchange
+ * and also ends the exchange.
+ *
+ * @param[in] exch Stateful session's exchange.
+ *
+ */
+void async_remote_state_release_exchange(async_exch_t *exch)
+{
+	if (exch == NULL)
+		return;
+	
+	async_sess_t *sess = exch->sess;
+	assert(fibril_mutex_is_locked(&sess->remote_state_mtx));
+	
+	async_exchange_end(exch);
+	fibril_mutex_unlock(&sess->remote_state_mtx);
+}
+
 /** @}
  */
Index: uspace/lib/c/generic/async_obsolete.c
===================================================================
--- uspace/lib/c/generic/async_obsolete.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/async_obsolete.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,4 +38,5 @@
 #include <async.h>
 #include <async_obsolete.h>
+#include "private/async.h"
 #undef LIBC_ASYNC_C_
 #undef LIBC_ASYNC_OBSOLETE_C_
@@ -44,5 +45,4 @@
 #include <malloc.h>
 #include <errno.h>
-#include "private/async.h"
 
 /** Send message and return id of the sent message.
Index: uspace/lib/c/generic/ddi.c
===================================================================
--- uspace/lib/c/generic/ddi.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/ddi.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -31,6 +31,8 @@
  */
 /** @file
- */ 
+ */
 
+#include <sys/types.h>
+#include <abi/ddi/arg.h>
 #include <ddi.h>
 #include <libarch/ddi.h>
@@ -40,5 +42,4 @@
 #include <align.h>
 #include <libarch/config.h>
-#include <kernel/ddi/ddi_arg.h>
 
 /** Return unique device number.
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/devman.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,5 +1,5 @@
 /*
  * Copyright (c) 2007 Josef Cejka
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * Copyright (c) 2010 Lenka Trochtova
  * All rights reserved.
@@ -89,5 +89,5 @@
 			if (devman_driver_block_sess == NULL)
 				devman_driver_block_sess =
-				    service_connect_blocking(EXCHANGE_SERIALIZE,
+				    service_connect_blocking(EXCHANGE_PARALLEL,
 				    SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
 		}
@@ -138,5 +138,5 @@
 		if (devman_driver_sess == NULL)
 			devman_driver_sess =
-			    service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAN,
+			    service_connect(EXCHANGE_PARALLEL, SERVICE_DEVMAN,
 			    DEVMAN_DRIVER, 0);
 		
@@ -195,5 +195,5 @@
 	
 	exch = devman_exchange_begin(DEVMAN_DRIVER);
-	async_connect_to_me(exch, 0, 0, 0, NULL, NULL);
+	async_connect_to_me(exch, 0, 0, 0, conn, NULL);
 	devman_exchange_end(exch);
 	
@@ -271,14 +271,14 @@
 }
 
-int devman_add_device_to_class(devman_handle_t devman_handle,
-    const char *class_name)
+int devman_add_device_to_category(devman_handle_t devman_handle,
+    const char *cat_name)
 {
 	async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
 	
 	ipc_call_t answer;
-	aid_t req = async_send_1(exch, DEVMAN_ADD_DEVICE_TO_CLASS,
+	aid_t req = async_send_1(exch, DEVMAN_ADD_DEVICE_TO_CATEGORY,
 	    devman_handle, &answer);
-	sysarg_t retval = async_data_write_start(exch, class_name,
-	    str_size(class_name));
+	sysarg_t retval = async_data_write_start(exch, cat_name,
+	    str_size(cat_name));
 	
 	devman_exchange_end(exch);
@@ -308,4 +308,23 @@
 }
 
+/** Remove function from device.
+ *
+ * Request devman to remove function owned by this driver task.
+ * @param funh      Devman handle of the function
+ *
+ * @return EOK on success or negative error code.
+ */
+int devman_remove_function(devman_handle_t funh)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	
+	exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
+	retval = async_req_1_0(exch, DEVMAN_REMOVE_FUNCTION, (sysarg_t) funh);
+	devman_exchange_end(exch);
+	
+	return (int) retval;
+}
+
 async_sess_t *devman_parent_device_connect(exch_mgmt_t mgmt,
     devman_handle_t handle, unsigned int flags)
@@ -323,5 +342,5 @@
 }
 
-int devman_device_get_handle(const char *pathname, devman_handle_t *handle,
+int devman_fun_get_handle(const char *pathname, devman_handle_t *handle,
     unsigned int flags)
 {
@@ -333,5 +352,5 @@
 		exch = devman_exchange_begin(DEVMAN_CLIENT);
 		if (exch == NULL)
-			return errno;
+			return ENOMEM;
 	}
 	
@@ -364,101 +383,162 @@
 }
 
-int devman_device_get_handle_by_class(const char *classname,
-    const char *devname, devman_handle_t *handle, unsigned int flags)
+static int devman_get_str_internal(sysarg_t method, sysarg_t arg1, char *buf,
+    size_t buf_size)
 {
 	async_exch_t *exch;
-	
-	if (flags & IPC_FLAG_BLOCKING)
-		exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
-	else {
-		exch = devman_exchange_begin(DEVMAN_CLIENT);
-		if (exch == NULL)
-			return errno;
-	}
+	ipc_call_t dreply;
+	size_t act_size;
+	sysarg_t dretval;
+	
+	exch = devman_exchange_begin_blocking(LOC_PORT_CONSUMER);
 	
 	ipc_call_t answer;
-	aid_t req = async_send_1(exch, DEVMAN_DEVICE_GET_HANDLE_BY_CLASS,
-	    flags, &answer);
-	sysarg_t retval = async_data_write_start(exch, classname,
-	    str_size(classname));
+	aid_t req = async_send_1(exch, method, arg1, &answer);
+	aid_t dreq = async_data_read(exch, buf, buf_size - 1, &dreply);
+	async_wait_for(dreq, &dretval);
+	
+	devman_exchange_end(exch);
+	
+	if (dretval != EOK) {
+		async_wait_for(req, NULL);
+		return dretval;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK)
+		return retval;
+	
+	act_size = IPC_GET_ARG2(dreply);
+	assert(act_size <= buf_size - 1);
+	buf[act_size] = '\0';
+	
+	return EOK;
+}
+
+int devman_fun_get_path(devman_handle_t handle, char *buf, size_t buf_size)
+{
+	return devman_get_str_internal(DEVMAN_FUN_GET_PATH, handle, buf,
+	    buf_size);
+}
+
+int devman_fun_get_name(devman_handle_t handle, char *buf, size_t buf_size)
+{
+	return devman_get_str_internal(DEVMAN_FUN_GET_NAME, handle, buf,
+	    buf_size);
+}
+
+static int devman_get_handles_once(sysarg_t method, sysarg_t arg1,
+    devman_handle_t *handle_buf, size_t buf_size, size_t *act_size)
+{
+	async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, arg1, &answer);
+	int rc = async_data_read_start(exch, handle_buf, buf_size);
+	
+	devman_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return rc;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
 	
 	if (retval != EOK) {
-		devman_exchange_end(exch);
-		async_wait_for(req, NULL);
-		return retval;
-	}
-	
-	retval = async_data_write_start(exch, devname,
-	    str_size(devname));
-	
-	devman_exchange_end(exch);
-	
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		return retval;
-	}
-	
-	async_wait_for(req, &retval);
-	
-	if (retval != EOK) {
-		if (handle != NULL)
-			*handle = (devman_handle_t) -1;
-		
-		return retval;
-	}
-	
-	if (handle != NULL)
-		*handle = (devman_handle_t) IPC_GET_ARG1(answer);
-	
-	return retval;
-}
-
-int devman_get_device_path(devman_handle_t handle, char *path, size_t path_size)
+		return retval;
+	}
+	
+	*act_size = IPC_GET_ARG1(answer);
+	return EOK;
+}
+
+/** Get list of handles.
+ *
+ * Returns an allocated array of handles.
+ *
+ * @param method	IPC method
+ * @param arg1		IPC argument 1
+ * @param data		Place to store pointer to array of handles
+ * @param count		Place to store number of handles
+ * @return 		EOK on success or negative error code
+ */
+static int devman_get_handles_internal(sysarg_t method, sysarg_t arg1,
+    devman_handle_t **data, size_t *count)
+{
+	devman_handle_t *handles;
+	size_t act_size;
+	size_t alloc_size;
+	int rc;
+
+	*data = NULL;
+	act_size = 0;	/* silence warning */
+
+	rc = devman_get_handles_once(method, arg1, NULL, 0,
+	    &act_size);
+	if (rc != EOK)
+		return rc;
+
+	alloc_size = act_size;
+	handles = malloc(alloc_size);
+	if (handles == NULL)
+		return ENOMEM;
+
+	while (true) {
+		rc = devman_get_handles_once(method, arg1, handles, alloc_size,
+		    &act_size);
+		if (rc != EOK)
+			return rc;
+
+		if (act_size <= alloc_size)
+			break;
+
+		alloc_size *= 2;
+		free(handles);
+
+		handles = malloc(alloc_size);
+		if (handles == NULL)
+			return ENOMEM;
+	}
+
+	*count = act_size / sizeof(devman_handle_t);
+	*data = handles;
+	return EOK;
+}
+
+int devman_fun_get_child(devman_handle_t funh, devman_handle_t *devh)
 {
 	async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
 	if (exch == NULL)
-		return errno;
-	
-	ipc_call_t answer;
-	aid_t req = async_send_1(exch, DEVMAN_DEVICE_GET_DEVICE_PATH,
-	    handle, &answer);
-	
-	ipc_call_t data_request_call;
-	aid_t data_request = async_data_read(exch, path, path_size,
-	    &data_request_call);
-	
-	devman_exchange_end(exch);
-	
-	if (data_request == 0) {
-		async_wait_for(req, NULL);
 		return ENOMEM;
-	}
-	
-	sysarg_t data_request_rc;
-	async_wait_for(data_request, &data_request_rc);
-	
-	sysarg_t opening_request_rc;
-	async_wait_for(req, &opening_request_rc);
-	
-	if (data_request_rc != EOK) {
-		/* Prefer the return code of the opening request. */
-		if (opening_request_rc != EOK)
-			return (int) opening_request_rc;
-		else
-			return (int) data_request_rc;
-	}
-	
-	if (opening_request_rc != EOK)
-		return (int) opening_request_rc;
-	
-	/* To be on the safe-side. */
-	path[path_size - 1] = 0;
-	size_t transferred_size = IPC_GET_ARG2(data_request_call);
-	if (transferred_size >= path_size)
-		return ELIMIT;
-	
-	/* Terminate the string (trailing 0 not send over IPC). */
-	path[transferred_size] = 0;
-	return EOK;
+	
+	sysarg_t retval = async_req_1_1(exch, DEVMAN_FUN_GET_CHILD,
+	    funh, devh);
+	
+	devman_exchange_end(exch);
+	return (int) retval;
+}
+
+int devman_dev_get_functions(devman_handle_t devh, devman_handle_t **funcs,
+    size_t *count)
+{
+	return devman_get_handles_internal(DEVMAN_DEV_GET_FUNCTIONS,
+	    devh, funcs, count);
+}
+
+int devman_fun_sid_to_handle(service_id_t sid, devman_handle_t *handle)
+{
+	async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
+	if (exch == NULL)
+		return ENOMEM;
+	
+	sysarg_t retval = async_req_1_1(exch, DEVMAN_FUN_SID_TO_HANDLE,
+	    sid, handle);
+	
+	devman_exchange_end(exch);
+	return (int) retval;
 }
 
Index: pace/lib/c/generic/devmap.c
===================================================================
--- uspace/lib/c/generic/devmap.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,521 +1,0 @@
-/*
- * Copyright (c) 2007 Josef Cejka
- * 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.
- */
-
-#include <str.h>
-#include <ipc/services.h>
-#include <ns.h>
-#include <ipc/devmap.h>
-#include <devmap.h>
-#include <fibril_synch.h>
-#include <async.h>
-#include <errno.h>
-#include <malloc.h>
-#include <bool.h>
-
-static FIBRIL_MUTEX_INITIALIZE(devmap_driver_block_mutex);
-static FIBRIL_MUTEX_INITIALIZE(devmap_client_block_mutex);
-
-static FIBRIL_MUTEX_INITIALIZE(devmap_driver_mutex);
-static FIBRIL_MUTEX_INITIALIZE(devmap_client_mutex);
-
-static async_sess_t *devmap_driver_block_sess = NULL;
-static async_sess_t *devmap_client_block_sess = NULL;
-
-static async_sess_t *devmap_driver_sess = NULL;
-static async_sess_t *devmap_client_sess = NULL;
-
-static void clone_session(fibril_mutex_t *mtx, async_sess_t *src,
-    async_sess_t **dst)
-{
-	fibril_mutex_lock(mtx);
-	
-	if ((*dst == NULL) && (src != NULL))
-		*dst = src;
-	
-	fibril_mutex_unlock(mtx);
-}
-
-/** Start an async exchange on the devmap session (blocking).
- *
- * @param iface Device mapper interface to choose
- *
- * @return New exchange.
- *
- */
-async_exch_t *devmap_exchange_begin_blocking(devmap_interface_t iface)
-{
-	switch (iface) {
-	case DEVMAP_DRIVER:
-		fibril_mutex_lock(&devmap_driver_block_mutex);
-		
-		while (devmap_driver_block_sess == NULL) {
-			clone_session(&devmap_driver_mutex, devmap_driver_sess,
-			    &devmap_driver_block_sess);
-			
-			if (devmap_driver_block_sess == NULL)
-				devmap_driver_block_sess =
-				    service_connect_blocking(EXCHANGE_SERIALIZE,
-				    SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
-		}
-		
-		fibril_mutex_unlock(&devmap_driver_block_mutex);
-		
-		clone_session(&devmap_driver_mutex, devmap_driver_block_sess,
-		    &devmap_driver_sess);
-		
-		return async_exchange_begin(devmap_driver_block_sess);
-	case DEVMAP_CLIENT:
-		fibril_mutex_lock(&devmap_client_block_mutex);
-		
-		while (devmap_client_block_sess == NULL) {
-			clone_session(&devmap_client_mutex, devmap_client_sess,
-			    &devmap_client_block_sess);
-			
-			if (devmap_client_block_sess == NULL)
-				devmap_client_block_sess =
-				    service_connect_blocking(EXCHANGE_SERIALIZE,
-				    SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
-		}
-		
-		fibril_mutex_unlock(&devmap_client_block_mutex);
-		
-		clone_session(&devmap_client_mutex, devmap_client_block_sess,
-		    &devmap_client_sess);
-		
-		return async_exchange_begin(devmap_client_block_sess);
-	default:
-		return NULL;
-	}
-}
-
-/** Start an async exchange on the devmap session.
- *
- * @param iface Device mapper interface to choose
- *
- * @return New exchange.
- *
- */
-async_exch_t *devmap_exchange_begin(devmap_interface_t iface)
-{
-	switch (iface) {
-	case DEVMAP_DRIVER:
-		fibril_mutex_lock(&devmap_driver_mutex);
-		
-		if (devmap_driver_sess == NULL)
-			devmap_driver_sess =
-			    service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAP,
-			    DEVMAP_DRIVER, 0);
-		
-		fibril_mutex_unlock(&devmap_driver_mutex);
-		
-		if (devmap_driver_sess == NULL)
-			return NULL;
-		
-		return async_exchange_begin(devmap_driver_sess);
-	case DEVMAP_CLIENT:
-		fibril_mutex_lock(&devmap_client_mutex);
-		
-		if (devmap_client_sess == NULL)
-			devmap_client_sess =
-			    service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAP,
-			    DEVMAP_CLIENT, 0);
-		
-		fibril_mutex_unlock(&devmap_client_mutex);
-		
-		if (devmap_client_sess == NULL)
-			return NULL;
-		
-		return async_exchange_begin(devmap_client_sess);
-	default:
-		return NULL;
-	}
-}
-
-/** Finish an async exchange on the devmap session.
- *
- * @param exch Exchange to be finished.
- *
- */
-void devmap_exchange_end(async_exch_t *exch)
-{
-	async_exchange_end(exch);
-}
-
-/** Register new driver with devmap. */
-int devmap_driver_register(const char *name, async_client_conn_t conn)
-{
-	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_DRIVER);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(exch, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
-	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
-	
-	devmap_exchange_end(exch);
-	
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		return retval;
-	}
-	
-	async_set_client_connection(conn);
-	
-	exch = devmap_exchange_begin(DEVMAP_DRIVER);
-	async_connect_to_me(exch, 0, 0, 0, NULL, NULL);
-	devmap_exchange_end(exch);
-	
-	async_wait_for(req, &retval);
-	return retval;
-}
-
-/** Register new device.
- *
- * The @p interface is used when forwarding connection to the driver.
- * If not 0, the first argument is the interface and the second argument
- * is the devmap handle of the device.
- *
- * When the interface is zero (default), the first argument is directly
- * the handle (to ensure backward compatibility).
- *
- * @param      fqdn      Fully qualified device name.
- * @param[out] handle    Handle to the created instance of device.
- * @param      interface Interface when forwarding.
- *
- */
-int devmap_device_register_with_iface(const char *fqdn,
-    devmap_handle_t *handle, sysarg_t interface)
-{
-	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_DRIVER);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(exch, DEVMAP_DEVICE_REGISTER, interface, 0,
-	    &answer);
-	sysarg_t retval = async_data_write_start(exch, fqdn, str_size(fqdn));
-	
-	devmap_exchange_end(exch);
-	
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		return retval;
-	}
-	
-	async_wait_for(req, &retval);
-	
-	if (retval != EOK) {
-		if (handle != NULL)
-			*handle = -1;
-		
-		return retval;
-	}
-	
-	if (handle != NULL)
-		*handle = (devmap_handle_t) IPC_GET_ARG1(answer);
-	
-	return retval;
-}
-
-/** Register new device.
- *
- * @param fqdn   Fully qualified device name.
- * @param handle Output: Handle to the created instance of device.
- *
- */
-int devmap_device_register(const char *fqdn, devmap_handle_t *handle)
-{
-	return devmap_device_register_with_iface(fqdn, handle, 0);
-}
-
-int devmap_device_get_handle(const char *fqdn, devmap_handle_t *handle,
-    unsigned int flags)
-{
-	async_exch_t *exch;
-	
-	if (flags & IPC_FLAG_BLOCKING)
-		exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
-	else {
-		exch = devmap_exchange_begin(DEVMAP_CLIENT);
-		if (exch == NULL)
-			return errno;
-	}
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(exch, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
-	    &answer);
-	sysarg_t retval = async_data_write_start(exch, fqdn, str_size(fqdn));
-	
-	devmap_exchange_end(exch);
-	
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		return retval;
-	}
-	
-	async_wait_for(req, &retval);
-	
-	if (retval != EOK) {
-		if (handle != NULL)
-			*handle = (devmap_handle_t) -1;
-		
-		return retval;
-	}
-	
-	if (handle != NULL)
-		*handle = (devmap_handle_t) IPC_GET_ARG1(answer);
-	
-	return retval;
-}
-
-int devmap_namespace_get_handle(const char *name, devmap_handle_t *handle,
-    unsigned int flags)
-{
-	async_exch_t *exch;
-	
-	if (flags & IPC_FLAG_BLOCKING)
-		exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
-	else {
-		exch = devmap_exchange_begin(DEVMAP_CLIENT);
-		if (exch == NULL)
-			return errno;
-	}
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(exch, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
-	    &answer);
-	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
-	
-	devmap_exchange_end(exch);
-	
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		return retval;
-	}
-	
-	async_wait_for(req, &retval);
-	
-	if (retval != EOK) {
-		if (handle != NULL)
-			*handle = (devmap_handle_t) -1;
-		
-		return retval;
-	}
-	
-	if (handle != NULL)
-		*handle = (devmap_handle_t) IPC_GET_ARG1(answer);
-	
-	return retval;
-}
-
-devmap_handle_type_t devmap_handle_probe(devmap_handle_t handle)
-{
-	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
-	
-	sysarg_t type;
-	int retval = async_req_1_1(exch, DEVMAP_HANDLE_PROBE, handle, &type);
-	
-	devmap_exchange_end(exch);
-	
-	if (retval != EOK)
-		return DEV_HANDLE_NONE;
-	
-	return (devmap_handle_type_t) type;
-}
-
-async_sess_t *devmap_device_connect(exch_mgmt_t mgmt, devmap_handle_t handle,
-    unsigned int flags)
-{
-	async_sess_t *sess;
-	
-	if (flags & IPC_FLAG_BLOCKING)
-		sess = service_connect_blocking(mgmt, SERVICE_DEVMAP,
-		    DEVMAP_CONNECT_TO_DEVICE, handle);
-	else
-		sess = service_connect(mgmt, SERVICE_DEVMAP,
-		    DEVMAP_CONNECT_TO_DEVICE, handle);
-	
-	return sess;
-}
-
-int devmap_null_create(void)
-{
-	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
-	
-	sysarg_t null_id;
-	int retval = async_req_0_1(exch, DEVMAP_NULL_CREATE, &null_id);
-	
-	devmap_exchange_end(exch);
-	
-	if (retval != EOK)
-		return -1;
-	
-	return (int) null_id;
-}
-
-void devmap_null_destroy(int null_id)
-{
-	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
-	async_req_1_0(exch, DEVMAP_NULL_DESTROY, (sysarg_t) null_id);
-	devmap_exchange_end(exch);
-}
-
-static size_t devmap_count_namespaces_internal(async_exch_t *exch)
-{
-	sysarg_t count;
-	int retval = async_req_0_1(exch, DEVMAP_GET_NAMESPACE_COUNT, &count);
-	if (retval != EOK)
-		return 0;
-	
-	return count;
-}
-
-static size_t devmap_count_devices_internal(async_exch_t *exch,
-    devmap_handle_t ns_handle)
-{
-	sysarg_t count;
-	int retval = async_req_1_1(exch, DEVMAP_GET_DEVICE_COUNT, ns_handle,
-	    &count);
-	if (retval != EOK)
-		return 0;
-	
-	return count;
-}
-
-size_t devmap_count_namespaces(void)
-{
-	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
-	size_t size = devmap_count_namespaces_internal(exch);
-	devmap_exchange_end(exch);
-	
-	return size;
-}
-
-size_t devmap_count_devices(devmap_handle_t ns_handle)
-{
-	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
-	size_t size = devmap_count_devices_internal(exch, ns_handle);
-	devmap_exchange_end(exch);
-	
-	return size;
-}
-
-size_t devmap_get_namespaces(dev_desc_t **data)
-{
-	/* Loop until namespaces read succesful */
-	while (true) {
-		async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
-		size_t count = devmap_count_namespaces_internal(exch);
-		devmap_exchange_end(exch);
-		
-		if (count == 0)
-			return 0;
-		
-		dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
-		if (devs == NULL)
-			return 0;
-		
-		exch = devmap_exchange_begin(DEVMAP_CLIENT);
-		
-		ipc_call_t answer;
-		aid_t req = async_send_0(exch, DEVMAP_GET_NAMESPACES, &answer);
-		int rc = async_data_read_start(exch, devs, count * sizeof(dev_desc_t));
-		
-		devmap_exchange_end(exch);
-		
-		if (rc == EOVERFLOW) {
-			/*
-			 * Number of namespaces has changed since
-			 * the last call of DEVMAP_DEVICE_GET_NAMESPACE_COUNT
-			 */
-			free(devs);
-			continue;
-		}
-		
-		if (rc != EOK) {
-			async_wait_for(req, NULL);
-			free(devs);
-			return 0;
-		}
-		
-		sysarg_t retval;
-		async_wait_for(req, &retval);
-		
-		if (retval != EOK)
-			return 0;
-		
-		*data = devs;
-		return count;
-	}
-}
-
-size_t devmap_get_devices(devmap_handle_t ns_handle, dev_desc_t **data)
-{
-	/* Loop until devices read succesful */
-	while (true) {
-		async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
-		size_t count = devmap_count_devices_internal(exch, ns_handle);
-		devmap_exchange_end(exch);
-		
-		if (count == 0)
-			return 0;
-		
-		dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
-		if (devs == NULL)
-			return 0;
-		
-		exch = devmap_exchange_begin(DEVMAP_CLIENT);
-		
-		ipc_call_t answer;
-		aid_t req = async_send_1(exch, DEVMAP_GET_DEVICES, ns_handle, &answer);
-		int rc = async_data_read_start(exch, devs, count * sizeof(dev_desc_t));
-		
-		devmap_exchange_end(exch);
-		
-		if (rc == EOVERFLOW) {
-			/*
-			 * Number of devices has changed since
-			 * the last call of DEVMAP_DEVICE_GET_DEVICE_COUNT
-			 */
-			free(devs);
-			continue;
-		}
-		
-		if (rc != EOK) {
-			async_wait_for(req, NULL);
-			free(devs);
-			return 0;
-		}
-		
-		sysarg_t retval;
-		async_wait_for(req, &retval);
-		
-		if (retval != EOK)
-			return 0;
-		
-		*data = devs;
-		return count;
-	}
-}
Index: uspace/lib/c/generic/elf/elf_load.c
===================================================================
--- uspace/lib/c/generic/elf/elf_load.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/generic/elf/elf_load.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2006 Sergey Bondari
+ * Copyright (c) 2006 Jakub Jermar
+ * 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 generic
+ * @{
+ */
+
+/**
+ * @file
+ * @brief	Userspace ELF loader.
+ *
+ * This module allows loading ELF binaries (both executables and
+ * shared objects) from VFS. The current implementation allocates
+ * anonymous memory, fills it with segment data and then adjusts
+ * the memory areas' flags to the final value. In the future,
+ * the segments will be mapped directly from the file.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <align.h>
+#include <assert.h>
+#include <as.h>
+#include <elf/elf.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <smc.h>
+#include <loader/pcb.h>
+#include <entry_point.h>
+
+#include <elf/elf_load.h>
+
+#define DPRINTF(...)
+
+static const char *error_codes[] = {
+	"no error",
+	"invalid image",
+	"address space error",
+	"incompatible image",
+	"unsupported image type",
+	"irrecoverable error"
+};
+
+static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
+static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
+static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
+static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
+
+/** Load ELF binary from a file.
+ *
+ * Load an ELF binary from the specified file. If the file is
+ * an executable program, it is loaded unbiased. If it is a shared
+ * object, it is loaded with the bias @a so_bias. Some information
+ * extracted from the binary is stored in a elf_info_t structure
+ * pointed to by @a info.
+ *
+ * @param file_name Path to the ELF file.
+ * @param so_bias   Bias to use if the file is a shared object.
+ * @param info      Pointer to a structure for storing information
+ *                  extracted from the binary.
+ *
+ * @return EOK on success or negative error code.
+ *
+ */
+int elf_load_file(const char *file_name, size_t so_bias, eld_flags_t flags,
+    elf_info_t *info)
+{
+	elf_ld_t elf;
+
+	int fd;
+	int rc;
+	
+	fd = open(file_name, O_RDONLY);
+	if (fd < 0) {
+		DPRINTF("failed opening file\n");
+		return -1;
+	}
+
+	elf.fd = fd;
+	elf.info = info;
+	elf.flags = flags;
+
+	rc = elf_load(&elf, so_bias);
+
+	close(fd);
+
+	return rc;
+}
+
+/** Create the program control block (PCB).
+ *
+ * Fills the program control block @a pcb with information from
+ * @a info.
+ *
+ * @param info	Program info structure
+ * @return EOK on success or negative error code
+ */
+void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
+{
+	pcb->entry = info->entry;
+	pcb->dynamic = info->dynamic;
+	pcb->rtld_runtime = NULL;
+}
+
+
+/** Load an ELF binary.
+ *
+ * The @a elf structure contains the loader state, including
+ * an open file, from which the binary will be loaded,
+ * a pointer to the @c info structure etc.
+ *
+ * @param elf		Pointer to loader state buffer.
+ * @param so_bias	Bias to use if the file is a shared object.
+ * @return EE_OK on success or EE_xx error code.
+ */
+static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
+{
+	elf_header_t header_buf;
+	elf_header_t *header = &header_buf;
+	int i, rc;
+
+	rc = read_all(elf->fd, header, sizeof(elf_header_t));
+	if (rc != sizeof(elf_header_t)) {
+		DPRINTF("Read error.\n"); 
+		return EE_INVALID;
+	}
+
+	elf->header = header;
+
+	/* Identify ELF */
+	if (header->e_ident[EI_MAG0] != ELFMAG0 ||
+	    header->e_ident[EI_MAG1] != ELFMAG1 || 
+	    header->e_ident[EI_MAG2] != ELFMAG2 ||
+	    header->e_ident[EI_MAG3] != ELFMAG3) {
+		DPRINTF("Invalid header.\n");
+		return EE_INVALID;
+	}
+	
+	/* Identify ELF compatibility */
+	if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
+	    header->e_machine != ELF_MACHINE || 
+	    header->e_ident[EI_VERSION] != EV_CURRENT ||
+	    header->e_version != EV_CURRENT ||
+	    header->e_ident[EI_CLASS] != ELF_CLASS) {
+		DPRINTF("Incompatible data/version/class.\n");
+		return EE_INCOMPATIBLE;
+	}
+
+	if (header->e_phentsize != sizeof(elf_segment_header_t)) {
+		DPRINTF("e_phentsize:%d != %d\n", header->e_phentsize,
+		    sizeof(elf_segment_header_t));
+		return EE_INCOMPATIBLE;
+	}
+
+	if (header->e_shentsize != sizeof(elf_section_header_t)) {
+		DPRINTF("e_shentsize:%d != %d\n", header->e_shentsize,
+		    sizeof(elf_section_header_t));
+		return EE_INCOMPATIBLE;
+	}
+
+	/* Check if the object type is supported. */
+	if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
+		DPRINTF("Object type %d is not supported\n", header->e_type);
+		return EE_UNSUPPORTED;
+	}
+
+	/* Shared objects can be loaded with a bias */
+	if (header->e_type == ET_DYN)
+		elf->bias = so_bias;
+	else
+		elf->bias = 0;
+
+	elf->info->interp = NULL;
+	elf->info->dynamic = NULL;
+
+	/* Walk through all segment headers and process them. */
+	for (i = 0; i < header->e_phnum; i++) {
+		elf_segment_header_t segment_hdr;
+
+		/* Seek to start of segment header */
+		lseek(elf->fd, header->e_phoff
+		        + i * sizeof(elf_segment_header_t), SEEK_SET);
+
+		rc = read_all(elf->fd, &segment_hdr,
+		    sizeof(elf_segment_header_t));
+		if (rc != sizeof(elf_segment_header_t)) {
+			DPRINTF("Read error.\n");
+			return EE_INVALID;
+		}
+
+		rc = segment_header(elf, &segment_hdr);
+		if (rc != EE_OK)
+			return rc;
+	}
+
+	DPRINTF("Parse sections.\n");
+
+	/* Inspect all section headers and proccess them. */
+	for (i = 0; i < header->e_shnum; i++) {
+		elf_section_header_t section_hdr;
+
+		/* Seek to start of section header */
+		lseek(elf->fd, header->e_shoff
+		    + i * sizeof(elf_section_header_t), SEEK_SET);
+
+		rc = read_all(elf->fd, &section_hdr,
+		    sizeof(elf_section_header_t));
+		if (rc != sizeof(elf_section_header_t)) {
+			DPRINTF("Read error.\n");
+			return EE_INVALID;
+		}
+
+		rc = section_header(elf, &section_hdr);
+		if (rc != EE_OK)
+			return rc;
+	}
+
+	elf->info->entry =
+	    (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
+
+	DPRINTF("Done.\n");
+
+	return EE_OK;
+}
+
+/** Print error message according to error code.
+ *
+ * @param rc Return code returned by elf_load().
+ *
+ * @return NULL terminated description of error.
+ */
+const char *elf_error(unsigned int rc)
+{
+	assert(rc < sizeof(error_codes) / sizeof(char *));
+
+	return error_codes[rc];
+}
+
+/** Process segment header.
+ *
+ * @param entry	Segment header.
+ *
+ * @return EE_OK on success, error code otherwise.
+ */
+static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
+{
+	switch (entry->p_type) {
+	case PT_NULL:
+	case PT_PHDR:
+	case PT_NOTE:
+		break;
+	case PT_LOAD:
+		return load_segment(elf, entry);
+		break;
+	case PT_INTERP:
+		/* Assume silently interp == "/app/dload" */
+		elf->info->interp = "/app/dload";
+		break;
+	case PT_DYNAMIC:
+		/* Record pointer to dynamic section into info structure */
+		elf->info->dynamic =
+		    (void *)((uint8_t *)entry->p_vaddr + elf->bias);
+		DPRINTF("dynamic section found at 0x%x\n",
+			(uintptr_t)elf->info->dynamic);
+		break;
+	case 0x70000000:
+		/* FIXME: MIPS reginfo */
+		break;
+	case PT_SHLIB:
+//	case PT_LOPROC:
+//	case PT_HIPROC:
+	default:
+		DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
+		return EE_UNSUPPORTED;
+		break;
+	}
+	return EE_OK;
+}
+
+/** Load segment described by program header entry.
+ *
+ * @param elf	Loader state.
+ * @param entry Program header entry describing segment to be loaded.
+ *
+ * @return EE_OK on success, error code otherwise.
+ */
+int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
+{
+	void *a;
+	int flags = 0;
+	uintptr_t bias;
+	uintptr_t base;
+	void *seg_ptr;
+	uintptr_t seg_addr;
+	size_t mem_sz;
+	ssize_t rc;
+
+	bias = elf->bias;
+
+	seg_addr = entry->p_vaddr + bias;
+	seg_ptr = (void *) seg_addr;
+
+	DPRINTF("Load segment at addr %p, size 0x%x\n", (void *) seg_addr,
+		entry->p_memsz);
+
+	if (entry->p_align > 1) {
+		if ((entry->p_offset % entry->p_align) !=
+		    (seg_addr % entry->p_align)) {
+			DPRINTF("Align check 1 failed offset%%align=%d, "
+			    "vaddr%%align=%d\n",
+			    entry->p_offset % entry->p_align,
+			    seg_addr % entry->p_align
+			);
+			return EE_INVALID;
+		}
+	}
+
+	/* Final flags that will be set for the memory area */
+
+	if (entry->p_flags & PF_X)
+		flags |= AS_AREA_EXEC;
+	if (entry->p_flags & PF_W)
+		flags |= AS_AREA_WRITE;
+	if (entry->p_flags & PF_R)
+		flags |= AS_AREA_READ;
+	flags |= AS_AREA_CACHEABLE;
+	
+	base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
+	mem_sz = entry->p_memsz + (entry->p_vaddr - base);
+
+	DPRINTF("Map to seg_addr=%p-%p.\n", (void *) seg_addr,
+	    (void *) (entry->p_vaddr + bias +
+	    ALIGN_UP(entry->p_memsz, PAGE_SIZE)));
+
+	/*
+	 * For the course of loading, the area needs to be readable
+	 * and writeable.
+	 */
+	a = as_area_create((uint8_t *)base + bias, mem_sz,
+	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
+	if (a == (void *)(-1)) {
+		DPRINTF("memory mapping failed (0x%x, %d)\n",
+			base+bias, mem_sz);
+		return EE_MEMORY;
+	}
+
+	DPRINTF("as_area_create(%p, %#zx, %d) -> %p\n",
+	    (void *) (base + bias), mem_sz, flags, (void *) a);
+
+	/*
+	 * Load segment data
+	 */
+	rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
+	if (rc < 0) {
+		printf("seek error\n");
+		return EE_INVALID;
+	}
+
+/*	rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
+	if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
+
+	/* Long reads are not possible yet. Load segment piecewise. */
+
+	unsigned left, now;
+	uint8_t *dp;
+
+	left = entry->p_filesz;
+	dp = seg_ptr;
+
+	while (left > 0) {
+		now = 16384;
+		if (now > left) now = left;
+
+		rc = read_all(elf->fd, dp, now);
+
+		if (rc != (ssize_t) now) { 
+			DPRINTF("Read error.\n");
+			return EE_INVALID;
+		}
+
+		left -= now;
+		dp += now;
+	}
+
+	/*
+	 * The caller wants to modify the segments first. He will then
+	 * need to set the right access mode and ensure SMC coherence.
+	 */
+	if ((elf->flags & ELDF_RW) != 0) return EE_OK;
+
+//	printf("set area flags to %d\n", flags);
+	rc = as_area_change_flags(seg_ptr, flags);
+	if (rc != 0) {
+		DPRINTF("Failed to set memory area flags.\n");
+		return EE_MEMORY;
+	}
+
+	if (flags & AS_AREA_EXEC) {
+		/* Enforce SMC coherence for the segment */
+		if (smc_coherence(seg_ptr, entry->p_filesz))
+			return EE_MEMORY;
+	}
+
+	return EE_OK;
+}
+
+/** Process section header.
+ *
+ * @param elf	Loader state.
+ * @param entry Segment header.
+ *
+ * @return EE_OK on success, error code otherwise.
+ */
+static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
+{
+	switch (entry->sh_type) {
+	case SHT_PROGBITS:
+		if (entry->sh_flags & SHF_TLS) {
+			/* .tdata */
+		}
+		break;
+	case SHT_NOBITS:
+		if (entry->sh_flags & SHF_TLS) {
+			/* .tbss */
+		}
+		break;
+	case SHT_DYNAMIC:
+		/* Record pointer to dynamic section into info structure */
+		elf->info->dynamic =
+		    (void *)((uint8_t *)entry->sh_addr + elf->bias);
+		DPRINTF("Dynamic section found at %p.\n",
+		    (void *) elf->info->dynamic);
+		break;
+	default:
+		break;
+	}
+	
+	return EE_OK;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/event.c
===================================================================
--- uspace/lib/c/generic/event.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/event.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,4 @@
 #include <libc.h>
 #include <event.h>
-#include <kernel/ipc/event_types.h>
 
 /** Subscribe event notifications.
@@ -50,4 +49,10 @@
  */
 int event_subscribe(event_type_t evno, sysarg_t imethod)
+{
+	return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) evno,
+	    (sysarg_t) imethod);
+}
+
+int event_task_subscribe(event_task_type_t evno, sysarg_t imethod)
 {
 	return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) evno,
@@ -67,4 +72,9 @@
 }
 
+int event_task_unmask(event_task_type_t evno)
+{
+	return __SYSCALL1(SYS_EVENT_UNMASK, (sysarg_t) evno);
+}
+
 /** @}
  */
Index: uspace/lib/c/generic/fibril.c
===================================================================
--- uspace/lib/c/generic/fibril.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/fibril.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,5 +41,5 @@
 #include <unistd.h>
 #include <stdio.h>
-#include <arch/barrier.h>
+#include <libarch/barrier.h>
 #include <libarch/faddr.h>
 #include <futex.h>
Index: uspace/lib/c/generic/io/io.c
===================================================================
--- uspace/lib/c/generic/io/io.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/io/io.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -45,5 +45,5 @@
 #include <vfs/vfs.h>
 #include <vfs/vfs_sess.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 #include <adt/list.h>
 #include "../private/io.h"
@@ -101,8 +101,8 @@
 static LIST_INITIALIZE(files);
 
-void __stdio_init(int filc, fdi_node_t *filv[])
+void __stdio_init(int filc)
 {
 	if (filc > 0) {
-		stdin = fopen_node(filv[0], "r");
+		stdin = fdopen(0, "r");
 	} else {
 		stdin = &stdin_null;
@@ -111,5 +111,5 @@
 	
 	if (filc > 1) {
-		stdout = fopen_node(filv[1], "w");
+		stdout = fdopen(1, "w");
 	} else {
 		stdout = &stdout_klog;
@@ -118,5 +118,5 @@
 	
 	if (filc > 2) {
-		stderr = fopen_node(filv[2], "w");
+		stderr = fdopen(2, "w");
 	} else {
 		stderr = &stderr_klog;
@@ -285,36 +285,4 @@
 }
 
-FILE *fopen_node(fdi_node_t *node, const char *mode)
-{
-	int flags;
-	if (!parse_mode(mode, &flags))
-		return NULL;
-	
-	/* Open file. */
-	FILE *stream = malloc(sizeof(FILE));
-	if (stream == NULL) {
-		errno = ENOMEM;
-		return NULL;
-	}
-	
-	stream->fd = open_node(node, flags);
-	if (stream->fd < 0) {
-		/* errno was set by open_node() */
-		free(stream);
-		return NULL;
-	}
-	
-	stream->error = false;
-	stream->eof = false;
-	stream->klog = false;
-	stream->sess = NULL;
-	stream->need_sync = false;
-	_setvbuf(stream);
-	
-	list_append(&stream->link, &files);
-	
-	return stream;
-}
-
 int fclose(FILE *stream)
 {
@@ -594,9 +562,10 @@
 		}
 		
-		buf += now;
+		data += now;
 		stream->buf_head += now;
 		buf_free -= now;
 		bytes_left -= now;
 		total_written += now;
+		stream->buf_state = _bs_write;
 		
 		if (buf_free == 0) {
@@ -606,7 +575,4 @@
 		}
 	}
-	
-	if (total_written > 0)
-		stream->buf_state = _bs_write;
 
 	if (need_flush)
@@ -714,4 +680,5 @@
 off64_t ftell(FILE *stream)
 {
+	_fflushbuf(stream);
 	return lseek(stream->fd, 0, SEEK_CUR);
 }
@@ -781,8 +748,10 @@
 }
 
-int fnode(FILE *stream, fdi_node_t *node)
-{
-	if (stream->fd >= 0)
-		return fd_node(stream->fd, node);
+int fhandle(FILE *stream, int *handle)
+{
+	if (stream->fd >= 0) {
+		*handle = stream->fd;
+		return EOK;
+	}
 	
 	return ENOENT;
Index: uspace/lib/c/generic/io/printf_core.c
===================================================================
--- uspace/lib/c/generic/io/printf_core.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/io/printf_core.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -206,5 +206,5 @@
 	}
 	
-	return (int) (counter + 1);
+	return (int) (counter);
 }
 
@@ -244,5 +244,5 @@
 	}
 	
-	return (int) (counter + 1);
+	return (int) (counter);
 }
 
Index: uspace/lib/c/generic/ipc.c
===================================================================
--- uspace/lib/c/generic/ipc.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/ipc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -47,4 +47,5 @@
 #include <futex.h>
 #include <fibril.h>
+#include <macros.h>
 
 /**
@@ -611,5 +612,5 @@
 /** Request callback connection.
  *
- * The @a taskhash and @a phonehash identifiers returned
+ * The @a task_id and @a phonehash identifiers returned
  * by the kernel can be used for connection tracking.
  *
@@ -618,5 +619,5 @@
  * @param arg2      User defined argument.
  * @param arg3      User defined argument.
- * @param taskhash  Opaque identifier of the client task.
+ * @param task_id   Identifier of the client task.
  * @param phonehash Opaque identifier of the phone that will
  *                  be used for incoming calls.
@@ -626,8 +627,14 @@
  */
 int ipc_connect_to_me(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
-    sysarg_t *taskhash, sysarg_t *phonehash)
-{
-	return ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_TO_ME, arg1, arg2,
-	    arg3, NULL, NULL, NULL, taskhash, phonehash);
+    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;
 }
 
Index: uspace/lib/c/generic/libc.c
===================================================================
--- uspace/lib/c/generic/libc.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/libc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -91,9 +91,9 @@
 		argc = 0;
 		argv = NULL;
-		__stdio_init(0, NULL);
+		__stdio_init(0);
 	} else {
 		argc = __pcb->argc;
 		argv = __pcb->argv;
-		__stdio_init(__pcb->filc, __pcb->filv);
+		__stdio_init(__pcb->filc);
 		(void) chdir(__pcb->cwd);
 	}
Index: uspace/lib/c/generic/loader.c
===================================================================
--- uspace/lib/c/generic/loader.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/loader.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -256,38 +256,28 @@
  *
  */
-int loader_set_files(loader_t *ldr, fdi_node_t *const files[])
-{
-	/*
-	 * Serialize the arguments into a single array. First
-	 * compute size of the buffer needed.
-	 */
-	fdi_node_t *const *ap = files;
-	size_t count = 0;
-	while (*ap != NULL) {
-		count++;
-		ap++;
-	}
-	
-	fdi_node_t *files_buf;
-	files_buf = (fdi_node_t *) malloc(count * sizeof(fdi_node_t));
-	if (files_buf == NULL)
-		return ENOMEM;
-	
-	/* Fill the buffer */
-	size_t i;
-	for (i = 0; i < count; i++)
-		files_buf[i] = *files[i];
-	
+int loader_set_files(loader_t *ldr, int * const files[])
+{
 	/* Send serialized files to the loader */
 	async_exch_t *exch = async_exchange_begin(ldr->sess);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_0(exch, LOADER_SET_FILES, &answer);
-	sysarg_t rc = async_data_write_start(exch, (void *) files_buf,
-	    count * sizeof(fdi_node_t));
-	
-	async_exchange_end(exch);
-	free(files_buf);
-	
+	async_exch_t *vfs_exch = vfs_exchange_begin();
+	
+	int i;
+	for (i = 0; files[i]; i++);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, LOADER_SET_FILES, i, &answer);
+
+	sysarg_t rc = EOK;
+	
+	for (i = 0; files[i]; i++) {
+		rc = async_state_change_start(exch, VFS_PASS_HANDLE, *files[i],
+		    0, vfs_exch); 
+		if (rc != EOK)
+			break;
+	}
+	
+	vfs_exchange_end(vfs_exch);
+	async_exchange_end(exch);
+
 	if (rc != EOK) {
 		async_wait_for(req, NULL);
Index: uspace/lib/c/generic/loc.c
===================================================================
--- uspace/lib/c/generic/loc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/generic/loc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,876 @@
+/*
+ * Copyright (c) 2007 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.
+ */
+
+#include <str.h>
+#include <ipc/services.h>
+#include <ns.h>
+#include <ipc/loc.h>
+#include <loc.h>
+#include <fibril_synch.h>
+#include <async.h>
+#include <errno.h>
+#include <malloc.h>
+#include <bool.h>
+
+static FIBRIL_MUTEX_INITIALIZE(loc_supp_block_mutex);
+static FIBRIL_MUTEX_INITIALIZE(loc_cons_block_mutex);
+
+static FIBRIL_MUTEX_INITIALIZE(loc_supplier_mutex);
+static FIBRIL_MUTEX_INITIALIZE(loc_consumer_mutex);
+
+static FIBRIL_MUTEX_INITIALIZE(loc_callback_mutex);
+static bool loc_callback_created = false;
+
+static async_sess_t *loc_supp_block_sess = NULL;
+static async_sess_t *loc_cons_block_sess = NULL;
+
+static async_sess_t *loc_supplier_sess = NULL;
+static async_sess_t *loc_consumer_sess = NULL;
+
+static loc_cat_change_cb_t cat_change_cb = NULL;
+
+static void loc_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	loc_cat_change_cb_t cb_fun;
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+		
+		int retval;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case LOC_EVENT_CAT_CHANGE:
+			fibril_mutex_lock(&loc_callback_mutex);
+			cb_fun = cat_change_cb;
+			if (cb_fun != NULL) {
+				(*cb_fun)();
+			}
+			fibril_mutex_unlock(&loc_callback_mutex);
+			retval = 0;
+			break;
+		default:
+			retval = ENOTSUP;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+
+static void clone_session(fibril_mutex_t *mtx, async_sess_t *src,
+    async_sess_t **dst)
+{
+	fibril_mutex_lock(mtx);
+	
+	if ((*dst == NULL) && (src != NULL))
+		*dst = src;
+	
+	fibril_mutex_unlock(mtx);
+}
+
+static int loc_callback_create(void)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	int rc = EOK;
+
+	fibril_mutex_lock(&loc_callback_mutex);
+	
+	if (!loc_callback_created) {
+		exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+		
+		ipc_call_t answer;
+		aid_t req = async_send_0(exch, LOC_CALLBACK_CREATE, &answer);
+		async_connect_to_me(exch, 0, 0, 0, loc_cb_conn, NULL);
+		loc_exchange_end(exch);
+		
+		async_wait_for(req, &retval);
+		if (rc != EOK)
+			goto done;
+		
+		if (retval != EOK) {
+			rc = retval;
+			goto done;
+		}
+		
+		loc_callback_created = true;
+	}
+	
+	rc = EOK;
+done:
+	fibril_mutex_unlock(&loc_callback_mutex);
+	return rc;
+}
+
+/** Start an async exchange on the loc session (blocking).
+ *
+ * @param iface Location service interface to choose
+ *
+ * @return New exchange.
+ *
+ */
+async_exch_t *loc_exchange_begin_blocking(loc_interface_t iface)
+{
+	switch (iface) {
+	case LOC_PORT_SUPPLIER:
+		fibril_mutex_lock(&loc_supp_block_mutex);
+		
+		while (loc_supp_block_sess == NULL) {
+			clone_session(&loc_supplier_mutex, loc_supplier_sess,
+			    &loc_supp_block_sess);
+			
+			if (loc_supp_block_sess == NULL)
+				loc_supp_block_sess =
+				    service_connect_blocking(EXCHANGE_SERIALIZE,
+				    SERVICE_LOC, LOC_PORT_SUPPLIER, 0);
+		}
+		
+		fibril_mutex_unlock(&loc_supp_block_mutex);
+		
+		clone_session(&loc_supplier_mutex, loc_supp_block_sess,
+		    &loc_supplier_sess);
+		
+		return async_exchange_begin(loc_supp_block_sess);
+	case LOC_PORT_CONSUMER:
+		fibril_mutex_lock(&loc_cons_block_mutex);
+		
+		while (loc_cons_block_sess == NULL) {
+			clone_session(&loc_consumer_mutex, loc_consumer_sess,
+			    &loc_cons_block_sess);
+			
+			if (loc_cons_block_sess == NULL)
+				loc_cons_block_sess =
+				    service_connect_blocking(EXCHANGE_SERIALIZE,
+				    SERVICE_LOC, LOC_PORT_CONSUMER, 0);
+		}
+		
+		fibril_mutex_unlock(&loc_cons_block_mutex);
+		
+		clone_session(&loc_consumer_mutex, loc_cons_block_sess,
+		    &loc_consumer_sess);
+		
+		return async_exchange_begin(loc_cons_block_sess);
+	default:
+		return NULL;
+	}
+}
+
+/** Start an async exchange on the loc session.
+ *
+ * @param iface Location service interface to choose
+ *
+ * @return New exchange.
+ *
+ */
+async_exch_t *loc_exchange_begin(loc_interface_t iface)
+{
+	switch (iface) {
+	case LOC_PORT_SUPPLIER:
+		fibril_mutex_lock(&loc_supplier_mutex);
+		
+		if (loc_supplier_sess == NULL)
+			loc_supplier_sess =
+			    service_connect(EXCHANGE_SERIALIZE, SERVICE_LOC,
+			    LOC_PORT_SUPPLIER, 0);
+		
+		fibril_mutex_unlock(&loc_supplier_mutex);
+		
+		if (loc_supplier_sess == NULL)
+			return NULL;
+		
+		return async_exchange_begin(loc_supplier_sess);
+	case LOC_PORT_CONSUMER:
+		fibril_mutex_lock(&loc_consumer_mutex);
+		
+		if (loc_consumer_sess == NULL)
+			loc_consumer_sess =
+			    service_connect(EXCHANGE_SERIALIZE, SERVICE_LOC,
+			    LOC_PORT_CONSUMER, 0);
+		
+		fibril_mutex_unlock(&loc_consumer_mutex);
+		
+		if (loc_consumer_sess == NULL)
+			return NULL;
+		
+		return async_exchange_begin(loc_consumer_sess);
+	default:
+		return NULL;
+	}
+}
+
+/** Finish an async exchange on the loc session.
+ *
+ * @param exch Exchange to be finished.
+ *
+ */
+void loc_exchange_end(async_exch_t *exch)
+{
+	async_exchange_end(exch);
+}
+
+/** Register new driver with loc. */
+int loc_server_register(const char *name, async_client_conn_t conn)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_SUPPLIER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, LOC_SERVER_REGISTER, 0, 0, &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	async_set_client_connection(conn);
+	
+	exch = loc_exchange_begin(LOC_PORT_SUPPLIER);
+	async_connect_to_me(exch, 0, 0, 0, NULL, NULL);
+	loc_exchange_end(exch);
+	
+	async_wait_for(req, &retval);
+	return retval;
+}
+
+/** Register new service.
+ *
+ * The @p interface is used when forwarding connection to the server.
+ * If not 0, the first argument is the interface and the second argument
+ * is the service ID.
+ *
+ * When the interface is zero (default), the first argument is directly
+ * the handle (to ensure backward compatibility).
+ *
+ * @param      fqsn      Fully qualified service name
+ * @param[out] sid       Service ID of new service
+ * @param      interface Interface when forwarding
+ *
+ */
+int loc_service_register_with_iface(const char *fqsn,
+    service_id_t *sid, sysarg_t interface)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_SUPPLIER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, LOC_SERVICE_REGISTER, interface, 0,
+	    &answer);
+	sysarg_t retval = async_data_write_start(exch, fqsn, str_size(fqsn));
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		if (sid != NULL)
+			*sid = -1;
+		
+		return retval;
+	}
+	
+	if (sid != NULL)
+		*sid = (service_id_t) IPC_GET_ARG1(answer);
+	
+	return retval;
+}
+
+/** Register new service.
+ *
+ * @param fqsn Fully qualified service name
+ * @param sid  Output: ID of new service
+ *
+ */
+int loc_service_register(const char *fqdn, service_id_t *sid)
+{
+	return loc_service_register_with_iface(fqdn, sid, 0);
+}
+
+/** Unregister service.
+ *
+ * @param sid	Service ID
+ */
+int loc_service_unregister(service_id_t sid)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	
+	exch = loc_exchange_begin_blocking(LOC_PORT_SUPPLIER);
+	retval = async_req_1_0(exch, LOC_SERVICE_UNREGISTER, sid);
+	loc_exchange_end(exch);
+	
+	return (int)retval;
+}
+
+int loc_service_get_id(const char *fqdn, service_id_t *handle,
+    unsigned int flags)
+{
+	async_exch_t *exch;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	else {
+		exch = loc_exchange_begin(LOC_PORT_CONSUMER);
+		if (exch == NULL)
+			return errno;
+	}
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, LOC_SERVICE_GET_ID, flags, 0,
+	    &answer);
+	sysarg_t retval = async_data_write_start(exch, fqdn, str_size(fqdn));
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		if (handle != NULL)
+			*handle = (service_id_t) -1;
+		
+		return retval;
+	}
+	
+	if (handle != NULL)
+		*handle = (service_id_t) IPC_GET_ARG1(answer);
+	
+	return retval;
+}
+
+/** Get object name.
+ *
+ * Provided ID of an object, return its name.
+ *
+ * @param method	IPC method
+ * @param id		Object ID
+ * @param name		Place to store pointer to new string. Caller should
+ *			free it using free().
+ * @return		EOK on success or negative error code
+ */
+static int loc_get_name_internal(sysarg_t method, sysarg_t id, char **name)
+{
+	async_exch_t *exch;
+	char name_buf[LOC_NAME_MAXLEN + 1];
+	ipc_call_t dreply;
+	size_t act_size;
+	sysarg_t dretval;
+	
+	*name = NULL;
+	exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, id, &answer);
+	aid_t dreq = async_data_read(exch, name_buf, LOC_NAME_MAXLEN,
+	    &dreply);
+	async_wait_for(dreq, &dretval);
+	
+	loc_exchange_end(exch);
+	
+	if (dretval != EOK) {
+		async_wait_for(req, NULL);
+		return dretval;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK)
+		return retval;
+	
+	act_size = IPC_GET_ARG2(dreply);
+	assert(act_size <= LOC_NAME_MAXLEN);
+	name_buf[act_size] = '\0';
+
+	*name = str_dup(name_buf);
+	if (*name == NULL)
+		return ENOMEM;
+	
+	return EOK;
+}
+
+/** Get category name.
+ *
+ * Provided ID of a service, return its name.
+ *
+ * @param cat_id	Category ID
+ * @param name		Place to store pointer to new string. Caller should
+ *			free it using free().
+ * @return		EOK on success or negative error code
+ */
+int loc_category_get_name(category_id_t cat_id, char **name)
+{
+	return loc_get_name_internal(LOC_CATEGORY_GET_NAME, cat_id, name);
+}
+
+/** Get service name.
+ *
+ * Provided ID of a service, return its name.
+ *
+ * @param svc_id	Service ID
+ * @param name		Place to store pointer to new string. Caller should
+ *			free it using free().
+ * @return		EOK on success or negative error code
+ */
+int loc_service_get_name(service_id_t svc_id, char **name)
+{
+	return loc_get_name_internal(LOC_SERVICE_GET_NAME, svc_id, name);
+}
+
+int loc_namespace_get_id(const char *name, service_id_t *handle,
+    unsigned int flags)
+{
+	async_exch_t *exch;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	else {
+		exch = loc_exchange_begin(LOC_PORT_CONSUMER);
+		if (exch == NULL)
+			return errno;
+	}
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, LOC_NAMESPACE_GET_ID, flags, 0,
+	    &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		if (handle != NULL)
+			*handle = (service_id_t) -1;
+		
+		return retval;
+	}
+	
+	if (handle != NULL)
+		*handle = (service_id_t) IPC_GET_ARG1(answer);
+	
+	return retval;
+}
+
+/** Get category ID.
+ *
+ * Provided name of a category, return its ID.
+ *
+ * @param name		Category name
+ * @param cat_id	Place to store ID
+ * @param flags		IPC_FLAG_BLOCKING to wait for location service to start
+ * @return		EOK on success or negative error code
+ */
+int loc_category_get_id(const char *name, category_id_t *cat_id,
+    unsigned int flags)
+{
+	async_exch_t *exch;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	else {
+		exch = loc_exchange_begin(LOC_PORT_CONSUMER);
+		if (exch == NULL)
+			return errno;
+	}
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, LOC_CATEGORY_GET_ID,
+	    &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		if (cat_id != NULL)
+			*cat_id = (category_id_t) -1;
+		
+		return retval;
+	}
+	
+	if (cat_id != NULL)
+		*cat_id = (category_id_t) IPC_GET_ARG1(answer);
+	
+	return retval;
+}
+
+
+loc_object_type_t loc_id_probe(service_id_t handle)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	
+	sysarg_t type;
+	int retval = async_req_1_1(exch, LOC_ID_PROBE, handle, &type);
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK)
+		return LOC_OBJECT_NONE;
+	
+	return (loc_object_type_t) type;
+}
+
+async_sess_t *loc_service_connect(exch_mgmt_t mgmt, service_id_t handle,
+    unsigned int flags)
+{
+	async_sess_t *sess;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		sess = service_connect_blocking(mgmt, SERVICE_LOC,
+		    LOC_CONNECT_TO_SERVICE, handle);
+	else
+		sess = service_connect(mgmt, SERVICE_LOC,
+		    LOC_CONNECT_TO_SERVICE, handle);
+	
+	return sess;
+}
+
+int loc_null_create(void)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	
+	sysarg_t null_id;
+	int retval = async_req_0_1(exch, LOC_NULL_CREATE, &null_id);
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK)
+		return -1;
+	
+	return (int) null_id;
+}
+
+void loc_null_destroy(int null_id)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	async_req_1_0(exch, LOC_NULL_DESTROY, (sysarg_t) null_id);
+	loc_exchange_end(exch);
+}
+
+static size_t loc_count_namespaces_internal(async_exch_t *exch)
+{
+	sysarg_t count;
+	int retval = async_req_0_1(exch, LOC_GET_NAMESPACE_COUNT, &count);
+	if (retval != EOK)
+		return 0;
+	
+	return count;
+}
+
+/** Add service to category.
+ *
+ * @param svc_id	Service ID
+ * @param cat_id	Category ID
+ * @return		EOK on success or negative error code
+ */
+int loc_service_add_to_cat(service_id_t svc_id, service_id_t cat_id)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	
+	exch = loc_exchange_begin_blocking(LOC_PORT_SUPPLIER);
+	retval = async_req_2_0(exch, LOC_SERVICE_ADD_TO_CAT, svc_id, cat_id);
+	loc_exchange_end(exch);
+	
+	return retval;
+}
+
+static size_t loc_count_services_internal(async_exch_t *exch,
+    service_id_t ns_handle)
+{
+	sysarg_t count;
+	int retval = async_req_1_1(exch, LOC_GET_SERVICE_COUNT, ns_handle,
+	    &count);
+	if (retval != EOK)
+		return 0;
+	
+	return count;
+}
+
+size_t loc_count_namespaces(void)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	size_t size = loc_count_namespaces_internal(exch);
+	loc_exchange_end(exch);
+	
+	return size;
+}
+
+size_t loc_count_services(service_id_t ns_handle)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	size_t size = loc_count_services_internal(exch, ns_handle);
+	loc_exchange_end(exch);
+	
+	return size;
+}
+
+size_t loc_get_namespaces(loc_sdesc_t **data)
+{
+	/* Loop until read is succesful */
+	while (true) {
+		async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+		size_t count = loc_count_namespaces_internal(exch);
+		loc_exchange_end(exch);
+		
+		if (count == 0)
+			return 0;
+		
+		loc_sdesc_t *devs = (loc_sdesc_t *) calloc(count, sizeof(loc_sdesc_t));
+		if (devs == NULL)
+			return 0;
+		
+		exch = loc_exchange_begin(LOC_PORT_CONSUMER);
+		
+		ipc_call_t answer;
+		aid_t req = async_send_0(exch, LOC_GET_NAMESPACES, &answer);
+		int rc = async_data_read_start(exch, devs, count * sizeof(loc_sdesc_t));
+		
+		loc_exchange_end(exch);
+		
+		if (rc == EOVERFLOW) {
+			/*
+			 * Number of namespaces has changed since
+			 * the last call of LOC_GET_NAMESPACE_COUNT
+			 */
+			free(devs);
+			continue;
+		}
+		
+		if (rc != EOK) {
+			async_wait_for(req, NULL);
+			free(devs);
+			return 0;
+		}
+		
+		sysarg_t retval;
+		async_wait_for(req, &retval);
+		
+		if (retval != EOK)
+			return 0;
+		
+		*data = devs;
+		return count;
+	}
+}
+
+size_t loc_get_services(service_id_t ns_handle, loc_sdesc_t **data)
+{
+	/* Loop until read is succesful */
+	while (true) {
+		async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+		size_t count = loc_count_services_internal(exch, ns_handle);
+		loc_exchange_end(exch);
+		
+		if (count == 0)
+			return 0;
+		
+		loc_sdesc_t *devs = (loc_sdesc_t *) calloc(count, sizeof(loc_sdesc_t));
+		if (devs == NULL)
+			return 0;
+		
+		exch = loc_exchange_begin(LOC_PORT_CONSUMER);
+		
+		ipc_call_t answer;
+		aid_t req = async_send_1(exch, LOC_GET_SERVICES, ns_handle, &answer);
+		int rc = async_data_read_start(exch, devs, count * sizeof(loc_sdesc_t));
+		
+		loc_exchange_end(exch);
+		
+		if (rc == EOVERFLOW) {
+			/*
+			 * Number of services has changed since
+			 * the last call of LOC_GET_SERVICE_COUNT
+			 */
+			free(devs);
+			continue;
+		}
+		
+		if (rc != EOK) {
+			async_wait_for(req, NULL);
+			free(devs);
+			return 0;
+		}
+		
+		sysarg_t retval;
+		async_wait_for(req, &retval);
+		
+		if (retval != EOK)
+			return 0;
+		
+		*data = devs;
+		return count;
+	}
+}
+
+static int loc_category_get_ids_once(sysarg_t method, sysarg_t arg1,
+    sysarg_t *id_buf, size_t buf_size, size_t *act_size)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, arg1, &answer);
+	int rc = async_data_read_start(exch, id_buf, buf_size);
+	
+	loc_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return rc;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		return retval;
+	}
+	
+	*act_size = IPC_GET_ARG1(answer);
+	return EOK;
+}
+
+/** Get list of IDs.
+ *
+ * Returns an allocated array of service IDs.
+ *
+ * @param method	IPC method
+ * @param arg1		IPC argument 1
+ * @param data		Place to store pointer to array of IDs
+ * @param count		Place to store number of IDs
+ * @return 		EOK on success or negative error code
+ */
+static int loc_get_ids_internal(sysarg_t method, sysarg_t arg1,
+    sysarg_t **data, size_t *count)
+{
+	service_id_t *ids;
+	size_t act_size;
+	size_t alloc_size;
+	int rc;
+
+	*data = NULL;
+	act_size = 0;	/* silence warning */
+
+	rc = loc_category_get_ids_once(method, arg1, NULL, 0,
+	    &act_size);
+	if (rc != EOK)
+		return rc;
+
+	alloc_size = act_size;
+	ids = malloc(alloc_size);
+	if (ids == NULL)
+		return ENOMEM;
+
+	while (true) {
+		rc = loc_category_get_ids_once(method, arg1, ids, alloc_size,
+		    &act_size);
+		if (rc != EOK)
+			return rc;
+
+		if (act_size <= alloc_size)
+			break;
+
+		alloc_size *= 2;
+		free(ids);
+
+		ids = malloc(alloc_size);
+		if (ids == NULL)
+			return ENOMEM;
+	}
+
+	*count = act_size / sizeof(category_id_t);
+	*data = ids;
+	return EOK;
+}
+
+/** Get list of services in category.
+ *
+ * Returns an allocated array of service IDs.
+ *
+ * @param cat_id	Category ID
+ * @param data		Place to store pointer to array of IDs
+ * @param count		Place to store number of IDs
+ * @return 		EOK on success or negative error code
+ */
+int loc_category_get_svcs(category_id_t cat_id, service_id_t **data,
+    size_t *count)
+{
+	return loc_get_ids_internal(LOC_CATEGORY_GET_SVCS, cat_id,
+	    data, count);
+}
+
+/** Get list of categories.
+ *
+ * Returns an allocated array of category IDs.
+ *
+ * @param data		Place to store pointer to array of IDs
+ * @param count		Place to store number of IDs
+ * @return 		EOK on success or negative error code
+ */
+int loc_get_categories(category_id_t **data, size_t *count)
+{
+	return loc_get_ids_internal(LOC_GET_CATEGORIES, 0,
+	    data, count);
+}
+
+int loc_register_cat_change_cb(loc_cat_change_cb_t cb_fun)
+{
+	if (loc_callback_create() != EOK)
+		return EIO;
+
+	cat_change_cb = cb_fun;
+	return EOK;
+}
Index: uspace/lib/c/generic/ns.c
===================================================================
--- uspace/lib/c/generic/ns.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/ns.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -56,4 +56,11 @@
 	async_exchange_end(exch);
 	
+	/*
+	 * FIXME Ugly hack to work around limitation of implementing
+	 * parallel exchanges using multiple connections. Shift out
+	 * first argument for non-initial connections.
+	 */
+	async_sess_args_set(sess, arg2, arg3, 0);
+	
 	return sess;
 }
@@ -66,4 +73,11 @@
 	    async_connect_me_to_blocking(mgmt, exch, service, arg2, arg3);
 	async_exchange_end(exch);
+	
+	/*
+	 * FIXME Ugly hack to work around limitation of implementing
+	 * parallel exchanges using multiple connections. Shift out
+	 * first argument for non-initial connections.
+	 */
+	async_sess_args_set(sess, arg2, arg3, 0);
 	
 	return sess;
Index: uspace/lib/c/generic/ns_obsolete.c
===================================================================
--- uspace/lib/c/generic/ns_obsolete.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/ns_obsolete.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,5 +36,5 @@
 #include <async_obsolete.h>
 #include <ns_obsolete.h>
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 
 int service_obsolete_connect(sysarg_t service, sysarg_t arg2, sysarg_t arg3)
Index: uspace/lib/c/generic/private/async.h
===================================================================
--- uspace/lib/c/generic/private/async.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/private/async.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,8 +36,58 @@
 #define LIBC_PRIVATE_ASYNC_H_
 
+#include <async.h>
 #include <adt/list.h>
 #include <fibril.h>
+#include <fibril_synch.h>
 #include <sys/time.h>
 #include <bool.h>
+
+/** Session data */
+struct _async_sess {
+	/** List of inactive exchanges */
+	list_t exch_list;
+	
+	/** Exchange management style */
+	exch_mgmt_t mgmt;
+	
+	/** Session identification */
+	int phone;
+	
+	/** First clone connection argument */
+	sysarg_t arg1;
+	
+	/** Second clone connection argument */
+	sysarg_t arg2;
+	
+	/** Third clone connection argument */
+	sysarg_t arg3;
+	
+	/** Exchange mutex */
+	fibril_mutex_t mutex;
+	
+	/** Number of opened exchanges */
+	atomic_t refcnt;
+	
+	/** Mutex for stateful connections */
+	fibril_mutex_t remote_state_mtx;
+	
+	/** Data for stateful connections */
+	void *remote_state_data;
+};
+
+/** Exchange data */
+struct _async_exch {
+	/** Link into list of inactive exchanges */
+	link_t sess_link;
+	
+	/** Link into global list of inactive exchanges */
+	link_t global_link;
+	
+	/** Session pointer */
+	async_sess_t *sess;
+	
+	/** Exchange identification */
+	int phone;
+};
 
 /** Structures of this type are used to track the timeout events. */
Index: uspace/lib/c/generic/private/io.h
===================================================================
--- uspace/lib/c/generic/private/io.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/private/io.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,7 +36,5 @@
 #define LIBC_PRIVATE_IO_H_
 
-#include <vfs/vfs.h>
-
-extern void __stdio_init(int filc, fdi_node_t *filv[]);
+extern void __stdio_init(int);
 extern void __stdio_done(void);
 
Index: uspace/lib/c/generic/private/thread.h
===================================================================
--- uspace/lib/c/generic/private/thread.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/private/thread.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,5 +36,5 @@
 #define LIBC_PRIVATE_THREAD_H_
 
-#include <kernel/proc/uarg.h>
+#include <abi/proc/uarg.h>
 
 extern void __thread_entry(void);
Index: pace/lib/c/generic/rtld/elf_load.c
===================================================================
--- uspace/lib/c/generic/rtld/elf_load.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,1 +1,0 @@
-../../../../srv/loader/elf_load.c
Index: uspace/lib/c/generic/rtld/module.c
===================================================================
--- uspace/lib/c/generic/rtld/module.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/rtld/module.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -35,10 +35,11 @@
  */
 
+#include <adt/list.h>
+#include <elf/elf_load.h>
+#include <fcntl.h>
+#include <loader/pcb.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <fcntl.h>
-#include <adt/list.h>
-#include <loader/pcb.h>
 
 #include <rtld/rtld.h>
@@ -47,5 +48,4 @@
 #include <rtld/rtld_arch.h>
 #include <rtld/module.h>
-#include <elf_load.h>
 
 /** (Eagerly) process all relocation tables in a module.
@@ -93,7 +93,4 @@
 module_t *module_find(const char *name)
 {
-	link_t *head = &runtime_env->modules_head;
-
-	link_t *cur;
 	module_t *m;
 	const char *p, *soname;
@@ -110,6 +107,5 @@
 
 	/* Traverse list of all modules. Not extremely fast, but simple */
-	DPRINTF("head = %p\n", head);
-	for (cur = head->next; cur != head; cur = cur->next) {
+	list_foreach(runtime_env->modules, cur) {
 		DPRINTF("cur = %p\n", cur);
 		m = list_get_instance(cur, module_t, modules_link);
@@ -177,5 +173,5 @@
 
 	/* Insert into the list of loaded modules */
-	list_append(&m->modules_link, &runtime_env->modules_head);
+	list_append(&m->modules_link, &runtime_env->modules);
 
 	return m;
@@ -249,10 +245,7 @@
 void modules_process_relocs(module_t *start)
 {
-	link_t *head = &runtime_env->modules_head;
-
-	link_t *cur;
-	module_t *m;
-
-	for (cur = head->next; cur != head; cur = cur->next) {
+	module_t *m;
+
+	list_foreach(runtime_env->modules, cur) {
 		m = list_get_instance(cur, module_t, modules_link);
 
@@ -268,10 +261,7 @@
 void modules_untag(void)
 {
-	link_t *head = &runtime_env->modules_head;
-
-	link_t *cur;
-	module_t *m;
-
-	for (cur = head->next; cur != head; cur = cur->next) {
+	module_t *m;
+
+	list_foreach(runtime_env->modules, cur) {
 		m = list_get_instance(cur, module_t, modules_link);
 		m->bfs_tag = false;
Index: uspace/lib/c/generic/rtld/rtld.c
===================================================================
--- uspace/lib/c/generic/rtld/rtld.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/rtld/rtld.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -44,5 +44,5 @@
 {
 	runtime_env = &rt_env_static;
-	list_initialize(&runtime_env->modules_head);
+	list_initialize(&runtime_env->modules);
 	runtime_env->next_bias = 0x2000000;
 	runtime_env->program = NULL;
Index: uspace/lib/c/generic/rtld/symbol.c
===================================================================
--- uspace/lib/c/generic/rtld/symbol.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/rtld/symbol.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,8 +38,8 @@
 #include <stdlib.h>
 
+#include <elf/elf.h>
 #include <rtld/rtld.h>
 #include <rtld/rtld_debug.h>
 #include <rtld/symbol.h>
-#include <elf.h>
 
 /*
@@ -118,5 +118,5 @@
 	module_t *m, *dm;
 	elf_symbol_t *sym, *s;
-	link_t queue_head;
+	list_t queue;
 	size_t i;
 
@@ -132,7 +132,7 @@
 
 	/* Insert root (the program) into the queue and tag it */
-	list_initialize(&queue_head);
+	list_initialize(&queue);
 	start->bfs_tag = true;
-	list_append(&start->queue_link, &queue_head);
+	list_append(&start->queue_link, &queue);
 
 	/* If the symbol is found, it will be stored in 'sym' */
@@ -140,7 +140,7 @@
 
 	/* While queue is not empty */
-	while (!list_empty(&queue_head)) {
+	while (!list_empty(&queue)) {
 		/* Pop first element from the queue */
-		m = list_get_instance(queue_head.next, module_t, queue_link);
+		m = list_get_instance(list_first(&queue), module_t, queue_link);
 		list_remove(&m->queue_link);
 
@@ -162,5 +162,5 @@
 			if (dm->bfs_tag == false) {
 				dm->bfs_tag = true;
-				list_append(&dm->queue_link, &queue_head);
+				list_append(&dm->queue_link, &queue);
 			}
 		}
@@ -168,6 +168,6 @@
 
 	/* Empty the queue so that we leave it in a clean state */
-	while (!list_empty(&queue_head))
-		list_remove(queue_head.next);
+	while (!list_empty(&queue))
+		list_remove(list_first(&queue));
 
 	if (!sym) {
Index: uspace/lib/c/generic/str.c
===================================================================
--- uspace/lib/c/generic/str.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/str.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -2,4 +2,5 @@
  * Copyright (c) 2005 Martin Decky
  * Copyright (c) 2008 Jiri Svoboda
+ * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
  *
@@ -718,4 +719,22 @@
 
 	dest[dlen - 1] = '\0';
+}
+
+/** Convert string to wide string.
+ *
+ * Convert string @a src to wide string. A new wide NULL-terminated
+ * string will be allocated on the heap.
+ *
+ * @param src	Source string.
+ */
+wchar_t *str_to_awstr(const char *str)
+{
+	size_t len = str_length(str);
+        wchar_t *wstr = calloc(len+1, sizeof(wchar_t));
+        if (wstr == NULL) {
+                return NULL;
+        }
+        str_to_wstr(wstr, len+1, str);
+	return wstr;
 }
 
Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/task.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -46,4 +46,5 @@
 #include <libc.h>
 #include "private/ns.h"
+#include <vfs/vfs.h>
 
 task_id_t task_get_id(void)
@@ -102,21 +103,21 @@
 {
 	/* Send default files */
-	fdi_node_t *files[4];
-	fdi_node_t stdin_node;
-	fdi_node_t stdout_node;
-	fdi_node_t stderr_node;
-	
-	if ((stdin != NULL) && (fnode(stdin, &stdin_node) == EOK))
-		files[0] = &stdin_node;
+	int *files[4];
+	int fd_stdin;
+	int fd_stdout;
+	int fd_stderr;
+	
+	if ((stdin != NULL) && (fhandle(stdin, &fd_stdin) == EOK))
+		files[0] = &fd_stdin;
 	else
 		files[0] = NULL;
 	
-	if ((stdout != NULL) && (fnode(stdout, &stdout_node) == EOK))
-		files[1] = &stdout_node;
+	if ((stdout != NULL) && (fhandle(stdout, &fd_stdout) == EOK))
+		files[1] = &fd_stdout;
 	else
 		files[1] = NULL;
 	
-	if ((stderr != NULL) && (fnode(stderr, &stderr_node) == EOK))
-		files[2] = &stderr_node;
+	if ((stderr != NULL) && (fhandle(stderr, &fd_stderr) == EOK))
+		files[2] = &fd_stderr;
 	else
 		files[2] = NULL;
@@ -142,5 +143,5 @@
  */
 int task_spawnvf(task_id_t *id, const char *path, const char *const args[],
-    fdi_node_t *const files[])
+    int *const files[])
 {
 	/* Connect to a program loader. */
Index: uspace/lib/c/generic/thread.c
===================================================================
--- uspace/lib/c/generic/thread.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/thread.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,5 +37,5 @@
 #include <stdlib.h>
 #include <libarch/faddr.h>
-#include <kernel/proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <fibril.h>
 #include <str.h>
Index: uspace/lib/c/generic/time.c
===================================================================
--- uspace/lib/c/generic/time.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/time.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,5 +36,5 @@
 #include <time.h>
 #include <bool.h>
-#include <arch/barrier.h>
+#include <libarch/barrier.h>
 #include <macros.h>
 #include <errno.h>
Index: uspace/lib/c/generic/udebug.c
===================================================================
--- uspace/lib/c/generic/udebug.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/udebug.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -35,5 +35,5 @@
 #include <udebug.h>
 #include <sys/types.h>
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 #include <async.h>
 
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -51,7 +51,7 @@
 #include <assert.h>
 #include <str.h>
-#include <devmap.h>
+#include <loc.h>
 #include <ipc/vfs.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 
 static FIBRIL_MUTEX_INITIALIZE(vfs_mutex);
@@ -69,5 +69,5 @@
  *
  */
-static async_exch_t *vfs_exchange_begin(void)
+async_exch_t *vfs_exchange_begin(void)
 {
 	fibril_mutex_lock(&vfs_mutex);
@@ -87,5 +87,5 @@
  *
  */
-static void vfs_exchange_end(async_exch_t *exch)
+void vfs_exchange_end(async_exch_t *exch)
 {
 	async_exchange_end(exch);
@@ -142,27 +142,27 @@
 }
 
-int mount(const char *fs_name, const char *mp, const char *fqdn,
+int mount(const char *fs_name, const char *mp, const char *fqsn,
     const char *opts, unsigned int flags)
 {
 	int null_id = -1;
-	char null[DEVMAP_NAME_MAXLEN];
-	
-	if (str_cmp(fqdn, "") == 0) {
+	char null[LOC_NAME_MAXLEN];
+	
+	if (str_cmp(fqsn, "") == 0) {
 		/* No device specified, create a fresh
 		   null/%d device instead */
-		null_id = devmap_null_create();
+		null_id = loc_null_create();
 		
 		if (null_id == -1)
 			return ENOMEM;
 		
-		snprintf(null, DEVMAP_NAME_MAXLEN, "null/%d", null_id);
-		fqdn = null;
-	}
-	
-	devmap_handle_t devmap_handle;
-	int res = devmap_device_get_handle(fqdn, &devmap_handle, flags);
+		snprintf(null, LOC_NAME_MAXLEN, "null/%d", null_id);
+		fqsn = null;
+	}
+	
+	service_id_t service_id;
+	int res = loc_service_get_id(fqsn, &service_id, flags);
 	if (res != EOK) {
 		if (null_id != -1)
-			devmap_null_destroy(null_id);
+			loc_null_destroy(null_id);
 		
 		return res;
@@ -173,5 +173,5 @@
 	if (!mpa) {
 		if (null_id != -1)
-			devmap_null_destroy(null_id);
+			loc_null_destroy(null_id);
 		
 		return ENOMEM;
@@ -181,5 +181,5 @@
 
 	sysarg_t rc_orig;
-	aid_t req = async_send_2(exch, VFS_IN_MOUNT, devmap_handle, flags, NULL);
+	aid_t req = async_send_2(exch, VFS_IN_MOUNT, service_id, flags, NULL);
 	sysarg_t rc = async_data_write_start(exch, (void *) mpa, mpa_size);
 	if (rc != EOK) {
@@ -189,5 +189,5 @@
 		
 		if (null_id != -1)
-			devmap_null_destroy(null_id);
+			loc_null_destroy(null_id);
 		
 		if (rc_orig == EOK)
@@ -204,5 +204,5 @@
 		
 		if (null_id != -1)
-			devmap_null_destroy(null_id);
+			loc_null_destroy(null_id);
 		
 		if (rc_orig == EOK)
@@ -219,5 +219,5 @@
 		
 		if (null_id != -1)
-			devmap_null_destroy(null_id);
+			loc_null_destroy(null_id);
 		
 		if (rc_orig == EOK)
@@ -235,5 +235,5 @@
 		
 		if (null_id != -1)
-			devmap_null_destroy(null_id);
+			loc_null_destroy(null_id);
 		
 		if (rc_orig == EOK)
@@ -248,5 +248,5 @@
 	
 	if ((rc != EOK) && (null_id != -1))
-		devmap_null_destroy(null_id);
+		loc_null_destroy(null_id);
 	
 	return (int) rc;
@@ -329,23 +329,4 @@
 }
 
-int open_node(fdi_node_t *node, int oflag)
-{
-	async_exch_t *exch = vfs_exchange_begin();
-	
-	ipc_call_t answer;
-	aid_t req = async_send_4(exch, VFS_IN_OPEN_NODE, node->fs_handle,
-	    node->devmap_handle, node->index, oflag, &answer);
-	
-	vfs_exchange_end(exch);
-
-	sysarg_t rc;
-	async_wait_for(req, &rc);
-	
-	if (rc != EOK)
-		return (int) rc;
-	
-	return (int) IPC_GET_ARG1(answer);
-}
-
 int close(int fildes)
 {
@@ -415,4 +396,66 @@
 	else
 		return -1;
+}
+
+/** Read entire buffer.
+ *
+ * In face of short reads this function continues reading until either
+ * the entire buffer is read or no more data is available (at end of file).
+ *
+ * @param fildes	File descriptor
+ * @param buf		Buffer, @a nbytes bytes long
+ * @param nbytes	Number of bytes to read
+ *
+ * @return		On success, positive number of bytes read.
+ *			On failure, negative error code from read().
+ */
+ssize_t read_all(int fildes, void *buf, size_t nbyte)
+{
+	ssize_t cnt = 0;
+	size_t nread = 0;
+	uint8_t *bp = (uint8_t *) buf;
+
+	do {
+		bp += cnt;
+		nread += cnt;
+		cnt = read(fildes, bp, nbyte - nread);
+	} while (cnt > 0 && (nbyte - nread - cnt) > 0);
+
+	if (cnt < 0)
+		return cnt;
+
+	return nread + cnt;
+}
+
+/** Write entire buffer.
+ *
+ * This function fails if it cannot write exactly @a len bytes to the file.
+ *
+ * @param fildes	File descriptor
+ * @param buf		Data, @a nbytes bytes long
+ * @param nbytes	Number of bytes to write
+ *
+ * @return		EOK on error, return value from write() if writing
+ *			failed.
+ */
+ssize_t write_all(int fildes, const void *buf, size_t nbyte)
+{
+	ssize_t cnt = 0;
+	ssize_t nwritten = 0;
+	const uint8_t *bp = (uint8_t *) buf;
+
+	do {
+		bp += cnt;
+		nwritten += cnt;
+		cnt = write(fildes, bp, nbyte - nwritten);
+	} while (cnt > 0 && ((ssize_t )nbyte - nwritten - cnt) > 0);
+
+	if (cnt < 0)
+		return cnt;
+
+	if ((ssize_t)nbyte - nwritten - cnt > 0)
+		return EIO;
+
+	return nbyte;
 }
 
@@ -749,24 +792,10 @@
 	}
 	
-	if (!stat.device) {
+	if (!stat.service) {
 		errno = ENOENT;
 		return NULL;
 	}
 	
-	return devmap_device_connect(mgmt, stat.device, 0);
-}
-
-int fd_node(int fildes, fdi_node_t *node)
-{
-	struct stat stat;
-	int rc = fstat(fildes, &stat);
-	
-	if (rc == EOK) {
-		node->fs_handle = stat.fs_handle;
-		node->devmap_handle = stat.devmap_handle;
-		node->index = stat.index;
-	}
-	
-	return rc;
+	return loc_service_connect(mgmt, stat.service, 0);
 }
 
@@ -786,4 +815,19 @@
 }
 
+int fd_wait(void)
+{
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	sysarg_t ret;
+	sysarg_t rc = async_req_0_1(exch, VFS_IN_WAIT_HANDLE, &ret);
+	
+	vfs_exchange_end(exch);
+	
+	if (rc == EOK)
+		return (int) ret;
+	
+	return (int) rc;
+}
+
 /** @}
  */
Index: uspace/lib/c/include/as.h
===================================================================
--- uspace/lib/c/include/as.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/as.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,6 +37,6 @@
 
 #include <sys/types.h>
+#include <abi/mm/as.h>
 #include <task.h>
-#include <kernel/mm/as.h>
 #include <libarch/config.h>
 
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/async.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,5 +42,4 @@
 #include <ipc/common.h>
 #include <fibril.h>
-#include <fibril_synch.h>
 #include <sys/time.h>
 #include <atomic.h>
@@ -96,45 +95,10 @@
 } exch_mgmt_t;
 
-/** Session data */
-typedef struct {
-	/** List of inactive exchanges */
-	list_t exch_list;
-	
-	/** Exchange management style */
-	exch_mgmt_t mgmt;
-	
-	/** Session identification */
-	int phone;
-	
-	/** First clone connection argument */
-	sysarg_t arg1;
-	
-	/** Second clone connection argument */
-	sysarg_t arg2;
-	
-	/** Third clone connection argument */
-	sysarg_t arg3;
-	
-	/** Exchange mutex */
-	fibril_mutex_t mutex;
-	
-	/** Number of opened exchanges */
-	atomic_t refcnt;
-} async_sess_t;
-
-/** Exchange data */
-typedef struct {
-	/** Link into list of inactive exchanges */
-	link_t sess_link;
-	
-	/** Link into global list of inactive exchanges */
-	link_t global_link;
-	
-	/** Session pointer */
-	async_sess_t *sess;
-	
-	/** Exchange identification */
-	int phone;
-} async_exch_t;
+/** Forward declarations */
+struct _async_exch;
+struct _async_sess;
+
+typedef struct _async_sess async_sess_t;
+typedef struct _async_exch async_exch_t;
 
 extern atomic_t threads_in_ipc_wait;
@@ -176,5 +140,5 @@
 extern int async_wait_timeout(aid_t, sysarg_t *, suseconds_t);
 
-extern fid_t async_new_connection(sysarg_t, sysarg_t, ipc_callid_t,
+extern fid_t async_new_connection(task_id_t, sysarg_t, ipc_callid_t,
     ipc_call_t *, async_client_conn_t, void *);
 
@@ -186,4 +150,6 @@
 extern void async_set_client_data_destructor(async_client_data_dtor_t);
 extern void *async_get_client_data(void);
+extern void *async_get_client_data_by_id(task_id_t);
+extern void async_put_client_data_by_id(task_id_t);
 
 extern void async_set_client_connection(async_client_conn_t);
@@ -371,4 +337,10 @@
 
 /*
+ * FIXME These functions just work around problems with parallel exchange
+ * management. Proper solution needs to be implemented.
+ */
+void async_sess_args_set(async_sess_t *sess, sysarg_t, sysarg_t, sysarg_t);
+
+/*
  * User-friendly wrappers for async_share_in_start().
  */
@@ -477,4 +449,15 @@
 extern async_sess_t *async_callback_receive_start(exch_mgmt_t, ipc_call_t *);
 
+extern int async_state_change_start(async_exch_t *, sysarg_t, sysarg_t,
+    sysarg_t, async_exch_t *);
+extern bool async_state_change_receive(ipc_callid_t *, sysarg_t *, sysarg_t *,
+    sysarg_t *);
+extern int async_state_change_finalize(ipc_callid_t, async_exch_t *);
+
+extern void *async_remote_state_acquire(async_sess_t *);
+extern void async_remote_state_update(async_sess_t *, void *);
+extern void async_remote_state_release(async_sess_t *);
+extern void async_remote_state_release_exchange(async_exch_t *);
+
 #endif
 
Index: uspace/lib/c/include/ddi.h
===================================================================
--- uspace/lib/c/include/ddi.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/ddi.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,5 +37,5 @@
 
 #include <sys/types.h>
-#include <kernel/ddi/irq.h>
+#include <abi/ddi/irq.h>
 #include <task.h>
 
Index: uspace/lib/c/include/devman.h
===================================================================
--- uspace/lib/c/include/devman.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/devman.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,4 +38,5 @@
 
 #include <ipc/devman.h>
+#include <ipc/loc.h>
 #include <async.h>
 #include <bool.h>
@@ -48,4 +49,5 @@
 extern int devman_add_function(const char *, fun_type_t, match_id_list_t *,
     devman_handle_t, devman_handle_t *);
+extern int devman_remove_function(devman_handle_t);
 
 extern async_sess_t *devman_device_connect(exch_mgmt_t, devman_handle_t,
@@ -54,11 +56,14 @@
     unsigned int);
 
-extern int devman_device_get_handle(const char *, devman_handle_t *,
+extern int devman_fun_get_handle(const char *, devman_handle_t *,
     unsigned int);
-extern int devman_device_get_handle_by_class(const char *, const char *,
-    devman_handle_t *, unsigned int);
-extern int devman_get_device_path(devman_handle_t, char *, size_t);
+extern int devman_fun_get_child(devman_handle_t, devman_handle_t *);
+extern int devman_dev_get_functions(devman_handle_t, devman_handle_t **,
+    size_t *);
+extern int devman_fun_get_name(devman_handle_t, char *, size_t);
+extern int devman_fun_get_path(devman_handle_t, char *, size_t);
 
-extern int devman_add_device_to_class(devman_handle_t, const char *);
+extern int devman_add_device_to_category(devman_handle_t, const char *);
+extern int devman_fun_sid_to_handle(service_id_t, devman_handle_t *);
 
 #endif
Index: pace/lib/c/include/devmap.h
===================================================================
--- uspace/lib/c/include/devmap.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,72 +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 libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_DEVMAP_H_
-#define LIBC_DEVMAP_H_
-
-#include <ipc/devmap.h>
-#include <async.h>
-#include <bool.h>
-
-extern async_exch_t *devmap_exchange_begin_blocking(devmap_interface_t);
-extern async_exch_t *devmap_exchange_begin(devmap_interface_t);
-extern void devmap_exchange_end(async_exch_t *);
-
-extern int devmap_driver_register(const char *, async_client_conn_t);
-extern int devmap_device_register(const char *, devmap_handle_t *);
-extern int devmap_device_register_with_iface(const char *, devmap_handle_t *,
-    sysarg_t);
-
-extern int devmap_device_get_handle(const char *, devmap_handle_t *,
-    unsigned int);
-extern int devmap_namespace_get_handle(const char *, devmap_handle_t *,
-    unsigned int);
-extern devmap_handle_type_t devmap_handle_probe(devmap_handle_t);
-
-extern async_sess_t *devmap_device_connect(exch_mgmt_t, devmap_handle_t,
-    unsigned int);
-
-extern int devmap_null_create(void);
-extern void devmap_null_destroy(int);
-
-extern size_t devmap_count_namespaces(void);
-extern size_t devmap_count_devices(devmap_handle_t);
-
-extern size_t devmap_get_namespaces(dev_desc_t **);
-extern size_t devmap_get_devices(devmap_handle_t, dev_desc_t **);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/elf/elf.h
===================================================================
--- uspace/lib/c/include/elf/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/include/elf/elf.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,45 @@
+/*
+ * 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 generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_ELF_H_
+#define LIBC_ELF_H_
+
+#include <sys/types.h>
+#include <abi/elf.h>
+#include <libarch/elf.h>
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/elf/elf_linux.h
===================================================================
--- uspace/lib/c/include/elf/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/include/elf/elf_linux.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,72 @@
+/*
+ * 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 generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_ELF_LINUX_H_
+#define LIBC_ELF_LINUX_H_
+
+#include <elf/elf.h>
+#include <libarch/elf_linux.h>
+
+/*
+ * Note types
+ */
+#define NT_PRSTATUS	1
+
+typedef int pid_t;
+typedef struct {
+	long tv_sec;
+	long tv_usec;
+} linux_timeval_t;
+
+typedef struct {
+	int sig_info[3];
+	short cursig;
+	unsigned long sigpend;
+	unsigned long sighold;
+	pid_t pid;
+	pid_t ppid;
+	pid_t pgrp;
+	pid_t sid;
+	linux_timeval_t pr_utime;
+	linux_timeval_t pr_stime;
+	linux_timeval_t pr_cutime;
+	linux_timeval_t pr_sid;
+	elf_regs_t regs;
+	int fpvalid;
+} elf_prstatus_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/elf/elf_load.h
===================================================================
--- uspace/lib/c/include/elf/elf_load.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/include/elf/elf_load.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2006 Sergey Bondari
+ * 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 generic
+ * @{
+ */
+/** @file
+ * @brief ELF loader structures and public functions.
+ */
+
+#ifndef ELF_LOAD_H_
+#define ELF_LOAD_H_
+
+#include <elf/elf.h>
+#include <sys/types.h>
+#include <loader/pcb.h>
+
+/**
+ * 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
+
+typedef enum {
+	/** Leave all segments in RW access mode. */
+	ELDF_RW = 1
+} eld_flags_t;
+
+/**
+ * Some data extracted from the headers are stored here
+ */
+typedef struct {
+	/** Entry point */
+	entry_point_t entry;
+
+	/** ELF interpreter name or NULL if statically-linked */
+	const char *interp;
+
+	/** Pointer to the dynamic section */
+	void *dynamic;
+} elf_info_t;
+
+/**
+ * Holds information about an ELF binary being loaded.
+ */
+typedef struct {
+	/** Filedescriptor of the file from which we are loading */
+	int fd;
+
+	/** Difference between run-time addresses and link-time addresses */
+	uintptr_t bias;
+
+	/** Flags passed to the ELF loader. */
+	eld_flags_t flags;
+
+	/** A copy of the ELF file header */
+	elf_header_t *header;
+
+	/** Store extracted info here */
+	elf_info_t *info;
+} elf_ld_t;
+
+extern const char *elf_error(unsigned int);
+extern int elf_load_file(const char *, size_t, eld_flags_t, elf_info_t *);
+extern void elf_create_pcb(elf_info_t *, pcb_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/errno.h
===================================================================
--- uspace/lib/c/include/errno.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/errno.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,5 +36,5 @@
 #define LIBC_ERRNO_H_
 
-#include <kernel/errno.h>
+#include <abi/errno.h>
 #include <fibril.h>
 
Index: uspace/lib/c/include/event.h
===================================================================
--- uspace/lib/c/include/event.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/event.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,8 +36,11 @@
 #define LIBC_EVENT_H_
 
-#include <kernel/ipc/event_types.h>
+#include <abi/ipc/event.h>
+#include <libarch/types.h>
 
 extern int event_subscribe(event_type_t, sysarg_t);
+extern int event_task_subscribe(event_task_type_t, sysarg_t);
 extern int event_unmask(event_type_t);
+extern int event_task_unmask(event_task_type_t);
 
 #endif
Index: uspace/lib/c/include/ipc/common.h
===================================================================
--- uspace/lib/c/include/ipc/common.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/ipc/common.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,6 +37,7 @@
 
 #include <sys/types.h>
+#include <abi/ipc/ipc.h>
 #include <atomic.h>
-#include <kernel/ipc/ipc.h>
+#include <task.h>
 
 #define IPC_FLAG_BLOCKING  0x01
@@ -44,5 +45,5 @@
 typedef struct {
 	sysarg_t args[IPC_CALL_LEN];
-	sysarg_t in_task_hash;
+	task_id_t in_task_id;
 	sysarg_t in_phone_hash;
 } ipc_call_t;
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/ipc/devman.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -130,5 +130,5 @@
 	DEVMAN_CLIENT,
 	DEVMAN_CONNECT_TO_DEVICE,
-	DEVMAN_CONNECT_FROM_DEVMAP,
+	DEVMAN_CONNECT_FROM_LOC,
 	DEVMAN_CONNECT_TO_PARENTS_DEVICE
 } devman_interface_t;
@@ -138,6 +138,6 @@
 	DEVMAN_ADD_FUNCTION,
 	DEVMAN_ADD_MATCH_ID,
-	DEVMAN_ADD_DEVICE_TO_CLASS
-
+	DEVMAN_ADD_DEVICE_TO_CATEGORY,
+	DEVMAN_REMOVE_FUNCTION
 } driver_to_devman_t;
 
@@ -149,6 +149,9 @@
 typedef enum {
 	DEVMAN_DEVICE_GET_HANDLE = IPC_FIRST_USER_METHOD,
-	DEVMAN_DEVICE_GET_HANDLE_BY_CLASS,
-	DEVMAN_DEVICE_GET_DEVICE_PATH
+	DEVMAN_DEV_GET_FUNCTIONS,
+	DEVMAN_FUN_GET_CHILD,
+	DEVMAN_FUN_GET_NAME,
+	DEVMAN_FUN_GET_PATH,
+	DEVMAN_FUN_SID_TO_HANDLE
 } client_to_devman_t;
 
Index: pace/lib/c/include/ipc/devmap.h
===================================================================
--- uspace/lib/c/include/ipc/devmap.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,85 +1,0 @@
-/*
- * Copyright (c) 2007 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 devmap
- * @{
- */
-
-#ifndef LIBC_IPC_DEVMAP_H_
-#define LIBC_IPC_DEVMAP_H_
-
-#include <ipc/common.h>
-
-#define DEVMAP_NAME_MAXLEN  255
-
-typedef sysarg_t devmap_handle_t;
-
-typedef enum {
-	DEV_HANDLE_NONE,
-	DEV_HANDLE_NAMESPACE,
-	DEV_HANDLE_DEVICE
-} devmap_handle_type_t;
-
-typedef enum {
-	DEVMAP_DRIVER_REGISTER = IPC_FIRST_USER_METHOD,
-	DEVMAP_DRIVER_UNREGISTER,
-	DEVMAP_DEVICE_REGISTER,
-	DEVMAP_DEVICE_UNREGISTER,
-	DEVMAP_DEVICE_GET_HANDLE,
-	DEVMAP_NAMESPACE_GET_HANDLE,
-	DEVMAP_HANDLE_PROBE,
-	DEVMAP_NULL_CREATE,
-	DEVMAP_NULL_DESTROY,
-	DEVMAP_GET_NAMESPACE_COUNT,
-	DEVMAP_GET_DEVICE_COUNT,
-	DEVMAP_GET_NAMESPACES,
-	DEVMAP_GET_DEVICES
-} devmap_request_t;
-
-/** Interface provided by devmap.
- *
- * Every process that connects to devmap must ask one of following
- * interfaces otherwise connection will be refused.
- *
- */
-typedef enum {
-	/** Connect as device driver */
-	DEVMAP_DRIVER = 1,
-	/** Connect as client */
-	DEVMAP_CLIENT,
-	/** Create new connection to instance of device that
-	    is specified by second argument of call. */
-	DEVMAP_CONNECT_TO_DEVICE
-} devmap_interface_t;
-
-typedef struct {
-	devmap_handle_t handle;
-	char name[DEVMAP_NAME_MAXLEN + 1];
-} dev_desc_t;
-
-#endif
Index: uspace/lib/c/include/ipc/fb.h
===================================================================
--- uspace/lib/c/include/ipc/fb.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/ipc/fb.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -55,14 +55,14 @@
 	FB_DRAW_TEXT_DATA,
 	FB_FLUSH,
-	FB_DRAW_PPM,
+	FB_DRAW_IMGMAP,
 	FB_PREPARE_SHM,
 	FB_DROP_SHM,
-	FB_SHM2PIXMAP,
-	FB_VP_DRAW_PIXMAP,
-	FB_VP2PIXMAP,
-	FB_DROP_PIXMAP,
+	FB_SHM2IMGMAP,
+	FB_VP_DRAW_IMGMAP,
+	FB_VP2IMGMAP,
+	FB_DROP_IMGMAP,
 	FB_ANIM_CREATE,
 	FB_ANIM_DROP,
-	FB_ANIM_ADDPIXMAP,
+	FB_ANIM_ADDIMGMAP,
 	FB_ANIM_CHGVP,
 	FB_ANIM_START,
Index: uspace/lib/c/include/ipc/ipc.h
===================================================================
--- uspace/lib/c/include/ipc/ipc.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/ipc/ipc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,6 +42,6 @@
 #include <sys/types.h>
 #include <ipc/common.h>
-#include <kernel/ipc/ipc_methods.h>
-#include <kernel/synch/synch.h>
+#include <abi/ipc/methods.h>
+#include <abi/synch.h>
 #include <task.h>
 
@@ -254,5 +254,5 @@
     sysarg_t, sysarg_t, void *, ipc_async_callback_t, bool);
 
-extern int ipc_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t *,
+extern int ipc_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t, task_id_t *,
     sysarg_t *);
 extern int ipc_connect_me(int);
Index: uspace/lib/c/include/ipc/loc.h
===================================================================
--- uspace/lib/c/include/ipc/loc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/include/ipc/loc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2007 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 loc
+ * @{
+ */
+
+#ifndef LIBC_IPC_LOC_H_
+#define LIBC_IPC_LOC_H_
+
+#include <ipc/common.h>
+
+#define LOC_NAME_MAXLEN  255
+
+typedef sysarg_t service_id_t;
+typedef sysarg_t category_id_t;
+
+typedef enum {
+	LOC_OBJECT_NONE,
+	LOC_OBJECT_NAMESPACE,
+	LOC_OBJECT_SERVICE
+} loc_object_type_t;
+
+typedef enum {
+	LOC_SERVER_REGISTER = IPC_FIRST_USER_METHOD,
+	LOC_SERVER_UNREGISTER,
+	LOC_SERVICE_ADD_TO_CAT,
+	LOC_SERVICE_REGISTER,
+	LOC_SERVICE_UNREGISTER,
+	LOC_SERVICE_GET_ID,
+	LOC_SERVICE_GET_NAME,
+	LOC_NAMESPACE_GET_ID,
+	LOC_CALLBACK_CREATE,
+	LOC_CATEGORY_GET_ID,
+	LOC_CATEGORY_GET_NAME,
+	LOC_CATEGORY_GET_SVCS,
+	LOC_ID_PROBE,
+	LOC_NULL_CREATE,
+	LOC_NULL_DESTROY,
+	LOC_GET_NAMESPACE_COUNT,
+	LOC_GET_SERVICE_COUNT,
+	LOC_GET_CATEGORIES,
+	LOC_GET_NAMESPACES,
+	LOC_GET_SERVICES
+} loc_request_t;
+
+typedef enum {
+	LOC_EVENT_CAT_CHANGE = IPC_FIRST_USER_METHOD
+} loc_event_t;
+
+/** Ports provided by location service.
+ *
+ * Every process that connects to loc must ask one of following
+ * ports, otherwise connection will be refused.
+ *
+ */
+typedef enum {
+	/** Service supplier (server) port */
+	LOC_PORT_SUPPLIER = 1,
+	/** Service consumer (client) port */
+	LOC_PORT_CONSUMER,
+	/** Create new connection to instance of device that
+	    is specified by second argument of call. */
+	LOC_CONNECT_TO_SERVICE
+} loc_interface_t;
+
+typedef struct {
+	service_id_t id;
+	char name[LOC_NAME_MAXLEN + 1];
+} loc_sdesc_t;
+
+#endif
Index: uspace/lib/c/include/ipc/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/ipc/services.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -45,5 +45,5 @@
 	SERVICE_VIDEO      = FOURCC('v', 'i', 'd', ' '),
 	SERVICE_VFS        = FOURCC('v', 'f', 's', ' '),
-	SERVICE_DEVMAP     = FOURCC('d', 'e', 'v', 'p'),
+	SERVICE_LOC        = FOURCC('l', 'o', 'c', ' '),
 	SERVICE_DEVMAN     = FOURCC('d', 'e', 'v', 'n'),
 	SERVICE_IRC        = FOURCC('i', 'r', 'c', ' '),
Index: uspace/lib/c/include/ipc/vfs.h
===================================================================
--- uspace/lib/c/include/ipc/vfs.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/ipc/vfs.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -62,5 +62,4 @@
 typedef enum {
 	VFS_IN_OPEN = IPC_FIRST_USER_METHOD,
-	VFS_IN_OPEN_NODE,
 	VFS_IN_READ,
 	VFS_IN_WRITE,
@@ -78,5 +77,6 @@
 	VFS_IN_RENAME,
 	VFS_IN_STAT,
-	VFS_IN_DUP
+	VFS_IN_DUP,
+	VFS_IN_WAIT_HANDLE,
 } vfs_in_request_t;
 
Index: uspace/lib/c/include/libc.h
===================================================================
--- uspace/lib/c/include/libc.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/libc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,5 +37,5 @@
 
 #include <sys/types.h>
-#include <kernel/syscall/syscall.h>
+#include <abi/syscall.h>
 #include <libarch/syscall.h>
 
Index: uspace/lib/c/include/loader/loader.h
===================================================================
--- uspace/lib/c/include/loader/loader.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/loader/loader.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,4 @@
 
 #include <task.h>
-#include <vfs/vfs.h>
 
 /** Forward declararion */
@@ -50,5 +49,5 @@
 extern int loader_set_pathname(loader_t *, const char *);
 extern int loader_set_args(loader_t *, const char *const[]);
-extern int loader_set_files(loader_t *, fdi_node_t *const[]);
+extern int loader_set_files(loader_t *, int *const[]);
 extern int loader_load_program(loader_t *);
 extern int loader_run(loader_t *);
Index: uspace/lib/c/include/loader/pcb.h
===================================================================
--- uspace/lib/c/include/loader/pcb.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/loader/pcb.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,4 @@
 
 #include <sys/types.h>
-#include <vfs/vfs.h>
 
 typedef void (*entry_point_t)(void);
@@ -62,7 +61,5 @@
 	
 	/** Number of preset files. */
-	int filc;
-	/** Preset files. */
-	fdi_node_t **filv;
+	unsigned int filc;
 	
 	/*
Index: uspace/lib/c/include/loc.h
===================================================================
--- uspace/lib/c/include/loc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/c/include/loc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_LOC_H_
+#define LIBC_LOC_H_
+
+#include <ipc/loc.h>
+#include <async.h>
+#include <bool.h>
+
+typedef void (*loc_cat_change_cb_t)(void);
+
+extern async_exch_t *loc_exchange_begin_blocking(loc_interface_t);
+extern async_exch_t *loc_exchange_begin(loc_interface_t);
+extern void loc_exchange_end(async_exch_t *);
+
+extern int loc_server_register(const char *, async_client_conn_t);
+extern int loc_service_register(const char *, service_id_t *);
+extern int loc_service_register_with_iface(const char *, service_id_t *,
+    sysarg_t);
+extern int loc_service_unregister(service_id_t);
+extern int loc_service_add_to_cat(service_id_t, category_id_t);
+
+extern int loc_service_get_id(const char *, service_id_t *,
+    unsigned int);
+extern int loc_service_get_name(service_id_t, char **);
+extern int loc_namespace_get_id(const char *, service_id_t *,
+    unsigned int);
+extern int loc_category_get_id(const char *, category_id_t *,
+    unsigned int);
+extern int loc_category_get_name(category_id_t, char **);
+extern int loc_category_get_svcs(category_id_t, category_id_t **, size_t *);
+extern loc_object_type_t loc_id_probe(service_id_t);
+
+extern async_sess_t *loc_service_connect(exch_mgmt_t, service_id_t,
+    unsigned int);
+
+extern int loc_null_create(void);
+extern void loc_null_destroy(int);
+
+extern size_t loc_count_namespaces(void);
+extern size_t loc_count_services(service_id_t);
+
+extern size_t loc_get_namespaces(loc_sdesc_t **);
+extern size_t loc_get_services(service_id_t, loc_sdesc_t **);
+extern int loc_get_categories(category_id_t **, size_t *);
+extern int loc_register_cat_change_cb(loc_cat_change_cb_t);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/rtld/elf_dyn.h
===================================================================
--- uspace/lib/c/include/rtld/elf_dyn.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/rtld/elf_dyn.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,8 +36,6 @@
 #define LIBC_RTLD_ELF_DYN_H_
 
-#include <arch/elf.h>
 #include <sys/types.h>
-
-#include <elf.h>
+#include <elf/elf.h>
 #include <libarch/rtld/elf_dyn.h>
 
Index: uspace/lib/c/include/rtld/rtld.h
===================================================================
--- uspace/lib/c/include/rtld/rtld.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/rtld/rtld.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -49,5 +49,5 @@
 
 	/** List of all loaded modules including rtld and the program */
-	link_t modules_head;
+	list_t modules;
 
 	/** Temporary hack to place each module at different address. */
Index: uspace/lib/c/include/rtld/symbol.h
===================================================================
--- uspace/lib/c/include/rtld/symbol.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/rtld/symbol.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,6 +36,6 @@
 #define LIBC_RTLD_SYMBOL_H_
 
+#include <elf/elf.h>
 #include <rtld/rtld.h>
-#include <elf.h>
 
 elf_symbol_t *symbol_bfs_find(const char *name, module_t *start, module_t **mod);
Index: uspace/lib/c/include/stats.h
===================================================================
--- uspace/lib/c/include/stats.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/stats.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -40,5 +40,6 @@
 #include <stdint.h>
 #include <bool.h>
-#include <kernel/sysinfo/abi.h>
+#include <sys/types.h>
+#include <abi/sysinfo.h>
 
 extern stats_cpu_t *stats_get_cpus(size_t *);
Index: uspace/lib/c/include/str.h
===================================================================
--- uspace/lib/c/include/str.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/str.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -83,4 +83,5 @@
 extern char *wstr_to_astr(const wchar_t *src);
 extern void str_to_wstr(wchar_t *dest, size_t dlen, const char *src);
+extern wchar_t *str_to_awstr(const char *src);
 
 extern char *str_chr(const char *str, wchar_t ch);
Index: uspace/lib/c/include/sys/stat.h
===================================================================
--- uspace/lib/c/include/sys/stat.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/sys/stat.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,9 +39,9 @@
 #include <bool.h>
 #include <ipc/vfs.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 
 struct stat {
 	fs_handle_t fs_handle;
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 	fs_index_t index;
 	unsigned int lnkcnt;
@@ -49,5 +49,5 @@
 	bool is_directory;
 	aoff64_t size;
-	devmap_handle_t device;
+	service_id_t service;
 };
 
Index: uspace/lib/c/include/syscall.h
===================================================================
--- uspace/lib/c/include/syscall.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/syscall.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -45,5 +45,5 @@
 
 #include <sys/types.h>
-#include <kernel/syscall/syscall.h>
+#include <abi/syscall.h>
 
 #define __syscall0  __syscall
Index: uspace/lib/c/include/task.h
===================================================================
--- uspace/lib/c/include/task.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/task.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,5 +37,4 @@
 
 #include <sys/types.h>
-#include <vfs/vfs.h>
 
 typedef uint64_t task_id_t;
@@ -53,5 +52,5 @@
 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 [],
-    fdi_node_t *const []);
+    int *const []);
 extern int task_spawnl(task_id_t *, const char *path, ...);
 
Index: uspace/lib/c/include/udebug.h
===================================================================
--- uspace/lib/c/include/udebug.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/udebug.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,5 +36,5 @@
 #define LIBC_UDEBUG_H_
 
-#include <kernel/udebug/udebug.h>
+#include <abi/udebug.h>
 #include <sys/types.h>
 #include <async.h>
Index: uspace/lib/c/include/unistd.h
===================================================================
--- uspace/lib/c/include/unistd.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/unistd.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -63,4 +63,7 @@
 extern ssize_t read(int, void *, size_t);
 
+extern ssize_t read_all(int, void *, size_t);
+extern ssize_t write_all(int, const void *, size_t);
+
 extern off64_t lseek(int, off64_t, int);
 extern int ftruncate(int, aoff64_t);
Index: uspace/lib/c/include/vfs/vfs.h
===================================================================
--- uspace/lib/c/include/vfs/vfs.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/c/include/vfs/vfs.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,18 +38,11 @@
 #include <sys/types.h>
 #include <ipc/vfs.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 #include <stdio.h>
+#include <async.h>
 
-/** Libc version of the VFS triplet.
- *
- * Unique identification of a file system node
- * within a file system instance.
- *
- */
-typedef struct {
-	fs_handle_t fs_handle;
-	devmap_handle_t devmap_handle;
-	fs_index_t index;
-} fdi_node_t;
+enum vfs_change_state_type {
+	VFS_PASS_HANDLE
+};
 
 extern char *absolutize(const char *, size_t *);
@@ -59,9 +52,10 @@
 extern int unmount(const char *);
 
-extern int open_node(fdi_node_t *, int);
-extern int fd_node(int, fdi_node_t *);
+extern int fhandle(FILE *, int *);
 
-extern FILE *fopen_node(fdi_node_t *, const char *);
-extern int fnode(FILE *, fdi_node_t *);
+extern int fd_wait(void);
+
+extern async_exch_t *vfs_exchange_begin(void);
+extern void vfs_exchange_end(async_exch_t *);
 
 #endif
Index: uspace/lib/clui/tinput.c
===================================================================
--- uspace/lib/clui/tinput.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/clui/tinput.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -27,4 +27,5 @@
  */
 
+#include <sort.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -42,4 +43,7 @@
 #include <tinput.h>
 
+#define LIN_TO_COL(ti, lpos) ((lpos) % ((ti)->con_cols))
+#define LIN_TO_ROW(ti, lpos) ((lpos) / ((ti)->con_cols))
+
 /** Seek direction */
 typedef enum {
@@ -61,4 +65,10 @@
 static void tinput_post_seek(tinput_t *, bool);
 
+static void tinput_console_set_lpos(tinput_t *ti, unsigned lpos)
+{
+	console_set_pos(ti->console, LIN_TO_COL(ti, lpos),
+	    LIN_TO_ROW(ti, lpos));
+}
+
 /** Create a new text input field. */
 tinput_t *tinput_new(void)
@@ -66,5 +76,5 @@
 	tinput_t *ti;
 	
-	ti = malloc(sizeof(tinput_t));
+	ti = calloc(1, sizeof(tinput_t));
 	if (ti == NULL)
 		return NULL;
@@ -77,5 +87,17 @@
 void tinput_destroy(tinput_t *ti)
 {
+	if (ti->prompt != NULL)
+		free(ti->prompt);
 	free(ti);
+}
+
+static void tinput_display_prompt(tinput_t *ti)
+{
+	tinput_console_set_lpos(ti, ti->prompt_coord);
+
+	console_set_style(ti->console, STYLE_EMPHASIS);
+	printf("%s", ti->prompt);
+	console_flush(ti->console);
+	console_set_style(ti->console, STYLE_NORMAL);
 }
 
@@ -88,6 +110,5 @@
 	tinput_sel_get_bounds(ti, &sa, &sb);
 	
-	console_set_pos(ti->console, (ti->col0 + start) % ti->con_cols,
-	    ti->row0 + (ti->col0 + start) / ti->con_cols);
+	tinput_console_set_lpos(ti, ti->text_coord + start);
 	console_set_style(ti->console, STYLE_NORMAL);
 	
@@ -134,17 +155,45 @@
 static void tinput_position_caret(tinput_t *ti)
 {
-	console_set_pos(ti->console, (ti->col0 + ti->pos) % ti->con_cols,
-	    ti->row0 + (ti->col0 + ti->pos) / ti->con_cols);
-}
-
-/** Update row0 in case the screen could have scrolled. */
+	tinput_console_set_lpos(ti, ti->text_coord + ti->pos);
+}
+
+/** Update text_coord, prompt_coord in case the screen could have scrolled. */
 static void tinput_update_origin(tinput_t *ti)
 {
-	sysarg_t width = ti->col0 + ti->nc;
-	sysarg_t rows = (width / ti->con_cols) + 1;
-	
-	/* Update row0 if the screen scrolled. */
-	if (ti->row0 + rows > ti->con_rows)
-		ti->row0 = ti->con_rows - rows;
+	unsigned end_coord = ti->text_coord + ti->nc;
+	unsigned end_row = LIN_TO_ROW(ti, end_coord);
+
+	unsigned scroll_rows;
+
+	/* Update coords if the screen scrolled. */
+	if (end_row >= ti->con_rows) {
+		scroll_rows = end_row - ti->con_rows + 1;
+		ti->text_coord -= ti->con_cols * scroll_rows;
+		ti->prompt_coord -= ti->con_cols * scroll_rows;
+	}
+}
+
+static void tinput_jump_after(tinput_t *ti)
+{
+	tinput_console_set_lpos(ti, ti->text_coord + ti->nc);
+	console_flush(ti->console);
+	putchar('\n');
+}
+
+static int tinput_display(tinput_t *ti)
+{
+	sysarg_t col0, row0;
+	
+	if (console_get_pos(ti->console, &col0, &row0) != EOK)
+		return EIO;
+	
+	ti->prompt_coord = row0 * ti->con_cols + col0;
+	ti->text_coord = ti->prompt_coord + str_length(ti->prompt);
+
+	tinput_display_prompt(ti);
+	tinput_display_tail(ti, 0, 0);
+	tinput_position_caret(ti);
+
+	return EOK;
 }
 
@@ -154,5 +203,5 @@
 		return;
 	
-	sysarg_t new_width = ti->col0 + ti->nc + 1;
+	unsigned new_width = LIN_TO_COL(ti, ti->text_coord) + ti->nc + 1;
 	if (new_width % ti->con_cols == 0) {
 		/* Advancing to new line. */
@@ -185,6 +234,6 @@
 		return;
 	
-	sysarg_t new_width = ti->col0 + ti->nc + ilen;
-	sysarg_t new_height = (new_width / ti->con_cols) + 1;
+	unsigned new_width = LIN_TO_COL(ti, ti->text_coord) + ti->nc + ilen;
+	unsigned new_height = (new_width / ti->con_cols) + 1;
 	if (new_height >= ti->con_rows) {
 		/* Disallow text longer than 1 page for now. */
@@ -511,4 +560,179 @@
 }
 
+/** Compare two entries in array of completions. */
+static int compl_cmp(void *va, void *vb, void *arg)
+{
+	const char *a = *(const char **) va;
+	const char *b = *(const char **) vb;
+
+	return str_cmp(a, b);
+}
+
+static size_t common_pref_len(const char *a, const char *b)
+{
+	size_t i;
+	size_t a_off, b_off;
+	wchar_t ca, cb;
+
+	i = 0;
+	a_off = 0;
+	b_off = 0;
+
+	while (true) {
+		ca = str_decode(a, &a_off, STR_NO_LIMIT);
+		cb = str_decode(b, &b_off, STR_NO_LIMIT);
+
+		if (ca == '\0' || cb == '\0' || ca != cb)
+			break;
+		++i;
+	}
+
+	return i;
+}
+
+/* Print a list of completions */
+static void tinput_show_completions(tinput_t *ti, char **compl, size_t cnum)
+{
+	unsigned int i;
+	/* Determine the maximum length of the completion in chars */
+	size_t max_length = 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;
+	unsigned int rows = cnum / cols + ((cnum % cols) != 0);
+	
+	unsigned int row, col;
+	
+	for (row = 0; row < rows; row++) {
+		bool wlc = false;
+		for (col = 0; col < cols; col++) {
+			size_t compl_idx = col * rows + row;
+			if (compl_idx >= cnum)
+				break;
+			if (col)
+				printf(" ");
+			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++) {
+					printf(" ");
+				}
+			}
+		}
+		if (!wlc) printf("\n");
+	}
+}
+
+
+static void tinput_text_complete(tinput_t *ti)
+{
+	void *state;
+	size_t cstart;
+	char *ctmp;
+	char **compl;     	/* Array of completions */
+	size_t compl_len;	/* Current length of @c compl array */
+	size_t cnum;
+	size_t i;
+	int rc;
+
+	if (ti->compl_ops == NULL)
+		return;
+
+	/*
+	 * Obtain list of all possible completions (growing array).
+	 */
+
+	rc = (*ti->compl_ops->init)(ti->buffer, ti->pos, &cstart, &state);
+	if (rc != EOK)
+		return;
+
+	cnum = 0;
+
+	compl_len = 1;
+	compl = malloc(compl_len * sizeof(char *));
+	if (compl == NULL) {
+		printf("Error: Out of memory.\n");
+		return;
+	}
+
+	while (true) {
+		rc = (*ti->compl_ops->get_next)(state, &ctmp);
+		if (rc != EOK)
+			break;
+
+		if (cnum >= compl_len) {
+			/* Extend array */
+			compl_len = 2 * compl_len;
+			compl = realloc(compl, compl_len * sizeof(char *));
+			if (compl == NULL) {
+				printf("Error: Out of memory.\n");
+				break;
+			}
+		}
+
+		compl[cnum] = str_dup(ctmp);
+		if (compl[cnum] == NULL) {
+			printf("Error: Out of memory.\n");
+			break;
+		}
+		cnum++;
+	}
+
+	(*ti->compl_ops->fini)(state);
+
+	if (cnum > 1) {
+		/*
+		 * More than one match. Determine maximum common prefix.
+		 */
+		size_t cplen;
+
+		cplen = str_length(compl[0]);
+		for (i = 1; i < cnum; i++)
+			cplen = min(cplen, common_pref_len(compl[0], compl[i]));
+
+		/* Compute how many bytes we should skip. */
+		size_t istart = str_lsize(compl[0], ti->pos - cstart);
+
+		if (cplen > istart) {
+			/* Insert common prefix. */
+
+			/* Copy remainder of common prefix. */
+			char *cpref = str_ndup(compl[0] + istart,
+			    str_lsize(compl[0], cplen - istart));
+
+			/* Insert it. */
+			tinput_insert_string(ti, cpref);
+			free(cpref);
+		} else {
+			/* No common prefix. Sort and display all entries. */
+
+			qsort(compl, cnum, sizeof(char *), compl_cmp, NULL);
+
+			tinput_jump_after(ti);
+			tinput_show_completions(ti, compl, cnum);
+			tinput_display(ti);
+		}
+	} else if (cnum == 1) {
+		/*
+		 * We have exactly one match. Insert it.
+		 */
+
+		/* Compute how many bytes of completion string we should skip. */
+		size_t istart = str_lsize(compl[0], ti->pos - cstart);
+
+		/* Insert remainder of completion string at current position. */
+		tinput_insert_string(ti, compl[0] + istart);
+	}
+
+	for (i = 0; i < cnum; i++)
+		free(compl[i]);
+	free(compl);
+}
+
 /** Initialize text input field.
  *
@@ -521,4 +745,33 @@
 	ti->hpos = 0;
 	ti->history[0] = NULL;
+}
+
+/** Set prompt string.
+ *
+ * @param ti		Text input
+ * @param prompt	Prompt string
+ *
+ * @return		EOK on success, ENOMEM if out of memory.
+ */
+int tinput_set_prompt(tinput_t *ti, const char *prompt)
+{
+	if (ti->prompt != NULL)
+		free(ti->prompt);
+	
+	ti->prompt = str_dup(prompt);
+	if (ti->prompt == NULL)
+		return ENOMEM;
+	
+	return EOK;
+}
+
+/** Set completion ops.
+ *
+ * Set pointer to completion ops structure that will be used for text
+ * completion.
+ */
+void tinput_set_compl_ops(tinput_t *ti, tinput_compl_ops_t *compl_ops)
+{
+	ti->compl_ops = compl_ops;
 }
 
@@ -539,7 +792,4 @@
 		return EIO;
 	
-	if (console_get_pos(ti->console, &ti->col0, &ti->row0) != EOK)
-		return EIO;
-	
 	ti->pos = 0;
 	ti->sel_start = 0;
@@ -549,4 +799,7 @@
 	ti->exit_clui = false;
 	
+	if (tinput_display(ti) != EOK)
+		return EIO;
+	
 	while (!ti->done) {
 		console_flush(ti->console);
@@ -714,4 +967,7 @@
 		tinput_history_seek(ti, -1);
 		break;
+	case KC_TAB:
+		tinput_text_complete(ti);
+		break;
 	default:
 		break;
Index: uspace/lib/clui/tinput.h
===================================================================
--- uspace/lib/clui/tinput.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/clui/tinput.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -37,11 +37,65 @@
 #define LIBCLUI_TINPUT_H_
 
-#include <stdio.h>
+#include <adt/list.h>
 #include <async.h>
 #include <inttypes.h>
 #include <io/console.h>
+#include <stdio.h>
 
 #define HISTORY_LEN     10
 #define INPUT_MAX_SIZE  1024
+
+/** Begin enumeration of text completions.
+ *
+ * When user requests text completion, tinput will call this function to start
+ * text completion operation. @a *cstart should be set to the position
+ * (character index) of the first character of the 'word' that is being
+ * completed. The resulting text is obtained by replacing the range of text
+ * starting at @a *cstart and ending at @a pos with the completion text.
+ *
+ * The function can pass information to the get_next and fini functions
+ * via @a state. The init function allocates the state object and stores
+ * a pointer to it to @a *state. The fini function destroys the state object.
+ *
+ * @param text		Current contents of edit buffer (null-terminated).
+ * @param pos		Current caret position.
+ * @param cstart	Output, position in text where completion begins from.
+ * @param state		Output, pointer to a client state object.
+ *
+ * @return		EOK on success, negative error code on failure.
+ */
+typedef int (*tinput_compl_init_fn)(wchar_t *text, size_t pos, size_t *cstart,
+    void **state);
+
+/** Obtain one text completion alternative.
+ *
+ * Upon success the function sets @a *compl to point to a string, the
+ * completion text. The caller (Tinput) should not modify or free the text.
+ * The pointer is only valid until the next invocation of any completion
+ * function.
+ *
+ * @param state		Pointer to state object created by the init funtion.
+ * @param compl		Output, the completion text, ownership retained.
+ *
+ * @return		EOK on success, negative error code on failure.
+ */
+typedef int (*tinput_compl_get_next_fn)(void *state, char **compl);
+
+
+/** Finish enumeration of text completions.
+ *
+ * The function must deallocate any state information allocated by the init
+ * function or temporary data allocated by the get_next function.
+ *
+ * @param state		Pointer to state object created by the init funtion.
+ */
+typedef void (*tinput_compl_fini_fn)(void *state);
+
+/** Text completion ops. */
+typedef struct {
+	tinput_compl_init_fn init;
+	tinput_compl_get_next_fn get_next;
+	tinput_compl_fini_fn fini;
+} tinput_compl_ops_t;
 
 /** Text input field (command line).
@@ -53,10 +107,17 @@
 	console_ctrl_t *console;
 	
+	/** Prompt string */
+	char *prompt;
+	
+	/** Completion ops. */
+	tinput_compl_ops_t *compl_ops;
+	
 	/** Buffer holding text currently being edited */
 	wchar_t buffer[INPUT_MAX_SIZE + 1];
 	
-	/** Screen coordinates of the top-left corner of the text field */
-	sysarg_t col0;
-	sysarg_t row0;
+	/** Linear position on screen where the prompt starts */
+	unsigned prompt_coord;
+	/** Linear position on screen where the text field starts */
+	unsigned text_coord;
 	
 	/** Screen dimensions */
@@ -90,4 +151,6 @@
 
 extern tinput_t *tinput_new(void);
+extern int tinput_set_prompt(tinput_t *, const char *);
+extern void tinput_set_compl_ops(tinput_t *, tinput_compl_ops_t *);
 extern void tinput_destroy(tinput_t *);
 extern int tinput_read(tinput_t *, char **);
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/drv/generic/driver.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -314,4 +314,10 @@
 		    " %" PRIun " was found.\n", driver->name, handle);
 		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	if (fun->conn_handler != NULL) {
+		/* Driver has a custom connection handler. */
+		(*fun->conn_handler)(iid, icall, (void *)fun);
 		return;
 	}
@@ -422,6 +428,16 @@
 static void driver_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
+	sysarg_t conn_type;
+
+	if (iid == 0) {
+		/* Callback connection from devman */
+		/* XXX Use separate handler for this type of connection */
+		conn_type = DRIVER_DEVMAN;
+	} else {
+		conn_type = IPC_GET_ARG1(*icall);
+	}
+
 	/* Select interface */
-	switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
+	switch (conn_type) {
 	case DRIVER_DEVMAN:
 		/* Handle request from device manager */
@@ -576,4 +592,5 @@
 int ddf_fun_bind(ddf_fun_t *fun)
 {
+	assert(fun->bound == false);
 	assert(fun->name != NULL);
 	
@@ -592,4 +609,29 @@
 }
 
+/** Unbind a function node.
+ *
+ * Unbind the specified function from the system. This effectively makes
+ * the function invisible to the system.
+ *
+ * @param fun		Function to bind
+ * @return		EOK on success or negative error code
+ */
+int ddf_fun_unbind(ddf_fun_t *fun)
+{
+	int res;
+	
+	assert(fun->bound == true);
+	
+	add_to_functions_list(fun);
+	res = devman_remove_function(fun->handle);
+	if (res != EOK)
+		return res;
+
+	remove_from_functions_list(fun);
+	
+	fun->bound = false;
+	return EOK;
+}
+
 /** Add single match ID to inner function.
  *
@@ -614,5 +656,5 @@
 		return ENOMEM;
 	
-	match_id->id = match_id_str;
+	match_id->id = str_dup(match_id_str);
 	match_id->score = 90;
 	
@@ -629,14 +671,14 @@
 }
 
-/** Add exposed function to class.
+/** Add exposed function to category.
  *
  * Must only be called when the function is bound.
  */
-int ddf_fun_add_to_class(ddf_fun_t *fun, const char *class_name)
+int ddf_fun_add_to_category(ddf_fun_t *fun, const char *cat_name)
 {
 	assert(fun->bound == true);
 	assert(fun->ftype == fun_exposed);
 	
-	return devman_add_device_to_class(fun->handle, class_name);
+	return devman_add_device_to_category(fun->handle, cat_name);
 }
 
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/drv/include/ddf/driver.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -118,4 +118,6 @@
 	/** 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 */
@@ -147,7 +149,8 @@
 extern void ddf_fun_destroy(ddf_fun_t *);
 extern int ddf_fun_bind(ddf_fun_t *);
+extern int ddf_fun_unbind(ddf_fun_t *);
 extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int);
 
-extern int ddf_fun_add_to_class(ddf_fun_t *, const char *);
+extern int ddf_fun_add_to_category(ddf_fun_t *, const char *);
 
 #endif
Index: uspace/lib/drv/include/ddf/interrupt.h
===================================================================
--- uspace/lib/drv/include/ddf/interrupt.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/drv/include/ddf/interrupt.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,5 +36,5 @@
 #define DDF_INTERRUPT_H_
 
-#include <kernel/ddi/irq.h>
+#include <abi/ddi/irq.h>
 #include <adt/list.h>
 #include <ddi.h>
Index: uspace/lib/ext2/libext2_filesystem.c
===================================================================
--- uspace/lib/ext2/libext2_filesystem.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/ext2/libext2_filesystem.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -50,9 +50,9 @@
  * 
  * @param fs			Pointer to ext2_filesystem_t to initialize
- * @param devmap_handle	Device handle of the block device
- * 
- * @return 		EOK on success or negative error code on failure
- */
-int ext2_filesystem_init(ext2_filesystem_t *fs, devmap_handle_t devmap_handle)
+ * @param service_id	Service ID of the block device
+ * 
+ * @return 		EOK on success or negative error code on failure
+ */
+int ext2_filesystem_init(ext2_filesystem_t *fs, service_id_t service_id)
 {
 	int rc;
@@ -60,5 +60,5 @@
 	size_t block_size;
 	
-	fs->device = devmap_handle;
+	fs->device = service_id;
 	
 	rc = block_init(EXCHANGE_SERIALIZE, fs->device, 2048);
@@ -80,5 +80,5 @@
 	}
 	
-	rc = block_cache_init(devmap_handle, block_size, 0, CACHE_MODE_WT);
+	rc = block_cache_init(service_id, block_size, 0, CACHE_MODE_WT);
 	if (rc != EOK) {
 		block_fini(fs->device);
Index: uspace/lib/ext2/libext2_filesystem.h
===================================================================
--- uspace/lib/ext2/libext2_filesystem.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/ext2/libext2_filesystem.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -43,5 +43,5 @@
 
 typedef struct ext2_filesystem {
-	devmap_handle_t		device;
+	service_id_t		device;
 	ext2_superblock_t *	superblock;
 } ext2_filesystem_t;
@@ -59,5 +59,5 @@
 #define EXT2_SUPPORTED_READ_ONLY_FEATURES 0
 
-extern int ext2_filesystem_init(ext2_filesystem_t *, devmap_handle_t);
+extern int ext2_filesystem_init(ext2_filesystem_t *, service_id_t);
 extern int ext2_filesystem_check_sanity(ext2_filesystem_t *);
 extern int ext2_filesystem_check_flags(ext2_filesystem_t *, bool *);
Index: uspace/lib/ext2/libext2_superblock.c
===================================================================
--- uspace/lib/ext2/libext2_superblock.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/ext2/libext2_superblock.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -321,10 +321,10 @@
 /** Read a superblock directly from device (i.e. no libblock cache)
  * 
- * @param devmap_handle	Device handle of the block device.
+ * @param service_id	Service ID of the block device.
  * @param superblock	Pointer where to store pointer to new superblock
  * 
  * @return		EOK on success or negative error code on failure.
  */
-int ext2_superblock_read_direct(devmap_handle_t devmap_handle,
+int ext2_superblock_read_direct(service_id_t service_id,
     ext2_superblock_t **superblock)
 {
@@ -337,5 +337,5 @@
 	}
 	
-	rc = block_read_bytes_direct(devmap_handle, EXT2_SUPERBLOCK_OFFSET,
+	rc = block_read_bytes_direct(service_id, EXT2_SUPERBLOCK_OFFSET,
 	    EXT2_SUPERBLOCK_SIZE, data);
 	if (rc != EOK) {
Index: uspace/lib/ext2/libext2_superblock.h
===================================================================
--- uspace/lib/ext2/libext2_superblock.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/ext2/libext2_superblock.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -110,5 +110,5 @@
 extern uint32_t	ext2_superblock_get_features_read_only(ext2_superblock_t *);
 
-extern int ext2_superblock_read_direct(devmap_handle_t, ext2_superblock_t **);
+extern int ext2_superblock_read_direct(service_id_t, ext2_superblock_t **);
 extern int ext2_superblock_check_sanity(ext2_superblock_t *);
 
Index: uspace/lib/fmtutil/Makefile
===================================================================
--- uspace/lib/fmtutil/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/fmtutil/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../..
+EXTRA_CFLAGS = -I.
+LIBRARY = libfmtutil
+
+SOURCES = \
+	fmtutil.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/fmtutil/fmtutil.c
===================================================================
--- uspace/lib/fmtutil/fmtutil.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/fmtutil/fmtutil.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,238 @@
+/*
+ * 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 <io/console.h>
+#include <errno.h>
+#include <malloc.h>
+#include <fmtutil.h>
+
+typedef struct {
+	align_mode_t alignment;
+	bool newline_always;
+	size_t width;
+} printmode_t;
+
+int print_wrapped_console(const char *str, align_mode_t alignment)
+{
+	console_ctrl_t *console = console_init(stdin, stdout);
+	if (console == NULL) {
+		printf("%s", str);
+		return EOK;
+	}
+	sysarg_t con_rows, con_cols, con_col, con_row;
+	int rc = console_get_size(console, &con_cols, &con_rows);
+	if (rc != EOK) {
+		return rc;
+	}
+	rc = console_get_pos(console, &con_col, &con_row);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (con_col != 0) {
+		printf("\n");
+	}
+	return print_wrapped(str, con_cols, alignment);
+}
+
+/** Line consumer that prints the lines aligned according to spec
+ *
+ **/
+static int print_line(wchar_t *wstr, size_t chars, bool last, void *data)
+{
+	printmode_t *pm = (printmode_t *) data;
+	wchar_t old_char = wstr[chars];
+	wstr[chars] = 0;
+	int rc = print_aligned_w(wstr, pm->width, last, pm->alignment);
+	wstr[chars] = old_char;
+	return rc;
+}
+
+int print_wrapped(const char *str, size_t width, align_mode_t mode)
+{
+	printmode_t pm;
+	pm.alignment = mode;
+	pm.newline_always = false;
+	pm.width = width;
+	wchar_t *wstr = str_to_awstr(str);
+	if (wstr == NULL) {
+		return ENOMEM;
+	}
+	int rc = wrap(wstr, width, print_line, &pm);
+	free(wstr);
+	return rc;
+}
+
+int print_aligned_w(const wchar_t *wstr, size_t width, bool last,
+    align_mode_t mode)
+{
+	size_t i;
+	size_t len = wstr_length(wstr);
+	if (mode == ALIGN_LEFT || (mode == ALIGN_JUSTIFY && last)) {
+		for (i = 0; i < width; i++) {
+			if (i < len)
+				putchar(wstr[i]);
+			else
+				putchar(' ');
+		}
+	}
+	else if (mode == ALIGN_RIGHT) {
+		for (i = 0; i < width; i++) {
+			if (i < width - len)
+				putchar(' ');
+			else
+				putchar(wstr[i- (width - len)]);
+		}
+	}
+	else if (mode == ALIGN_CENTER) {
+		size_t padding = (width - len) / 2;
+		for (i = 0; i < width; i++) {
+			if ((i < padding) || ((i - padding) >= len))
+				putchar(' ');
+			else
+				putchar(wstr[i-padding]);
+		}
+	}
+	else if (mode == ALIGN_JUSTIFY) {
+		size_t words = 0;
+		size_t word_chars = 0;
+		bool space = true;
+		for (i = 0; i < len; i++) {
+			if (space && wstr[i] != ' ') {
+				words++;
+			}
+			space = wstr[i] == ' ';
+			if (!space) word_chars++;
+		}
+		size_t done_words = 0;
+		size_t done_chars = 0;
+		if (words == 0)
+			goto skip_words;
+		size_t excess_spaces = width - word_chars - (words-1);
+		space = true;
+		i = 0;
+		size_t j;
+		while (i < len) {
+			/* Find a word */
+			while (i < len && wstr[i] == ' ') i++;
+			if (i == len) break;
+			if (done_words) {
+				size_t spaces = 1 + (((done_words *
+				    excess_spaces) / (words - 1)) -
+				    (((done_words - 1) * excess_spaces) /
+				    (words - 1)));
+				for (j = 0; j < spaces; j++) {
+					putchar(' ');
+				}
+				done_chars += spaces;
+			}
+			while (i < len && wstr[i] != ' ') {
+				putchar(wstr[i++]);
+				done_chars++;
+			}
+			done_words++;
+		}
+skip_words:
+		while (done_chars < width) {
+			putchar(' ');
+			done_chars++;
+		}
+	}
+	else {
+		return EINVAL;
+	}
+	
+	return EOK;
+}
+int print_aligned(const char *str, size_t width, bool last, align_mode_t mode)
+{
+	wchar_t *wstr = str_to_awstr(str);
+	if (wstr == NULL) {
+		return ENOMEM;
+	}
+	int rc = print_aligned_w(wstr, width, last, mode);
+	free(wstr);
+	return rc;
+}
+
+int wrap(wchar_t *wstr, size_t width, line_consumer_fn consumer, void *data)
+{
+	size_t word_start = 0;
+	size_t last_word_end = 0;
+	size_t line_start = 0;
+	size_t line_len = 0;
+	size_t pos = 0;
+	
+	/*
+	 * Invariants:
+	 *  * line_len = last_word_end - line_start
+	 *  * line_start <= last_word_end <= word_start <= pos
+	 */
+	
+	while (wstr[pos] != 0) {
+		/* Skip spaces and process newlines */
+		while (wstr[pos] == ' ' || wstr[pos] == '\n') {
+			if (wstr[pos] == '\n') {
+				consumer(wstr + line_start, line_len, true,
+				    data);
+				last_word_end = line_start = pos + 1;
+				line_len = 0;
+			}
+			pos++;
+		}
+		word_start = pos;
+		/* Find end of word */
+		while (wstr[pos] != 0 && wstr[pos] != ' ' &&
+		    wstr[pos] != '\n')
+			pos++;
+		bool last = wstr[pos] == 0;
+		/* Check if the line still fits width */
+		if (pos - line_start > width) {
+			if (line_len > 0)
+				consumer(wstr + line_start, line_len, last,
+				    data);
+			line_start = last_word_end = word_start;
+			line_len = 0;
+		}
+		/* Check if we need to force wrap of long word*/
+		if (pos - word_start > width) {
+			consumer(wstr + word_start, width, last, data);
+			pos = line_start = last_word_end = word_start + width;
+			line_len = 0;
+		}
+		last_word_end = pos;
+		line_len = last_word_end - line_start;
+	}
+	/* Here we have less than width chars starting from line_start.
+	 * Moreover, the last portion does not contain spaces or newlines 
+	 */
+	if (pos - line_start > 0)
+		consumer(wstr + line_start, pos - line_start, true, data);
+
+	return EOK;
+}
+
Index: uspace/lib/fmtutil/fmtutil.h
===================================================================
--- uspace/lib/fmtutil/fmtutil.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/fmtutil/fmtutil.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+typedef enum {
+	ALIGN_LEFT,
+	ALIGN_RIGHT,
+	ALIGN_CENTER,
+	ALIGN_JUSTIFY
+} align_mode_t;
+
+/** Callback that processes a line of characters.
+ * (e.g. as a result of wrap operation)
+ * 
+ * @param content pointer to line data (note: this is NOT null-terminated)
+ * @param size number of characters in line
+ * @param end_of_para true if the line is the last line of the paragraph
+ * @param data user data
+ * 
+ * @returns EOK on success or error code on failure
+ */
+typedef int (*line_consumer_fn)(wchar_t *, size_t, bool, void *);
+
+extern int print_aligned_w(const wchar_t *, size_t, bool, align_mode_t);
+extern int print_aligned(const char *, size_t, bool, align_mode_t);
+extern int print_wrapped(const char *, size_t, align_mode_t);
+extern int print_wrapped_console(const char *, align_mode_t);
+
+/** Wrap characters in a wide string to the given length.
+ *
+ * @param wstr the null-terminated wide string to wrap
+ * @param size number of characters to wrap to
+ * @param consumer the function that receives wrapped lines
+ * @param data user data to pass to the consumer function
+ */
+extern int wrap(wchar_t *, size_t, line_consumer_fn, void *);
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/fs/libfs.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -45,4 +45,5 @@
 #include <mem.h>
 #include <sys/stat.h>
+#include <stdlib.h>
 
 #define on_error(rc, action) \
@@ -61,4 +62,226 @@
 	} while (0)
 
+static fs_reg_t reg;
+
+static vfs_out_ops_t *vfs_out_ops = NULL;
+static libfs_ops_t *libfs_ops = NULL;
+
+static void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
+static void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *);
+static void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t,
+    ipc_call_t *);
+static void libfs_stat(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
+static void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t,
+    ipc_call_t *);
+
+static void vfs_out_mounted(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	char *opts;
+	int rc;
+	
+	/* Accept the mount options. */
+	rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
+	if (rc != EOK) {
+		async_answer_0(rid, rc);
+		return;
+	}
+
+	fs_index_t index;
+	aoff64_t size;
+	unsigned lnkcnt;
+	rc = vfs_out_ops->mounted(service_id, opts, &index, &size, &lnkcnt);
+
+	if (rc == EOK)
+		async_answer_4(rid, EOK, index, LOWER32(size), UPPER32(size),
+		    lnkcnt);
+	else
+		async_answer_0(rid, rc);
+
+	free(opts);
+}
+
+static void vfs_out_mount(ipc_callid_t rid, ipc_call_t *req)
+{
+	libfs_mount(libfs_ops, reg.fs_handle, rid, req);
+}
+
+static void vfs_out_unmounted(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	int rc; 
+
+	rc = vfs_out_ops->unmounted(service_id);
+
+	async_answer_0(rid, rc);
+}
+
+static void vfs_out_unmount(ipc_callid_t rid, ipc_call_t *req)
+{
+		
+	libfs_unmount(libfs_ops, rid, req);
+}
+
+static void vfs_out_lookup(ipc_callid_t rid, ipc_call_t *req)
+{
+	libfs_lookup(libfs_ops, reg.fs_handle, rid, req);
+}
+
+static void vfs_out_read(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
+	aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
+	    IPC_GET_ARG4(*req));
+	size_t rbytes;
+	int rc;
+
+	rc = vfs_out_ops->read(service_id, index, pos, &rbytes);
+
+	if (rc == EOK)
+		async_answer_1(rid, EOK, rbytes);
+	else
+		async_answer_0(rid, rc);
+}
+
+static void vfs_out_write(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
+	aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
+	    IPC_GET_ARG4(*req));
+	size_t wbytes;
+	aoff64_t nsize;
+	int rc;
+
+	rc = vfs_out_ops->write(service_id, index, pos, &wbytes, &nsize);
+
+	if (rc == EOK)
+		async_answer_3(rid, EOK, wbytes, LOWER32(nsize), UPPER32(nsize));
+	else
+		async_answer_0(rid, rc);
+}
+
+static void vfs_out_truncate(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
+	aoff64_t size = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
+	    IPC_GET_ARG4(*req));
+	int rc;
+
+	rc = vfs_out_ops->truncate(service_id, index, size);
+
+	async_answer_0(rid, rc);
+}
+
+static void vfs_out_close(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
+	int rc;
+
+	rc = vfs_out_ops->close(service_id, index);
+
+	async_answer_0(rid, rc);
+}
+
+static void vfs_out_destroy(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
+	int rc;
+
+	rc = vfs_out_ops->destroy(service_id, index);
+
+	async_answer_0(rid, rc);
+}
+
+static void vfs_out_open_node(ipc_callid_t rid, ipc_call_t *req)
+{
+	libfs_open_node(libfs_ops, reg.fs_handle, rid, req);
+}
+
+static void vfs_out_stat(ipc_callid_t rid, ipc_call_t *req)
+{
+	libfs_stat(libfs_ops, reg.fs_handle, rid, req);
+}
+
+static void vfs_out_sync(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
+	int rc;
+
+	rc = vfs_out_ops->sync(service_id, index);
+
+	async_answer_0(rid, rc);
+}
+
+static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	if (iid) {
+		/*
+		 * This only happens for connections opened by
+		 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
+		 * created by IPC_M_CONNECT_TO_ME.
+		 */
+		async_answer_0(iid, EOK);
+	}
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call))
+			return;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case VFS_OUT_MOUNTED:
+			vfs_out_mounted(callid, &call);
+			break;
+		case VFS_OUT_MOUNT:
+			vfs_out_mount(callid, &call);
+			break;
+		case VFS_OUT_UNMOUNTED:
+			vfs_out_unmounted(callid, &call);
+			break;
+		case VFS_OUT_UNMOUNT:
+			vfs_out_unmount(callid, &call);
+			break;
+		case VFS_OUT_LOOKUP:
+			vfs_out_lookup(callid, &call);
+			break;
+		case VFS_OUT_READ:
+			vfs_out_read(callid, &call);
+			break;
+		case VFS_OUT_WRITE:
+			vfs_out_write(callid, &call);
+			break;
+		case VFS_OUT_TRUNCATE:
+			vfs_out_truncate(callid, &call);
+			break;
+		case VFS_OUT_CLOSE:
+			vfs_out_close(callid, &call);
+			break;
+		case VFS_OUT_DESTROY:
+			vfs_out_destroy(callid, &call);
+			break;
+		case VFS_OUT_OPEN_NODE:
+			vfs_out_open_node(callid, &call);
+			break;
+		case VFS_OUT_STAT:
+			vfs_out_stat(callid, &call);
+			break;
+		case VFS_OUT_SYNC:
+			vfs_out_sync(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+			break;
+		}
+	}
+}
+
 /** Register file system server.
  *
@@ -68,16 +291,14 @@
  *
  * @param sess Session for communication with VFS.
- * @param reg  File system registration structure. It will be
- *             initialized by this function.
  * @param info VFS info structure supplied by the file system
  *             implementation.
- * @param conn Connection fibril for handling all calls originating in
- *             VFS.
+ * @param vops Address of the vfs_out_ops_t structure.
+ * @param lops Address of the libfs_ops_t structure.
  *
  * @return EOK on success or a non-zero error code on errror.
  *
  */
-int fs_register(async_sess_t *sess, fs_reg_t *reg, vfs_info_t *info,
-    async_client_conn_t conn)
+int fs_register(async_sess_t *sess, vfs_info_t *info, vfs_out_ops_t *vops,
+    libfs_ops_t *lops)
 {
 	/*
@@ -104,13 +325,19 @@
 	
 	/*
+	 * Set VFS_OUT and libfs operations.
+	 */
+	vfs_out_ops = vops;
+	libfs_ops = lops;
+
+	/*
 	 * Ask VFS for callback connection.
 	 */
-	async_connect_to_me(exch, 0, 0, 0, conn, NULL);
+	async_connect_to_me(exch, 0, 0, 0, vfs_connection, NULL);
 	
 	/*
 	 * Allocate piece of address space for PLB.
 	 */
-	reg->plb_ro = as_get_mappable_page(PLB_SIZE);
-	if (!reg->plb_ro) {
+	reg.plb_ro = as_get_mappable_page(PLB_SIZE);
+	if (!reg.plb_ro) {
 		async_exchange_end(exch);
 		async_wait_for(req, NULL);
@@ -121,5 +348,5 @@
 	 * Request sharing the Path Lookup Buffer with VFS.
 	 */
-	rc = async_share_in_start_0_0(exch, reg->plb_ro, PLB_SIZE);
+	rc = async_share_in_start_0_0(exch, reg.plb_ro, PLB_SIZE);
 	
 	async_exchange_end(exch);
@@ -134,5 +361,5 @@
 	 */
 	async_wait_for(req, NULL);
-	reg->fs_handle = (int) IPC_GET_ARG1(answer);
+	reg.fs_handle = (int) IPC_GET_ARG1(answer);
 	
 	/*
@@ -140,5 +367,5 @@
 	 * the same connection fibril as well.
 	 */
-	async_set_client_connection(conn);
+	async_set_client_connection(vfs_connection);
 	
 	return IPC_GET_RETVAL(answer);
@@ -151,10 +378,10 @@
 
 void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
-    ipc_call_t *request)
-{
-	devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
-	fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request);
-	devmap_handle_t mr_devmap_handle = (devmap_handle_t) IPC_GET_ARG4(*request);
+    ipc_call_t *req)
+{
+	service_id_t mp_service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req);
+	fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*req);
+	service_id_t mr_service_id = (service_id_t) IPC_GET_ARG4(*req);
 	
 	async_sess_t *mountee_sess = async_clone_receive(EXCHANGE_PARALLEL);
@@ -165,5 +392,5 @@
 	
 	fs_node_t *fn;
-	int res = ops->node_get(&fn, mp_devmap_handle, mp_fs_index);
+	int res = ops->node_get(&fn, mp_service_id, mp_fs_index);
 	if ((res != EOK) || (!fn)) {
 		async_hangup(mountee_sess);
@@ -195,5 +422,5 @@
 	ipc_call_t answer;
 	int rc = async_data_write_forward_1_1(exch, VFS_OUT_MOUNTED,
-	    mr_devmap_handle, &answer);
+	    mr_service_id, &answer);
 	async_exchange_end(exch);
 	
@@ -201,5 +428,5 @@
 		fn->mp_data.mp_active = true;
 		fn->mp_data.fs_handle = mr_fs_handle;
-		fn->mp_data.devmap_handle = mr_devmap_handle;
+		fn->mp_data.service_id = mr_service_id;
 		fn->mp_data.sess = mountee_sess;
 	}
@@ -208,16 +435,16 @@
 	 * Do not release the FS node so that it stays in memory.
 	 */
-	async_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
-	    IPC_GET_ARG3(answer));
-}
-
-void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
+	async_answer_4(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
+	    IPC_GET_ARG3(answer), IPC_GET_ARG4(answer));
+}
+
+void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t mp_service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req);
 	fs_node_t *fn;
 	int res;
 
-	res = ops->node_get(&fn, mp_devmap_handle, mp_fs_index);
+	res = ops->node_get(&fn, mp_service_id, mp_fs_index);
 	if ((res != EOK) || (!fn)) {
 		async_answer_0(rid, combine_rc(res, ENOENT));
@@ -238,5 +465,5 @@
 	 */
 	async_exch_t *exch = async_exchange_begin(fn->mp_data.sess);
-	res = async_req_1_0(exch, VFS_OUT_UNMOUNTED, fn->mp_data.devmap_handle);
+	res = async_req_1_0(exch, VFS_OUT_UNMOUNTED, fn->mp_data.service_id);
 	async_exchange_end(exch);
 
@@ -248,5 +475,5 @@
 		fn->mp_data.mp_active = false;
 		fn->mp_data.fs_handle = 0;
-		fn->mp_data.devmap_handle = 0;
+		fn->mp_data.service_id = 0;
 		fn->mp_data.sess = NULL;
 		
@@ -257,4 +484,9 @@
 	(void) ops->node_put(fn);
 	async_answer_0(rid, res);
+}
+
+static char plb_get_char(unsigned pos)
+{
+	return reg.plb_ro[pos % PLB_SIZE];
 }
 
@@ -273,12 +505,12 @@
  */
 void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
-    ipc_call_t *request)
-{
-	unsigned int first = IPC_GET_ARG1(*request);
-	unsigned int last = IPC_GET_ARG2(*request);
+    ipc_call_t *req)
+{
+	unsigned int first = IPC_GET_ARG1(*req);
+	unsigned int last = IPC_GET_ARG2(*req);
 	unsigned int next = first;
-	devmap_handle_t devmap_handle = IPC_GET_ARG3(*request);
-	int lflag = IPC_GET_ARG4(*request);
-	fs_index_t index = IPC_GET_ARG5(*request);
+	service_id_t service_id = IPC_GET_ARG3(*req);
+	int lflag = IPC_GET_ARG4(*req);
+	fs_index_t index = IPC_GET_ARG5(*req);
 	char component[NAME_MAX + 1];
 	int len;
@@ -292,5 +524,5 @@
 	fs_node_t *tmp = NULL;
 	
-	rc = ops->root_get(&cur, devmap_handle);
+	rc = ops->root_get(&cur, service_id);
 	on_error(rc, goto out_with_answer);
 	
@@ -298,5 +530,6 @@
 		async_exch_t *exch = async_exchange_begin(cur->mp_data.sess);
 		async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last,
-		    cur->mp_data.devmap_handle, lflag, index, IPC_FF_ROUTE_FROM_ME);
+		    cur->mp_data.service_id, lflag, index,
+		    IPC_FF_ROUTE_FROM_ME);
 		async_exchange_end(exch);
 		
@@ -306,5 +539,5 @@
 	
 	/* Eat slash */
-	if (ops->plb_get_char(next) == '/')
+	if (plb_get_char(next) == '/')
 		next++;
 	
@@ -319,5 +552,5 @@
 		/* Collect the component */
 		len = 0;
-		while ((next <= last) && (ops->plb_get_char(next) != '/')) {
+		while ((next <= last) && (plb_get_char(next) != '/')) {
 			if (len + 1 == NAME_MAX) {
 				/* Component length overflow */
@@ -325,5 +558,5 @@
 				goto out;
 			}
-			component[len++] = ops->plb_get_char(next);
+			component[len++] = plb_get_char(next);
 			/* Process next character */
 			next++;
@@ -357,6 +590,6 @@
 			
 			async_exch_t *exch = async_exchange_begin(tmp->mp_data.sess);
-			async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last,
-			    tmp->mp_data.devmap_handle, lflag, index,
+			async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next,
+			    last, tmp->mp_data.service_id, lflag, index,
 			    IPC_FF_ROUTE_FROM_ME);
 			async_exchange_end(exch);
@@ -387,8 +620,8 @@
 				fs_node_t *fn;
 				if (lflag & L_CREATE)
-					rc = ops->create(&fn, devmap_handle,
+					rc = ops->create(&fn, service_id,
 					    lflag);
 				else
-					rc = ops->node_get(&fn, devmap_handle,
+					rc = ops->node_get(&fn, service_id,
 					    index);
 				on_error(rc, goto out_with_answer);
@@ -405,5 +638,5 @@
 						aoff64_t size = ops->size_get(fn);
 						async_answer_5(rid, fs_handle,
-						    devmap_handle,
+						    service_id,
 						    ops->index_get(fn),
 						    LOWER32(size),
@@ -451,5 +684,5 @@
 			len = 0;
 			while (next <= last) {
-				if (ops->plb_get_char(next) == '/') {
+				if (plb_get_char(next) == '/') {
 					/* More than one component */
 					async_answer_0(rid, ENOENT);
@@ -463,5 +696,5 @@
 				}
 				
-				component[len++] = ops->plb_get_char(next);
+				component[len++] = plb_get_char(next);
 				/* Process next character */
 				next++;
@@ -473,7 +706,7 @@
 			fs_node_t *fn;
 			if (lflag & L_CREATE)
-				rc = ops->create(&fn, devmap_handle, lflag);
+				rc = ops->create(&fn, service_id, lflag);
 			else
-				rc = ops->node_get(&fn, devmap_handle, index);
+				rc = ops->node_get(&fn, service_id, index);
 			on_error(rc, goto out_with_answer);
 			
@@ -489,5 +722,5 @@
 					aoff64_t size = ops->size_get(fn);
 					async_answer_5(rid, fs_handle,
-					    devmap_handle,
+					    service_id,
 					    ops->index_get(fn),
 					    LOWER32(size),
@@ -515,5 +748,5 @@
 		if (rc == EOK) {
 			aoff64_t size = ops->size_get(cur);
-			async_answer_5(rid, fs_handle, devmap_handle,
+			async_answer_5(rid, fs_handle, service_id,
 			    ops->index_get(cur), LOWER32(size), UPPER32(size),
 			    old_lnkcnt);
@@ -553,5 +786,5 @@
 		if (rc == EOK) {
 			aoff64_t size = ops->size_get(cur);
-			async_answer_5(rid, fs_handle, devmap_handle,
+			async_answer_5(rid, fs_handle, service_id,
 			    ops->index_get(cur), LOWER32(size), UPPER32(size),
 			    ops->lnkcnt_get(cur));
@@ -577,9 +810,9 @@
     ipc_call_t *request)
 {
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request);
 	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
 	
 	fs_node_t *fn;
-	int rc = ops->node_get(&fn, devmap_handle, index);
+	int rc = ops->node_get(&fn, service_id, index);
 	on_error(rc, answer_and_return(rid, rc));
 	
@@ -598,5 +831,5 @@
 	
 	stat.fs_handle = fs_handle;
-	stat.devmap_handle = devmap_handle;
+	stat.service_id = service_id;
 	stat.index = index;
 	stat.lnkcnt = ops->lnkcnt_get(fn);
@@ -604,5 +837,5 @@
 	stat.is_directory = ops->is_directory(fn);
 	stat.size = ops->size_get(fn);
-	stat.device = ops->device_get(fn);
+	stat.service = ops->device_get(fn);
 	
 	ops->node_put(fn);
@@ -623,9 +856,9 @@
     ipc_call_t *request)
 {
-	devmap_handle_t devmap_handle = IPC_GET_ARG1(*request);
+	service_id_t service_id = IPC_GET_ARG1(*request);
 	fs_index_t index = IPC_GET_ARG2(*request);
 	
 	fs_node_t *fn;
-	int rc = ops->node_get(&fn, devmap_handle, index);
+	int rc = ops->node_get(&fn, service_id, index);
 	on_error(rc, answer_and_return(rid, rc));
 	
@@ -637,5 +870,6 @@
 	rc = ops->node_open(fn);
 	aoff64_t size = ops->size_get(fn);
-	async_answer_4(rid, rc, LOWER32(size), UPPER32(size), ops->lnkcnt_get(fn),
+	async_answer_4(rid, rc, LOWER32(size), UPPER32(size),
+	    ops->lnkcnt_get(fn),
 	    (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0));
 	
Index: uspace/lib/fs/libfs.h
===================================================================
--- uspace/lib/fs/libfs.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/fs/libfs.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -40,5 +40,18 @@
 #include <stdint.h>
 #include <async.h>
-#include <devmap.h>
+#include <loc.h>
+
+typedef struct {
+	int (* mounted)(service_id_t, const char *, fs_index_t *, aoff64_t *,
+	    unsigned *);
+	int (* unmounted)(service_id_t);
+	int (* read)(service_id_t, fs_index_t, aoff64_t, size_t *);
+	int (* write)(service_id_t, fs_index_t, aoff64_t, size_t *,
+	    aoff64_t *);
+	int (* truncate)(service_id_t, fs_index_t, aoff64_t);
+	int (* close)(service_id_t, fs_index_t);
+	int (* destroy)(service_id_t, fs_index_t);
+	int (* sync)(service_id_t, fs_index_t);
+} vfs_out_ops_t;
 
 typedef struct {
@@ -46,5 +59,5 @@
 	async_sess_t *sess;
 	fs_handle_t fs_handle;
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 } mp_data_t;
 
@@ -60,10 +73,10 @@
 	 * argument holds the output argument.
 	 */
-	int (* root_get)(fs_node_t **, devmap_handle_t);
+	int (* root_get)(fs_node_t **, service_id_t);
 	int (* match)(fs_node_t **, fs_node_t *, const char *);
-	int (* node_get)(fs_node_t **, devmap_handle_t, fs_index_t);
+	int (* node_get)(fs_node_t **, service_id_t, fs_index_t);
 	int (* node_open)(fs_node_t *);
 	int (* node_put)(fs_node_t *);
-	int (* create)(fs_node_t **, devmap_handle_t, int);
+	int (* create)(fs_node_t **, service_id_t, int);
 	int (* destroy)(fs_node_t *);
 	int (* link)(fs_node_t *, fs_node_t *, const char *);
@@ -71,14 +84,13 @@
 	int (* has_children)(bool *, fs_node_t *);
 	/*
-	 * The second set of methods are usually mere getters that do not return
-	 * an integer error code.
+	 * The second set of methods are usually mere getters that do not
+	 * return an integer error code.
 	 */
 	fs_index_t (* index_get)(fs_node_t *);
 	aoff64_t (* size_get)(fs_node_t *);
 	unsigned int (* lnkcnt_get)(fs_node_t *);
-	char (* plb_get_char)(unsigned pos);
 	bool (* is_directory)(fs_node_t *);
 	bool (* is_file)(fs_node_t *);
-	devmap_handle_t (* device_get)(fs_node_t *);
+	service_id_t (* device_get)(fs_node_t *);
 } libfs_ops_t;
 
@@ -88,15 +100,8 @@
 } fs_reg_t;
 
-extern int fs_register(async_sess_t *, fs_reg_t *, vfs_info_t *,
-    async_client_conn_t);
+extern int fs_register(async_sess_t *, vfs_info_t *, vfs_out_ops_t *,
+    libfs_ops_t *);
 
 extern void fs_node_initialize(fs_node_t *);
-
-extern void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
-extern void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *);
-extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
-extern void libfs_stat(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
-extern void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t,
-    ipc_call_t *);
 
 #endif
Index: uspace/lib/imgmap/Makefile
===================================================================
--- uspace/lib/imgmap/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/imgmap/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,35 @@
+#
+# 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 = libimgmap
+
+SOURCES = \
+	imgmap.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/imgmap/imgmap.c
===================================================================
--- uspace/lib/imgmap/imgmap.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/imgmap/imgmap.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,259 @@
+/*
+ * 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 "imgmap.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 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).
+ *
+ * @return Newly allocated image map.
+ * @return NULL on error or unsupported format.
+ *
+ */
+imgmap_t *imgmap_decode_tga(void *data, size_t size)
+{
+	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;
+	size_t bsize = twidth * theight * 3;
+	
+	imgmap_t *imgmap = (imgmap_t *) malloc(sizeof(imgmap_t) + bsize);
+	if (imgmap == NULL)
+		return NULL;
+	
+	imgmap->size = sizeof(imgmap_t) + bsize;
+	imgmap->width = twidth;
+	imgmap->height = theight;
+	imgmap->visual = VISUAL_BGR_8_8_8;
+	
+	memset(imgmap->data, 0, bsize);
+	
+	/*
+	 * TGA is encoded in a bottom-up manner.
+	 */
+	
+	switch (tga.img_type) {
+	case IMG_BGRA:
+		for (sysarg_t y = tga.starty; y < theight; y++) {
+			size_t src_offset = (y - tga.starty) * tga.width * 3;
+			size_t dst_offset = ((theight - y - 1) * twidth + tga.startx) * 3;
+			
+			memcpy(imgmap->data + dst_offset, tga.img_data + src_offset,
+			    tga.width * 3);
+		}
+		break;
+	case IMG_GRAY:
+		for (sysarg_t y = tga.starty; y < theight; y++) {
+			for (sysarg_t x = tga.startx; x < twidth; x++) {
+				uint8_t val =
+				    ((uint8_t *) tga.img_data)[(y - tga.starty) * tga.width + (x - tga.startx)];
+				size_t dst_offset = ((theight - y - 1) * twidth + x) * 3;
+				memset(imgmap->data + dst_offset, val, 3);
+			}
+		}
+		break;
+	default:
+		break;
+	}
+	
+	return imgmap;
+}
+
+/** @}
+ */
Index: uspace/lib/imgmap/imgmap.h
===================================================================
--- uspace/lib/imgmap/imgmap.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/lib/imgmap/imgmap.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,55 @@
+/*
+ * 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>
+
+typedef struct {
+	size_t size;
+	sysarg_t width;
+	sysarg_t height;
+	visual_t visual;
+	uint8_t data[];
+} imgmap_t;
+
+extern imgmap_t *imgmap_decode_tga(void *, size_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/scsi/include/scsi/sbc.h
===================================================================
--- uspace/lib/scsi/include/scsi/sbc.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/scsi/include/scsi/sbc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -56,9 +56,25 @@
 };
 
+/** SCSI Read (10) command */
+typedef struct {
+	/** Operation code (SCSI_CMD_READ_10) */
+	uint8_t op_code;
+	/** RdProtect, DPO, FUA, Reserved, FUA_NV, Obsolete */
+	uint8_t flags;
+	/** Logical block address */
+	uint32_t lba;
+	/** Reserved, Group Number */
+	uint8_t group_no;
+	/** Transfer length */
+	uint16_t xfer_len;
+	/** Control */
+	uint8_t control;
+} __attribute__((packed)) scsi_cdb_read_10_t;
+
 /** SCSI Read (12) command */
 typedef struct {
 	/** Operation code (SCSI_CMD_READ_12) */
 	uint8_t op_code;
-	/** RdProtect, DPO, FUA, Reserved, FUA_NV, Reserved */
+	/** RdProtect, DPO, FUA, Reserved, FUA_NV, Obsolete */
 	uint8_t flags;
 	/** Logical block address */
@@ -115,9 +131,25 @@
 } scsi_read_capacity_10_data_t;
 
+/** SCSI Write (10) command */
+typedef struct {
+	/** Operation code (SCSI_CMD_WRITE_10) */
+	uint8_t op_code;
+	/** WrProtect, DPO, FUA, Reserved, FUA_NV, Obsolete */
+	uint8_t flags;
+	/** Logical block address */
+	uint32_t lba;
+	/** Reserved, Group Number */
+	uint8_t group_no;
+	/** Transfer length */
+	uint16_t xfer_len;
+	/** Control */
+	uint8_t control;
+} __attribute__((packed)) scsi_cdb_write_10_t;
+
 /** SCSI Write (12) command */
 typedef struct {
 	/** Operation code (SCSI_CMD_WRITE_12) */
 	uint8_t op_code;
-	/** WrProtect, DPO, FUA, Reserved, FUA_NV, Reserved */
+	/** WrProtect, DPO, FUA, Reserved, FUA_NV, Obsolete */
 	uint8_t flags;
 	/** Logical block address */
Index: uspace/lib/scsi/include/scsi/spc.h
===================================================================
--- uspace/lib/scsi/include/scsi/spc.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/scsi/include/scsi/spc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -179,5 +179,5 @@
 	uint8_t additional_len;
 	/** Command-specific Information */
-	uint8_t cmd_spec;
+	uint32_t cmd_spec;
 	/** Additional Sense Code */
 	uint8_t additional_code;
@@ -205,9 +205,14 @@
 	SCSI_SK_ABORTED_COMMAND	= 0xb,
 	SCSI_SK_VOLUME_OVERFLOW	= 0xd,
-	SCSI_SK_MISCOMPARE	= 0xe
+	SCSI_SK_MISCOMPARE	= 0xe,
+
+	SCSI_SK_LIMIT		= 0x10
 };
 
 extern const char *scsi_dev_type_str[SCSI_DEV_LIMIT];
+extern const char *scsi_sense_key_str[SCSI_SK_LIMIT];
+
 extern const char *scsi_get_dev_type_str(unsigned);
+extern const char *scsi_get_sense_key_str(unsigned);
 
 #endif
Index: uspace/lib/scsi/src/spc.c
===================================================================
--- uspace/lib/scsi/src/spc.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/scsi/src/spc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -44,4 +44,21 @@
 };
 
+const char *scsi_sense_key_str[SCSI_SK_LIMIT] = {
+	[SCSI_SK_NO_SENSE]		= "No Sense",
+	[SCSI_SK_RECOVERED_ERROR]	= "Recovered Error",
+	[SCSI_SK_NOT_READY]		= "Not Ready",
+	[SCSI_SK_MEDIUM_ERROR]		= "Medium Error",
+	[SCSI_SK_HARDWARE_ERROR]	= "Hardware Error",
+	[SCSI_SK_ILLEGAL_REQUEST]	= "Illegal Request",
+	[SCSI_SK_UNIT_ATTENTION]	= "Unit Attention",
+	[SCSI_SK_DATA_PROTECT]		= "Data Protect",
+	[SCSI_SK_BLANK_CHECK]		= "Blank Check",
+	[SCSI_SK_VENDOR_SPECIFIC]	= "Vendor-specific",
+	[SCSI_SK_COPY_ABORTED]		= "Copy Aborted",
+	[SCSI_SK_ABORTED_COMMAND]	= "Aborted Command",
+	[SCSI_SK_VOLUME_OVERFLOW]	= "Volume Overflow",
+	[SCSI_SK_MISCOMPARE]		= "Miscompare"
+};
+
 /** Get peripheral device type string.
  *
@@ -53,6 +70,21 @@
 {
 	if (dev_type >= SCSI_DEV_LIMIT || scsi_dev_type_str[dev_type] == NULL)
-		return "<unknown>";
+		return "Unknown";
 
 	return scsi_dev_type_str[dev_type];
 }
+
+/** Get sense key string.
+ *
+ * Return string description of SCSI sense key.
+ * The returned string is valid indefinitely, the caller should
+ * not attempt to free it.
+ */
+const char *scsi_get_sense_key_str(unsigned sense_key)
+{
+	if (sense_key >= SCSI_SK_LIMIT || scsi_sense_key_str[sense_key] == NULL)
+		return "Unknown";
+
+	return scsi_sense_key_str[sense_key];
+}
+
Index: uspace/lib/usb/include/usb/classes/hub.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hub.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/usb/include/usb/classes/hub.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -119,4 +119,6 @@
      */
     uint16_t hub_characteristics;
+#define HUB_CHAR_POWER_PER_PORT_FLAG  (1 << 0)
+#define HUB_CHAR_NO_POWER_SWITCH_FLAG (1 << 1)
 
     /**
Index: uspace/lib/usb/include/usb/hc.h
===================================================================
--- uspace/lib/usb/include/usb/hc.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/usb/include/usb/hc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,4 +38,5 @@
 #include <sys/types.h>
 #include <ipc/devman.h>
+#include <ipc/loc.h>
 #include <ddf/driver.h>
 #include <bool.h>
@@ -68,5 +69,5 @@
     devman_handle_t *);
 
-int usb_ddf_get_hc_handle_by_class(size_t, devman_handle_t *);
+int usb_ddf_get_hc_handle_by_sid(service_id_t, devman_handle_t *);
 
 
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/usb/include/usb/usb.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -174,6 +174,6 @@
 } usb_packet_id;
 
-/** Class name for USB host controllers. */
-#define USB_HC_DDF_CLASS_NAME "usbhc"
+/** Category for USB host controllers. */
+#define USB_HC_CATEGORY "usbhc"
 
 #endif
Index: uspace/lib/usb/src/hc.c
===================================================================
--- uspace/lib/usb/src/hc.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/usb/src/hc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -201,32 +201,19 @@
 /** Get host controller handle by its class index.
  *
- * @param class_index Class index for the host controller.
+ * @param sid Service ID of the HC function.
  * @param hc_handle Where to store the HC handle
  *	(can be NULL for existence test only).
  * @return Error code.
  */
-int usb_ddf_get_hc_handle_by_class(size_t class_index,
-    devman_handle_t *hc_handle)
-{
-	char *class_index_str;
-	devman_handle_t hc_handle_tmp;
+int usb_ddf_get_hc_handle_by_sid(service_id_t sid, devman_handle_t *hc_handle)
+{
+	devman_handle_t handle;
 	int rc;
-
-	rc = asprintf(&class_index_str, "%zu", class_index);
-	if (rc < 0) {
-		return ENOMEM;
-	}
-	rc = devman_device_get_handle_by_class("usbhc", class_index_str,
-	    &hc_handle_tmp, 0);
-	free(class_index_str);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	if (hc_handle != NULL) {
-		*hc_handle = hc_handle_tmp;
-	}
-
-	return EOK;
+	
+	rc = devman_fun_sid_to_handle(sid, &handle);
+	if (hc_handle != NULL)
+		*hc_handle = handle;
+	
+	return rc;
 }
 
Index: uspace/lib/usb/src/resolve.c
===================================================================
--- uspace/lib/usb/src/resolve.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/usb/src/resolve.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -46,10 +46,10 @@
     devman_handle_t *out_hc_handle, usb_address_t *out_device_address)
 {
-	size_t class_index;
+	uint64_t sid;
 	size_t address;
 	int rc;
 	char *ptr;
 
-	rc = str_size_t(path, &ptr, 10, false, &class_index);
+	rc = str_uint64(path, &ptr, 10, false, &sid);
 	if (rc != EOK) {
 		return false;
@@ -64,5 +64,5 @@
 		return false;
 	}
-	rc = usb_ddf_get_hc_handle_by_class(class_index, out_hc_handle);
+	rc = usb_ddf_get_hc_handle_by_sid(sid, out_hc_handle);
 	if (rc != EOK) {
 		return false;
@@ -152,5 +152,5 @@
 		if (str_length(func_start) > 0) {
 			char tmp_path[MAX_DEVICE_PATH ];
-			rc = devman_get_device_path(dev_handle,
+			rc = devman_fun_get_path(dev_handle,
 			    tmp_path, MAX_DEVICE_PATH);
 			if (rc != EOK) {
@@ -173,5 +173,5 @@
 
 	/* First try to get the device handle. */
-	rc = devman_device_get_handle(path, &dev_handle, 0);
+	rc = devman_fun_get_handle(path, &dev_handle, 0);
 	if (rc != EOK) {
 		free(path);
@@ -184,5 +184,5 @@
 		/* Get device handle first. */
 		devman_handle_t tmp_handle;
-		rc = devman_device_get_handle(path, &tmp_handle, 0);
+		rc = devman_fun_get_handle(path, &tmp_handle, 0);
 		if (rc != EOK) {
 			free(path);
Index: uspace/lib/usbhost/include/usb/host/endpoint.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/endpoint.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/usbhost/include/usb/host/endpoint.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -61,7 +61,7 @@
 } endpoint_t;
 
-int endpoint_init(endpoint_t *instance, usb_address_t address,
-    usb_endpoint_t endpoint, usb_direction_t direction,
-    usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size);
+endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint,
+    usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
+    size_t max_packet_size);
 
 void endpoint_destroy(endpoint_t *instance);
Index: uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -82,21 +82,15 @@
     size_t data_size)
 {
-	endpoint_t *ep = malloc(sizeof(endpoint_t));
-	if (ep == NULL)
+	endpoint_t *ep = endpoint_get(
+	    address, endpoint, direction, type, speed, max_packet_size);
+	if (!ep)
 		return ENOMEM;
 
-	int ret = endpoint_init(ep, address, endpoint, direction, type, speed,
-	    max_packet_size);
-	if (ret != EOK) {
-		free(ep);
-		return ret;
-	}
-
-	ret = usb_endpoint_manager_register_ep(instance, ep, data_size);
+	const int ret =
+	    usb_endpoint_manager_register_ep(instance, ep, data_size);
 	if (ret != EOK) {
 		endpoint_destroy(ep);
-		return ret;
 	}
-	return EOK;
+	return ret;
 }
 #endif
Index: uspace/lib/usbhost/src/batch.c
===================================================================
--- uspace/lib/usbhost/src/batch.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/usbhost/src/batch.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -109,4 +109,5 @@
 	assert(instance);
 	assert(instance->ep);
+	assert(instance->next_step);
 	endpoint_release(instance->ep);
 	instance->next_step(instance);
@@ -128,5 +129,5 @@
 	memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
 
-	usb_log_debug("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n",
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n",
 	    instance, USB_TRANSFER_BATCH_ARGS(*instance),
 	    instance->transfered_size, str_error(instance->error));
@@ -145,5 +146,5 @@
 	assert(instance->callback_out);
 
-	usb_log_debug("Batch %p " USB_TRANSFER_BATCH_FMT " completed: %s.\n",
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed: %s.\n",
 	    instance, USB_TRANSFER_BATCH_ARGS(*instance),
 	    str_error(instance->error));
Index: uspace/lib/usbhost/src/endpoint.c
===================================================================
--- uspace/lib/usbhost/src/endpoint.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/usbhost/src/endpoint.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,21 +39,23 @@
 #include <usb/host/endpoint.h>
 
-int endpoint_init(endpoint_t *instance, usb_address_t address,
-    usb_endpoint_t endpoint, usb_direction_t direction,
-    usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size)
+endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint,
+    usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
+    size_t max_packet_size)
 {
-	assert(instance);
-	instance->address = address;
-	instance->endpoint = endpoint;
-	instance->direction = direction;
-	instance->transfer_type = type;
-	instance->speed = speed;
-	instance->max_packet_size = max_packet_size;
-	instance->toggle = 0;
-	instance->active = false;
-	fibril_mutex_initialize(&instance->guard);
-	fibril_condvar_initialize(&instance->avail);
-	endpoint_clear_hc_data(instance);
-	return EOK;
+	endpoint_t *instance = malloc(sizeof(endpoint_t));
+	if (instance) {
+		instance->address = address;
+		instance->endpoint = endpoint;
+		instance->direction = direction;
+		instance->transfer_type = type;
+		instance->speed = speed;
+		instance->max_packet_size = max_packet_size;
+		instance->toggle = 0;
+		instance->active = false;
+		fibril_mutex_initialize(&instance->guard);
+		fibril_condvar_initialize(&instance->avail);
+		endpoint_clear_hc_data(instance);
+	}
+	return instance;
 }
 /*----------------------------------------------------------------------------*/
Index: uspace/lib/usbvirt/src/device.c
===================================================================
--- uspace/lib/usbvirt/src/device.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/lib/usbvirt/src/device.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -87,5 +87,5 @@
 	
 	devman_handle_t handle;
-	int rc = devman_device_get_handle(vhc_path, &handle, 0);
+	int rc = devman_fun_get_handle(vhc_path, &handle, 0);
 	if (rc != EOK)
 		return rc;
Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -57,5 +57,5 @@
 #include <stdint.h>
 #include <str.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sys/types.h>
 #include <inttypes.h>
@@ -80,7 +80,4 @@
  */
 static const size_t identify_data_size = 512;
-
-/** Size of the communication area. */
-static size_t comm_size;
 
 /** I/O base address of the command registers. */
@@ -179,5 +176,5 @@
 		
 		snprintf(name, 16, "%s/ata%udisk%d", NAMESPACE, ctl_num, i);
-		rc = devmap_device_register(name, &disk[i].devmap_handle);
+		rc = loc_service_register(name, &disk[i].service_id);
 		if (rc != EOK) {
 			printf(NAME ": Unable to register device %s.\n", name);
@@ -247,5 +244,5 @@
 	int rc;
 
-	rc = devmap_driver_register(NAME, ata_bd_connection);
+	rc = loc_server_register(NAME, ata_bd_connection);
 	if (rc < 0) {
 		printf(NAME ": Unable to register driver.\n");
@@ -280,5 +277,6 @@
 	ipc_call_t call;
 	sysarg_t method;
-	devmap_handle_t dh;
+	service_id_t dsid;
+	size_t comm_size;	/**< Size of the communication area. */
 	unsigned int flags;
 	int retval;
@@ -287,11 +285,11 @@
 	int disk_id, i;
 
-	/* Get the device handle. */
-	dh = IPC_GET_ARG1(*icall);
+	/* 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 < MAX_DISKS; i++)
-		if (disk[i].devmap_handle == dh)
+		if (disk[i].service_id == dsid)
 			disk_id = i;
 
Index: uspace/srv/bd/ata_bd/ata_bd.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/bd/ata_bd/ata_bd.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -116,5 +116,5 @@
 
 	fibril_mutex_t lock;
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 } disk_t;
 
Index: uspace/srv/bd/file_bd/file_bd.c
===================================================================
--- uspace/srv/bd/file_bd/file_bd.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/bd/file_bd/file_bd.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -45,5 +45,5 @@
 #include <as.h>
 #include <fibril_synch.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sys/types.h>
 #include <sys/typefmt.h>
@@ -61,5 +61,5 @@
 static FILE *img;
 
-static devmap_handle_t devmap_handle;
+static service_id_t service_id;
 static fibril_mutex_t dev_lock;
 
@@ -117,5 +117,5 @@
 		return -1;
 
-	rc = devmap_device_register(device_name, &devmap_handle);
+	rc = loc_service_register(device_name, &service_id);
 	if (rc != EOK) {
 		printf(NAME ": Unable to register device '%s'.\n",
@@ -142,5 +142,5 @@
 	long img_size;
 
-	rc = devmap_driver_register(NAME, file_bd_connection);
+	rc = loc_server_register(NAME, file_bd_connection);
 	if (rc < 0) {
 		printf(NAME ": Unable to register driver.\n");
Index: uspace/srv/bd/gxe_bd/gxe_bd.c
===================================================================
--- uspace/srv/bd/gxe_bd/gxe_bd.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/bd/gxe_bd/gxe_bd.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -43,5 +43,5 @@
 #include <as.h>
 #include <fibril_synch.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sys/types.h>
 #include <errno.h>
@@ -92,5 +92,5 @@
 static gxe_bd_t *dev;
 
-static devmap_handle_t devmap_handle[MAX_DISKS];
+static service_id_t service_id[MAX_DISKS];
 
 static fibril_mutex_t dev_lock[MAX_DISKS];
@@ -126,5 +126,5 @@
 	char name[16];
 
-	rc = devmap_driver_register(NAME, gxe_bd_connection);
+	rc = loc_server_register(NAME, gxe_bd_connection);
 	if (rc < 0) {
 		printf(NAME ": Unable to register driver.\n");
@@ -142,5 +142,5 @@
 	for (i = 0; i < MAX_DISKS; i++) {
 		snprintf(name, 16, "%s/disk%d", NAMESPACE, i);
-		rc = devmap_device_register(name, &devmap_handle[i]);
+		rc = loc_service_register(name, &service_id[i]);
 		if (rc != EOK) {
 			printf(NAME ": Unable to register device %s.\n", name);
@@ -159,5 +159,5 @@
 	ipc_call_t call;
 	sysarg_t method;
-	devmap_handle_t dh;
+	service_id_t dsid;
 	unsigned int flags;
 	int retval;
@@ -167,10 +167,10 @@
 
 	/* Get the device handle. */
-	dh = IPC_GET_ARG1(*icall);
+	dsid = IPC_GET_ARG1(*icall);
 
 	/* Determine which disk device is the client connecting to. */
 	disk_id = -1;
 	for (i = 0; i < MAX_DISKS; i++)
-		if (devmap_handle[i] == dh)
+		if (service_id[i] == dsid)
 			disk_id = i;
 
Index: uspace/srv/bd/part/guid_part/guid_part.c
===================================================================
--- uspace/srv/bd/part/guid_part/guid_part.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/bd/part/guid_part/guid_part.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -51,10 +51,10 @@
 #include <as.h>
 #include <fibril_synch.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sys/types.h>
 #include <sys/typefmt.h>
 #include <inttypes.h>
 #include <libblock.h>
-#include <devmap.h>
+#include <loc.h>
 #include <errno.h>
 #include <bool.h>
@@ -81,6 +81,6 @@
 	/** Number of blocks */
 	aoff64_t length;
-	/** Device representing the partition (outbound device) */
-	devmap_handle_t dev;
+	/** Service representing the partition (outbound device) */
+	service_id_t dsid;
 	/** Points to next partition structure. */
 	struct part *next;
@@ -90,5 +90,5 @@
 
 /** Partitioned device (inbound device) */
-static devmap_handle_t indev_handle;
+static service_id_t indev_sid;
 
 /** List of partitions. This structure is an empty head. */
@@ -129,9 +129,9 @@
 	int i;
 	char *name;
-	devmap_handle_t dev;
+	service_id_t dsid;
 	uint64_t size_mb;
 	part_t *part;
 
-	rc = devmap_device_get_handle(dev_name, &indev_handle, 0);
+	rc = loc_service_get_id(dev_name, &indev_sid, 0);
 	if (rc != EOK) {
 		printf(NAME ": could not resolve device `%s'.\n", dev_name);
@@ -139,5 +139,5 @@
 	}
 
-	rc = block_init(EXCHANGE_SERIALIZE, indev_handle, 2048);
+	rc = block_init(EXCHANGE_SERIALIZE, indev_sid, 2048);
 	if (rc != EOK)  {
 		printf(NAME ": could not init libblock.\n");
@@ -147,5 +147,5 @@
 	/* Determine and verify block size. */
 
-	rc = block_get_bsize(indev_handle, &block_size);
+	rc = block_get_bsize(indev_sid, &block_size);
 	if (rc != EOK) {
 		printf(NAME ": error getting block size.\n");
@@ -163,8 +163,8 @@
 		return rc;
 
-	/* Register the driver with device mapper. */
-	rc = devmap_driver_register(NAME, gpt_connection);
+	/* Register server with location service. */
+	rc = loc_server_register(NAME, gpt_connection);
 	if (rc != EOK) {
-		printf(NAME ": Unable to register driver.\n");
+		printf(NAME ": Unable to register server.\n");
 		return rc;
 	}
@@ -188,7 +188,7 @@
 			return ENOMEM;
 
-		rc = devmap_device_register(name, &dev);
+		rc = loc_service_register(name, &dsid);
 		if (rc != EOK) {
-			printf(NAME ": Unable to register device %s.\n", name);
+			printf(NAME ": Unable to register service %s.\n", name);
 			return rc;
 		}
@@ -199,5 +199,5 @@
 		    "%" PRIuOFF64 " MB.\n", name, part->length, size_mb);
 
-		part->dev = dev;
+		part->dsid = dsid;
 		free(name);
 
@@ -228,5 +228,5 @@
 	}
 
-	rc = block_read_direct(indev_handle, GPT_HDR_BA, 1, gpt_hdr);
+	rc = block_read_direct(indev_sid, GPT_HDR_BA, 1, gpt_hdr);
 	if (rc != EOK) {
 		printf(NAME ": Failed reading GPT header block.\n");
@@ -256,5 +256,5 @@
 	}
 
-	rc = block_read_direct(indev_handle, ba, bcnt, etable);
+	rc = block_read_direct(indev_sid, ba, bcnt, etable);
 	if (rc != EOK) {
 		printf(NAME ": Failed reading GPT entries.\n");
@@ -303,5 +303,5 @@
 	}
 
-	part->dev = 0;
+	part->dsid = 0;
 	part->next = NULL;
 }
@@ -314,5 +314,5 @@
 	ipc_call_t call;
 	sysarg_t method;
-	devmap_handle_t dh;
+	service_id_t dh;
 	unsigned int flags;
 	int retval;
@@ -330,5 +330,5 @@
 	 */
 	part = plist_head.next;
-	while (part != NULL && part->dev != dh)
+	while (part != NULL && part->dsid != dh)
 		part = part->next;
 
@@ -410,5 +410,5 @@
 		return ELIMIT;
 
-	return block_read_direct(indev_handle, gba, cnt, buf);
+	return block_read_direct(indev_sid, gba, cnt, buf);
 }
 
@@ -421,5 +421,5 @@
 		return ELIMIT;
 
-	return block_write_direct(indev_handle, gba, cnt, buf);
+	return block_write_direct(indev_sid, gba, cnt, buf);
 }
 
Index: uspace/srv/bd/part/mbr_part/mbr_part.c
===================================================================
--- uspace/srv/bd/part/mbr_part/mbr_part.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/bd/part/mbr_part/mbr_part.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -61,10 +61,9 @@
 #include <as.h>
 #include <fibril_synch.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sys/types.h>
 #include <sys/typefmt.h>
 #include <inttypes.h>
 #include <libblock.h>
-#include <devmap.h>
 #include <errno.h>
 #include <bool.h>
@@ -100,5 +99,5 @@
 	aoff64_t length;
 	/** Device representing the partition (outbound device) */
-	devmap_handle_t dev;
+	service_id_t dsid;
 	/** Points to next partition structure. */
 	struct part *next;
@@ -141,5 +140,5 @@
 
 /** Partitioned device (inbound device) */
-static devmap_handle_t indev_handle;
+static service_id_t indef_sid;
 
 /** List of partitions. This structure is an empty head. */
@@ -180,9 +179,9 @@
 	int i;
 	char *name;
-	devmap_handle_t dev;
+	service_id_t dsid;
 	uint64_t size_mb;
 	part_t *part;
 
-	rc = devmap_device_get_handle(dev_name, &indev_handle, 0);
+	rc = loc_service_get_id(dev_name, &indef_sid, 0);
 	if (rc != EOK) {
 		printf(NAME ": could not resolve device `%s'.\n", dev_name);
@@ -190,5 +189,5 @@
 	}
 
-	rc = block_init(EXCHANGE_SERIALIZE, indev_handle, 2048);
+	rc = block_init(EXCHANGE_SERIALIZE, indef_sid, 2048);
 	if (rc != EOK)  {
 		printf(NAME ": could not init libblock.\n");
@@ -198,5 +197,5 @@
 	/* Determine and verify block size. */
 
-	rc = block_get_bsize(indev_handle, &block_size);
+	rc = block_get_bsize(indef_sid, &block_size);
 	if (rc != EOK) {
 		printf(NAME ": error getting block size.\n");
@@ -214,8 +213,8 @@
 		return rc;
 
-	/* Register the driver with device mapper. */
-	rc = devmap_driver_register(NAME, mbr_connection);
+	/* Register server with location service. */
+	rc = loc_server_register(NAME, mbr_connection);
 	if (rc != EOK) {
-		printf(NAME ": Unable to register driver.\n");
+		printf(NAME ": Unable to register server.\n");
 		return rc;
 	}
@@ -239,7 +238,7 @@
 			return ENOMEM;
 
-		rc = devmap_device_register(name, &dev);
+		rc = loc_service_register(name, &dsid);
 		if (rc != EOK) {
-			printf(NAME ": Unable to register device %s.\n", name);
+			printf(NAME ": Unable to register service %s.\n", name);
 			return rc;
 		}
@@ -250,5 +249,5 @@
 		    "%" PRIu64 " MB.\n", name, part->length, size_mb);
 
-		part->dev = dev;
+		part->dsid = dsid;
 		free(name);
 
@@ -281,5 +280,5 @@
 	 */
 
-	rc = block_read_direct(indev_handle, 0, 1, brb);
+	rc = block_read_direct(indef_sid, 0, 1, brb);
 	if (rc != EOK) {
 		printf(NAME ": Failed reading MBR block.\n");
@@ -332,5 +331,5 @@
 		 */
 		ba = cp.start_addr;
-		rc = block_read_direct(indev_handle, ba, 1, brb);
+		rc = block_read_direct(indef_sid, ba, 1, brb);
 		if (rc != EOK) {
 			printf(NAME ": Failed reading EBR block at %"
@@ -381,5 +380,5 @@
 	part->present = (pte->ptype != PT_UNUSED) ? true : false;
 
-	part->dev = 0;
+	part->dsid = 0;
 	part->next = NULL;
 }
@@ -392,5 +391,5 @@
 	ipc_call_t call;
 	sysarg_t method;
-	devmap_handle_t dh;
+	service_id_t dh;
 	unsigned int flags;
 	int retval;
@@ -408,5 +407,5 @@
 	 */
 	part = plist_head.next;
-	while (part != NULL && part->dev != dh)
+	while (part != NULL && part->dsid != dh)
 		part = part->next;
 
@@ -488,5 +487,5 @@
 		return ELIMIT;
 
-	return block_read_direct(indev_handle, gba, cnt, buf);
+	return block_read_direct(indef_sid, gba, cnt, buf);
 }
 
@@ -499,5 +498,5 @@
 		return ELIMIT;
 
-	return block_write_direct(indev_handle, gba, cnt, buf);
+	return block_write_direct(indef_sid, gba, cnt, buf);
 }
 
Index: uspace/srv/bd/rd/rd.c
===================================================================
--- uspace/srv/bd/rd/rd.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/bd/rd/rd.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -52,5 +52,5 @@
 #include <fibril_synch.h>
 #include <stdio.h>
-#include <devmap.h>
+#include <loc.h>
 #include <ipc/bd.h>
 #include <macros.h>
@@ -235,5 +235,5 @@
 	    (void *) rd_ph_addr, rd_size);
 	
-	int rc = devmap_driver_register(NAME, rd_connection);
+	int rc = loc_server_register(NAME, rd_connection);
 	if (rc < 0) {
 		printf("%s: Unable to register driver (%d)\n", NAME, rc);
@@ -241,7 +241,7 @@
 	}
 	
-	devmap_handle_t devmap_handle;
-	if (devmap_device_register("bd/initrd", &devmap_handle) != EOK) {
-		printf("%s: Unable to register device\n", NAME);
+	service_id_t service_id;
+	if (loc_service_register("bd/initrd", &service_id) != EOK) {
+		printf("%s: Unable to register device service\n", NAME);
 		return false;
 	}
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/devman/devman.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -37,5 +37,5 @@
 #include <ipc/driver.h>
 #include <ipc/devman.h>
-#include <devmap.h>
+#include <loc.h>
 #include <str_error.h>
 #include <stdio.h>
@@ -66,19 +66,9 @@
 }
 
-static int devmap_functions_compare(unsigned long key[], hash_count_t keys,
+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, devmap_fun);
-	return (fun->devmap_handle == (devmap_handle_t) key[0]);
-}
-
-static int devmap_devices_class_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
-{
-	dev_class_info_t *class_info
-	    = hash_table_get_instance(item, dev_class_info_t, devmap_link);
-	assert(class_info != NULL);
-
-	return (class_info->devmap_handle == (devmap_handle_t) key[0]);
+	fun_node_t *fun = hash_table_get_instance(item, fun_node_t, loc_fun);
+	return (fun->service_id == (service_id_t) key[0]);
 }
 
@@ -99,13 +89,7 @@
 };
 
-static hash_table_operations_t devmap_devices_ops = {
+static hash_table_operations_t loc_devices_ops = {
 	.hash = devices_hash,
-	.compare = devmap_functions_compare,
-	.remove_callback = devices_remove_callback
-};
-
-static hash_table_operations_t devmap_devices_class_ops = {
-	.hash = devices_hash,
-	.compare = devmap_devices_class_compare,
+	.compare = loc_functions_compare,
 	.remove_callback = devices_remove_callback
 };
@@ -270,7 +254,8 @@
 	}
 	
-	ssize_t read_bytes = safe_read(fd, buf, len);
+	ssize_t read_bytes = read_all(fd, buf, len);
 	if (read_bytes <= 0) {
-		log_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path);
+		log_msg(LVL_ERROR, "Unable to read file '%s' (%zd).", conf_path,
+		    read_bytes);
 		goto cleanup;
 	}
@@ -421,7 +406,7 @@
 	}
 	
-	insert_fun_node(tree, fun, clone_string(""), NULL);
+	insert_fun_node(tree, fun, str_dup(""), NULL);
 	match_id_t *id = create_match_id();
-	id->id = clone_string("root");
+	id->id = str_dup("root");
 	id->score = 100;
 	add_match_id(&fun->match_ids, id);
@@ -563,14 +548,4 @@
 
 	fibril_mutex_lock(&driver->driver_mutex);
-	
-	async_exch_t *exch = async_exchange_begin(driver->sess);
-	async_sess_t *sess = async_connect_me_to(EXCHANGE_SERIALIZE, exch,
-	    DRIVER_DEVMAN, 0, 0);
-	async_exchange_end(exch);
-
-	if (!sess) {
-		fibril_mutex_unlock(&driver->driver_mutex);
-		return;
-	}
 
 	/*
@@ -598,5 +573,5 @@
 		fibril_mutex_unlock(&driver->driver_mutex);
 
-		add_device(sess, driver, dev, tree);
+		add_device(driver, dev, tree);
 
 		/*
@@ -618,6 +593,4 @@
 		link = driver->devices.head.next;
 	}
-
-	async_hangup(sess);
 
 	/*
@@ -700,30 +673,30 @@
 }
 
-/** Create devmap path and name for the function. */
-void devmap_register_tree_function(fun_node_t *fun, dev_tree_t *tree)
-{
-	char *devmap_pathname = NULL;
-	char *devmap_name = NULL;
-	
-	asprintf(&devmap_name, "%s", fun->pathname);
-	if (devmap_name == NULL)
+/** Create loc path and name for the function. */
+void loc_register_tree_function(fun_node_t *fun, dev_tree_t *tree)
+{
+	char *loc_pathname = NULL;
+	char *loc_name = NULL;
+	
+	asprintf(&loc_name, "%s", fun->pathname);
+	if (loc_name == NULL)
 		return;
 	
-	replace_char(devmap_name, '/', DEVMAP_SEPARATOR);
-	
-	asprintf(&devmap_pathname, "%s/%s", DEVMAP_DEVICE_NAMESPACE,
-	    devmap_name);
-	if (devmap_pathname == NULL) {
-		free(devmap_name);
+	replace_char(loc_name, '/', LOC_SEPARATOR);
+	
+	asprintf(&loc_pathname, "%s/%s", LOC_DEVICE_NAMESPACE,
+	    loc_name);
+	if (loc_pathname == NULL) {
+		free(loc_name);
 		return;
 	}
 	
-	devmap_device_register_with_iface(devmap_pathname,
-	    &fun->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
-	
-	tree_add_devmap_function(tree, fun);
-	
-	free(devmap_name);
-	free(devmap_pathname);
+	loc_service_register_with_iface(loc_pathname,
+	    &fun->service_id, DEVMAN_CONNECT_FROM_LOC);
+	
+	tree_add_loc_function(tree, fun);
+	
+	free(loc_name);
+	free(loc_pathname);
 }
 
@@ -733,6 +706,5 @@
  * @param node		The device's node in the device tree.
  */
-void add_device(async_sess_t *sess, driver_t *drv, dev_node_t *dev,
-    dev_tree_t *tree)
+void add_device(driver_t *drv, dev_node_t *dev, dev_tree_t *tree)
 {
 	/*
@@ -751,5 +723,5 @@
 	}
 	
-	async_exch_t *exch = async_exchange_begin(sess);
+	async_exch_t *exch = async_exchange_begin(drv->sess);
 	
 	ipc_call_t answer;
@@ -821,16 +793,7 @@
 	fibril_mutex_unlock(&drv->driver_mutex);
 
-	if (is_running) {
-		/* Notify the driver about the new device. */
-		async_exch_t *exch = async_exchange_begin(drv->sess);
-		async_sess_t *sess = async_connect_me_to(EXCHANGE_SERIALIZE, exch,
-		    DRIVER_DEVMAN, 0, 0);
-		async_exchange_end(exch);
-		
-		if (sess) {
-			add_device(sess, drv, dev, tree);
-			async_hangup(sess);
-		}
-	}
+	/* Notify the driver about the new device. */
+	if (is_running)
+		add_device(drv, dev, tree);
 	
 	return true;
@@ -855,6 +818,6 @@
 	hash_table_create(&tree->devman_functions, DEVICE_BUCKETS, 1,
 	    &devman_functions_ops);
-	hash_table_create(&tree->devmap_functions, DEVICE_BUCKETS, 1,
-	    &devmap_devices_ops);
+	hash_table_create(&tree->loc_functions, DEVICE_BUCKETS, 1,
+	    &loc_devices_ops);
 	
 	fibril_rwlock_initialize(&tree->rwlock);
@@ -935,4 +898,35 @@
 }
 
+/** Get list of device functions. */
+int dev_get_functions(dev_tree_t *tree, dev_node_t *dev,
+    devman_handle_t *hdl_buf, size_t buf_size, size_t *act_size)
+{
+	size_t act_cnt;
+	size_t buf_cnt;
+
+	assert(fibril_rwlock_is_locked(&tree->rwlock));
+
+	buf_cnt = buf_size / sizeof(devman_handle_t);
+
+	act_cnt = list_count(&dev->functions);
+	*act_size = act_cnt * sizeof(devman_handle_t);
+
+	if (buf_size % sizeof(devman_handle_t) != 0)
+		return EINVAL;
+
+	size_t pos = 0;
+	list_foreach(dev->functions, item) {
+		fun_node_t *fun =
+		    list_get_instance(item, fun_node_t, dev_functions);
+
+		if (pos < buf_cnt)
+			hdl_buf[pos] = fun->handle;
+		pos++;
+	}
+
+	return EOK;
+}
+
+
 /* Function nodes */
 
@@ -949,7 +943,6 @@
 		link_initialize(&res->dev_functions);
 		list_initialize(&res->match_ids.ids);
-		list_initialize(&res->classes);
 		link_initialize(&res->devman_fun);
-		link_initialize(&res->devmap_fun);
+		link_initialize(&res->loc_fun);
 	}
 	
@@ -1114,4 +1107,24 @@
 	
 	return true;
+}
+
+/** Remove function from device tree.
+ *
+ * @param tree		Device tree
+ * @param node		Function node to remove
+ */
+void remove_fun_node(dev_tree_t *tree, fun_node_t *fun)
+{
+	assert(tree != NULL);
+	assert(fun != NULL);
+	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
+	
+	/* Remove the node from the handle-to-node map. */
+	unsigned long key = fun->handle;
+	hash_table_remove(&tree->devman_functions, &key, 1);
+	
+	/* Remove the node from the list of its parent's children. */
+	if (fun->dev != NULL)
+		list_remove(&fun->dev_functions);
 }
 
@@ -1141,5 +1154,5 @@
 	char *rel_path = path;
 	char *next_path_elem = NULL;
-	bool cont = true;
+	bool cont = (rel_path[1] != '\0');
 	
 	while (cont && fun != NULL) {
@@ -1192,34 +1205,4 @@
 }
 
-/** Find function node by its class name and index. */
-fun_node_t *find_fun_node_by_class(class_list_t *class_list,
-    const char *class_name, const char *dev_name)
-{
-	assert(class_list != NULL);
-	assert(class_name != NULL);
-	assert(dev_name != NULL);
-
-	fibril_rwlock_read_lock(&class_list->rwlock);
-
-	dev_class_t *cl = find_dev_class_no_lock(class_list, class_name);
-	if (cl == NULL) {
-		fibril_rwlock_read_unlock(&class_list->rwlock);
-		return NULL;
-	}
-
-	dev_class_info_t *dev = find_dev_in_class(cl, dev_name);
-	if (dev == NULL) {
-		fibril_rwlock_read_unlock(&class_list->rwlock);
-		return NULL;
-	}
-
-	fun_node_t *fun = dev->fun;
-
-	fibril_rwlock_read_unlock(&class_list->rwlock);
-
-	return fun;
-}
-
-
 /** Find child function node with a specified name.
  *
@@ -1235,199 +1218,16 @@
 }
 
-/* Device classes */
-
-/** Create device class.
- *
- * @return	Device class.
- */
-dev_class_t *create_dev_class(void)
-{
-	dev_class_t *cl;
-	
-	cl = (dev_class_t *) malloc(sizeof(dev_class_t));
-	if (cl != NULL) {
-		memset(cl, 0, sizeof(dev_class_t));
-		list_initialize(&cl->devices);
-		fibril_mutex_initialize(&cl->mutex);
-	}
-	
-	return cl;
-}
-
-/** Create device class info.
- *
- * @return		Device class info.
- */
-dev_class_info_t *create_dev_class_info(void)
-{
-	dev_class_info_t *info;
-	
-	info = (dev_class_info_t *) malloc(sizeof(dev_class_info_t));
-	if (info != NULL) {
-		memset(info, 0, sizeof(dev_class_info_t));
-		link_initialize(&info->dev_classes);
-		link_initialize(&info->devmap_link);
-		link_initialize(&info->link);
-	}
-	
-	return info;
-}
-
-size_t get_new_class_dev_idx(dev_class_t *cl)
-{
-	size_t dev_idx;
-	
-	fibril_mutex_lock(&cl->mutex);
-	dev_idx = ++cl->curr_dev_idx;
-	fibril_mutex_unlock(&cl->mutex);
-	
-	return dev_idx;
-}
-
-
-/** Create unique device name within the class.
- *
- * @param cl		The class.
- * @param base_dev_name	Contains the base name for the device if it was
- *			specified by the driver when it registered the device by
- *			the class; NULL if driver specified no base name.
- * @return		The unique name for the device within the class.
- */
-char *create_dev_name_for_class(dev_class_t *cl, const char *base_dev_name)
-{
-	char *dev_name;
-	const char *base_name;
-	
-	if (base_dev_name != NULL)
-		base_name = base_dev_name;
-	else
-		base_name = cl->base_dev_name;
-	
-	size_t idx = get_new_class_dev_idx(cl);
-	asprintf(&dev_name, "%s%zu", base_name, idx);
-	
-	return dev_name;
-}
-
-/** Add the device function to the class.
- *
- * The device may be added to multiple classes and a class may contain multiple
- * devices. The class and the device are associated with each other by the
- * dev_class_info_t structure.
- *
- * @param dev		The device.
- * @param class		The class.
- * @param base_dev_name	The base name of the device within the class if
- *			specified by the driver, NULL otherwise.
- * @return		dev_class_info_t structure which associates the device
- *			with the class.
- */
-dev_class_info_t *add_function_to_class(fun_node_t *fun, dev_class_t *cl,
-    const char *base_dev_name)
-{
-	dev_class_info_t *info;
-
-	assert(fun != NULL);
-	assert(cl != NULL);
-
-	info = create_dev_class_info();
-
-	
-	if (info != NULL) {
-		info->dev_class = cl;
-		info->fun = fun;
-		
-		/* Add the device to the class. */
-		fibril_mutex_lock(&cl->mutex);
-		list_append(&info->link, &cl->devices);
-		fibril_mutex_unlock(&cl->mutex);
-		
-		/* Add the class to the device. */
-		list_append(&info->dev_classes, &fun->classes);
-		
-		/* Create unique name for the device within the class. */
-		info->dev_name = create_dev_name_for_class(cl, base_dev_name);
-	}
-	
-	return info;
-}
-
-dev_class_t *get_dev_class(class_list_t *class_list, char *class_name)
-{
-	dev_class_t *cl;
-	
-	fibril_rwlock_write_lock(&class_list->rwlock);
-	cl = find_dev_class_no_lock(class_list, class_name);
-	if (cl == NULL) {
-		cl = create_dev_class();
-		if (cl != NULL) {
-			cl->name = class_name;
-			cl->base_dev_name = "";
-			add_dev_class_no_lock(class_list, cl);
-		}
-	}
-
-	fibril_rwlock_write_unlock(&class_list->rwlock);
-	return cl;
-}
-
-dev_class_t *find_dev_class_no_lock(class_list_t *class_list,
-    const char *class_name)
-{
-	dev_class_t *cl;
-	
-	list_foreach(class_list->classes, link) {
-		cl = list_get_instance(link, dev_class_t, link);
-		if (str_cmp(cl->name, class_name) == 0) {
-			return cl;
-		}
-	}
-	
-	return NULL;
-}
-
-void add_dev_class_no_lock(class_list_t *class_list, dev_class_t *cl)
-{
-	list_append(&cl->link, &class_list->classes);
-}
-
-dev_class_info_t *find_dev_in_class(dev_class_t *dev_class, const char *dev_name)
-{
-	assert(dev_class != NULL);
-	assert(dev_name != NULL);
-
-	list_foreach(dev_class->devices, link) {
-		dev_class_info_t *dev = list_get_instance(link,
-		    dev_class_info_t, link);
-
-		if (str_cmp(dev->dev_name, dev_name) == 0) {
-			return dev;
-		}
-	}
-
-	return NULL;
-}
-
-void init_class_list(class_list_t *class_list)
-{
-	list_initialize(&class_list->classes);
-	fibril_rwlock_initialize(&class_list->rwlock);
-	hash_table_create(&class_list->devmap_functions, DEVICE_BUCKETS, 1,
-	    &devmap_devices_class_ops);
-}
-
-
-/* Devmap devices */
-
-fun_node_t *find_devmap_tree_function(dev_tree_t *tree, devmap_handle_t devmap_handle)
+/* loc devices */
+
+fun_node_t *find_loc_tree_function(dev_tree_t *tree, service_id_t service_id)
 {
 	fun_node_t *fun = NULL;
 	link_t *link;
-	unsigned long key = (unsigned long) devmap_handle;
+	unsigned long key = (unsigned long) service_id;
 	
 	fibril_rwlock_read_lock(&tree->rwlock);
-	link = hash_table_find(&tree->devmap_functions, &key);
+	link = hash_table_find(&tree->loc_functions, &key);
 	if (link != NULL)
-		fun = hash_table_get_instance(link, fun_node_t, devmap_fun);
+		fun = hash_table_get_instance(link, fun_node_t, loc_fun);
 	fibril_rwlock_read_unlock(&tree->rwlock);
 	
@@ -1435,40 +1235,9 @@
 }
 
-fun_node_t *find_devmap_class_function(class_list_t *classes,
-    devmap_handle_t devmap_handle)
-{
-	fun_node_t *fun = NULL;
-	dev_class_info_t *cli;
-	link_t *link;
-	unsigned long key = (unsigned long)devmap_handle;
-	
-	fibril_rwlock_read_lock(&classes->rwlock);
-	link = hash_table_find(&classes->devmap_functions, &key);
-	if (link != NULL) {
-		cli = hash_table_get_instance(link, dev_class_info_t,
-		    devmap_link);
-		fun = cli->fun;
-	}
-	fibril_rwlock_read_unlock(&classes->rwlock);
-	
-	return fun;
-}
-
-void class_add_devmap_function(class_list_t *class_list, dev_class_info_t *cli)
-{
-	unsigned long key = (unsigned long) cli->devmap_handle;
-	
-	fibril_rwlock_write_lock(&class_list->rwlock);
-	hash_table_insert(&class_list->devmap_functions, &key, &cli->devmap_link);
-	fibril_rwlock_write_unlock(&class_list->rwlock);
-
-	assert(find_devmap_class_function(class_list, cli->devmap_handle) != NULL);
-}
-
-void tree_add_devmap_function(dev_tree_t *tree, fun_node_t *fun)
-{
-	unsigned long key = (unsigned long) fun->devmap_handle;
+void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun)
+{
+	unsigned long key = (unsigned long) fun->service_id;
 	fibril_rwlock_write_lock(&tree->rwlock);
-	hash_table_insert(&tree->devmap_functions, &key, &fun->devmap_fun);
+	hash_table_insert(&tree->loc_functions, &key, &fun->loc_fun);
 	fibril_rwlock_write_unlock(&tree->rwlock);
 }
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/devman/devman.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -41,5 +42,5 @@
 #include <adt/hash_table.h>
 #include <ipc/devman.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 #include <fibril_synch.h>
 #include <atomic.h>
@@ -53,7 +54,6 @@
 #define DEVICE_BUCKETS 256
 
-#define DEVMAP_CLASS_NAMESPACE "class"
-#define DEVMAP_DEVICE_NAMESPACE "devices"
-#define DEVMAP_SEPARATOR '\\'
+#define LOC_DEVICE_NAMESPACE "devices"
+#define LOC_SEPARATOR '\\'
 
 struct dev_node;
@@ -62,4 +62,9 @@
 struct fun_node;
 typedef struct fun_node fun_node_t;
+
+typedef struct {
+	fibril_mutex_t mutex;
+	struct driver *driver;
+} client_t;
 
 typedef enum {
@@ -155,4 +160,6 @@
 	/** Name of the function, assigned by the device driver */
 	char *name;
+	/** Function type */
+	fun_type_t ftype;
 	
 	/** Full path and name of the device in device hierarchy */
@@ -170,8 +177,6 @@
 	match_id_list_t match_ids;
 	
-	/** List of device classes to which this device function belongs. */
-	list_t classes;
-	/** Devmap handle if the device function is registered by devmap. */
-	devmap_handle_t devmap_handle;
+	/** Service ID if the device function is registered with loc. */
+	service_id_t service_id;
 	
 	/**
@@ -181,7 +186,7 @@
 	
 	/**
-	 * Used by the hash table of functions indexed by devmap device handles.
-	 */
-	link_t devmap_fun;
+	 * Used by the hash table of functions indexed by service IDs.
+	 */
+	link_t loc_fun;
 };
 
@@ -208,87 +213,9 @@
 	
 	/**
-	 * Hash table of devices registered by devmapper, indexed by devmap
-	 * handles.
-	 */
-	hash_table_t devmap_functions;
+	 * Hash table of services registered with location service, indexed by
+	 * service IDs.
+	 */
+	hash_table_t loc_functions;
 } dev_tree_t;
-
-typedef struct dev_class {
-	/** The name of the class. */
-	const char *name;
-	
-	/**
-	 * Pointer to the previous and next class in the list of registered
-	 * classes.
-	 */
-	link_t link;
-	
-	/**
-	 * List of dev_class_info structures - one for each device registered by
-	 * this class.
-	 */
-	list_t devices;
-	
-	/**
-	 * Default base name for the device within the class, might be overrided
-	 * by the driver.
-	 */
-	const char *base_dev_name;
-	
-	/** Unique numerical identifier of the newly added device. */
-	size_t curr_dev_idx;
-	/** Synchronize access to the list of devices in this class. */
-	fibril_mutex_t mutex;
-} dev_class_t;
-
-/**
- * Provides n-to-m mapping between function nodes and classes - each function
- * can register in an arbitrary number of classes and each class can contain
- * an arbitrary number of device functions.
- */
-typedef struct dev_class_info {
-	/** The class. */
-	dev_class_t *dev_class;
-	/** The device. */
-	fun_node_t *fun;
-	
-	/**
-	 * Pointer to the previous and next class info in the list of devices
-	 * registered by the class.
-	 */
-	link_t link;
-	
-	/**
-	 * Pointer to the previous and next class info in the list of classes
-	 * by which the device is registered.
-	 */
-	link_t dev_classes;
-	
-	/** The name of the device function within the class. */
-	char *dev_name;
-	/** The handle of the device by device mapper in the class namespace. */
-	devmap_handle_t devmap_handle;
-	
-	/**
-	 * Link in the hash table of devices registered by the devmapper using
-	 * their class names.
-	 */
-	link_t devmap_link;
-} dev_class_info_t;
-
-/** The list of device classes. */
-typedef struct class_list {
-	/** List of classes. */
-	list_t classes;
-	
-	/**
-	 * Hash table of devices registered by devmapper using their class name,
-	 * indexed by devmap handles.
-	 */
-	hash_table_t devmap_functions;
-	
-	/** Fibril mutex for list of classes. */
-	fibril_rwlock_t rwlock;
-} class_list_t;
 
 /* Match ids and scores */
@@ -313,5 +240,5 @@
 extern void add_driver(driver_list_t *, driver_t *);
 extern void attach_driver(dev_node_t *, driver_t *);
-extern void add_device(async_sess_t *, driver_t *, dev_node_t *, dev_tree_t *);
+extern void add_device(driver_t *, dev_node_t *, dev_tree_t *);
 extern bool start_driver(driver_t *);
 
@@ -331,4 +258,6 @@
 extern dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle);
 extern dev_node_t *find_dev_function(dev_node_t *, const char *);
+extern int dev_get_functions(dev_tree_t *tree, dev_node_t *, devman_handle_t *,
+    size_t, size_t *);
 
 extern fun_node_t *create_fun_node(void);
@@ -339,5 +268,4 @@
 extern fun_node_t *find_fun_node_by_path(dev_tree_t *, char *);
 extern fun_node_t *find_fun_node_in_device(dev_node_t *, const char *);
-extern fun_node_t *find_fun_node_by_class(class_list_t *, const char *, const char *);
 
 /* Device tree */
@@ -347,30 +275,13 @@
 extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *);
 extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *);
-
-/* Device classes */
-
-extern dev_class_t *create_dev_class(void);
-extern dev_class_info_t *create_dev_class_info(void);
-extern size_t get_new_class_dev_idx(dev_class_t *);
-extern char *create_dev_name_for_class(dev_class_t *, const char *);
-extern dev_class_info_t *add_function_to_class(fun_node_t *, dev_class_t *,
-    const char *);
-
-extern void init_class_list(class_list_t *);
-
-extern dev_class_t *get_dev_class(class_list_t *, char *);
-extern dev_class_t *find_dev_class_no_lock(class_list_t *, const char *);
-extern dev_class_info_t *find_dev_in_class(dev_class_t *, const char *);
-extern void add_dev_class_no_lock(class_list_t *, dev_class_t *);
-
-/* Devmap devices */
-
-extern void devmap_register_tree_function(fun_node_t *, dev_tree_t *);
-
-extern fun_node_t *find_devmap_tree_function(dev_tree_t *, devmap_handle_t);
-extern fun_node_t *find_devmap_class_function(class_list_t *, devmap_handle_t);
-
-extern void class_add_devmap_function(class_list_t *, dev_class_info_t *);
-extern void tree_add_devmap_function(dev_tree_t *, fun_node_t *);
+extern void remove_fun_node(dev_tree_t *, fun_node_t *);
+
+/* Loc services */
+
+extern void loc_register_tree_function(fun_node_t *, dev_tree_t *);
+
+extern fun_node_t *find_loc_tree_function(dev_tree_t *, service_id_t);
+
+extern void tree_add_loc_function(dev_tree_t *, fun_node_t *);
 
 #endif
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/devman/main.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -56,5 +56,5 @@
 #include <ipc/driver.h>
 #include <thread.h>
-#include <devmap.h>
+#include <loc.h>
 
 #include "devman.h"
@@ -64,27 +64,19 @@
 static driver_list_t drivers_list;
 static dev_tree_t device_tree;
-static class_list_t class_list;
+
+static int init_running_drv(void *drv);
 
 /** Register running driver. */
-static driver_t *devman_driver_register(void)
-{
-	ipc_call_t icall;
-	ipc_callid_t iid;
+static driver_t *devman_driver_register(ipc_callid_t callid, ipc_call_t *call)
+{
 	driver_t *driver = NULL;
+	char *drv_name = NULL;
 
 	log_msg(LVL_DEBUG, "devman_driver_register");
-	
-	iid = async_get_call(&icall);
-	if (IPC_GET_IMETHOD(icall) != DEVMAN_DRIVER_REGISTER) {
-		async_answer_0(iid, EREFUSED);
-		return NULL;
-	}
-	
-	char *drv_name = NULL;
 	
 	/* Get driver name. */
 	int rc = async_data_write_accept((void **) &drv_name, true, 0, 0, 0, 0);
 	if (rc != EOK) {
-		async_answer_0(iid, rc);
+		async_answer_0(callid, rc);
 		return NULL;
 	}
@@ -99,5 +91,5 @@
 		free(drv_name);
 		drv_name = NULL;
-		async_answer_0(iid, ENOENT);
+		async_answer_0(callid, ENOENT);
 		return NULL;
 	}
@@ -113,5 +105,5 @@
 		    driver->name);
 		fibril_mutex_unlock(&driver->driver_mutex);
-		async_answer_0(iid, EEXISTS);
+		async_answer_0(callid, EEXISTS);
 		return NULL;
 	}
@@ -135,12 +127,12 @@
 	log_msg(LVL_DEBUG, "Creating connection to the `%s' driver.",
 	    driver->name);
-	driver->sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	driver->sess = async_callback_receive(EXCHANGE_PARALLEL);
 	if (!driver->sess) {
 		fibril_mutex_unlock(&driver->driver_mutex);
-		async_answer_0(iid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
 		return NULL;
 	}
-	
-	fibril_mutex_unlock(&driver->driver_mutex);
+	/* FIXME: Work around problem with callback sessions */
+	async_sess_args_set(driver->sess, DRIVER_DEVMAN, 0, 0);
 	
 	log_msg(LVL_NOTE,
@@ -148,6 +140,22 @@
 	    driver->name);
 	
-	async_answer_0(iid, EOK);
-	
+	/*
+	 * Initialize the driver as running (e.g. pass assigned devices to it)
+	 * in a separate fibril; the separate fibril is used to enable the
+	 * driver to use devman service during the driver's initialization.
+	 */
+	fid_t fid = fibril_create(init_running_drv, driver);
+	if (fid == 0) {
+		log_msg(LVL_ERROR, "Failed to create initialization fibril " \
+		    "for driver `%s'.", driver->name);
+		fibril_mutex_unlock(&driver->driver_mutex);
+		async_answer_0(callid, ENOMEM);
+		return NULL;
+	}
+	
+	fibril_add_ready(fid);
+	fibril_mutex_unlock(&driver->driver_mutex);
+	
+	async_answer_0(callid, EOK);
 	return driver;
 }
@@ -279,6 +287,8 @@
 		return;
 	}
-
+	
 	fun_node_t *fun = create_fun_node();
+	fun->ftype = ftype;
+	
 	if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
@@ -326,5 +336,5 @@
 		}
 	} else {
-		devmap_register_tree_function(fun, tree);
+		loc_register_tree_function(fun, tree);
 	}
 	
@@ -333,37 +343,13 @@
 }
 
-static void devmap_register_class_dev(dev_class_info_t *cli)
-{
-	/* Create devmap path and name for the device. */
-	char *devmap_pathname = NULL;
-
-	asprintf(&devmap_pathname, "%s/%s%c%s", DEVMAP_CLASS_NAMESPACE,
-	    cli->dev_class->name, DEVMAP_SEPARATOR, cli->dev_name);
-	if (devmap_pathname == NULL)
-		return;
-	
-	/*
-	 * Register the device by the device mapper and remember its devmap
-	 * handle.
-	 */
-	devmap_device_register_with_iface(devmap_pathname,
-	    &cli->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
-	
-	/*
-	 * Add device to the hash map of class devices registered by device
-	 * mapper.
-	 */
-	class_add_devmap_function(&class_list, cli);
-	
-	free(devmap_pathname);
-}
-
-static void devman_add_function_to_class(ipc_callid_t callid, ipc_call_t *call)
+static void devman_add_function_to_cat(ipc_callid_t callid, ipc_call_t *call)
 {
 	devman_handle_t handle = IPC_GET_ARG1(*call);
-	
-	/* Get class name. */
-	char *class_name;
-	int rc = async_data_write_accept((void **) &class_name, true,
+	category_id_t cat_id;
+	int rc;
+	
+	/* Get category name. */
+	char *cat_name;
+	rc = async_data_write_accept((void **) &cat_name, true,
 	    0, 0, 0, 0);
 	if (rc != EOK) {
@@ -378,13 +364,57 @@
 	}
 	
-	dev_class_t *cl = get_dev_class(&class_list, class_name);
-	dev_class_info_t *class_info = add_function_to_class(fun, cl, NULL);
-	
-	/* Register the device's class alias by devmapper. */
-	devmap_register_class_dev(class_info);
-	
-	log_msg(LVL_NOTE, "Function `%s' added to class `%s' as `%s'.",
-	    fun->pathname, class_name, class_info->dev_name);
-
+	rc = loc_category_get_id(cat_name, &cat_id, IPC_FLAG_BLOCKING);
+	if (rc == EOK) {
+		loc_service_add_to_cat(fun->service_id, cat_id);
+	} else {
+		log_msg(LVL_ERROR, "Failed adding function `%s' to category "
+		    "`%s'.", fun->pathname, cat_name);
+	}
+	
+	log_msg(LVL_NOTE, "Function `%s' added to category `%s'.",
+	    fun->pathname, cat_name);
+
+	async_answer_0(callid, EOK);
+}
+
+/** Remove function. */
+static void devman_remove_function(ipc_callid_t callid, ipc_call_t *call)
+{
+	devman_handle_t fun_handle = IPC_GET_ARG1(*call);
+	dev_tree_t *tree = &device_tree;
+	int rc;
+	
+	fibril_rwlock_write_lock(&tree->rwlock);
+	
+	fun_node_t *fun = find_fun_node_no_lock(&device_tree, fun_handle);
+	if (fun == NULL) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);
+	
+	if (fun->ftype == fun_inner) {
+		/* Handle possible descendants */
+		/* TODO */
+		log_msg(LVL_WARN, "devman_remove_function(): not handling "
+		    "descendants\n");
+	} else {
+		/* Unregister from location service */
+		rc = loc_service_unregister(fun->service_id);
+		if (rc != EOK) {
+			log_msg(LVL_ERROR, "Failed unregistering tree service.");
+			fibril_rwlock_write_unlock(&tree->rwlock);
+			async_answer_0(callid, EIO);
+			return;
+		}
+	}
+	
+	remove_fun_node(&device_tree, fun);
+	fibril_rwlock_write_unlock(&tree->rwlock);
+	delete_fun_node(fun);
+	
+	log_msg(LVL_DEBUG, "devman_remove_function() succeeded.");
 	async_answer_0(callid, EOK);
 }
@@ -408,23 +438,15 @@
 static void devman_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
 {
+	client_t *client;
+	driver_t *driver;
+	
 	/* Accept the connection. */
 	async_answer_0(iid, EOK);
 	
-	driver_t *driver = devman_driver_register();
-	if (driver == NULL)
-		return;
-	
-	/*
-	 * Initialize the driver as running (e.g. pass assigned devices to it)
-	 * in a separate fibril; the separate fibril is used to enable the
-	 * driver to use devman service during the driver's initialization.
-	 */
-	fid_t fid = fibril_create(init_running_drv, driver);
-	if (fid == 0) {
-		log_msg(LVL_ERROR, "Failed to create initialization fibril " \
-		    "for driver `%s'.", driver->name);
-		return;
-	}
-	fibril_add_ready(fid);
+	client = async_get_client_data();
+	if (client == NULL) {
+		log_msg(LVL_ERROR, "Failed to allocate client data.");
+		return;
+	}
 	
 	while (true) {
@@ -435,10 +457,34 @@
 			break;
 		
+		if (IPC_GET_IMETHOD(call) != DEVMAN_DRIVER_REGISTER) {
+			fibril_mutex_lock(&client->mutex);
+			driver = client->driver;
+			fibril_mutex_unlock(&client->mutex);
+			if (driver == NULL) {
+				/* First call must be to DEVMAN_DRIVER_REGISTER */
+				async_answer_0(callid, ENOTSUP);
+				continue;
+			}
+		}
+		
 		switch (IPC_GET_IMETHOD(call)) {
+		case DEVMAN_DRIVER_REGISTER:
+			fibril_mutex_lock(&client->mutex);
+			if (client->driver != NULL) {
+				fibril_mutex_unlock(&client->mutex);
+				async_answer_0(callid, EINVAL);
+				continue;
+			}
+			client->driver = devman_driver_register(callid, &call);
+			fibril_mutex_unlock(&client->mutex);
+			break;
 		case DEVMAN_ADD_FUNCTION:
 			devman_add_function(callid, &call);
 			break;
-		case DEVMAN_ADD_DEVICE_TO_CLASS:
-			devman_add_function_to_class(callid, &call);
+		case DEVMAN_ADD_DEVICE_TO_CATEGORY:
+			devman_add_function_to_cat(callid, &call);
+			break;
+		case DEVMAN_REMOVE_FUNCTION:
+			devman_remove_function(callid, &call);
 			break;
 		default:
@@ -473,41 +519,6 @@
 }
 
-/** Find handle for the device instance identified by device class name. */
-static void devman_function_get_handle_by_class(ipc_callid_t iid,
-    ipc_call_t *icall)
-{
-	char *classname;
-	char *devname;
-
-	int rc = async_data_write_accept((void **) &classname, true, 0, 0, 0, 0);
-	if (rc != EOK) {
-		async_answer_0(iid, rc);
-		return;
-	}
-	rc = async_data_write_accept((void **) &devname, true, 0, 0, 0, 0);
-	if (rc != EOK) {
-		free(classname);
-		async_answer_0(iid, rc);
-		return;
-	}
-
-
-	fun_node_t *fun = find_fun_node_by_class(&class_list,
-	    classname, devname);
-
-	free(classname);
-	free(devname);
-
-	if (fun == NULL) {
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-
-	async_answer_1(iid, EOK, fun->handle);
-}
-
-/** Find device path by its handle. */
-static void devman_get_device_path_by_handle(ipc_callid_t iid,
-    ipc_call_t *icall)
+/** Get device name. */
+static void devman_fun_get_name(ipc_callid_t iid, ipc_call_t *icall)
 {
 	devman_handle_t handle = IPC_GET_ARG1(*icall);
@@ -533,4 +544,41 @@
 	}
 
+	size_t sent_length = str_size(fun->name);
+	if (sent_length > data_len) {
+		sent_length = data_len;
+	}
+
+	async_data_read_finalize(data_callid, fun->name, sent_length);
+	async_answer_0(iid, EOK);
+
+	free(buffer);
+}
+
+
+/** Get device path. */
+static void devman_fun_get_path(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t handle = IPC_GET_ARG1(*icall);
+
+	fun_node_t *fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	size_t data_len;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
 	size_t sent_length = str_size(fun->pathname);
 	if (sent_length > data_len) {
@@ -544,4 +592,92 @@
 }
 
+static void devman_dev_get_functions(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	int rc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+	
+	dev_node_t *dev = find_dev_node_no_lock(&device_tree,
+	    IPC_GET_ARG1(*icall));
+	if (dev == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
+	if (hdl_buf == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	rc = dev_get_functions(&device_tree, dev, hdl_buf, size, &act_size);
+	if (rc != EOK) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	
+	sysarg_t retval = async_data_read_finalize(callid, hdl_buf, size);
+	free(hdl_buf);
+	
+	async_answer_1(iid, retval, act_size);
+}
+
+
+/** Get handle for child device of a function. */
+static void devman_fun_get_child(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fun_node_t *fun;
+	
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+	
+	fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
+	if (fun == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	if (fun->child == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	async_answer_1(iid, EOK, fun->child->handle);
+	
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+}
+
+/** Find handle for the function instance identified by its service ID. */
+static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fun_node_t *fun;
+
+	fun = find_loc_tree_function(&device_tree, IPC_GET_ARG1(*icall));
+	
+	if (fun == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	async_answer_1(iid, EOK, fun->handle);
+}
 
 /** Function for handling connections from a client to the device manager. */
@@ -562,9 +698,18 @@
 			devman_function_get_handle(callid, &call);
 			break;
-		case DEVMAN_DEVICE_GET_HANDLE_BY_CLASS:
-			devman_function_get_handle_by_class(callid, &call);
-			break;
-		case DEVMAN_DEVICE_GET_DEVICE_PATH:
-			devman_get_device_path_by_handle(callid, &call);
+		case DEVMAN_DEV_GET_FUNCTIONS:
+			devman_dev_get_functions(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_CHILD:
+			devman_fun_get_child(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_NAME:
+			devman_fun_get_name(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_PATH:
+			devman_fun_get_path(callid, &call);
+			break;
+		case DEVMAN_FUN_SID_TO_HANDLE:
+			devman_fun_sid_to_handle(callid, &call);
 			break;
 		default:
@@ -659,17 +804,17 @@
 }
 
-/** Function for handling connections from a client forwarded by the device
- * mapper to the device manager. */
-static void devman_connection_devmapper(ipc_callid_t iid, ipc_call_t *icall)
-{
-	devmap_handle_t devmap_handle = IPC_GET_ARG2(*icall);
+/** Function for handling connections from a client forwarded by the location
+ * service to the device manager. */
+static void devman_connection_loc(ipc_callid_t iid, ipc_call_t *icall)
+{
+	service_id_t service_id = IPC_GET_ARG2(*icall);
 	fun_node_t *fun;
 	dev_node_t *dev;
 
-	fun = find_devmap_tree_function(&device_tree, devmap_handle);
-	if (fun == NULL)
-		fun = find_devmap_class_function(&class_list, devmap_handle);
+	fun = find_loc_tree_function(&device_tree, service_id);
 	
 	if (fun == NULL || fun->dev->drv == NULL) {
+		log_msg(LVL_WARN, "devman_connection_loc(): function "
+		    "not found.\n");
 		async_answer_0(iid, ENOENT);
 		return;
@@ -677,9 +822,4 @@
 	
 	dev = fun->dev;
-	
-	if ((dev->state != DEVICE_USABLE) || (!dev->drv->sess)) {
-		async_answer_0(iid, EINVAL);
-		return;
-	}
 	
 	async_exch_t *exch = async_exchange_begin(dev->drv->sess);
@@ -689,5 +829,5 @@
 	
 	log_msg(LVL_DEBUG,
-	    "Forwarding devmapper request for `%s' function to driver `%s'.",
+	    "Forwarding loc service request for `%s' function to driver `%s'.",
 	    fun->pathname, dev->drv->name);
 }
@@ -696,5 +836,5 @@
 static void devman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	/* Select interface. */
+	/* Select port. */
 	switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
 	case DEVMAN_DRIVER:
@@ -708,7 +848,7 @@
 		devman_forward(iid, icall, false);
 		break;
-	case DEVMAN_CONNECT_FROM_DEVMAP:
-		/* Someone connected through devmap node. */
-		devman_connection_devmapper(iid, icall);
+	case DEVMAN_CONNECT_FROM_LOC:
+		/* Someone connected through loc node. */
+		devman_connection_loc(iid, icall);
 		break;
 	case DEVMAN_CONNECT_TO_PARENTS_DEVICE:
@@ -722,4 +862,21 @@
 }
 
+static void *devman_client_data_create(void)
+{
+	client_t *client;
+	
+	client = calloc(1, sizeof(client_t));
+	if (client == NULL)
+		return NULL;
+	
+	fibril_mutex_initialize(&client->mutex);
+	return client;
+}
+
+static void devman_client_data_destroy(void *data)
+{
+	free(data);
+}
+
 /** Initialize device manager internal structures. */
 static bool devman_init(void)
@@ -743,13 +900,11 @@
 	}
 
-	init_class_list(&class_list);
-	
 	/*
-	 * !!! devman_connection ... as the device manager is not a real devmap
+	 * !!! devman_connection ... as the device manager is not a real loc
 	 * driver (it uses a completely different ipc protocol than an ordinary
-	 * devmap driver) forwarding a connection from client to the devman by
-	 * devmapper would not work.
+	 * loc driver) forwarding a connection from client to the devman by
+	 * location service would not work.
 	 */
-	devmap_driver_register(NAME, devman_connection);
+	loc_server_register(NAME, devman_connection);
 	
 	return true;
@@ -760,5 +915,5 @@
 	printf(NAME ": HelenOS Device Manager\n");
 
-	if (log_init(NAME, LVL_ERROR) != EOK) {
+	if (log_init(NAME, LVL_WARN) != EOK) {
 		printf(NAME ": Error initializing logging subsystem.\n");
 		return -1;
@@ -770,5 +925,7 @@
 	}
 	
-	/* Set a handler of incomming connections. */
+	/* Set handlers for incoming connections. */
+	async_set_client_data_constructor(devman_client_data_create);
+	async_set_client_data_destructor(devman_client_data_destroy);
 	async_set_client_connection(devman_connection);
 
Index: uspace/srv/devman/util.c
===================================================================
--- uspace/srv/devman/util.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/devman/util.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -91,15 +91,4 @@
 }
 
-char *clone_string(const char *s)
-{
-	size_t size = str_size(s) + 1;
-	char *str;
-	
-	str = (char *) malloc(size);
-	if (str != NULL)
-		str_cpy(str, size, s);
-	return str;
-}
-
 void replace_char(char *str, char orig, char repl)
 {
@@ -111,31 +100,4 @@
 }
 
-ssize_t safe_read(int fd, void *buffer, size_t size)
-{
-	if (size == 0) {
-		return 0;
-	}
-
-	uint8_t *buf_ptr = (uint8_t *) buffer;
-
-	size_t total_read = 0;
-	while (total_read < size) {
-		ssize_t bytes_read = read(fd, buf_ptr, size - total_read);
-		if (bytes_read < 0) {
-			/* Error. */
-			return bytes_read;
-		} else if (bytes_read == 0) {
-			/* Possibly end of file. */
-			break;
-		} else {
-			/* Read at least something. */
-			buf_ptr += bytes_read;
-			total_read += bytes_read;
-		}
-	}
-
-	return (ssize_t) total_read;
-}
-
 /** @}
  */
Index: uspace/srv/devman/util.h
===================================================================
--- uspace/srv/devman/util.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/devman/util.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -44,8 +44,5 @@
 extern size_t get_nonspace_len(const char *);
 extern void free_not_null(const void *);
-extern char *clone_string(const char *);
 extern void replace_char(char *, char, char);
-
-extern ssize_t safe_read(int, void *, size_t);
 
 #endif
Index: pace/srv/devmap/Makefile
===================================================================
--- uspace/srv/devmap/Makefile	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,37 +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 = ../..
-BINARY = devmap
-STATIC_NEEDED = y
-
-SOURCES = \
-	devmap.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,1163 +1,0 @@
-/*
- * Copyright (c) 2007 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.
- */
-
-/**
- * @defgroup devmap Device mapper.
- * @brief HelenOS device mapper.
- * @{
- */
-
-/** @file
- */
-
-#include <ipc/services.h>
-#include <ns.h>
-#include <async.h>
-#include <stdio.h>
-#include <errno.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <stdlib.h>
-#include <str.h>
-#include <ipc/devmap.h>
-#include <assert.h>
-
-#define NAME          "devmap"
-#define NULL_DEVICES  256
-
-/** Representation of device driver.
- *
- * Each driver is responsible for a set of devices.
- *
- */
-typedef struct {
-	/** Link to drivers_list */
-	link_t drivers;
-	
-	/** List of devices controlled by this driver */
-	list_t devices;
-	
-	/** Session asociated with this driver */
-	async_sess_t *sess;
-	
-	/** Device driver name */
-	char *name;
-	
-	/** Fibril mutex for list of devices owned by this driver */
-	fibril_mutex_t devices_mutex;
-} devmap_driver_t;
-
-/** Info about registered namespaces
- *
- */
-typedef struct {
-	/** Link to namespaces_list */
-	link_t namespaces;
-	
-	/** Unique namespace identifier */
-	devmap_handle_t handle;
-	
-	/** Namespace name */
-	char *name;
-	
-	/** Reference count */
-	size_t refcnt;
-} devmap_namespace_t;
-
-/** Info about registered device
- *
- */
-typedef struct {
-	/** Link to global list of devices (devices_list) */
-	link_t devices;
-	/** Link to driver list of devices (devmap_driver_t.devices) */
-	link_t driver_devices;
-	/** Unique device identifier */
-	devmap_handle_t handle;
-	/** Device namespace */
-	devmap_namespace_t *namespace;
-	/** Device name */
-	char *name;
-	/** Device driver handling this device */
-	devmap_driver_t *driver;
-	/** Use this interface when forwarding to driver. */
-	sysarg_t forward_interface;
-} devmap_device_t;
-
-LIST_INITIALIZE(devices_list);
-LIST_INITIALIZE(namespaces_list);
-LIST_INITIALIZE(drivers_list);
-
-/* Locking order:
- *  drivers_list_mutex
- *  devices_list_mutex
- *  (devmap_driver_t *)->devices_mutex
- *  create_handle_mutex
- **/
-
-static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
-static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv);
-static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
-static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
-static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex);
-
-static devmap_handle_t last_handle = 0;
-static devmap_device_t *null_devices[NULL_DEVICES];
-
-/*
- * Dummy list for null devices. This is necessary so that null devices can
- * be used just as any other devices, e.g. in devmap_device_unregister_core().
- */
-static LIST_INITIALIZE(dummy_null_driver_devices);
-
-static devmap_handle_t devmap_create_handle(void)
-{
-	/* TODO: allow reusing old handles after their unregistration
-	 * and implement some version of LRU algorithm, avoid overflow
-	 */
-	
-	fibril_mutex_lock(&create_handle_mutex);
-	last_handle++;
-	fibril_mutex_unlock(&create_handle_mutex);
-	
-	return last_handle;
-}
-
-/** Convert fully qualified device name to namespace and device name.
- *
- * A fully qualified device name can be either a plain device name
- * (then the namespace is considered to be an empty string) or consist
- * of two components separated by a slash. No more than one slash
- * is allowed.
- *
- */
-static bool devmap_fqdn_split(const char *fqdn, char **ns_name, char **name)
-{
-	size_t cnt = 0;
-	size_t slash_offset = 0;
-	size_t slash_after = 0;
-	
-	size_t offset = 0;
-	size_t offset_prev = 0;
-	wchar_t c;
-	
-	while ((c = str_decode(fqdn, &offset, STR_NO_LIMIT)) != 0) {
-		if (c == '/') {
-			cnt++;
-			slash_offset = offset_prev;
-			slash_after = offset;
-		}
-		offset_prev = offset;
-	}
-	
-	/* More than one slash */
-	if (cnt > 1)
-		return false;
-	
-	/* No slash -> namespace is empty */
-	if (cnt == 0) {
-		*ns_name = str_dup("");
-		if (*ns_name == NULL)
-			return false;
-		
-		*name = str_dup(fqdn);
-		if (*name == NULL) {
-			free(*ns_name);
-			return false;
-		}
-		
-		if (str_cmp(*name, "") == 0) {
-			free(*name);
-			free(*ns_name);
-			return false;
-		}
-		
-		return true;
-	}
-	
-	/* Exactly one slash */
-	*ns_name = str_ndup(fqdn, slash_offset);
-	if (*ns_name == NULL)
-		return false;
-	
-	*name = str_dup(fqdn + slash_after);
-	if (*name == NULL) {
-		free(*ns_name);
-		return false;
-	}
-	
-	if (str_cmp(*name, "") == 0) {
-		free(*name);
-		free(*ns_name);
-		return false;
-	}
-	
-	return true;
-}
-
-/** Find namespace with given name. */
-static devmap_namespace_t *devmap_namespace_find_name(const char *name)
-{
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-	
-	list_foreach(namespaces_list, item) {
-		devmap_namespace_t *namespace =
-		    list_get_instance(item, devmap_namespace_t, namespaces);
-		if (str_cmp(namespace->name, name) == 0)
-			return namespace;
-	}
-	
-	return NULL;
-}
-
-/** Find namespace with given handle.
- *
- * @todo: use hash table
- *
- */
-static devmap_namespace_t *devmap_namespace_find_handle(devmap_handle_t handle)
-{
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-	
-	list_foreach(namespaces_list, item) {
-		devmap_namespace_t *namespace =
-		    list_get_instance(item, devmap_namespace_t, namespaces);
-		if (namespace->handle == handle)
-			return namespace;
-	}
-	
-	return NULL;
-}
-
-/** Find device with given name. */
-static devmap_device_t *devmap_device_find_name(const char *ns_name,
-    const char *name)
-{
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-	
-	list_foreach(devices_list, item) {
-		devmap_device_t *device =
-		    list_get_instance(item, devmap_device_t, devices);
-		if ((str_cmp(device->namespace->name, ns_name) == 0)
-		    && (str_cmp(device->name, name) == 0))
-			return device;
-	}
-	
-	return NULL;
-}
-
-/** Find device with given handle.
- *
- * @todo: use hash table
- *
- */
-static devmap_device_t *devmap_device_find_handle(devmap_handle_t handle)
-{
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-	
-	list_foreach(devices_list, item) {
-		devmap_device_t *device =
-		    list_get_instance(item, devmap_device_t, devices);
-		if (device->handle == handle)
-			return device;
-	}
-	
-	return NULL;
-}
-
-/** Create a namespace (if not already present). */
-static devmap_namespace_t *devmap_namespace_create(const char *ns_name)
-{
-	devmap_namespace_t *namespace;
-	
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-	
-	namespace = devmap_namespace_find_name(ns_name);
-	if (namespace != NULL)
-		return namespace;
-	
-	namespace = (devmap_namespace_t *) malloc(sizeof(devmap_namespace_t));
-	if (namespace == NULL)
-		return NULL;
-	
-	namespace->name = str_dup(ns_name);
-	if (namespace->name == NULL) {
-		free(namespace);
-		return NULL;
-	}
-	
-	namespace->handle = devmap_create_handle();
-	namespace->refcnt = 0;
-	
-	/*
-	 * Insert new namespace into list of registered namespaces
-	 */
-	list_append(&(namespace->namespaces), &namespaces_list);
-	
-	return namespace;
-}
-
-/** Destroy a namespace (if it is no longer needed). */
-static void devmap_namespace_destroy(devmap_namespace_t *namespace)
-{
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-
-	if (namespace->refcnt == 0) {
-		list_remove(&(namespace->namespaces));
-		
-		free(namespace->name);
-		free(namespace);
-	}
-}
-
-/** Increase namespace reference count by including device. */
-static void devmap_namespace_addref(devmap_namespace_t *namespace,
-    devmap_device_t *device)
-{
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-
-	device->namespace = namespace;
-	namespace->refcnt++;
-}
-
-/** Decrease namespace reference count. */
-static void devmap_namespace_delref(devmap_namespace_t *namespace)
-{
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-
-	namespace->refcnt--;
-	devmap_namespace_destroy(namespace);
-}
-
-/** Unregister device and free it. */
-static void devmap_device_unregister_core(devmap_device_t *device)
-{
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-
-	devmap_namespace_delref(device->namespace);
-	list_remove(&(device->devices));
-	list_remove(&(device->driver_devices));
-	
-	free(device->name);
-	free(device);
-}
-
-/**
- * Read info about new driver and add it into linked list of registered
- * drivers.
- */
-static devmap_driver_t *devmap_driver_register(void)
-{
-	ipc_call_t icall;
-	ipc_callid_t iid = async_get_call(&icall);
-	
-	if (IPC_GET_IMETHOD(icall) != DEVMAP_DRIVER_REGISTER) {
-		async_answer_0(iid, EREFUSED);
-		return NULL;
-	}
-	
-	devmap_driver_t *driver =
-	    (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
-	if (driver == NULL) {
-		async_answer_0(iid, ENOMEM);
-		return NULL;
-	}
-	
-	/*
-	 * Get driver name
-	 */
-	int rc = async_data_write_accept((void **) &driver->name, true, 0,
-	    DEVMAP_NAME_MAXLEN, 0, NULL);
-	if (rc != EOK) {
-		free(driver);
-		async_answer_0(iid, rc);
-		return NULL;
-	}
-	
-	/*
-	 * Create connection to the driver
-	 */
-	driver->sess = async_callback_receive(EXCHANGE_SERIALIZE);
-	if (!driver->sess) {
-		free(driver->name);
-		free(driver);
-		async_answer_0(iid, ENOTSUP);
-		return NULL;
-	}
-	
-	/*
-	 * Initialize mutex for list of devices
-	 * owned by this driver
-	 */
-	fibril_mutex_initialize(&driver->devices_mutex);
-	
-	/*
-	 * Initialize list of asociated devices
-	 */
-	list_initialize(&driver->devices);
-
-	link_initialize(&driver->drivers);
-	
-	fibril_mutex_lock(&drivers_list_mutex);
-	
-	/* TODO:
-	 * Check that no driver with name equal to
-	 * driver->name is registered
-	 */
-	
-	/*
-	 * Insert new driver into list of registered drivers
-	 */
-	list_append(&(driver->drivers), &drivers_list);
-	fibril_mutex_unlock(&drivers_list_mutex);
-	
-	async_answer_0(iid, EOK);
-	
-	return driver;
-}
-
-/**
- * Unregister device driver, unregister all its devices and free driver
- * structure.
- *
- */
-static int devmap_driver_unregister(devmap_driver_t *driver)
-{
-	if (driver == NULL)
-		return EEXISTS;
-	
-	fibril_mutex_lock(&drivers_list_mutex);
-	
-	if (driver->sess)
-		async_hangup(driver->sess);
-	
-	/* Remove it from list of drivers */
-	list_remove(&(driver->drivers));
-	
-	/* Unregister all its devices */
-	fibril_mutex_lock(&devices_list_mutex);
-	fibril_mutex_lock(&driver->devices_mutex);
-	
-	while (!list_empty(&driver->devices)) {
-		devmap_device_t *device = list_get_instance(
-		    list_first(&driver->devices), devmap_device_t,
-		    driver_devices);
-		devmap_device_unregister_core(device);
-	}
-	
-	fibril_mutex_unlock(&driver->devices_mutex);
-	fibril_mutex_unlock(&devices_list_mutex);
-	fibril_mutex_unlock(&drivers_list_mutex);
-	
-	/* Free name and driver */
-	if (driver->name != NULL)
-		free(driver->name);
-	
-	free(driver);
-	
-	return EOK;
-}
-
-/** Register instance of device
- *
- */
-static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall,
-    devmap_driver_t *driver)
-{
-	if (driver == NULL) {
-		async_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	/* Create new device entry */
-	devmap_device_t *device =
-	    (devmap_device_t *) malloc(sizeof(devmap_device_t));
-	if (device == NULL) {
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	/* Set the interface, if any. */
-	device->forward_interface = IPC_GET_ARG1(*icall);
-
-	/* Get fqdn */
-	char *fqdn;
-	int rc = async_data_write_accept((void **) &fqdn, true, 0,
-	    DEVMAP_NAME_MAXLEN, 0, NULL);
-	if (rc != EOK) {
-		free(device);
-		async_answer_0(iid, rc);
-		return;
-	}
-	
-	char *ns_name;
-	if (!devmap_fqdn_split(fqdn, &ns_name, &device->name)) {
-		free(fqdn);
-		free(device);
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	free(fqdn);
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	devmap_namespace_t *namespace = devmap_namespace_create(ns_name);
-	free(ns_name);
-	if (namespace == NULL) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		free(device->name);
-		free(device);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	link_initialize(&device->devices);
-	link_initialize(&device->driver_devices);
-	
-	/* Check that device is not already registered */
-	if (devmap_device_find_name(namespace->name, device->name) != NULL) {
-		printf("%s: Device '%s/%s' already registered\n", NAME,
-		    namespace->name, device->name);
-		devmap_namespace_destroy(namespace);
-		fibril_mutex_unlock(&devices_list_mutex);
-		free(device->name);
-		free(device);
-		async_answer_0(iid, EEXISTS);
-		return;
-	}
-	
-	/* Get unique device handle */
-	device->handle = devmap_create_handle();
-
-	devmap_namespace_addref(namespace, device);
-	device->driver = driver;
-	
-	/* Insert device into list of all devices  */
-	list_append(&device->devices, &devices_list);
-	
-	/* Insert device into list of devices that belog to one driver */
-	fibril_mutex_lock(&device->driver->devices_mutex);
-	
-	list_append(&device->driver_devices, &device->driver->devices);
-	
-	fibril_mutex_unlock(&device->driver->devices_mutex);
-	fibril_condvar_broadcast(&devices_list_cv);
-	fibril_mutex_unlock(&devices_list_mutex);
-	
-	async_answer_1(iid, EOK, device->handle);
-}
-
-/**
- *
- */
-static int devmap_device_unregister(ipc_callid_t iid, ipc_call_t *icall, 
-    devmap_driver_t *driver)
-{
-	/* TODO */
-	return EOK;
-}
-
-/** Connect client to the device.
- *
- * Find device driver owning requested device and forward
- * the message to it.
- *
- */
-static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
-{
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	/*
-	 * Get handle from request
-	 */
-	devmap_handle_t handle = IPC_GET_ARG2(*call);
-	devmap_device_t *dev = devmap_device_find_handle(handle);
-	
-	if ((dev == NULL) || (dev->driver == NULL) || (!dev->driver->sess)) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-	
-	async_exch_t *exch = async_exchange_begin(dev->driver->sess);
-	
-	if (dev->forward_interface == 0)
-		async_forward_fast(callid, exch, dev->handle, 0, 0, IPC_FF_NONE);
-	else
-		async_forward_fast(callid, exch, dev->forward_interface,
-		    dev->handle, 0, IPC_FF_NONE);
-	
-	async_exchange_end(exch);
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-}
-
-/** Find handle for device instance identified by name.
- *
- * In answer will be send EOK and device handle in arg1 or a error
- * code from errno.h.
- *
- */
-static void devmap_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
-{
-	char *fqdn;
-	
-	/* Get fqdn */
-	int rc = async_data_write_accept((void **) &fqdn, true, 0,
-	    DEVMAP_NAME_MAXLEN, 0, NULL);
-	if (rc != EOK) {
-		async_answer_0(iid, rc);
-		return;
-	}
-	
-	char *ns_name;
-	char *name;
-	if (!devmap_fqdn_split(fqdn, &ns_name, &name)) {
-		free(fqdn);
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	free(fqdn);
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	const devmap_device_t *dev;
-	
-recheck:
-	
-	/*
-	 * Find device name in the list of known devices.
-	 */
-	dev = devmap_device_find_name(ns_name, name);
-	
-	/*
-	 * Device was not found.
-	 */
-	if (dev == NULL) {
-		if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
-			/* Blocking lookup */
-			fibril_condvar_wait(&devices_list_cv,
-			    &devices_list_mutex);
-			goto recheck;
-		}
-		
-		async_answer_0(iid, ENOENT);
-		free(ns_name);
-		free(name);
-		fibril_mutex_unlock(&devices_list_mutex);
-		return;
-	}
-	
-	async_answer_1(iid, EOK, dev->handle);
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-	free(ns_name);
-	free(name);
-}
-
-/** Find handle for namespace identified by name.
- *
- * In answer will be send EOK and device handle in arg1 or a error
- * code from errno.h.
- *
- */
-static void devmap_namespace_get_handle(ipc_callid_t iid, ipc_call_t *icall)
-{
-	char *name;
-	
-	/* Get device name */
-	int rc = async_data_write_accept((void **) &name, true, 0,
-	    DEVMAP_NAME_MAXLEN, 0, NULL);
-	if (rc != EOK) {
-		async_answer_0(iid, rc);
-		return;
-	}
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	const devmap_namespace_t *namespace;
-	
-recheck:
-	
-	/*
-	 * Find namespace name in the list of known namespaces.
-	 */
-	namespace = devmap_namespace_find_name(name);
-	
-	/*
-	 * Namespace was not found.
-	 */
-	if (namespace == NULL) {
-		if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
-			/* Blocking lookup */
-			fibril_condvar_wait(&devices_list_cv,
-			    &devices_list_mutex);
-			goto recheck;
-		}
-		
-		async_answer_0(iid, ENOENT);
-		free(name);
-		fibril_mutex_unlock(&devices_list_mutex);
-		return;
-	}
-	
-	async_answer_1(iid, EOK, namespace->handle);
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-	free(name);
-}
-
-static void devmap_handle_probe(ipc_callid_t iid, ipc_call_t *icall)
-{
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	devmap_namespace_t *namespace =
-	    devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
-	if (namespace == NULL) {
-		devmap_device_t *dev =
-		    devmap_device_find_handle(IPC_GET_ARG1(*icall));
-		if (dev == NULL)
-			async_answer_1(iid, EOK, DEV_HANDLE_NONE);
-		else
-			async_answer_1(iid, EOK, DEV_HANDLE_DEVICE);
-	} else
-		async_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE);
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-}
-
-static void devmap_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
-{
-	fibril_mutex_lock(&devices_list_mutex);
-	async_answer_1(iid, EOK, list_count(&namespaces_list));
-	fibril_mutex_unlock(&devices_list_mutex);
-}
-
-static void devmap_get_device_count(ipc_callid_t iid, ipc_call_t *icall)
-{
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	devmap_namespace_t *namespace =
-	    devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
-	if (namespace == NULL)
-		async_answer_0(iid, EEXISTS);
-	else
-		async_answer_1(iid, EOK, namespace->refcnt);
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-}
-
-static void devmap_get_namespaces(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, EREFUSED);
-		async_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	if ((size % sizeof(dev_desc_t)) != 0) {
-		async_answer_0(callid, EINVAL);
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	size_t count = size / sizeof(dev_desc_t);
-	if (count != list_count(&namespaces_list)) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		async_answer_0(callid, EOVERFLOW);
-		async_answer_0(iid, EOVERFLOW);
-		return;
-	}
-	
-	dev_desc_t *desc = (dev_desc_t *) malloc(size);
-	if (desc == NULL) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		async_answer_0(callid, ENOMEM);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	size_t pos = 0;
-	list_foreach(namespaces_list, item) {
-		devmap_namespace_t *namespace =
-		    list_get_instance(item, devmap_namespace_t, namespaces);
-		
-		desc[pos].handle = namespace->handle;
-		str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, namespace->name);
-		pos++;
-	}
-	
-	sysarg_t retval = async_data_read_finalize(callid, desc, size);
-	
-	free(desc);
-	fibril_mutex_unlock(&devices_list_mutex);
-	
-	async_answer_0(iid, retval);
-}
-
-static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* FIXME: Use faster algorithm which can make better use
-	   of namespaces */
-	
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_data_read_receive(&callid, &size)) {
-		async_answer_0(callid, EREFUSED);
-		async_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	if ((size % sizeof(dev_desc_t)) != 0) {
-		async_answer_0(callid, EINVAL);
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	devmap_namespace_t *namespace =
-	    devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
-	if (namespace == NULL) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		async_answer_0(callid, ENOENT);
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	size_t count = size / sizeof(dev_desc_t);
-	if (count != namespace->refcnt) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		async_answer_0(callid, EOVERFLOW);
-		async_answer_0(iid, EOVERFLOW);
-		return;
-	}
-	
-	dev_desc_t *desc = (dev_desc_t *) malloc(size);
-	if (desc == NULL) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		async_answer_0(callid, ENOMEM);
-		async_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	size_t pos = 0;
-	list_foreach(devices_list, item) {
-		devmap_device_t *device =
-		    list_get_instance(item, devmap_device_t, devices);
-		
-		if (device->namespace == namespace) {
-			desc[pos].handle = device->handle;
-			str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
-			pos++;
-		}
-	}
-	
-	sysarg_t retval = async_data_read_finalize(callid, desc, size);
-	
-	free(desc);
-	fibril_mutex_unlock(&devices_list_mutex);
-	
-	async_answer_0(iid, retval);
-}
-
-static void devmap_null_create(ipc_callid_t iid, ipc_call_t *icall)
-{
-	fibril_mutex_lock(&null_devices_mutex);
-	
-	unsigned int i;
-	bool fnd = false;
-	
-	for (i = 0; i < NULL_DEVICES; i++) {
-		if (null_devices[i] == NULL) {
-			fnd = true;
-			break;
-		}
-	}
-	
-	if (!fnd) {
-		fibril_mutex_unlock(&null_devices_mutex);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	char null[DEVMAP_NAME_MAXLEN];
-	snprintf(null, DEVMAP_NAME_MAXLEN, "%u", i);
-	
-	char *dev_name = str_dup(null);
-	if (dev_name == NULL) {
-		fibril_mutex_unlock(&null_devices_mutex);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	devmap_device_t *device =
-	    (devmap_device_t *) malloc(sizeof(devmap_device_t));
-	if (device == NULL) {
-		fibril_mutex_unlock(&null_devices_mutex);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	devmap_namespace_t *namespace = devmap_namespace_create("null");
-	if (namespace == NULL) {
-		fibril_mutex_lock(&devices_list_mutex);
-		fibril_mutex_unlock(&null_devices_mutex);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	link_initialize(&device->devices);
-	link_initialize(&device->driver_devices);
-	
-	/* Get unique device handle */
-	device->handle = devmap_create_handle();
-	device->driver = NULL;
-	
-	devmap_namespace_addref(namespace, device);
-	device->name = dev_name;
-	
-	/*
-	 * Insert device into list of all devices and into null devices array.
-	 * Insert device into a dummy list of null driver's devices so that it
-	 * can be safely removed later.
-	 */
-	list_append(&device->devices, &devices_list);
-	list_append(&device->driver_devices, &dummy_null_driver_devices);
-	null_devices[i] = device;
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-	fibril_mutex_unlock(&null_devices_mutex);
-	
-	async_answer_1(iid, EOK, (sysarg_t) i);
-}
-
-static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
-{
-	sysarg_t i = IPC_GET_ARG1(*icall);
-	if (i >= NULL_DEVICES) {
-		async_answer_0(iid, ELIMIT);
-		return;
-	}
-	
-	fibril_mutex_lock(&null_devices_mutex);
-	
-	if (null_devices[i] == NULL) {
-		fibril_mutex_unlock(&null_devices_mutex);
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	devmap_device_unregister_core(null_devices[i]);
-	fibril_mutex_unlock(&devices_list_mutex);
-	
-	null_devices[i] = NULL;
-	
-	fibril_mutex_unlock(&null_devices_mutex);
-	async_answer_0(iid, EOK);
-}
-
-/** Initialize device mapper.
- *
- *
- */
-static bool devmap_init(void)
-{
-	fibril_mutex_lock(&null_devices_mutex);
-	
-	unsigned int i;
-	for (i = 0; i < NULL_DEVICES; i++)
-		null_devices[i] = NULL;
-	
-	fibril_mutex_unlock(&null_devices_mutex);
-	
-	return true;
-}
-
-/** Handle connection with device driver.
- *
- */
-static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Accept connection */
-	async_answer_0(iid, EOK);
-	
-	devmap_driver_t *driver = devmap_driver_register();
-	if (driver == NULL)
-		return;
-	
-	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 DEVMAP_DRIVER_UNREGISTER:
-			if (NULL == driver)
-				async_answer_0(callid, ENOENT);
-			else
-				async_answer_0(callid, EOK);
-			break;
-		case DEVMAP_DEVICE_REGISTER:
-			/* Register one instance of device */
-			devmap_device_register(callid, &call, driver);
-			break;
-		case DEVMAP_DEVICE_UNREGISTER:
-			/* Remove instance of device identified by handler */
-			devmap_device_unregister(callid, &call, driver);
-			break;
-		case DEVMAP_DEVICE_GET_HANDLE:
-			devmap_device_get_handle(callid, &call);
-			break;
-		case DEVMAP_NAMESPACE_GET_HANDLE:
-			devmap_namespace_get_handle(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOENT);
-		}
-	}
-	
-	if (driver != NULL) {
-		/*
-		 * Unregister the device driver and all its devices.
-		 */
-		devmap_driver_unregister(driver);
-		driver = NULL;
-	}
-}
-
-/** Handle connection with device client.
- *
- */
-static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Accept 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))
-			break;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case DEVMAP_DEVICE_GET_HANDLE:
-			devmap_device_get_handle(callid, &call);
-			break;
-		case DEVMAP_NAMESPACE_GET_HANDLE:
-			devmap_namespace_get_handle(callid, &call);
-			break;
-		case DEVMAP_HANDLE_PROBE:
-			devmap_handle_probe(callid, &call);
-			break;
-		case DEVMAP_NULL_CREATE:
-			devmap_null_create(callid, &call);
-			break;
-		case DEVMAP_NULL_DESTROY:
-			devmap_null_destroy(callid, &call);
-			break;
-		case DEVMAP_GET_NAMESPACE_COUNT:
-			devmap_get_namespace_count(callid, &call);
-			break;
-		case DEVMAP_GET_DEVICE_COUNT:
-			devmap_get_device_count(callid, &call);
-			break;
-		case DEVMAP_GET_NAMESPACES:
-			devmap_get_namespaces(callid, &call);
-			break;
-		case DEVMAP_GET_DEVICES:
-			devmap_get_devices(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOENT);
-		}
-	}
-}
-
-/** Function for handling connections to devmap
- *
- */
-static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	/* Select interface */
-	switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
-	case DEVMAP_DRIVER:
-		devmap_connection_driver(iid, icall);
-		break;
-	case DEVMAP_CLIENT:
-		devmap_connection_client(iid, icall);
-		break;
-	case DEVMAP_CONNECT_TO_DEVICE:
-		/* Connect client to selected device */
-		devmap_forward(iid, icall);
-		break;
-	default:
-		/* No such interface */
-		async_answer_0(iid, ENOENT);
-	}
-}
-
-/**
- *
- */
-int main(int argc, char *argv[])
-{
-	printf("%s: HelenOS Device Mapper\n", NAME);
-	
-	if (!devmap_init()) {
-		printf("%s: Error while initializing service\n", NAME);
-		return -1;
-	}
-	
-	/* Set a handler of incomming connections */
-	async_set_client_connection(devmap_connection);
-	
-	/* Register device mapper at naming service */
-	if (service_register(SERVICE_DEVMAP) != EOK)
-		return -1;
-	
-	printf("%s: Accepting connections\n", NAME);
-	async_manager();
-	
-	/* Never reached */
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/srv/fs/devfs/Makefile
===================================================================
--- uspace/srv/fs/devfs/Makefile	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,40 +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 = $(LIBFS_PREFIX)/libfs.a
-EXTRA_CFLAGS += -I$(LIBFS_PREFIX)
-BINARY = devfs
-STATIC_NEEDED = y
-
-SOURCES = \
-	devfs.c \
-	devfs_ops.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/fs/devfs/devfs.c
===================================================================
--- uspace/srv/fs/devfs/devfs.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,153 +1,0 @@
-/*
- * 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 fs
- * @{
- */
-
-/**
- * @file devfs.c
- * @brief Devices file system.
- *
- * Every device registered to device mapper is represented as a file in this
- * file system.
- */
-
-#include <stdio.h>
-#include <ipc/services.h>
-#include <ns.h>
-#include <async.h>
-#include <errno.h>
-#include <task.h>
-#include <libfs.h>
-#include "devfs.h"
-#include "devfs_ops.h"
-
-#define NAME  "devfs"
-
-static vfs_info_t devfs_vfs_info = {
-	.name = NAME,
-	.concurrent_read_write = false,
-	.write_retains_size = false,
-};
-
-fs_reg_t devfs_reg;
-
-static void devfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	if (iid)
-		async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			return;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case VFS_OUT_MOUNTED:
-			devfs_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			devfs_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			devfs_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			devfs_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			devfs_lookup(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			devfs_open_node(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			devfs_stat(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			devfs_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			devfs_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			devfs_truncate(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			devfs_close(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			devfs_sync(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			devfs_destroy(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
-int main(int argc, char *argv[])
-{
-	printf("%s: HelenOS Device Filesystem\n", NAME);
-	
-	if (!devfs_init()) {
-		printf("%s: failed to initialize devfs\n", NAME);
-		return -1;
-	}
-	
-	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
-	    SERVICE_VFS, 0, 0);
-	if (!vfs_sess) {
-		printf("%s: Unable to connect to VFS\n", NAME);
-		return -1;
-	}
-	
-	int rc = fs_register(vfs_sess, &devfs_reg, &devfs_vfs_info,
-	    devfs_connection);
-	if (rc != EOK) {
-		printf("%s: Failed to register file system (%d)\n", NAME, rc);
-		return rc;
-	}
-	
-	printf("%s: Accepting connections\n", NAME);
-	task_retval(0);
-	async_manager();
-	
-	/* Not reached */
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/srv/fs/devfs/devfs.h
===================================================================
--- uspace/srv/fs/devfs/devfs.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,44 +1,0 @@
-/*
- * 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 fs
- * @{
- */ 
-
-#ifndef DEVFS_DEVFS_H_
-#define DEVFS_DEVFS_H_
-
-#include <libfs.h>
-
-extern fs_reg_t devfs_reg;
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,836 +1,0 @@
-/*
- * 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 fs
- * @{
- */
-
-/**
- * @file devfs_ops.c
- * @brief Implementation of VFS operations for the devfs file system server.
- */
-
-#include <macros.h>
-#include <bool.h>
-#include <errno.h>
-#include <malloc.h>
-#include <str.h>
-#include <libfs.h>
-#include <fibril_synch.h>
-#include <adt/hash_table.h>
-#include <ipc/devmap.h>
-#include <sys/stat.h>
-#include <libfs.h>
-#include <assert.h>
-#include "devfs.h"
-#include "devfs_ops.h"
-
-typedef struct {
-	devmap_handle_type_t type;
-	devmap_handle_t handle;
-} devfs_node_t;
-
-/** Opened devices structure */
-typedef struct {
-	devmap_handle_t handle;
-	async_sess_t *sess;       /**< If NULL, the structure is incomplete. */
-	size_t refcount;
-	link_t link;
-	fibril_condvar_t cv;      /**< Broadcast when completed. */
-} device_t;
-
-/** Hash table of opened devices */
-static hash_table_t devices;
-
-/** Hash table mutex */
-static FIBRIL_MUTEX_INITIALIZE(devices_mutex);
-
-#define DEVICES_KEYS        1
-#define DEVICES_KEY_HANDLE  0
-#define DEVICES_BUCKETS     256
-
-/* Implementation of hash table interface for the nodes hash table. */
-static hash_index_t devices_hash(unsigned long key[])
-{
-	return key[DEVICES_KEY_HANDLE] % DEVICES_BUCKETS;
-}
-
-static int devices_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	device_t *dev = hash_table_get_instance(item, device_t, link);
-	return (dev->handle == (devmap_handle_t) key[DEVICES_KEY_HANDLE]);
-}
-
-static void devices_remove_callback(link_t *item)
-{
-	free(hash_table_get_instance(item, device_t, link));
-}
-
-static hash_table_operations_t devices_ops = {
-	.hash = devices_hash,
-	.compare = devices_compare,
-	.remove_callback = devices_remove_callback
-};
-
-static int devfs_node_get_internal(fs_node_t **rfn, devmap_handle_type_t type,
-    devmap_handle_t handle)
-{
-	devfs_node_t *node = (devfs_node_t *) malloc(sizeof(devfs_node_t));
-	if (node == NULL) {
-		*rfn = NULL;
-		return ENOMEM;
-	}
-	
-	*rfn = (fs_node_t *) malloc(sizeof(fs_node_t));
-	if (*rfn == NULL) {
-		free(node);
-		*rfn = NULL;
-		return ENOMEM;
-	}
-	
-	fs_node_initialize(*rfn);
-	node->type = type;
-	node->handle = handle;
-	
-	(*rfn)->data = node;
-	return EOK;
-}
-
-static int devfs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
-{
-	return devfs_node_get_internal(rfn, DEV_HANDLE_NONE, 0);
-}
-
-static int devfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
-{
-	devfs_node_t *node = (devfs_node_t *) pfn->data;
-	int ret;
-	
-	if (node->handle == 0) {
-		/* Root directory */
-		
-		dev_desc_t *devs;
-		size_t count = devmap_get_namespaces(&devs);
-		
-		if (count > 0) {
-			size_t pos;
-			for (pos = 0; pos < count; pos++) {
-				/* Ignore root namespace */
-				if (str_cmp(devs[pos].name, "") == 0)
-					continue;
-				
-				if (str_cmp(devs[pos].name, component) == 0) {
-					ret = devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
-					free(devs);
-					return ret;
-				}
-			}
-			
-			free(devs);
-		}
-		
-		/* Search root namespace */
-		devmap_handle_t namespace;
-		if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
-			count = devmap_get_devices(namespace, &devs);
-			
-			if (count > 0) {
-				size_t pos;
-				for (pos = 0; pos < count; pos++) {
-					if (str_cmp(devs[pos].name, component) == 0) {
-						ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
-						free(devs);
-						return ret;
-					}
-				}
-				
-				free(devs);
-			}
-		}
-		
-		*rfn = NULL;
-		return EOK;
-	}
-	
-	if (node->type == DEV_HANDLE_NAMESPACE) {
-		/* Namespace directory */
-		
-		dev_desc_t *devs;
-		size_t count = devmap_get_devices(node->handle, &devs);
-		if (count > 0) {
-			size_t pos;
-			for (pos = 0; pos < count; pos++) {
-				if (str_cmp(devs[pos].name, component) == 0) {
-					ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
-					free(devs);
-					return ret;
-				}
-			}
-			
-			free(devs);
-		}
-		
-		*rfn = NULL;
-		return EOK;
-	}
-	
-	*rfn = NULL;
-	return EOK;
-}
-
-static int devfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
-{
-	return devfs_node_get_internal(rfn, devmap_handle_probe(index), index);
-}
-
-static int devfs_node_open(fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	
-	if (node->handle == 0) {
-		/* Root directory */
-		return EOK;
-	}
-	
-	devmap_handle_type_t type = devmap_handle_probe(node->handle);
-	
-	if (type == DEV_HANDLE_NAMESPACE) {
-		/* Namespace directory */
-		return EOK;
-	}
-	
-	if (type == DEV_HANDLE_DEVICE) {
-		/* Device node */
-		
-		unsigned long key[] = {
-			[DEVICES_KEY_HANDLE] = (unsigned long) node->handle
-		};
-		link_t *lnk;
-		
-		fibril_mutex_lock(&devices_mutex);
-restart:
-		lnk = hash_table_find(&devices, key);
-		if (lnk == NULL) {
-			device_t *dev = (device_t *) malloc(sizeof(device_t));
-			if (dev == NULL) {
-				fibril_mutex_unlock(&devices_mutex);
-				return ENOMEM;
-			}
-			
-			dev->handle = node->handle;
-			
-			/* Mark as incomplete */
-			dev->sess = NULL;
-			dev->refcount = 1;
-			fibril_condvar_initialize(&dev->cv);
-			
-			/*
-			 * Insert the incomplete device structure so that other
-			 * fibrils will not race with us when we drop the mutex
-			 * below.
-			 */
-			hash_table_insert(&devices, key, &dev->link);
-			
-			/*
-			 * Drop the mutex to allow recursive devfs requests.
-			 */
-			fibril_mutex_unlock(&devices_mutex);
-			
-			async_sess_t *sess = devmap_device_connect(EXCHANGE_SERIALIZE,
-			    node->handle, 0);
-			
-			fibril_mutex_lock(&devices_mutex);
-			
-			/*
-			 * Notify possible waiters about this device structure
-			 * being completed (or destroyed).
-			 */
-			fibril_condvar_broadcast(&dev->cv);
-			
-			if (!sess) {
-				/*
-				 * Connecting failed, need to remove the
-				 * entry and free the device structure.
-				 */
-				hash_table_remove(&devices, key, DEVICES_KEYS);
-				fibril_mutex_unlock(&devices_mutex);
-				
-				return ENOENT;
-			}
-			
-			/* Set the correct session. */
-			dev->sess = sess;
-		} else {
-			device_t *dev = hash_table_get_instance(lnk, device_t, link);
-			
-			if (!dev->sess) {
-				/*
-				 * Wait until the device structure is completed
-				 * and start from the beginning as the device
-				 * structure might have entirely disappeared
-				 * while we were not holding the mutex in
-				 * fibril_condvar_wait().
-				 */
-				fibril_condvar_wait(&dev->cv, &devices_mutex);
-				goto restart;
-			}
-
-			dev->refcount++;
-		}
-		
-		fibril_mutex_unlock(&devices_mutex);
-		
-		return EOK;
-	}
-	
-	return ENOENT;
-}
-
-static int devfs_node_put(fs_node_t *fn)
-{
-	free(fn->data);
-	free(fn);
-	return EOK;
-}
-
-static int devfs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int lflag)
-{
-	assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
-	
-	*rfn = NULL;
-	return ENOTSUP;
-}
-
-static int devfs_destroy_node(fs_node_t *fn)
-{
-	return ENOTSUP;
-}
-
-static int devfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
-{
-	return ENOTSUP;
-}
-
-static int devfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
-{
-	return ENOTSUP;
-}
-
-static int devfs_has_children(bool *has_children, fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	
-	if (node->handle == 0) {
-		size_t count = devmap_count_namespaces();
-		if (count > 0) {
-			*has_children = true;
-			return EOK;
-		}
-		
-		/* Root namespace */
-		devmap_handle_t namespace;
-		if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
-			count = devmap_count_devices(namespace);
-			if (count > 0) {
-				*has_children = true;
-				return EOK;
-			}
-		}
-		
-		*has_children = false;
-		return EOK;
-	}
-	
-	if (node->type == DEV_HANDLE_NAMESPACE) {
-		size_t count = devmap_count_devices(node->handle);
-		if (count > 0) {
-			*has_children = true;
-			return EOK;
-		}
-		
-		*has_children = false;
-		return EOK;
-	}
-	
-	*has_children = false;
-	return EOK;
-}
-
-static fs_index_t devfs_index_get(fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	return node->handle;
-}
-
-static aoff64_t devfs_size_get(fs_node_t *fn)
-{
-	return 0;
-}
-
-static unsigned int devfs_lnkcnt_get(fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	
-	if (node->handle == 0)
-		return 0;
-	
-	return 1;
-}
-
-static char devfs_plb_get_char(unsigned pos)
-{
-	return devfs_reg.plb_ro[pos % PLB_SIZE];
-}
-
-static bool devfs_is_directory(fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	
-	return ((node->type == DEV_HANDLE_NONE) || (node->type == DEV_HANDLE_NAMESPACE));
-}
-
-static bool devfs_is_file(fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	
-	return (node->type == DEV_HANDLE_DEVICE);
-}
-
-static devmap_handle_t devfs_device_get(fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	
-	if (node->type == DEV_HANDLE_DEVICE)
-		return node->handle;
-	
-	return 0;
-}
-
-/** libfs operations */
-libfs_ops_t devfs_libfs_ops = {
-	.root_get = devfs_root_get,
-	.match = devfs_match,
-	.node_get = devfs_node_get,
-	.node_open = devfs_node_open,
-	.node_put = devfs_node_put,
-	.create = devfs_create_node,
-	.destroy = devfs_destroy_node,
-	.link = devfs_link_node,
-	.unlink = devfs_unlink_node,
-	.has_children = devfs_has_children,
-	.index_get = devfs_index_get,
-	.size_get = devfs_size_get,
-	.lnkcnt_get = devfs_lnkcnt_get,
-	.plb_get_char = devfs_plb_get_char,
-	.is_directory = devfs_is_directory,
-	.is_file = devfs_is_file,
-	.device_get = devfs_device_get
-};
-
-bool devfs_init(void)
-{
-	if (!hash_table_create(&devices, DEVICES_BUCKETS,
-	    DEVICES_KEYS, &devices_ops))
-		return false;
-	
-	return true;
-}
-
-void devfs_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	char *opts;
-	
-	/* Accept the mount options */
-	sysarg_t retval = async_data_write_accept((void **) &opts, true, 0, 0,
-	    0, NULL);
-	if (retval != EOK) {
-		async_answer_0(rid, retval);
-		return;
-	}
-	
-	free(opts);
-	async_answer_3(rid, EOK, 0, 0, 0);
-}
-
-void devfs_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_mount(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
-
-void devfs_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&devfs_libfs_ops, rid, request);
-}
-
-void devfs_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_open_node(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_stat(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
-	if (index == 0) {
-		ipc_callid_t callid;
-		size_t size;
-		if (!async_data_read_receive(&callid, &size)) {
-			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
-		}
-		
-		dev_desc_t *desc;
-		size_t count = devmap_get_namespaces(&desc);
-		
-		/* Get rid of root namespace */
-		size_t i;
-		for (i = 0; i < count; i++) {
-			if (str_cmp(desc[i].name, "") == 0) {
-				if (pos >= i)
-					pos++;
-				
-				break;
-			}
-		}
-		
-		if (pos < count) {
-			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
-			free(desc);
-			async_answer_1(rid, EOK, 1);
-			return;
-		}
-		
-		free(desc);
-		pos -= count;
-		
-		/* Search root namespace */
-		devmap_handle_t namespace;
-		if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
-			count = devmap_get_devices(namespace, &desc);
-			
-			if (pos < count) {
-				async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
-				free(desc);
-				async_answer_1(rid, EOK, 1);
-				return;
-			}
-			
-			free(desc);
-		}
-		
-		async_answer_0(callid, ENOENT);
-		async_answer_1(rid, ENOENT, 0);
-		return;
-	}
-	
-	devmap_handle_type_t type = devmap_handle_probe(index);
-	
-	if (type == DEV_HANDLE_NAMESPACE) {
-		/* Namespace directory */
-		ipc_callid_t callid;
-		size_t size;
-		if (!async_data_read_receive(&callid, &size)) {
-			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
-		}
-		
-		dev_desc_t *desc;
-		size_t count = devmap_get_devices(index, &desc);
-		
-		if (pos < count) {
-			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
-			free(desc);
-			async_answer_1(rid, EOK, 1);
-			return;
-		}
-		
-		free(desc);
-		async_answer_0(callid, ENOENT);
-		async_answer_1(rid, ENOENT, 0);
-		return;
-	}
-	
-	if (type == DEV_HANDLE_DEVICE) {
-		/* Device node */
-		
-		unsigned long key[] = {
-			[DEVICES_KEY_HANDLE] = (unsigned long) index
-		};
-		
-		fibril_mutex_lock(&devices_mutex);
-		link_t *lnk = hash_table_find(&devices, key);
-		if (lnk == NULL) {
-			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
-		}
-		
-		device_t *dev = hash_table_get_instance(lnk, device_t, link);
-		assert(dev->sess);
-		
-		ipc_callid_t callid;
-		if (!async_data_read_receive(&callid, NULL)) {
-			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
-		}
-		
-		/* Make a request at the driver */
-		async_exch_t *exch = async_exchange_begin(dev->sess);
-		
-		ipc_call_t answer;
-		aid_t msg = async_send_3(exch, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
-		    IPC_GET_ARG3(*request), &answer);
-		
-		/* Forward the IPC_M_DATA_READ request to the driver */
-		async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
-		
-		async_exchange_end(exch);
-		
-		fibril_mutex_unlock(&devices_mutex);
-		
-		/* Wait for reply from the driver. */
-		sysarg_t rc;
-		async_wait_for(msg, &rc);
-		size_t bytes = IPC_GET_ARG1(answer);
-		
-		/* Driver reply is the final result of the whole operation */
-		async_answer_1(rid, rc, bytes);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	if (index == 0) {
-		async_answer_0(rid, ENOTSUP);
-		return;
-	}
-	
-	devmap_handle_type_t type = devmap_handle_probe(index);
-	
-	if (type == DEV_HANDLE_NAMESPACE) {
-		/* Namespace directory */
-		async_answer_0(rid, ENOTSUP);
-		return;
-	}
-	
-	if (type == DEV_HANDLE_DEVICE) {
-		/* Device node */
-		unsigned long key[] = {
-			[DEVICES_KEY_HANDLE] = (unsigned long) index
-		};
-		
-		fibril_mutex_lock(&devices_mutex);
-		link_t *lnk = hash_table_find(&devices, key);
-		if (lnk == NULL) {
-			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
-		}
-		
-		device_t *dev = hash_table_get_instance(lnk, device_t, link);
-		assert(dev->sess);
-		
-		ipc_callid_t callid;
-		if (!async_data_write_receive(&callid, NULL)) {
-			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
-		}
-		
-		/* Make a request at the driver */
-		async_exch_t *exch = async_exchange_begin(dev->sess);
-		
-		ipc_call_t answer;
-		aid_t msg = async_send_3(exch, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
-		    IPC_GET_ARG3(*request), &answer);
-		
-		/* Forward the IPC_M_DATA_WRITE request to the driver */
-		async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
-		
-		async_exchange_end(exch);
-		
-		fibril_mutex_unlock(&devices_mutex);
-		
-		/* Wait for reply from the driver. */
-		sysarg_t rc;
-		async_wait_for(msg, &rc);
-		size_t bytes = IPC_GET_ARG1(answer);
-		
-		/* Driver reply is the final result of the whole operation */
-		async_answer_1(rid, rc, bytes);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
-
-void devfs_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
-	if (index == 0) {
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	devmap_handle_type_t type = devmap_handle_probe(index);
-	
-	if (type == DEV_HANDLE_NAMESPACE) {
-		/* Namespace directory */
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	if (type == DEV_HANDLE_DEVICE) {
-		unsigned long key[] = {
-			[DEVICES_KEY_HANDLE] = (unsigned long) index
-		};
-		
-		fibril_mutex_lock(&devices_mutex);
-		link_t *lnk = hash_table_find(&devices, key);
-		if (lnk == NULL) {
-			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
-		}
-		
-		device_t *dev = hash_table_get_instance(lnk, device_t, link);
-		assert(dev->sess);
-		dev->refcount--;
-		
-		if (dev->refcount == 0) {
-			async_hangup(dev->sess);
-			hash_table_remove(&devices, key, DEVICES_KEYS);
-		}
-		
-		fibril_mutex_unlock(&devices_mutex);
-		
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_sync(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
-	if (index == 0) {
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	devmap_handle_type_t type = devmap_handle_probe(index);
-	
-	if (type == DEV_HANDLE_NAMESPACE) {
-		/* Namespace directory */
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	if (type == DEV_HANDLE_DEVICE) {
-		unsigned long key[] = {
-			[DEVICES_KEY_HANDLE] = (unsigned long) index
-		};
-		
-		fibril_mutex_lock(&devices_mutex);
-		link_t *lnk = hash_table_find(&devices, key);
-		if (lnk == NULL) {
-			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
-		}
-		
-		device_t *dev = hash_table_get_instance(lnk, device_t, link);
-		assert(dev->sess);
-		
-		/* Make a request at the driver */
-		async_exch_t *exch = async_exchange_begin(dev->sess);
-		
-		ipc_call_t answer;
-		aid_t msg = async_send_2(exch, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer);
-		
-		async_exchange_end(exch);
-		
-		fibril_mutex_unlock(&devices_mutex);
-		
-		/* Wait for reply from the driver */
-		sysarg_t rc;
-		async_wait_for(msg, &rc);
-		
-		/* Driver reply is the final result of the whole operation */
-		async_answer_0(rid, rc);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
-
-/**
- * @}
- */
Index: pace/srv/fs/devfs/devfs_ops.h
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/*
- * 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 fs
- * @{
- */
-
-#ifndef DEVFS_DEVFS_OPS_H_
-#define DEVFS_DEVFS_OPS_H_
-
-#include <ipc/common.h>
-#include <bool.h>
-
-extern bool devfs_init(void);
-
-extern void devfs_mounted(ipc_callid_t, ipc_call_t *);
-extern void devfs_mount(ipc_callid_t, ipc_call_t *);
-extern void devfs_unmounted(ipc_callid_t, ipc_call_t *);
-extern void devfs_unmount(ipc_callid_t, ipc_call_t *);
-extern void devfs_lookup(ipc_callid_t, ipc_call_t *);
-extern void devfs_open_node(ipc_callid_t, ipc_call_t *);
-extern void devfs_stat(ipc_callid_t, ipc_call_t *);
-extern void devfs_sync(ipc_callid_t, ipc_call_t *);
-extern void devfs_read(ipc_callid_t, ipc_call_t *);
-extern void devfs_write(ipc_callid_t, ipc_call_t *);
-extern void devfs_truncate(ipc_callid_t, ipc_call_t *);
-extern void devfs_close(ipc_callid_t, ipc_call_t *);
-extern void devfs_destroy(ipc_callid_t, ipc_call_t *);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/srv/fs/ext2fs/ext2fs.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/ext2fs/ext2fs.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,5 +1,4 @@
 /*
  * Copyright (c) 2006 Martin Decky
- * Copyright (c) 2008 Jakub Jermar
  * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
@@ -55,90 +54,4 @@
 };
 
-fs_reg_t ext2fs_reg;
-
-/**
- * This connection fibril processes VFS requests from VFS.
- *
- * In order to support simultaneous VFS requests, our design is as follows.
- * The connection fibril accepts VFS requests from VFS. If there is only one
- * instance of the fibril, VFS will need to serialize all VFS requests it sends
- * to EXT2FS. To overcome this bottleneck, VFS can send EXT2FS the IPC_M_CONNECT_ME_TO
- * call. In that case, a new connection fibril will be created, which in turn
- * will accept the call. Thus, a new phone will be opened for VFS.
- *
- * There are few issues with this arrangement. First, VFS can run out of
- * available phones. In that case, VFS can close some other phones or use one
- * phone for more serialized requests. Similarily, EXT2FS can refuse to duplicate
- * the connection. VFS should then just make use of already existing phones and
- * route its requests through them. To avoid paying the fibril creation price 
- * upon each request, EXT2FS might want to keep the connections open after the
- * request has been completed.
- */
-static void ext2fs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	if (iid) {
-		/*
-		 * This only happens for connections opened by
-		 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
-		 * created by IPC_M_CONNECT_TO_ME.
-		 */
-		async_answer_0(iid, EOK);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			return;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case VFS_OUT_MOUNTED:
-			ext2fs_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			ext2fs_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			ext2fs_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			ext2fs_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			ext2fs_lookup(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			ext2fs_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			ext2fs_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			ext2fs_truncate(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			ext2fs_stat(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			ext2fs_close(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			ext2fs_destroy(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			ext2fs_open_node(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			ext2fs_sync(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char **argv)
 {
@@ -158,5 +71,6 @@
 	}	
 		
-	rc = fs_register(vfs_sess, &ext2fs_reg, &ext2fs_vfs_info, ext2fs_connection);
+	rc = fs_register(vfs_sess, &ext2fs_vfs_info, &ext2fs_ops,
+	    &ext2fs_libfs_ops);
 	if (rc != EOK) {
 		fprintf(stdout, NAME ": Failed to register fs (%d)\n", rc);
Index: uspace/srv/fs/ext2fs/ext2fs.h
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/ext2fs/ext2fs.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,4 +1,3 @@
 /*
- * Copyright (c) 2008 Jakub Jermar
  * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
@@ -36,35 +35,14 @@
 
 #include <libext2.h>
-#include <fibril_synch.h>
 #include <libfs.h>
-#include <atomic.h>
 #include <sys/types.h>
-#include <bool.h>
-#include "../../vfs/vfs.h"
-
-#ifndef dprintf
-#define dprintf(...)	printf(__VA_ARGS__)
-#endif
 
 #define min(a, b)		((a) < (b) ? (a) : (b))
 
-extern fs_reg_t ext2fs_reg;
+extern vfs_out_ops_t ext2fs_ops;
+extern libfs_ops_t ext2fs_libfs_ops;
 
 extern int ext2fs_global_init(void);
 extern int ext2fs_global_fini(void);
-extern void ext2fs_mounted(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_mount(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_unmounted(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_unmount(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_lookup(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_read(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_write(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_truncate(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_stat(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_close(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_destroy(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_open_node(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_stat(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_sync(ipc_callid_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/fs/ext2fs/ext2fs_ops.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -1,4 +1,3 @@
 /*
- * Copyright (c) 2008 Jakub Jermar
  * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
@@ -43,5 +42,5 @@
 #include <libext2.h>
 #include <ipc/services.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 #include <macros.h>
 #include <async.h>
@@ -70,5 +69,5 @@
 typedef struct ext2fs_instance {
 	link_t link;
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 	ext2_filesystem_t *filesystem;
 	unsigned int open_nodes_count;
@@ -86,9 +85,9 @@
  * Forward declarations of auxiliary functions
  */
-static int ext2fs_instance_get(devmap_handle_t, ext2fs_instance_t **);
-static void ext2fs_read_directory(ipc_callid_t, ipc_callid_t, aoff64_t,
-	size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
-static void ext2fs_read_file(ipc_callid_t, ipc_callid_t, aoff64_t,
-	size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
+static int ext2fs_instance_get(service_id_t, ext2fs_instance_t **);
+static int ext2fs_read_directory(ipc_callid_t, aoff64_t, size_t,
+    ext2fs_instance_t *, ext2_inode_ref_t *, size_t *);
+static int ext2fs_read_file(ipc_callid_t, aoff64_t, size_t, ext2fs_instance_t *,
+    ext2_inode_ref_t *, size_t *);
 static bool ext2fs_is_dots(const uint8_t *, size_t);
 static int ext2fs_node_get_core(fs_node_t **, ext2fs_instance_t *, fs_index_t);
@@ -98,10 +97,10 @@
  * Forward declarations of EXT2 libfs operations.
  */
-static int ext2fs_root_get(fs_node_t **, devmap_handle_t);
+static int ext2fs_root_get(fs_node_t **, service_id_t);
 static int ext2fs_match(fs_node_t **, fs_node_t *, const char *);
-static int ext2fs_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
+static int ext2fs_node_get(fs_node_t **, service_id_t, fs_index_t);
 static int ext2fs_node_open(fs_node_t *);
 static int ext2fs_node_put(fs_node_t *);
-static int ext2fs_create_node(fs_node_t **, devmap_handle_t, int);
+static int ext2fs_create_node(fs_node_t **, service_id_t, int);
 static int ext2fs_destroy_node(fs_node_t *);
 static int ext2fs_link(fs_node_t *, fs_node_t *, const char *);
@@ -111,8 +110,7 @@
 static aoff64_t ext2fs_size_get(fs_node_t *);
 static unsigned ext2fs_lnkcnt_get(fs_node_t *);
-static char ext2fs_plb_get_char(unsigned);
 static bool ext2fs_is_directory(fs_node_t *);
 static bool ext2fs_is_file(fs_node_t *node);
-static devmap_handle_t ext2fs_device_get(fs_node_t *node);
+static service_id_t ext2fs_device_get(fs_node_t *node);
 
 /*
@@ -136,6 +134,6 @@
 	ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link);
 	assert(keys > 0);
-	if (enode->instance->devmap_handle !=
-	    ((devmap_handle_t) key[OPEN_NODES_DEV_HANDLE_KEY])) {
+	if (enode->instance->service_id !=
+	    ((service_id_t) key[OPEN_NODES_DEV_HANDLE_KEY])) {
 		return false;
 	}
@@ -182,9 +180,9 @@
 
 /**
- * Find an instance of filesystem for the given devmap_handle
- */
-int ext2fs_instance_get(devmap_handle_t devmap_handle, ext2fs_instance_t **inst)
-{
-	EXT2FS_DBG("(%" PRIun ", -)", devmap_handle);
+ * Find an instance of filesystem for the given service_id
+ */
+int ext2fs_instance_get(service_id_t service_id, ext2fs_instance_t **inst)
+{
+	EXT2FS_DBG("(%" PRIun ", -)", service_id);
 	ext2fs_instance_t *tmp;
 	
@@ -200,5 +198,5 @@
 		tmp = list_get_instance(link, ext2fs_instance_t, link);
 		
-		if (tmp->devmap_handle == devmap_handle) {
+		if (tmp->service_id == service_id) {
 			*inst = tmp;
 			fibril_mutex_unlock(&instance_list_mutex);
@@ -215,8 +213,8 @@
 
 
-int ext2fs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
-{
-	EXT2FS_DBG("(-, %" PRIun ")", devmap_handle);
-	return ext2fs_node_get(rfn, devmap_handle, EXT2_INODE_ROOT_INDEX);
+int ext2fs_root_get(fs_node_t **rfn, service_id_t service_id)
+{
+	EXT2FS_DBG("(-, %" PRIun ")", service_id);
+	return ext2fs_node_get(rfn, service_id, EXT2_INODE_ROOT_INDEX);
 }
 
@@ -291,12 +289,12 @@
 
 /** Instantiate a EXT2 in-core node. */
-int ext2fs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
-{
-	EXT2FS_DBG("(-,%" PRIun ",%u)", devmap_handle, index);
+int ext2fs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
+{
+	EXT2FS_DBG("(-,%" PRIun ",%u)", service_id, index);
 	
 	ext2fs_instance_t *inst = NULL;
 	int rc;
 	
-	rc = ext2fs_instance_get(devmap_handle, &inst);
+	rc = ext2fs_instance_get(service_id, &inst);
 	if (rc != EOK) {
 		return rc;
@@ -319,5 +317,5 @@
 	/* Check if the node is not already open */
 	unsigned long key[] = {
-		[OPEN_NODES_DEV_HANDLE_KEY] = inst->devmap_handle,
+		[OPEN_NODES_DEV_HANDLE_KEY] = inst->service_id,
 		[OPEN_NODES_INODE_KEY] = index,
 	};
@@ -413,5 +411,5 @@
 
 	unsigned long key[] = {
-		[OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->devmap_handle,
+		[OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->service_id,
 		[OPEN_NODES_INODE_KEY] = enode->inode_ref->index,
 	};
@@ -431,5 +429,5 @@
 }
 
-int ext2fs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)
+int ext2fs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
 {
 	EXT2FS_DBG("");
@@ -540,9 +538,4 @@
 }
 
-char ext2fs_plb_get_char(unsigned pos)
-{
-	return ext2fs_reg.plb_ro[pos % PLB_SIZE];
-}
-
 bool ext2fs_is_directory(fs_node_t *fn)
 {
@@ -564,9 +557,9 @@
 }
 
-devmap_handle_t ext2fs_device_get(fs_node_t *fn)
+service_id_t ext2fs_device_get(fs_node_t *fn)
 {
 	EXT2FS_DBG("");
 	ext2fs_node_t *enode = EXT2FS_NODE(fn);
-	return enode->instance->devmap_handle;
+	return enode->instance->service_id;
 }
 
@@ -586,5 +579,4 @@
 	.size_get = ext2fs_size_get,
 	.lnkcnt_get = ext2fs_lnkcnt_get,
-	.plb_get_char = ext2fs_plb_get_char,
 	.is_directory = ext2fs_is_directory,
 	.is_file = ext2fs_is_file,
@@ -596,30 +588,17 @@
  */
 
-void ext2fs_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	int rc;
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+static int ext2fs_mounted(service_id_t service_id, const char *opts,
+   fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
+	EXT2FS_DBG("");
+	int rc;
 	ext2_filesystem_t *fs;
 	ext2fs_instance_t *inst;
 	bool read_only;
 	
-	/* Accept the mount options */
-	char *opts;
-	rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
-	
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-
-	free(opts);
-	
 	/* Allocate libext2 filesystem structure */
 	fs = (ext2_filesystem_t *) malloc(sizeof(ext2_filesystem_t));
-	if (fs == NULL) {
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
+	if (fs == NULL)
+		return ENOMEM;
 	
 	/* Allocate instance structure */
@@ -627,15 +606,13 @@
 	if (inst == NULL) {
 		free(fs);
-		async_answer_0(rid, ENOMEM);
-		return;
+		return ENOMEM;
 	}
 	
 	/* Initialize the filesystem  */
-	rc = ext2_filesystem_init(fs, devmap_handle);
+	rc = ext2_filesystem_init(fs, service_id);
 	if (rc != EOK) {
 		free(fs);
 		free(inst);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -646,6 +623,5 @@
 		free(fs);
 		free(inst);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -656,11 +632,10 @@
 		free(fs);
 		free(inst);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
 	/* Initialize instance */
 	link_initialize(&inst->link);
-	inst->devmap_handle = devmap_handle;
+	inst->service_id = service_id;
 	inst->filesystem = fs;
 	inst->open_nodes_count = 0;
@@ -673,6 +648,5 @@
 		free(fs);
 		free(inst);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	ext2fs_node_t *enode = EXT2FS_NODE(root_node);
@@ -683,31 +657,23 @@
 	fibril_mutex_unlock(&instance_list_mutex);
 	
-	async_answer_3(rid, EOK,
-	    EXT2_INODE_ROOT_INDEX,
-	    0,
-	    ext2_inode_get_usage_count(enode->inode_ref->inode));
+	*index = EXT2_INODE_ROOT_INDEX;
+	*size = 0;
+	*lnkcnt = ext2_inode_get_usage_count(enode->inode_ref->inode);
 	
 	ext2fs_node_put(root_node);
-}
-
-void ext2fs_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_mount(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
-}
-
-void ext2fs_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+
+	return EOK;
+}
+
+static int ext2fs_unmounted(service_id_t service_id)
+{
+	EXT2FS_DBG("");
 	ext2fs_instance_t *inst;
 	int rc;
 	
-	rc = ext2fs_instance_get(devmap_handle, &inst);
-	
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	rc = ext2fs_instance_get(service_id, &inst);
+	
+	if (rc != EOK)
+		return rc;
 	
 	fibril_mutex_lock(&open_nodes_lock);
@@ -716,6 +682,5 @@
 	if (inst->open_nodes_count != 0) {
 		fibril_mutex_unlock(&open_nodes_lock);
-		async_answer_0(rid, EBUSY);
-		return;
+		return EBUSY;
 	}
 	
@@ -729,26 +694,12 @@
 	ext2_filesystem_fini(inst->filesystem);
 	
-	async_answer_0(rid, EOK);
-}
-
-void ext2fs_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_unmount(&ext2fs_libfs_ops, rid, request);
-}
-
-void ext2fs_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_lookup(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
-}
-
-void ext2fs_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	return EOK;
+}
+
+static int
+ext2fs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
+	EXT2FS_DBG("");
 	
 	ext2fs_instance_t *inst;
@@ -763,13 +714,11 @@
 	if (!async_data_read_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
-	}
-	
-	rc = ext2fs_instance_get(devmap_handle, &inst);
+		return EINVAL;
+	}
+	
+	rc = ext2fs_instance_get(service_id, &inst);
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -777,24 +726,24 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
 	if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
-		    EXT2_INODE_MODE_FILE)) {
-		ext2fs_read_file(rid, callid, pos, size, inst, inode_ref);
-	}
-	else if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
-		    EXT2_INODE_MODE_DIRECTORY)) {
-		ext2fs_read_directory(rid, callid, pos, size, inst, inode_ref);
-	}
-	else {
+	    EXT2_INODE_MODE_FILE)) {
+		rc = ext2fs_read_file(callid, pos, size, inst, inode_ref,
+		    rbytes);
+	} else if (ext2_inode_is_type(inst->filesystem->superblock,
+	    inode_ref->inode, EXT2_INODE_MODE_DIRECTORY)) {
+		rc = ext2fs_read_directory(callid, pos, size, inst, inode_ref,
+		    rbytes);
+	} else {
 		/* Other inode types not supported */
 		async_answer_0(callid, ENOTSUP);
-		async_answer_0(rid, ENOTSUP);
+		rc = ENOTSUP;
 	}
 	
 	ext2_filesystem_put_inode_ref(inode_ref);
 	
+	return rc;
 }
 
@@ -814,6 +763,6 @@
 }
 
-void ext2fs_read_directory(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
-	size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
+int ext2fs_read_directory(ipc_callid_t callid, aoff64_t pos, size_t size,
+    ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes)
 {
 	ext2_directory_iterator_t it;
@@ -827,6 +776,5 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -841,5 +789,5 @@
 		
 		name_size = ext2_directory_entry_ll_get_name_length(
-			inst->filesystem->superblock, it.current);
+		    inst->filesystem->superblock, it.current);
 		
 		/* skip . and .. */
@@ -849,18 +797,17 @@
 		
 		/* 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
-			*/
+		 * end of entry name, so we copy it to new buffer
+		 * and add the \0 at the end
+		 */
 		buf = malloc(name_size+1);
 		if (buf == NULL) {
 			ext2_directory_iterator_fini(&it);
 			async_answer_0(callid, ENOMEM);
-			async_answer_0(rid, ENOMEM);
-			return;
+			return ENOMEM;
 		}
 		memcpy(buf, &it.current->name, name_size);
-		*(buf+name_size) = 0;
+		*(buf + name_size) = 0;
 		found = true;
-		(void) async_data_read_finalize(callid, buf, name_size+1);
+		(void) async_data_read_finalize(callid, buf, name_size + 1);
 		free(buf);
 		break;
@@ -871,6 +818,5 @@
 			ext2_directory_iterator_fini(&it);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 	}
@@ -878,28 +824,24 @@
 	if (found) {
 		rc = ext2_directory_iterator_next(&it);
-		if (rc != EOK) {
-			async_answer_0(rid, rc);
-			return;
-		}
+		if (rc != EOK)
+			return rc;
 		next = it.current_offset;
 	}
 	
 	rc = ext2_directory_iterator_fini(&it);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
 	
 	if (found) {
-		async_answer_1(rid, EOK, next-pos);
-	}
-	else {
+		*rbytes = next - pos;
+		return EOK;
+	} else {
 		async_answer_0(callid, ENOENT);
-		async_answer_0(rid, ENOENT);
-	}
-}
-
-void ext2fs_read_file(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
-	size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
+		return ENOENT;
+	}
+}
+
+int ext2fs_read_file(ipc_callid_t callid, aoff64_t pos, size_t size,
+    ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes)
 {
 	int rc;
@@ -919,6 +861,6 @@
 		/* Read 0 bytes successfully */
 		async_data_read_finalize(callid, NULL, 0);
-		async_answer_1(rid, EOK, 0);
-		return;
+		*rbytes = 0;
+		return EOK;
 	}
 	
@@ -939,6 +881,5 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -952,6 +893,5 @@
 		if (buffer == NULL) {
 			async_answer_0(callid, ENOMEM);
-			async_answer_0(rid, ENOMEM);
-			return;
+			return ENOMEM;
 		}
 		
@@ -959,17 +899,16 @@
 		
 		async_data_read_finalize(callid, buffer, bytes);
-		async_answer_1(rid, EOK, bytes);
+		*rbytes = bytes;
 		
 		free(buffer);
 		
-		return;
+		return EOK;
 	}
 	
 	/* Usual case - we need to read a block from device */
-	rc = block_get(&block, inst->devmap_handle, fs_block, BLOCK_FLAGS_NONE);
+	rc = block_get(&block, inst->service_id, fs_block, BLOCK_FLAGS_NONE);
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -978,75 +917,57 @@
 	
 	rc = block_put(block);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-		
-	async_answer_1(rid, EOK, bytes);
-}
-
-void ext2fs_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-//	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-//	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-//	aoff64_t pos =
-//	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
-	// TODO
-	async_answer_0(rid, ENOTSUP);
-}
-
-void ext2fs_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-//	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-//	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-//	aoff64_t size =
-//	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
-	// TODO
-	async_answer_0(rid, ENOTSUP);
-}
-
-void ext2fs_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	async_answer_0(rid, EOK);
-}
-
-void ext2fs_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-//	devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
-//	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	
-	// TODO
-	async_answer_0(rid, ENOTSUP);
-}
-
-void ext2fs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_open_node(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
-}
-
-void ext2fs_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_stat(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
-}
-
-void ext2fs_sync(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-//	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-//	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
-	// TODO
-	async_answer_0(rid, ENOTSUP);
-}
+	if (rc != EOK)
+		return rc;
+	
+	*rbytes = bytes;
+	return EOK;
+}
+
+static int
+ext2fs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+static int
+ext2fs_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+static int ext2fs_close(service_id_t service_id, fs_index_t index)
+{
+	EXT2FS_DBG("");
+	return EOK;
+}
+
+static int ext2fs_destroy(service_id_t service_id, fs_index_t index)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+static int ext2fs_sync(service_id_t service_id, fs_index_t index)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+vfs_out_ops_t ext2fs_ops = {
+	.mounted = ext2fs_mounted,
+	.unmounted = ext2fs_unmounted,
+	.read = ext2fs_read,
+	.write = ext2fs_write,
+	.truncate = ext2fs_truncate,
+	.close = ext2fs_close,
+	.destroy = ext2fs_destroy,
+	.sync = ext2fs_sync,
+};
 
 /**
  * @}
  */
+
Index: uspace/srv/fs/fat/fat.c
===================================================================
--- uspace/srv/fs/fat/fat.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/fat/fat.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -56,91 +56,4 @@
 };
 
-fs_reg_t fat_reg;
-
-/**
- * This connection fibril processes VFS requests from VFS.
- *
- * In order to support simultaneous VFS requests, our design is as follows.
- * The connection fibril accepts VFS requests from VFS. If there is only one
- * instance of the fibril, VFS will need to serialize all VFS requests it sends
- * to FAT. To overcome this bottleneck, VFS can send FAT the IPC_M_CONNECT_ME_TO
- * call. In that case, a new connection fibril will be created, which in turn
- * will accept the call. Thus, a new phone will be opened for VFS.
- *
- * There are few issues with this arrangement. First, VFS can run out of
- * available phones. In that case, VFS can close some other phones or use one
- * phone for more serialized requests. Similarily, FAT can refuse to duplicate
- * the connection. VFS should then just make use of already existing phones and
- * route its requests through them. To avoid paying the fibril creation price 
- * upon each request, FAT might want to keep the connections open after the
- * request has been completed.
- */
-static void fat_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	if (iid) {
-		/*
-		 * This only happens for connections opened by
-		 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
-		 * created by IPC_M_CONNECT_TO_ME.
-		 */
-		async_answer_0(iid, EOK);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			return;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case VFS_OUT_MOUNTED:
-			fat_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			fat_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			fat_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			fat_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			fat_lookup(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			fat_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			fat_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			fat_truncate(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			fat_stat(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			fat_close(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			fat_destroy(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			fat_open_node(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			fat_sync(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char **argv)
 {
@@ -158,5 +71,5 @@
 	}
 	
-	rc = fs_register(vfs_sess, &fat_reg, &fat_vfs_info, fat_connection);
+	rc = fs_register(vfs_sess, &fat_vfs_info, &fat_ops, &fat_libfs_ops);
 	if (rc != EOK) {
 		fat_idx_fini();
Index: uspace/srv/fs/fat/fat.h
===================================================================
--- uspace/srv/fs/fat/fat.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/fat/fat.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -175,5 +175,5 @@
 
 	fibril_mutex_t	lock;
-	devmap_handle_t	devmap_handle;
+	service_id_t	service_id;
 	fs_index_t	index;
 	/**
@@ -224,24 +224,10 @@
 } fat_node_t;
 
-extern fs_reg_t fat_reg;
-
-extern void fat_mounted(ipc_callid_t, ipc_call_t *);
-extern void fat_mount(ipc_callid_t, ipc_call_t *);
-extern void fat_unmounted(ipc_callid_t, ipc_call_t *);
-extern void fat_unmount(ipc_callid_t, ipc_call_t *);
-extern void fat_lookup(ipc_callid_t, ipc_call_t *);
-extern void fat_read(ipc_callid_t, ipc_call_t *);
-extern void fat_write(ipc_callid_t, ipc_call_t *);
-extern void fat_truncate(ipc_callid_t, ipc_call_t *);
-extern void fat_stat(ipc_callid_t, ipc_call_t *);
-extern void fat_close(ipc_callid_t, ipc_call_t *);
-extern void fat_destroy(ipc_callid_t, ipc_call_t *);
-extern void fat_open_node(ipc_callid_t, ipc_call_t *);
-extern void fat_stat(ipc_callid_t, ipc_call_t *);
-extern void fat_sync(ipc_callid_t, ipc_call_t *);
-
-extern int fat_idx_get_new(fat_idx_t **, devmap_handle_t);
-extern fat_idx_t *fat_idx_get_by_pos(devmap_handle_t, fat_cluster_t, unsigned);
-extern fat_idx_t *fat_idx_get_by_index(devmap_handle_t, fs_index_t);
+extern vfs_out_ops_t fat_ops;
+extern libfs_ops_t fat_libfs_ops;
+
+extern int fat_idx_get_new(fat_idx_t **, service_id_t);
+extern fat_idx_t *fat_idx_get_by_pos(service_id_t, fat_cluster_t, unsigned);
+extern fat_idx_t *fat_idx_get_by_index(service_id_t, fs_index_t);
 extern void fat_idx_destroy(fat_idx_t *);
 extern void fat_idx_hashin(fat_idx_t *);
@@ -250,6 +236,6 @@
 extern int fat_idx_init(void);
 extern void fat_idx_fini(void);
-extern int fat_idx_init_by_devmap_handle(devmap_handle_t);
-extern void fat_idx_fini_by_devmap_handle(devmap_handle_t);
+extern int fat_idx_init_by_service_id(service_id_t);
+extern void fat_idx_fini_by_service_id(service_id_t);
 
 #endif
Index: uspace/srv/fs/fat/fat_fat.c
===================================================================
--- uspace/srv/fs/fat/fat_fat.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/fat/fat_fat.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -71,5 +71,5 @@
  *
  * @param bs		Buffer holding the boot sector for the file.
- * @param devmap_handle	Device handle of the device with the file.
+ * @param service_id	Service ID of the device with the file.
  * @param firstc	First cluster to start the walk with.
  * @param lastc		If non-NULL, output argument hodling the last cluster
@@ -82,5 +82,5 @@
  */
 int 
-fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,
+fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc,
     fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
 {
@@ -109,5 +109,5 @@
 		fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
 		/* read FAT1 */
-		rc = block_get(&b, devmap_handle, RSCNT(bs) + fsec,
+		rc = block_get(&b, service_id, RSCNT(bs) + fsec,
 		    BLOCK_FLAGS_NONE);
 		if (rc != EOK)
@@ -160,5 +160,5 @@
 		 * when fortunately we have the last cluster number cached.
 		 */
-		return block_get(block, nodep->idx->devmap_handle,
+		return block_get(block, nodep->idx->service_id,
 		    CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags);
 	}
@@ -174,5 +174,5 @@
 
 fall_through:
-	rc = _fat_block_get(block, bs, nodep->idx->devmap_handle, firstc,
+	rc = _fat_block_get(block, bs, nodep->idx->service_id, firstc,
 	    &currc, relbn, flags);
 	if (rc != EOK)
@@ -193,5 +193,5 @@
  * @param block		Pointer to a block pointer for storing result.
  * @param bs		Buffer holding the boot sector of the file system.
- * @param devmap_handle	Device handle of the file system.
+ * @param service_id	Service ID handle of the file system.
  * @param fcl		First cluster used by the file. Can be zero if the file
  *			is empty.
@@ -205,5 +205,5 @@
  */
 int
-_fat_block_get(block_t **block, fat_bs_t *bs, devmap_handle_t devmap_handle,
+_fat_block_get(block_t **block, fat_bs_t *bs, service_id_t service_id,
     fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
 {
@@ -222,5 +222,5 @@
 		/* root directory special case */
 		assert(bn < RDS(bs));
-		rc = block_get(block, devmap_handle,
+		rc = block_get(block, service_id,
 		    RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags);
 		return rc;
@@ -228,10 +228,10 @@
 
 	max_clusters = bn / SPC(bs);
-	rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);
+	rc = fat_cluster_walk(bs, service_id, fcl, &c, &clusters, max_clusters);
 	if (rc != EOK)
 		return rc;
 	assert(clusters == max_clusters);
 
-	rc = block_get(block, devmap_handle, CLBN2PBN(bs, c, bn), flags);
+	rc = block_get(block, service_id, CLBN2PBN(bs, c, bn), flags);
 
 	if (clp)
@@ -281,5 +281,5 @@
 	/* zero out the initial part of the new cluster chain */
 	for (o = boundary; o < pos; o += BPS(bs)) {
-		rc = _fat_block_get(&b, bs, nodep->idx->devmap_handle, mcl,
+		rc = _fat_block_get(&b, bs, nodep->idx->service_id, mcl,
 		    NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD);
 		if (rc != EOK)
@@ -298,5 +298,5 @@
  *
  * @param bs		Buffer holding the boot sector for the file system.
- * @param devmap_handle	Device handle for the file system.
+ * @param service_id	Service ID for the file system.
  * @param clst		Cluster which to get.
  * @param value		Output argument holding the value of the cluster.
@@ -305,5 +305,5 @@
  */
 int
-fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
+fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     fat_cluster_t clst, fat_cluster_t *value)
 {
@@ -312,5 +312,5 @@
 	int rc;
 
-	rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
+	rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
 	    (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
 	if (rc != EOK)
@@ -327,5 +327,5 @@
  *
  * @param bs		Buffer holding the boot sector for the file system.
- * @param devmap_handle	Device handle for the file system.
+ * @param service_id	Device service ID for the file system.
  * @param fatno		Number of the FAT instance where to make the change.
  * @param clst		Cluster which is to be set.
@@ -335,5 +335,5 @@
  */
 int
-fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
+fat_set_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     fat_cluster_t clst, fat_cluster_t value)
 {
@@ -343,5 +343,5 @@
 
 	assert(fatno < FATCNT(bs));
-	rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
+	rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
 	    (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
 	if (rc != EOK)
@@ -358,5 +358,5 @@
  *
  * @param bs		Buffer holding the boot sector of the file system.
- * @param devmap_handle	Device handle of the file system.
+ * @param service_id	Service ID of the file system.
  * @param lifo		Chain of allocated clusters.
  * @param nclsts	Number of clusters in the lifo chain.
@@ -364,5 +364,5 @@
  * @return		EOK on success or a negative error code.
  */
-int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle,
+int fat_alloc_shadow_clusters(fat_bs_t *bs, service_id_t service_id,
     fat_cluster_t *lifo, unsigned nclsts)
 {
@@ -373,5 +373,5 @@
 	for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
 		for (c = 0; c < nclsts; c++) {
-			rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
+			rc = fat_set_cluster(bs, service_id, fatno, lifo[c],
 			    c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
 			if (rc != EOK)
@@ -391,5 +391,5 @@
  *
  * @param bs		Buffer holding the boot sector of the file system.
- * @param devmap_handle	Device handle of the file system.
+ * @param service_id	Device service ID of the file system.
  * @param nclsts	Number of clusters to allocate.
  * @param mcl		Output parameter where the first cluster in the chain
@@ -401,5 +401,5 @@
  */
 int
-fat_alloc_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts,
+fat_alloc_clusters(fat_bs_t *bs, service_id_t service_id, unsigned nclsts,
     fat_cluster_t *mcl, fat_cluster_t *lcl)
 {
@@ -419,5 +419,5 @@
 	fibril_mutex_lock(&fat_alloc_lock);
 	for (b = 0, cl = 0; b < SF(bs); b++) {
-		rc = block_get(&blk, devmap_handle, RSCNT(bs) + b,
+		rc = block_get(&blk, service_id, RSCNT(bs) + b,
 		    BLOCK_FLAGS_NONE);
 		if (rc != EOK)
@@ -458,5 +458,5 @@
 					/* update the shadow copies of FAT */
 					rc = fat_alloc_shadow_clusters(bs,
-					    devmap_handle, lifo, nclsts);
+					    service_id, lifo, nclsts);
 					if (rc != EOK)
 						goto error;
@@ -485,5 +485,5 @@
 	 */
 	while (found--) {
-		rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
+		rc = fat_set_cluster(bs, service_id, FAT1, lifo[found],
 		    FAT_CLST_RES0);
 		if (rc != EOK) {
@@ -500,5 +500,5 @@
  *
  * @param bs		Buffer hodling the boot sector of the file system.
- * @param devmap_handle	Device handle of the file system.
+ * @param service_id	Device service ID of the file system.
  * @param firstc	First cluster in the chain which is to be freed.
  *
@@ -506,5 +506,5 @@
  */
 int
-fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc)
+fat_free_clusters(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc)
 {
 	unsigned fatno;
@@ -515,9 +515,9 @@
 	while (firstc < FAT_CLST_LAST1) {
 		assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
-		rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc);
+		rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc);
 		if (rc != EOK)
 			return rc;
 		for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
-			rc = fat_set_cluster(bs, devmap_handle, fatno, firstc,
+			rc = fat_set_cluster(bs, service_id, fatno, firstc,
 			    FAT_CLST_RES0);
 			if (rc != EOK)
@@ -544,5 +544,5 @@
     fat_cluster_t lcl)
 {
-	devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
+	service_id_t service_id = nodep->idx->service_id;
 	fat_cluster_t lastc;
 	uint8_t fatno;
@@ -558,5 +558,5 @@
 			nodep->lastc_cached_valid = false;
 		} else {
-			rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,
+			rc = fat_cluster_walk(bs, service_id, nodep->firstc,
 			    &lastc, NULL, (uint16_t) -1);
 			if (rc != EOK)
@@ -565,5 +565,5 @@
 
 		for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
-			rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno,
+			rc = fat_set_cluster(bs, nodep->idx->service_id, fatno,
 			    lastc, mcl);
 			if (rc != EOK)
@@ -591,5 +591,5 @@
 {
 	int rc;
-	devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
+	service_id_t service_id = nodep->idx->service_id;
 
 	/*
@@ -602,5 +602,5 @@
 	if (lcl == FAT_CLST_RES0) {
 		/* The node will have zero size and no clusters allocated. */
-		rc = fat_free_clusters(bs, devmap_handle, nodep->firstc);
+		rc = fat_free_clusters(bs, service_id, nodep->firstc);
 		if (rc != EOK)
 			return rc;
@@ -611,5 +611,5 @@
 		unsigned fatno;
 
-		rc = fat_get_cluster(bs, devmap_handle, FAT1, lcl, &nextc);
+		rc = fat_get_cluster(bs, service_id, FAT1, lcl, &nextc);
 		if (rc != EOK)
 			return rc;
@@ -617,5 +617,5 @@
 		/* Terminate the cluster chain in all copies of FAT. */
 		for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
-			rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,
+			rc = fat_set_cluster(bs, service_id, fatno, lcl,
 			    FAT_CLST_LAST1);
 			if (rc != EOK)
@@ -624,5 +624,5 @@
 
 		/* Free all following clusters. */
-		rc = fat_free_clusters(bs, devmap_handle, nextc);
+		rc = fat_free_clusters(bs, service_id, nextc);
 		if (rc != EOK)
 			return rc;
@@ -639,5 +639,5 @@
 
 int
-fat_zero_cluster(struct fat_bs *bs, devmap_handle_t devmap_handle, fat_cluster_t c)
+fat_zero_cluster(struct fat_bs *bs, service_id_t service_id, fat_cluster_t c)
 {
 	int i;
@@ -646,5 +646,5 @@
 
 	for (i = 0; i < SPC(bs); i++) {
-		rc = _fat_block_get(&b, bs, devmap_handle, c, NULL, i,
+		rc = _fat_block_get(&b, bs, service_id, c, NULL, i,
 		    BLOCK_FLAGS_NOREAD);
 		if (rc != EOK)
@@ -666,5 +666,5 @@
  * does not contain a fat file system.
  */
-int fat_sanity_check(fat_bs_t *bs, devmap_handle_t devmap_handle)
+int fat_sanity_check(fat_bs_t *bs, service_id_t service_id)
 {
 	fat_cluster_t e0, e1;
@@ -707,9 +707,9 @@
 
 	for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
-		rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0);
+		rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0);
 		if (rc != EOK)
 			return EIO;
 
-		rc = fat_get_cluster(bs, devmap_handle, fat_no, 1, &e1);
+		rc = fat_get_cluster(bs, service_id, fat_no, 1, &e1);
 		if (rc != EOK)
 			return EIO;
Index: uspace/srv/fs/fat/fat_fat.h
===================================================================
--- uspace/srv/fs/fat/fat_fat.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/fat/fat_fat.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -61,10 +61,10 @@
 #define fat_clusters_get(numc, bs, dh, fc) \
     fat_cluster_walk((bs), (dh), (fc), NULL, (numc), (uint16_t) -1)
-extern int fat_cluster_walk(struct fat_bs *, devmap_handle_t, fat_cluster_t,
+extern int fat_cluster_walk(struct fat_bs *, service_id_t, fat_cluster_t,
     fat_cluster_t *, uint16_t *, uint16_t);
 
 extern int fat_block_get(block_t **, struct fat_bs *, struct fat_node *,
     aoff64_t, int);
-extern int _fat_block_get(block_t **, struct fat_bs *, devmap_handle_t,
+extern int _fat_block_get(block_t **, struct fat_bs *, service_id_t,
     fat_cluster_t, fat_cluster_t *, aoff64_t, int);
 
@@ -73,17 +73,17 @@
 extern int fat_chop_clusters(struct fat_bs *, struct fat_node *,
     fat_cluster_t);
-extern int fat_alloc_clusters(struct fat_bs *, devmap_handle_t, unsigned,
+extern int fat_alloc_clusters(struct fat_bs *, service_id_t, unsigned,
     fat_cluster_t *, fat_cluster_t *);
-extern int fat_free_clusters(struct fat_bs *, devmap_handle_t, fat_cluster_t);
-extern int fat_alloc_shadow_clusters(struct fat_bs *, devmap_handle_t,
+extern int fat_free_clusters(struct fat_bs *, service_id_t, fat_cluster_t);
+extern int fat_alloc_shadow_clusters(struct fat_bs *, service_id_t,
     fat_cluster_t *, unsigned);
-extern int fat_get_cluster(struct fat_bs *, devmap_handle_t, unsigned,
+extern int fat_get_cluster(struct fat_bs *, service_id_t, unsigned,
     fat_cluster_t, fat_cluster_t *);
-extern int fat_set_cluster(struct fat_bs *, devmap_handle_t, unsigned,
+extern int fat_set_cluster(struct fat_bs *, service_id_t, unsigned,
     fat_cluster_t, fat_cluster_t);
 extern int fat_fill_gap(struct fat_bs *, struct fat_node *, fat_cluster_t,
     aoff64_t);
-extern int fat_zero_cluster(struct fat_bs *, devmap_handle_t, fat_cluster_t);
-extern int fat_sanity_check(struct fat_bs *, devmap_handle_t);
+extern int fat_zero_cluster(struct fat_bs *, service_id_t, fat_cluster_t);
+extern int fat_sanity_check(struct fat_bs *, service_id_t);
 
 #endif
Index: uspace/srv/fs/fat/fat_idx.c
===================================================================
--- uspace/srv/fs/fat/fat_idx.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/fat/fat_idx.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -59,5 +59,5 @@
 typedef struct {
 	link_t		link;
-	devmap_handle_t devmap_handle;
+	service_id_t	service_id;
 
 	/** Next unassigned index. */
@@ -76,8 +76,8 @@
 static LIST_INITIALIZE(unused_list);
 
-static void unused_initialize(unused_t *u, devmap_handle_t devmap_handle)
+static void unused_initialize(unused_t *u, service_id_t service_id)
 {
 	link_initialize(&u->link);
-	u->devmap_handle = devmap_handle;
+	u->service_id = service_id;
 	u->next = 0;
 	u->remaining = ((uint64_t)((fs_index_t)-1)) + 1;
@@ -85,5 +85,5 @@
 }
 
-static unused_t *unused_find(devmap_handle_t devmap_handle, bool lock)
+static unused_t *unused_find(service_id_t service_id, bool lock)
 {
 	unused_t *u;
@@ -94,5 +94,5 @@
 	list_foreach(unused_list, l) {
 		u = list_get_instance(l, unused_t, link);
-		if (u->devmap_handle == devmap_handle) 
+		if (u->service_id == service_id) 
 			return u;
 	}
@@ -108,5 +108,5 @@
 /**
  * Global hash table of all used fat_idx_t structures.
- * The index structures are hashed by the devmap_handle, parent node's first
+ * The index structures are hashed by the service_id, parent node's first
  * cluster and index within the parent directory.
  */ 
@@ -122,5 +122,5 @@
 static hash_index_t pos_hash(unsigned long key[])
 {
-	devmap_handle_t devmap_handle = (devmap_handle_t)key[UPH_DH_KEY];
+	service_id_t service_id = (service_id_t)key[UPH_DH_KEY];
 	fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY];
 	unsigned pdi = (unsigned)key[UPH_PDI_KEY];
@@ -142,5 +142,5 @@
 	h |= (pdi & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
 	    (UPH_BUCKETS_LOG / 2); 
-	h |= (devmap_handle & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
+	h |= (service_id & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
 	    (3 * (UPH_BUCKETS_LOG / 4));
 
@@ -150,5 +150,5 @@
 static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item)
 {
-	devmap_handle_t devmap_handle = (devmap_handle_t)key[UPH_DH_KEY];
+	service_id_t service_id = (service_id_t)key[UPH_DH_KEY];
 	fat_cluster_t pfc;
 	unsigned pdi;
@@ -157,9 +157,9 @@
 	switch (keys) {
 	case 1:
-		return (devmap_handle == fidx->devmap_handle);
+		return (service_id == fidx->service_id);
 	case 3:
 		pfc = (fat_cluster_t) key[UPH_PFC_KEY];
 		pdi = (unsigned) key[UPH_PDI_KEY];
-		return (devmap_handle == fidx->devmap_handle) && (pfc == fidx->pfc) &&
+		return (service_id == fidx->service_id) && (pfc == fidx->pfc) &&
 		    (pdi == fidx->pdi);
 	default:
@@ -183,5 +183,5 @@
 /**
  * Global hash table of all used fat_idx_t structures.
- * The index structures are hashed by the devmap_handle and index.
+ * The index structures are hashed by the service_id and index.
  */
 static hash_table_t ui_hash;
@@ -195,10 +195,10 @@
 static hash_index_t idx_hash(unsigned long key[])
 {
-	devmap_handle_t devmap_handle = (devmap_handle_t)key[UIH_DH_KEY];
+	service_id_t service_id = (service_id_t)key[UIH_DH_KEY];
 	fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY];
 
 	hash_index_t h;
 
-	h = devmap_handle & ((1 << (UIH_BUCKETS_LOG / 2)) - 1);
+	h = service_id & ((1 << (UIH_BUCKETS_LOG / 2)) - 1);
 	h |= (index & ((1 << (UIH_BUCKETS_LOG / 2)) - 1)) <<
 	    (UIH_BUCKETS_LOG / 2);
@@ -209,5 +209,5 @@
 static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item)
 {
-	devmap_handle_t devmap_handle = (devmap_handle_t)key[UIH_DH_KEY];
+	service_id_t service_id = (service_id_t)key[UIH_DH_KEY];
 	fs_index_t index;
 	fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link);
@@ -215,8 +215,8 @@
 	switch (keys) {
 	case 1:
-		return (devmap_handle == fidx->devmap_handle);
+		return (service_id == fidx->service_id);
 	case 2:
 		index = (fs_index_t) key[UIH_INDEX_KEY];
-		return (devmap_handle == fidx->devmap_handle) &&
+		return (service_id == fidx->service_id) &&
 		    (index == fidx->index);
 	default:
@@ -241,10 +241,10 @@
 
 /** Allocate a VFS index which is not currently in use. */
-static bool fat_index_alloc(devmap_handle_t devmap_handle, fs_index_t *index)
+static bool fat_index_alloc(service_id_t service_id, fs_index_t *index)
 {
 	unused_t *u;
 	
 	assert(index);
-	u = unused_find(devmap_handle, true);
+	u = unused_find(service_id, true);
 	if (!u)
 		return false;	
@@ -303,9 +303,9 @@
 
 /** Free a VFS index, which is no longer in use. */
-static void fat_index_free(devmap_handle_t devmap_handle, fs_index_t index)
+static void fat_index_free(service_id_t service_id, fs_index_t index)
 {
 	unused_t *u;
 
-	u = unused_find(devmap_handle, true);
+	u = unused_find(service_id, true);
 	assert(u);
 
@@ -365,5 +365,5 @@
 }
 
-static int fat_idx_create(fat_idx_t **fidxp, devmap_handle_t devmap_handle)
+static int fat_idx_create(fat_idx_t **fidxp, service_id_t service_id)
 {
 	fat_idx_t *fidx;
@@ -372,5 +372,5 @@
 	if (!fidx) 
 		return ENOMEM;
-	if (!fat_index_alloc(devmap_handle, &fidx->index)) {
+	if (!fat_index_alloc(service_id, &fidx->index)) {
 		free(fidx);
 		return ENOSPC;
@@ -380,5 +380,5 @@
 	link_initialize(&fidx->uih_link);
 	fibril_mutex_initialize(&fidx->lock);
-	fidx->devmap_handle = devmap_handle;
+	fidx->service_id = service_id;
 	fidx->pfc = FAT_CLST_RES0;	/* no parent yet */
 	fidx->pdi = 0;
@@ -389,5 +389,5 @@
 }
 
-int fat_idx_get_new(fat_idx_t **fidxp, devmap_handle_t devmap_handle)
+int fat_idx_get_new(fat_idx_t **fidxp, service_id_t service_id)
 {
 	fat_idx_t *fidx;
@@ -395,5 +395,5 @@
 
 	fibril_mutex_lock(&used_lock);
-	rc = fat_idx_create(&fidx, devmap_handle);
+	rc = fat_idx_create(&fidx, service_id);
 	if (rc != EOK) {
 		fibril_mutex_unlock(&used_lock);
@@ -402,5 +402,5 @@
 		
 	unsigned long ikey[] = {
-		[UIH_DH_KEY] = devmap_handle,
+		[UIH_DH_KEY] = service_id,
 		[UIH_INDEX_KEY] = fidx->index,
 	};
@@ -415,10 +415,10 @@
 
 fat_idx_t *
-fat_idx_get_by_pos(devmap_handle_t devmap_handle, fat_cluster_t pfc, unsigned pdi)
+fat_idx_get_by_pos(service_id_t service_id, fat_cluster_t pfc, unsigned pdi)
 {
 	fat_idx_t *fidx;
 	link_t *l;
 	unsigned long pkey[] = {
-		[UPH_DH_KEY] = devmap_handle,
+		[UPH_DH_KEY] = service_id,
 		[UPH_PFC_KEY] = pfc,
 		[UPH_PDI_KEY] = pdi,
@@ -432,5 +432,5 @@
 		int rc;
 
-		rc = fat_idx_create(&fidx, devmap_handle);
+		rc = fat_idx_create(&fidx, service_id);
 		if (rc != EOK) {
 			fibril_mutex_unlock(&used_lock);
@@ -439,5 +439,5 @@
 		
 		unsigned long ikey[] = {
-			[UIH_DH_KEY] = devmap_handle,
+			[UIH_DH_KEY] = service_id,
 			[UIH_INDEX_KEY] = fidx->index,
 		};
@@ -458,5 +458,5 @@
 {
 	unsigned long pkey[] = {
-		[UPH_DH_KEY] = idx->devmap_handle,
+		[UPH_DH_KEY] = idx->service_id,
 		[UPH_PFC_KEY] = idx->pfc,
 		[UPH_PDI_KEY] = idx->pdi,
@@ -471,5 +471,5 @@
 {
 	unsigned long pkey[] = {
-		[UPH_DH_KEY] = idx->devmap_handle,
+		[UPH_DH_KEY] = idx->service_id,
 		[UPH_PFC_KEY] = idx->pfc,
 		[UPH_PDI_KEY] = idx->pdi,
@@ -482,10 +482,10 @@
 
 fat_idx_t *
-fat_idx_get_by_index(devmap_handle_t devmap_handle, fs_index_t index)
+fat_idx_get_by_index(service_id_t service_id, fs_index_t index)
 {
 	fat_idx_t *fidx = NULL;
 	link_t *l;
 	unsigned long ikey[] = {
-		[UIH_DH_KEY] = devmap_handle,
+		[UIH_DH_KEY] = service_id,
 		[UIH_INDEX_KEY] = index,
 	};
@@ -509,8 +509,8 @@
 {
 	unsigned long ikey[] = {
-		[UIH_DH_KEY] = idx->devmap_handle,
+		[UIH_DH_KEY] = idx->service_id,
 		[UIH_INDEX_KEY] = idx->index,
 	};
-	devmap_handle_t devmap_handle = idx->devmap_handle;
+	service_id_t service_id = idx->service_id;
 	fs_index_t index = idx->index;
 
@@ -526,5 +526,5 @@
 	fibril_mutex_unlock(&used_lock);
 	/* Release the VFS index. */
-	fat_index_free(devmap_handle, index);
+	fat_index_free(service_id, index);
 	/* The index structure itself is freed in idx_remove_callback(). */
 }
@@ -548,5 +548,5 @@
 }
 
-int fat_idx_init_by_devmap_handle(devmap_handle_t devmap_handle)
+int fat_idx_init_by_service_id(service_id_t service_id)
 {
 	unused_t *u;
@@ -556,7 +556,7 @@
 	if (!u)
 		return ENOMEM;
-	unused_initialize(u, devmap_handle);
+	unused_initialize(u, service_id);
 	fibril_mutex_lock(&unused_lock);
-	if (!unused_find(devmap_handle, false)) {
+	if (!unused_find(service_id, false)) {
 		list_append(&u->link, &unused_list);
 	} else {
@@ -568,11 +568,11 @@
 }
 
-void fat_idx_fini_by_devmap_handle(devmap_handle_t devmap_handle)
+void fat_idx_fini_by_service_id(service_id_t service_id)
 {
 	unsigned long ikey[] = {
-		[UIH_DH_KEY] = devmap_handle
+		[UIH_DH_KEY] = service_id
 	};
 	unsigned long pkey[] = {
-		[UPH_DH_KEY] = devmap_handle
+		[UPH_DH_KEY] = service_id
 	};
 
@@ -590,5 +590,5 @@
 	 * Free the unused and freed structures for this instance.
 	 */
-	unused_t *u = unused_find(devmap_handle, true);
+	unused_t *u = unused_find(service_id, true);
 	assert(u);
 	list_remove(&u->link);
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/fat/fat_ops.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -43,5 +43,5 @@
 #include <libblock.h>
 #include <ipc/services.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 #include <macros.h>
 #include <async.h>
@@ -72,10 +72,10 @@
  * Forward declarations of FAT libfs operations.
  */
-static int fat_root_get(fs_node_t **, devmap_handle_t);
+static int fat_root_get(fs_node_t **, service_id_t);
 static int fat_match(fs_node_t **, fs_node_t *, const char *);
-static int fat_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
+static int fat_node_get(fs_node_t **, service_id_t, fs_index_t);
 static int fat_node_open(fs_node_t *);
 static int fat_node_put(fs_node_t *);
-static int fat_create_node(fs_node_t **, devmap_handle_t, int);
+static int fat_create_node(fs_node_t **, service_id_t, int);
 static int fat_destroy_node(fs_node_t *);
 static int fat_link(fs_node_t *, fs_node_t *, const char *);
@@ -85,8 +85,7 @@
 static aoff64_t fat_size_get(fs_node_t *);
 static unsigned fat_lnkcnt_get(fs_node_t *);
-static char fat_plb_get_char(unsigned);
 static bool fat_is_directory(fs_node_t *);
 static bool fat_is_file(fs_node_t *node);
-static devmap_handle_t fat_device_get(fs_node_t *node);
+static service_id_t fat_device_get(fs_node_t *node);
 
 /*
@@ -120,8 +119,8 @@
 	assert(node->dirty);
 
-	bs = block_bb_get(node->idx->devmap_handle);
+	bs = block_bb_get(node->idx->service_id);
 	
 	/* Read the block that contains the dentry of interest. */
-	rc = _fat_block_get(&b, bs, node->idx->devmap_handle, node->idx->pfc,
+	rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc,
 	    NULL, (node->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
 	    BLOCK_FLAGS_NONE);
@@ -145,5 +144,5 @@
 }
 
-static int fat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle)
+static int fat_node_fini_by_service_id(service_id_t service_id)
 {
 	fat_node_t *nodep;
@@ -169,5 +168,5 @@
 			goto restart;
 		}
-		if (nodep->idx->devmap_handle != devmap_handle) {
+		if (nodep->idx->service_id != service_id) {
 			fibril_mutex_unlock(&nodep->idx->lock);
 			fibril_mutex_unlock(&nodep->lock);
@@ -299,8 +298,8 @@
 		return rc;
 
-	bs = block_bb_get(idxp->devmap_handle);
+	bs = block_bb_get(idxp->service_id);
 
 	/* Read the block that contains the dentry of interest. */
-	rc = _fat_block_get(&b, bs, idxp->devmap_handle, idxp->pfc, NULL,
+	rc = _fat_block_get(&b, bs, idxp->service_id, idxp->pfc, NULL,
 	    (idxp->pdi * sizeof(fat_dentry_t)) / BPS(bs), BLOCK_FLAGS_NONE);
 	if (rc != EOK) {
@@ -323,5 +322,5 @@
 		 */
 		uint16_t clusters;
-		rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle,
+		rc = fat_clusters_get(&clusters, bs, idxp->service_id,
 		    uint16_t_le2host(d->firstc));
 		if (rc != EOK) {
@@ -357,7 +356,7 @@
  */
 
-int fat_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
-{
-	return fat_node_get(rfn, devmap_handle, 0);
+int fat_root_get(fs_node_t **rfn, service_id_t service_id)
+{
+	return fat_node_get(rfn, service_id, 0);
 }
 
@@ -370,13 +369,13 @@
 	unsigned blocks;
 	fat_dentry_t *d;
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 	block_t *b;
 	int rc;
 
 	fibril_mutex_lock(&parentp->idx->lock);
-	devmap_handle = parentp->idx->devmap_handle;
+	service_id = parentp->idx->service_id;
 	fibril_mutex_unlock(&parentp->idx->lock);
 
-	bs = block_bb_get(devmap_handle);
+	bs = block_bb_get(service_id);
 	blocks = parentp->size / BPS(bs);
 	for (i = 0; i < blocks; i++) {
@@ -403,5 +402,5 @@
 				/* hit */
 				fat_node_t *nodep;
-				fat_idx_t *idx = fat_idx_get_by_pos(devmap_handle,
+				fat_idx_t *idx = fat_idx_get_by_pos(service_id,
 				    parentp->firstc, i * DPS(bs) + j);
 				if (!idx) {
@@ -436,5 +435,5 @@
 
 /** Instantiate a FAT in-core node. */
-int fat_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
+int fat_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
 {
 	fat_node_t *nodep;
@@ -442,5 +441,5 @@
 	int rc;
 
-	idxp = fat_idx_get_by_index(devmap_handle, index);
+	idxp = fat_idx_get_by_index(service_id, index);
 	if (!idxp) {
 		*rfn = NULL;
@@ -493,5 +492,5 @@
 }
 
-int fat_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)
+int fat_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
 {
 	fat_idx_t *idxp;
@@ -501,14 +500,14 @@
 	int rc;
 
-	bs = block_bb_get(devmap_handle);
+	bs = block_bb_get(service_id);
 	if (flags & L_DIRECTORY) {
 		/* allocate a cluster */
-		rc = fat_alloc_clusters(bs, devmap_handle, 1, &mcl, &lcl);
+		rc = fat_alloc_clusters(bs, service_id, 1, &mcl, &lcl);
 		if (rc != EOK)
 			return rc;
 		/* populate the new cluster with unused dentries */
-		rc = fat_zero_cluster(bs, devmap_handle, mcl);
+		rc = fat_zero_cluster(bs, service_id, mcl);
 		if (rc != EOK) {
-			(void) fat_free_clusters(bs, devmap_handle, mcl);
+			(void) fat_free_clusters(bs, service_id, mcl);
 			return rc;
 		}
@@ -517,10 +516,10 @@
 	rc = fat_node_get_new(&nodep);
 	if (rc != EOK) {
-		(void) fat_free_clusters(bs, devmap_handle, mcl);
-		return rc;
-	}
-	rc = fat_idx_get_new(&idxp, devmap_handle);
+		(void) fat_free_clusters(bs, service_id, mcl);
+		return rc;
+	}
+	rc = fat_idx_get_new(&idxp, service_id);
 	if (rc != EOK) {
-		(void) fat_free_clusters(bs, devmap_handle, mcl);	
+		(void) fat_free_clusters(bs, service_id, mcl);	
 		(void) fat_node_put(FS_NODE(nodep));
 		return rc;
@@ -571,9 +570,9 @@
 	assert(!has_children);
 
-	bs = block_bb_get(nodep->idx->devmap_handle);
+	bs = block_bb_get(nodep->idx->service_id);
 	if (nodep->firstc != FAT_CLST_RES0) {
 		assert(nodep->size);
 		/* Free all clusters allocated to the node. */
-		rc = fat_free_clusters(bs, nodep->idx->devmap_handle,
+		rc = fat_free_clusters(bs, nodep->idx->service_id,
 		    nodep->firstc);
 	}
@@ -621,5 +620,5 @@
 	
 	fibril_mutex_lock(&parentp->idx->lock);
-	bs = block_bb_get(parentp->idx->devmap_handle);
+	bs = block_bb_get(parentp->idx->service_id);
 
 	blocks = parentp->size / BPS(bs);
@@ -660,12 +659,12 @@
 		return ENOSPC;
 	}
-	rc = fat_alloc_clusters(bs, parentp->idx->devmap_handle, 1, &mcl, &lcl);
+	rc = fat_alloc_clusters(bs, parentp->idx->service_id, 1, &mcl, &lcl);
 	if (rc != EOK) {
 		fibril_mutex_unlock(&parentp->idx->lock);
 		return rc;
 	}
-	rc = fat_zero_cluster(bs, parentp->idx->devmap_handle, mcl);
+	rc = fat_zero_cluster(bs, parentp->idx->service_id, mcl);
 	if (rc != EOK) {
-		(void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl);
+		(void) fat_free_clusters(bs, parentp->idx->service_id, mcl);
 		fibril_mutex_unlock(&parentp->idx->lock);
 		return rc;
@@ -673,5 +672,5 @@
 	rc = fat_append_clusters(bs, parentp, mcl, lcl);
 	if (rc != EOK) {
-		(void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl);
+		(void) fat_free_clusters(bs, parentp->idx->service_id, mcl);
 		fibril_mutex_unlock(&parentp->idx->lock);
 		return rc;
@@ -790,7 +789,7 @@
 	assert(childp->lnkcnt == 1);
 	fibril_mutex_lock(&childp->idx->lock);
-	bs = block_bb_get(childp->idx->devmap_handle);
-
-	rc = _fat_block_get(&b, bs, childp->idx->devmap_handle, childp->idx->pfc,
+	bs = block_bb_get(childp->idx->service_id);
+
+	rc = _fat_block_get(&b, bs, childp->idx->service_id, childp->idx->pfc,
 	    NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
 	    BLOCK_FLAGS_NONE);
@@ -842,5 +841,5 @@
 	
 	fibril_mutex_lock(&nodep->idx->lock);
-	bs = block_bb_get(nodep->idx->devmap_handle);
+	bs = block_bb_get(nodep->idx->service_id);
 
 	blocks = nodep->size / BPS(bs);
@@ -901,9 +900,4 @@
 }
 
-char fat_plb_get_char(unsigned pos)
-{
-	return fat_reg.plb_ro[pos % PLB_SIZE];
-}
-
 bool fat_is_directory(fs_node_t *fn)
 {
@@ -916,5 +910,5 @@
 }
 
-devmap_handle_t fat_device_get(fs_node_t *node)
+service_id_t fat_device_get(fs_node_t *node)
 {
 	return 0;
@@ -936,5 +930,4 @@
 	.size_get = fat_size_get,
 	.lnkcnt_get = fat_lnkcnt_get,
-	.plb_get_char = fat_plb_get_char,
 	.is_directory = fat_is_directory,
 	.is_file = fat_is_file,
@@ -943,22 +936,15 @@
 
 /*
- * VFS operations.
+ * FAT VFS_OUT operations.
  */
 
-void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+static int
+fat_mounted(service_id_t service_id, const char *opts, fs_index_t *index,
+    aoff64_t *size, unsigned *linkcnt)
+{
 	enum cache_mode cmode;
 	fat_bs_t *bs;
-	
-	/* Accept the mount options */
-	char *opts;
-	int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
-	
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-
+	int rc;
+	
 	/* Check for option enabling write through. */
 	if (str_cmp(opts, "wtcache") == 0)
@@ -967,53 +953,44 @@
 		cmode = CACHE_MODE_WB;
 
-	free(opts);
-
 	/* initialize libblock */
-	rc = block_init(EXCHANGE_SERIALIZE, devmap_handle, BS_SIZE);
+	rc = block_init(EXCHANGE_SERIALIZE, service_id, BS_SIZE);
+	if (rc != EOK)
+		return rc;
+
+	/* prepare the boot block */
+	rc = block_bb_read(service_id, BS_BLOCK);
 	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-
-	/* prepare the boot block */
-	rc = block_bb_read(devmap_handle, BS_BLOCK);
+		block_fini(service_id);
+		return rc;
+	}
+
+	/* get the buffer with the boot sector */
+	bs = block_bb_get(service_id);
+	
+	if (BPS(bs) != BS_SIZE) {
+		block_fini(service_id);
+		return ENOTSUP;
+	}
+
+	/* Initialize the block cache */
+	rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode);
 	if (rc != EOK) {
-		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
-	}
-
-	/* get the buffer with the boot sector */
-	bs = block_bb_get(devmap_handle);
-	
-	if (BPS(bs) != BS_SIZE) {
-		block_fini(devmap_handle);
-		async_answer_0(rid, ENOTSUP);
-		return;
-	}
-
-	/* Initialize the block cache */
-	rc = block_cache_init(devmap_handle, BPS(bs), 0 /* XXX */, cmode);
+		block_fini(service_id);
+		return rc;
+	}
+
+	/* Do some simple sanity checks on the file system. */
+	rc = fat_sanity_check(bs, service_id);
 	if (rc != EOK) {
-		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
-	}
-
-	/* Do some simple sanity checks on the file system. */
-	rc = fat_sanity_check(bs, devmap_handle);
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		return rc;
+	}
+
+	rc = fat_idx_init_by_service_id(service_id);
 	if (rc != EOK) {
-		(void) block_cache_fini(devmap_handle);
-		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
-	}
-
-	rc = fat_idx_init_by_devmap_handle(devmap_handle);
-	if (rc != EOK) {
-		(void) block_cache_fini(devmap_handle);
-		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		return rc;
 	}
 
@@ -1021,9 +998,8 @@
 	fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
 	if (!rfn) {
-		(void) block_cache_fini(devmap_handle);
-		block_fini(devmap_handle);
-		fat_idx_fini_by_devmap_handle(devmap_handle);
-		async_answer_0(rid, ENOMEM);
-		return;
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		fat_idx_fini_by_service_id(service_id);
+		return ENOMEM;
 	}
 	fs_node_initialize(rfn);
@@ -1031,21 +1007,19 @@
 	if (!rootp) {
 		free(rfn);
-		(void) block_cache_fini(devmap_handle);
-		block_fini(devmap_handle);
-		fat_idx_fini_by_devmap_handle(devmap_handle);
-		async_answer_0(rid, ENOMEM);
-		return;
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		fat_idx_fini_by_service_id(service_id);
+		return ENOMEM;
 	}
 	fat_node_initialize(rootp);
 
-	fat_idx_t *ridxp = fat_idx_get_by_pos(devmap_handle, FAT_CLST_ROOTPAR, 0);
+	fat_idx_t *ridxp = fat_idx_get_by_pos(service_id, FAT_CLST_ROOTPAR, 0);
 	if (!ridxp) {
 		free(rfn);
 		free(rootp);
-		(void) block_cache_fini(devmap_handle);
-		block_fini(devmap_handle);
-		fat_idx_fini_by_devmap_handle(devmap_handle);
-		async_answer_0(rid, ENOMEM);
-		return;
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		fat_idx_fini_by_service_id(service_id);
+		return ENOMEM;
 	}
 	assert(ridxp->index == 0);
@@ -1064,24 +1038,20 @@
 	fibril_mutex_unlock(&ridxp->lock);
 
-	async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
-}
-
-void fat_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+	*index = ridxp->index;
+	*size = rootp->size;
+	*linkcnt = rootp->lnkcnt;
+
+	return EOK;
+}
+
+static int fat_unmounted(service_id_t service_id)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
 	int rc;
 
-	rc = fat_root_get(&fn, devmap_handle);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	rc = fat_root_get(&fn, service_id);
+	if (rc != EOK)
+		return rc;
 	nodep = FAT_NODE(fn);
 
@@ -1092,6 +1062,5 @@
 	if (nodep->refcnt != 2) {
 		(void) fat_node_put(fn);
-		async_answer_0(rid, EBUSY);
-		return;
+		return EBUSY;
 	}
 	
@@ -1107,28 +1076,16 @@
 	 * stop using libblock for this instance.
 	 */
-	(void) fat_node_fini_by_devmap_handle(devmap_handle);
-	fat_idx_fini_by_devmap_handle(devmap_handle);
-	(void) block_cache_fini(devmap_handle);
-	block_fini(devmap_handle);
-
-	async_answer_0(rid, EOK);
-}
-
-void fat_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&fat_libfs_ops, rid, request);
-}
-
-void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	(void) fat_node_fini_by_service_id(service_id);
+	fat_idx_fini_by_service_id(service_id);
+	(void) block_cache_fini(service_id);
+	block_fini(service_id);
+
+	return EOK;
+}
+
+static int
+fat_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1138,13 +1095,9 @@
 	int rc;
 
-	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	rc = fat_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 
@@ -1154,9 +1107,8 @@
 		fat_node_put(fn);
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
-	}
-
-	bs = block_bb_get(devmap_handle);
+		return EINVAL;
+	}
+
+	bs = block_bb_get(service_id);
 
 	if (nodep->type == FAT_FILE) {
@@ -1178,6 +1130,5 @@
 				fat_node_put(fn);
 				async_answer_0(callid, rc);
-				async_answer_0(rid, rc);
-				return;
+				return rc;
 			}
 			(void) async_data_read_finalize(callid,
@@ -1186,6 +1137,5 @@
 			if (rc != EOK) {
 				fat_node_put(fn);
-				async_answer_0(rid, rc);
-				return;
+				return rc;
 			}
 		}
@@ -1244,12 +1194,11 @@
 		rc = fat_node_put(fn);
 		async_answer_0(callid, rc != EOK ? rc : ENOENT);
-		async_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
-		return;
+		*rbytes = 0;
+		return rc != EOK ? rc : ENOENT;
 
 err:
 		(void) fat_node_put(fn);
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 
 hit:
@@ -1259,17 +1208,16 @@
 
 	rc = fat_node_put(fn);
-	async_answer_1(rid, rc, (sysarg_t)bytes);
-}
-
-void fat_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	*rbytes = bytes;
+	return rc;
+}
+
+static int
+fat_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
 	fat_bs_t *bs;
-	size_t bytes, size;
+	size_t bytes;
 	block_t *b;
 	aoff64_t boundary;
@@ -1277,13 +1225,9 @@
 	int rc;
 	
-	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	rc = fat_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 	
@@ -1293,9 +1237,8 @@
 		(void) fat_node_put(fn);
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
-	}
-
-	bs = block_bb_get(devmap_handle);
+		return EINVAL;
+	}
+
+	bs = block_bb_get(service_id);
 
 	/*
@@ -1322,6 +1265,5 @@
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		rc = fat_block_get(&b, bs, nodep, pos / BPS(bs), flags);
@@ -1329,6 +1271,5 @@
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		(void) async_data_write_finalize(callid,
@@ -1338,6 +1279,5 @@
 		if (rc != EOK) {
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		if (pos + bytes > nodep->size) {
@@ -1345,8 +1285,8 @@
 			nodep->dirty = true;	/* need to sync node */
 		}
-		size = nodep->size;
+		*wbytes = bytes;
+		*nsize = nodep->size;
 		rc = fat_node_put(fn);
-		async_answer_2(rid, rc, bytes, nodep->size);
-		return;
+		return rc;
 	} else {
 		/*
@@ -1359,29 +1299,26 @@
 		nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs);
 		/* create an independent chain of nclsts clusters in all FATs */
-		rc = fat_alloc_clusters(bs, devmap_handle, nclsts, &mcl, &lcl);
+		rc = fat_alloc_clusters(bs, service_id, nclsts, &mcl, &lcl);
 		if (rc != EOK) {
 			/* could not allocate a chain of nclsts clusters */
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		/* zero fill any gaps */
 		rc = fat_fill_gap(bs, nodep, mcl, pos);
 		if (rc != EOK) {
-			(void) fat_free_clusters(bs, devmap_handle, mcl);
+			(void) fat_free_clusters(bs, service_id, mcl);
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
-		}
-		rc = _fat_block_get(&b, bs, devmap_handle, lcl, NULL,
+			return rc;
+		}
+		rc = _fat_block_get(&b, bs, service_id, lcl, NULL,
 		    (pos / BPS(bs)) % SPC(bs), flags);
 		if (rc != EOK) {
-			(void) fat_free_clusters(bs, devmap_handle, mcl);
+			(void) fat_free_clusters(bs, service_id, mcl);
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		(void) async_data_write_finalize(callid,
@@ -1390,8 +1327,7 @@
 		rc = block_put(b);
 		if (rc != EOK) {
-			(void) fat_free_clusters(bs, devmap_handle, mcl);
+			(void) fat_free_clusters(bs, service_id, mcl);
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		/*
@@ -1401,23 +1337,19 @@
 		rc = fat_append_clusters(bs, nodep, mcl, lcl);
 		if (rc != EOK) {
-			(void) fat_free_clusters(bs, devmap_handle, mcl);
+			(void) fat_free_clusters(bs, service_id, mcl);
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
-		}
-		nodep->size = size = pos + bytes;
+			return rc;
+		}
+		*nsize = nodep->size = pos + bytes;
+		rc = fat_node_put(fn);
 		nodep->dirty = true;		/* need to sync node */
-		rc = fat_node_put(fn);
-		async_answer_2(rid, rc, bytes, size);
-		return;
-	}
-}
-
-void fat_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t size =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+		*wbytes = bytes;
+		return rc;
+	}
+}
+
+static int
+fat_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1425,16 +1357,12 @@
 	int rc;
 
-	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	rc = fat_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 
-	bs = block_bb_get(devmap_handle);
+	bs = block_bb_get(service_id);
 
 	if (nodep->size == size) {
@@ -1463,5 +1391,5 @@
 		} else {
 			fat_cluster_t lastc;
-			rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,
+			rc = fat_cluster_walk(bs, service_id, nodep->firstc,
 			    &lastc, NULL, (size - 1) / BPC(bs));
 			if (rc != EOK)
@@ -1477,30 +1405,23 @@
 out:
 	fat_node_put(fn);
-	async_answer_0(rid, rc);
-	return;
-}
-
-void fat_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, EOK);
-}
-
-void fat_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
+	return rc;
+}
+
+static int fat_close(service_id_t service_id, fs_index_t index)
+{
+	return EOK;
+}
+
+static int fat_destroy(service_id_t service_id, fs_index_t index)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
 	int rc;
 
-	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	rc = fat_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 
 	nodep = FAT_NODE(fn);
@@ -1512,32 +1433,15 @@
 
 	rc = fat_destroy_node(fn);
-	async_answer_0(rid, rc);
-}
-
-void fat_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_sync(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
+	return rc;
+}
+
+static int fat_sync(service_id_t service_id, fs_index_t index)
+{
 	fs_node_t *fn;
-	int rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	int rc = fat_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	
 	fat_node_t *nodep = FAT_NODE(fn);
@@ -1547,6 +1451,17 @@
 	
 	fat_node_put(fn);
-	async_answer_0(rid, rc);
-}
+	return rc;
+}
+
+vfs_out_ops_t fat_ops = {
+	.mounted = fat_mounted,
+	.unmounted = fat_unmounted,
+	.read = fat_read,
+	.write = fat_write,
+	.truncate = fat_truncate,
+	.close = fat_close,
+	.destroy = fat_destroy,
+	.sync = fat_sync,
+};
 
 /**
Index: uspace/srv/fs/locfs/Makefile
===================================================================
--- uspace/srv/fs/locfs/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/srv/fs/locfs/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,40 @@
+#
+# 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 = $(LIBFS_PREFIX)/libfs.a
+EXTRA_CFLAGS += -I$(LIBFS_PREFIX)
+BINARY = locfs
+STATIC_NEEDED = y
+
+SOURCES = \
+	locfs.c \
+	locfs_ops.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/fs/locfs/locfs.c
===================================================================
--- uspace/srv/fs/locfs/locfs.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/srv/fs/locfs/locfs.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,93 @@
+/*
+ * 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 fs
+ * @{
+ */
+
+/**
+ * @file locfs.c
+ * @brief Location-service file system.
+ *
+ * Every service registered with location service is represented as a file in this
+ * file system.
+ */
+
+#include <stdio.h>
+#include <ipc/services.h>
+#include <ns.h>
+#include <async.h>
+#include <errno.h>
+#include <task.h>
+#include <libfs.h>
+#include "locfs.h"
+#include "locfs_ops.h"
+
+#define NAME  "locfs"
+
+static vfs_info_t locfs_vfs_info = {
+	.name = NAME,
+	.concurrent_read_write = false,
+	.write_retains_size = false,
+};
+
+int main(int argc, char *argv[])
+{
+	printf("%s: HelenOS Device Filesystem\n", NAME);
+	
+	if (!locfs_init()) {
+		printf("%s: failed to initialize locfs\n", NAME);
+		return -1;
+	}
+	
+	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+	    SERVICE_VFS, 0, 0);
+	if (!vfs_sess) {
+		printf("%s: Unable to connect to VFS\n", NAME);
+		return -1;
+	}
+	
+	int rc = fs_register(vfs_sess, &locfs_vfs_info, &locfs_ops,
+	    &locfs_libfs_ops);
+	if (rc != EOK) {
+		printf("%s: Failed to register file system (%d)\n", NAME, rc);
+		return rc;
+	}
+	
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
+	async_manager();
+	
+	/* Not reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
+
Index: uspace/srv/fs/locfs/locfs.h
===================================================================
--- uspace/srv/fs/locfs/locfs.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/srv/fs/locfs/locfs.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,45 @@
+/*
+ * 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 fs
+ * @{
+ */ 
+
+#ifndef LOCFS_LOCFS_H_
+#define LOCFS_LOCFS_H_
+
+#include <libfs.h>
+
+extern vfs_out_ops_t locfs_ops;
+extern libfs_ops_t locfs_libfs_ops;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/locfs/locfs_ops.c
===================================================================
--- uspace/srv/fs/locfs/locfs_ops.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/srv/fs/locfs/locfs_ops.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,779 @@
+/*
+ * 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 fs
+ * @{
+ */
+
+/**
+ * @file locfs_ops.c
+ * @brief Implementation of VFS operations for the locfs file system server.
+ */
+
+#include <macros.h>
+#include <bool.h>
+#include <errno.h>
+#include <malloc.h>
+#include <str.h>
+#include <libfs.h>
+#include <fibril_synch.h>
+#include <adt/hash_table.h>
+#include <ipc/loc.h>
+#include <sys/stat.h>
+#include <libfs.h>
+#include <assert.h>
+#include "locfs.h"
+#include "locfs_ops.h"
+
+typedef struct {
+	loc_object_type_t type;
+	service_id_t service_id;
+} locfs_node_t;
+
+/** Opened services structure */
+typedef struct {
+	service_id_t service_id;
+	async_sess_t *sess;       /**< If NULL, the structure is incomplete. */
+	size_t refcount;
+	link_t link;
+	fibril_condvar_t cv;      /**< Broadcast when completed. */
+} service_t;
+
+/** Hash table of opened services */
+static hash_table_t services;
+
+/** Hash table mutex */
+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 = {
+	.hash = services_hash,
+	.compare = services_compare,
+	.remove_callback = services_remove_callback
+};
+
+static int locfs_node_get_internal(fs_node_t **rfn, loc_object_type_t type,
+    service_id_t service_id)
+{
+	locfs_node_t *node = (locfs_node_t *) malloc(sizeof(locfs_node_t));
+	if (node == NULL) {
+		*rfn = NULL;
+		return ENOMEM;
+	}
+	
+	*rfn = (fs_node_t *) malloc(sizeof(fs_node_t));
+	if (*rfn == NULL) {
+		free(node);
+		*rfn = NULL;
+		return ENOMEM;
+	}
+	
+	fs_node_initialize(*rfn);
+	node->type = type;
+	node->service_id = service_id;
+	
+	(*rfn)->data = node;
+	return EOK;
+}
+
+static int locfs_root_get(fs_node_t **rfn, service_id_t service_id)
+{
+	return locfs_node_get_internal(rfn, LOC_OBJECT_NONE, 0);
+}
+
+static int locfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
+{
+	locfs_node_t *node = (locfs_node_t *) pfn->data;
+	int ret;
+	
+	if (node->service_id == 0) {
+		/* Root directory */
+		
+		loc_sdesc_t *nspaces;
+		size_t count = loc_get_namespaces(&nspaces);
+		
+		if (count > 0) {
+			size_t pos;
+			for (pos = 0; pos < count; pos++) {
+				/* Ignore root namespace */
+				if (str_cmp(nspaces[pos].name, "") == 0)
+					continue;
+				
+				if (str_cmp(nspaces[pos].name, component) == 0) {
+					ret = locfs_node_get_internal(rfn, LOC_OBJECT_NAMESPACE, nspaces[pos].id);
+					free(nspaces);
+					return ret;
+				}
+			}
+			
+			free(nspaces);
+		}
+		
+		/* Search root namespace */
+		service_id_t namespace;
+		loc_sdesc_t *svcs;
+		if (loc_namespace_get_id("", &namespace, 0) == EOK) {
+			count = loc_get_services(namespace, &svcs);
+			
+			if (count > 0) {
+				size_t pos;
+				for (pos = 0; pos < count; pos++) {
+					if (str_cmp(svcs[pos].name, component) == 0) {
+						ret = locfs_node_get_internal(rfn, LOC_OBJECT_SERVICE, svcs[pos].id);
+						free(svcs);
+						return ret;
+					}
+				}
+				
+				free(svcs);
+			}
+		}
+		
+		*rfn = NULL;
+		return EOK;
+	}
+	
+	if (node->type == LOC_OBJECT_NAMESPACE) {
+		/* Namespace directory */
+		
+		loc_sdesc_t *svcs;
+		size_t count = loc_get_services(node->service_id, &svcs);
+		if (count > 0) {
+			size_t pos;
+			for (pos = 0; pos < count; pos++) {
+				if (str_cmp(svcs[pos].name, component) == 0) {
+					ret = locfs_node_get_internal(rfn, LOC_OBJECT_SERVICE, svcs[pos].id);
+					free(svcs);
+					return ret;
+				}
+			}
+			
+			free(svcs);
+		}
+		
+		*rfn = NULL;
+		return EOK;
+	}
+	
+	*rfn = NULL;
+	return EOK;
+}
+
+static int locfs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
+{
+	return locfs_node_get_internal(rfn, loc_id_probe(index), index);
+}
+
+static int locfs_node_open(fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	
+	if (node->service_id == 0) {
+		/* Root directory */
+		return EOK;
+	}
+	
+	loc_object_type_t type = loc_id_probe(node->service_id);
+	
+	if (type == LOC_OBJECT_NAMESPACE) {
+		/* Namespace directory */
+		return EOK;
+	}
+	
+	if (type == LOC_OBJECT_SERVICE) {
+		/* Device node */
+		
+		unsigned long key[] = {
+			[SERVICES_KEY_HANDLE] = (unsigned long) node->service_id
+		};
+		link_t *lnk;
+		
+		fibril_mutex_lock(&services_mutex);
+restart:
+		lnk = hash_table_find(&services, key);
+		if (lnk == NULL) {
+			service_t *dev = (service_t *) malloc(sizeof(service_t));
+			if (dev == NULL) {
+				fibril_mutex_unlock(&services_mutex);
+				return ENOMEM;
+			}
+			
+			dev->service_id = node->service_id;
+			
+			/* Mark as incomplete */
+			dev->sess = NULL;
+			dev->refcount = 1;
+			fibril_condvar_initialize(&dev->cv);
+			
+			/*
+			 * Insert the incomplete device structure so that other
+			 * fibrils will not race with us when we drop the mutex
+			 * below.
+			 */
+			hash_table_insert(&services, key, &dev->link);
+			
+			/*
+			 * Drop the mutex to allow recursive locfs requests.
+			 */
+			fibril_mutex_unlock(&services_mutex);
+			
+			async_sess_t *sess = loc_service_connect(
+			    EXCHANGE_SERIALIZE, node->service_id, 0);
+			
+			fibril_mutex_lock(&services_mutex);
+			
+			/*
+			 * Notify possible waiters about this device structure
+			 * being completed (or destroyed).
+			 */
+			fibril_condvar_broadcast(&dev->cv);
+			
+			if (!sess) {
+				/*
+				 * Connecting failed, need to remove the
+				 * entry and free the device structure.
+				 */
+				hash_table_remove(&services, key, SERVICES_KEYS);
+				fibril_mutex_unlock(&services_mutex);
+				
+				return ENOENT;
+			}
+			
+			/* Set the correct session. */
+			dev->sess = sess;
+		} else {
+			service_t *dev = hash_table_get_instance(lnk, service_t, link);
+			
+			if (!dev->sess) {
+				/*
+				 * Wait until the device structure is completed
+				 * and start from the beginning as the device
+				 * structure might have entirely disappeared
+				 * while we were not holding the mutex in
+				 * fibril_condvar_wait().
+				 */
+				fibril_condvar_wait(&dev->cv, &services_mutex);
+				goto restart;
+			}
+
+			dev->refcount++;
+		}
+		
+		fibril_mutex_unlock(&services_mutex);
+		
+		return EOK;
+	}
+	
+	return ENOENT;
+}
+
+static int locfs_node_put(fs_node_t *fn)
+{
+	free(fn->data);
+	free(fn);
+	return EOK;
+}
+
+static int locfs_create_node(fs_node_t **rfn, service_id_t service_id, int lflag)
+{
+	assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
+	
+	*rfn = NULL;
+	return ENOTSUP;
+}
+
+static int locfs_destroy_node(fs_node_t *fn)
+{
+	return ENOTSUP;
+}
+
+static int locfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
+{
+	return ENOTSUP;
+}
+
+static int locfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
+{
+	return ENOTSUP;
+}
+
+static int locfs_has_children(bool *has_children, fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	
+	if (node->service_id == 0) {
+		size_t count = loc_count_namespaces();
+		if (count > 0) {
+			*has_children = true;
+			return EOK;
+		}
+		
+		/* Root namespace */
+		service_id_t namespace;
+		if (loc_namespace_get_id("", &namespace, 0) == EOK) {
+			count = loc_count_services(namespace);
+			if (count > 0) {
+				*has_children = true;
+				return EOK;
+			}
+		}
+		
+		*has_children = false;
+		return EOK;
+	}
+	
+	if (node->type == LOC_OBJECT_NAMESPACE) {
+		size_t count = loc_count_services(node->service_id);
+		if (count > 0) {
+			*has_children = true;
+			return EOK;
+		}
+		
+		*has_children = false;
+		return EOK;
+	}
+	
+	*has_children = false;
+	return EOK;
+}
+
+static fs_index_t locfs_index_get(fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	return node->service_id;
+}
+
+static aoff64_t locfs_size_get(fs_node_t *fn)
+{
+	return 0;
+}
+
+static unsigned int locfs_lnkcnt_get(fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	
+	if (node->service_id == 0)
+		return 0;
+	
+	return 1;
+}
+
+static bool locfs_is_directory(fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	
+	return ((node->type == LOC_OBJECT_NONE) || (node->type == LOC_OBJECT_NAMESPACE));
+}
+
+static bool locfs_is_file(fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	
+	return (node->type == LOC_OBJECT_SERVICE);
+}
+
+static service_id_t locfs_device_get(fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	
+	if (node->type == LOC_OBJECT_SERVICE)
+		return node->service_id;
+	
+	return 0;
+}
+
+/** libfs operations */
+libfs_ops_t locfs_libfs_ops = {
+	.root_get = locfs_root_get,
+	.match = locfs_match,
+	.node_get = locfs_node_get,
+	.node_open = locfs_node_open,
+	.node_put = locfs_node_put,
+	.create = locfs_create_node,
+	.destroy = locfs_destroy_node,
+	.link = locfs_link_node,
+	.unlink = locfs_unlink_node,
+	.has_children = locfs_has_children,
+	.index_get = locfs_index_get,
+	.size_get = locfs_size_get,
+	.lnkcnt_get = locfs_lnkcnt_get,
+	.is_directory = locfs_is_directory,
+	.is_file = locfs_is_file,
+	.device_get = locfs_device_get
+};
+
+bool locfs_init(void)
+{
+	if (!hash_table_create(&services, SERVICES_BUCKETS,
+	    SERVICES_KEYS, &services_ops))
+		return false;
+	
+	return true;
+}
+
+static int locfs_mounted(service_id_t service_id, const char *opts,
+    fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
+	*index = 0;
+	*size = 0;
+	*lnkcnt = 0;
+	return EOK;
+}
+
+static int locfs_unmounted(service_id_t service_id)
+{
+	return ENOTSUP;
+}
+
+static int
+locfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
+	if (index == 0) {
+		ipc_callid_t callid;
+		size_t size;
+		if (!async_data_read_receive(&callid, &size)) {
+			async_answer_0(callid, EINVAL);
+			return EINVAL;
+		}
+		
+		loc_sdesc_t *desc;
+		size_t count = loc_get_namespaces(&desc);
+		
+		/* Get rid of root namespace */
+		size_t i;
+		for (i = 0; i < count; i++) {
+			if (str_cmp(desc[i].name, "") == 0) {
+				if (pos >= i)
+					pos++;
+				
+				break;
+			}
+		}
+		
+		if (pos < count) {
+			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
+			free(desc);
+			*rbytes = 1;
+			return EOK;
+		}
+		
+		free(desc);
+		pos -= count;
+		
+		/* Search root namespace */
+		service_id_t namespace;
+		if (loc_namespace_get_id("", &namespace, 0) == EOK) {
+			count = loc_get_services(namespace, &desc);
+			
+			if (pos < count) {
+				async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
+				free(desc);
+				*rbytes = 1;
+				return EOK;
+			}
+			
+			free(desc);
+		}
+		
+		async_answer_0(callid, ENOENT);
+		return ENOENT;
+	}
+	
+	loc_object_type_t type = loc_id_probe(index);
+	
+	if (type == LOC_OBJECT_NAMESPACE) {
+		/* Namespace directory */
+		ipc_callid_t callid;
+		size_t size;
+		if (!async_data_read_receive(&callid, &size)) {
+			async_answer_0(callid, EINVAL);
+			return EINVAL;
+		}
+		
+		loc_sdesc_t *desc;
+		size_t count = loc_get_services(index, &desc);
+		
+		if (pos < count) {
+			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
+			free(desc);
+			*rbytes = 1;
+			return EOK;
+		}
+		
+		free(desc);
+		async_answer_0(callid, ENOENT);
+		return ENOENT;
+	}
+	
+	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);
+		if (lnk == NULL) {
+			fibril_mutex_unlock(&services_mutex);
+			return ENOENT;
+		}
+		
+		service_t *dev = hash_table_get_instance(lnk, service_t, link);
+		assert(dev->sess);
+		
+		ipc_callid_t callid;
+		if (!async_data_read_receive(&callid, NULL)) {
+			fibril_mutex_unlock(&services_mutex);
+			async_answer_0(callid, EINVAL);
+			return EINVAL;
+		}
+		
+		/* Make a request at the driver */
+		async_exch_t *exch = async_exchange_begin(dev->sess);
+		
+		ipc_call_t answer;
+		aid_t msg = async_send_4(exch, VFS_OUT_READ, service_id,
+		    index, LOWER32(pos), UPPER32(pos), &answer);
+		
+		/* Forward the IPC_M_DATA_READ request to the driver */
+		async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+		
+		async_exchange_end(exch);
+		
+		fibril_mutex_unlock(&services_mutex);
+		
+		/* Wait for reply from the driver. */
+		sysarg_t rc;
+		async_wait_for(msg, &rc);
+		
+		*rbytes = IPC_GET_ARG1(answer);
+		return rc;
+	}
+	
+	return ENOENT;
+}
+
+static int
+locfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
+	if (index == 0)
+		return ENOTSUP;
+	
+	loc_object_type_t type = loc_id_probe(index);
+	
+	if (type == LOC_OBJECT_NAMESPACE) {
+		/* Namespace directory */
+		return ENOTSUP;
+	}
+	
+	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);
+		if (lnk == NULL) {
+			fibril_mutex_unlock(&services_mutex);
+			return ENOENT;
+		}
+		
+		service_t *dev = hash_table_get_instance(lnk, service_t, link);
+		assert(dev->sess);
+		
+		ipc_callid_t callid;
+		if (!async_data_write_receive(&callid, NULL)) {
+			fibril_mutex_unlock(&services_mutex);
+			async_answer_0(callid, EINVAL);
+			return EINVAL;
+		}
+		
+		/* Make a request at the driver */
+		async_exch_t *exch = async_exchange_begin(dev->sess);
+		
+		ipc_call_t answer;
+		aid_t msg = async_send_4(exch, VFS_OUT_WRITE, service_id,
+		    index, LOWER32(pos), UPPER32(pos), &answer);
+		
+		/* Forward the IPC_M_DATA_WRITE request to the driver */
+		async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+		
+		async_exchange_end(exch);
+		
+		fibril_mutex_unlock(&services_mutex);
+		
+		/* Wait for reply from the driver. */
+		sysarg_t rc;
+		async_wait_for(msg, &rc);
+		
+		*wbytes = IPC_GET_ARG1(answer);
+		*nsize = 0;
+		return rc;
+	}
+	
+	return ENOENT;
+}
+
+static int
+locfs_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
+{
+	return ENOTSUP;
+}
+
+static int locfs_close(service_id_t service_id, fs_index_t index)
+{
+	if (index == 0)
+		return EOK;
+	
+	loc_object_type_t type = loc_id_probe(index);
+	
+	if (type == LOC_OBJECT_NAMESPACE) {
+		/* Namespace directory */
+		return EOK;
+	}
+	
+	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);
+		if (lnk == NULL) {
+			fibril_mutex_unlock(&services_mutex);
+			return ENOENT;
+		}
+		
+		service_t *dev = hash_table_get_instance(lnk, service_t, link);
+		assert(dev->sess);
+		dev->refcount--;
+		
+		if (dev->refcount == 0) {
+			async_hangup(dev->sess);
+			hash_table_remove(&services, key, SERVICES_KEYS);
+		}
+		
+		fibril_mutex_unlock(&services_mutex);
+		
+		return EOK;
+	}
+	
+	return ENOENT;
+}
+
+static int locfs_sync(service_id_t service_id, fs_index_t index)
+{
+	if (index == 0)
+		return EOK;
+	
+	loc_object_type_t type = loc_id_probe(index);
+	
+	if (type == LOC_OBJECT_NAMESPACE) {
+		/* Namespace directory */
+		return EOK;
+	}
+	
+	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);
+		if (lnk == NULL) {
+			fibril_mutex_unlock(&services_mutex);
+			return ENOENT;
+		}
+		
+		service_t *dev = hash_table_get_instance(lnk, service_t, link);
+		assert(dev->sess);
+		
+		/* Make a request at the driver */
+		async_exch_t *exch = async_exchange_begin(dev->sess);
+		
+		ipc_call_t answer;
+		aid_t msg = async_send_2(exch, VFS_OUT_SYNC, service_id,
+		    index, &answer);
+		
+		async_exchange_end(exch);
+		
+		fibril_mutex_unlock(&services_mutex);
+		
+		/* Wait for reply from the driver */
+		sysarg_t rc;
+		async_wait_for(msg, &rc);
+		
+		return rc;
+	}
+	
+	return  ENOENT;
+}
+
+static int locfs_destroy(service_id_t service_id, fs_index_t index)
+{
+	return ENOTSUP;
+}
+
+vfs_out_ops_t locfs_ops = {
+	.mounted = locfs_mounted,
+	.unmounted = locfs_unmounted,
+	.read = locfs_read,
+	.write = locfs_write,
+	.truncate = locfs_truncate,
+	.close = locfs_close,
+	.destroy = locfs_destroy,
+	.sync = locfs_sync,
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/locfs/locfs_ops.h
===================================================================
--- uspace/srv/fs/locfs/locfs_ops.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/srv/fs/locfs/locfs_ops.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,44 @@
+/*
+ * 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 fs
+ * @{
+ */
+
+#ifndef LOCFS_LOCFS_OPS_H_
+#define LOCFS_LOCFS_OPS_H_
+
+#include <bool.h>
+
+extern bool locfs_init(void);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/tmpfs/tmpfs.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/tmpfs/tmpfs.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -61,92 +61,4 @@
 };
 
-fs_reg_t tmpfs_reg;
-
-/**
- * This connection fibril processes VFS requests from VFS.
- *
- * In order to support simultaneous VFS requests, our design is as follows.
- * The connection fibril accepts VFS requests from VFS. If there is only one
- * instance of the fibril, VFS will need to serialize all VFS requests it sends
- * to FAT. To overcome this bottleneck, VFS can send TMPFS the
- * IPC_M_CONNECT_ME_TO call. In that case, a new connection fibril will be
- * created, which in turn will accept the call. Thus, a new phone will be
- * opened for VFS.
- *
- * There are few issues with this arrangement. First, VFS can run out of
- * available phones. In that case, VFS can close some other phones or use one
- * phone for more serialized requests. Similarily, TMPFS can refuse to duplicate
- * the connection. VFS should then just make use of already existing phones and
- * route its requests through them. To avoid paying the fibril creation price 
- * upon each request, TMPFS might want to keep the connections open after the
- * request has been completed.
- */
-static void tmpfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	if (iid) {
-		/*
-		 * This only happens for connections opened by
-		 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
-		 * created by IPC_M_CONNECT_TO_ME.
-		 */
-		async_answer_0(iid, EOK);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			return;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case VFS_OUT_MOUNTED:
-			tmpfs_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			tmpfs_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			tmpfs_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			tmpfs_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			tmpfs_lookup(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			tmpfs_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			tmpfs_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			tmpfs_truncate(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			tmpfs_close(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			tmpfs_destroy(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			tmpfs_open_node(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			tmpfs_stat(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			tmpfs_sync(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char **argv)
 {
@@ -165,6 +77,6 @@
 	}
 	
-	int rc = fs_register(vfs_sess, &tmpfs_reg, &tmpfs_vfs_info,
-	    tmpfs_connection);
+	int rc = fs_register(vfs_sess, &tmpfs_vfs_info, &tmpfs_ops,
+	    &tmpfs_libfs_ops);
 	if (rc != EOK) {
 		printf(NAME ": Failed to register file system (%d)\n", rc);
Index: uspace/srv/fs/tmpfs/tmpfs.h
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/tmpfs/tmpfs.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -61,5 +61,5 @@
 	fs_node_t *bp;		/**< Back pointer to the FS node. */
 	fs_index_t index;	/**< TMPFS node index. */
-	devmap_handle_t devmap_handle;/**< Device handle. */
+	service_id_t service_id;/**< Service ID of block device. */
 	link_t nh_link;		/**< Nodes hash table link. */
 	tmpfs_dentry_type_t type;
@@ -70,25 +70,9 @@
 } tmpfs_node_t;
 
-extern fs_reg_t tmpfs_reg;
-
+extern vfs_out_ops_t tmpfs_ops;
 extern libfs_ops_t tmpfs_libfs_ops;
 
 extern bool tmpfs_init(void);
-
-extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_mount(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_unmounted(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_unmount(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_read(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_write(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_stat(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_close(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_open_node(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_sync(ipc_callid_t, ipc_call_t *);
-
-extern bool tmpfs_restore(devmap_handle_t);
+extern bool tmpfs_restore(service_id_t);
 
 #endif
Index: uspace/srv/fs/tmpfs/tmpfs_dump.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_dump.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/tmpfs/tmpfs_dump.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -55,5 +55,5 @@
 
 static bool
-tmpfs_restore_recursion(devmap_handle_t dev, size_t *bufpos, size_t *buflen,
+tmpfs_restore_recursion(service_id_t dsid, size_t *bufpos, size_t *buflen,
     aoff64_t *pos, fs_node_t *pfn)
 {
@@ -68,5 +68,5 @@
 		uint32_t size;
 		
-		if (block_seqread(dev, bufpos, buflen, pos, &entry,
+		if (block_seqread(dsid, bufpos, buflen, pos, &entry,
 		    sizeof(entry)) != EOK)
 			return false;
@@ -82,5 +82,5 @@
 				return false;
 			
-			rc = ops->create(&fn, dev, L_FILE);
+			rc = ops->create(&fn, dsid, L_FILE);
 			if (rc != EOK || fn == NULL) {
 				free(fname);
@@ -88,5 +88,5 @@
 			}
 			
-			if (block_seqread(dev, bufpos, buflen, pos, fname,
+			if (block_seqread(dsid, bufpos, buflen, pos, fname,
 			    entry.len) != EOK) {
 				(void) ops->destroy(fn);
@@ -104,5 +104,5 @@
 			free(fname);
 			
-			if (block_seqread(dev, bufpos, buflen, pos, &size,
+			if (block_seqread(dsid, bufpos, buflen, pos, &size,
 			    sizeof(size)) != EOK)
 				return false;
@@ -116,5 +116,5 @@
 			
 			nodep->size = size;
-			if (block_seqread(dev, bufpos, buflen, pos, nodep->data,
+			if (block_seqread(dsid, bufpos, buflen, pos, nodep->data,
 			    size) != EOK)
 				return false;
@@ -126,5 +126,5 @@
 				return false;
 			
-			rc = ops->create(&fn, dev, L_DIRECTORY);
+			rc = ops->create(&fn, dsid, L_DIRECTORY);
 			if (rc != EOK || fn == NULL) {
 				free(fname);
@@ -132,5 +132,5 @@
 			}
 			
-			if (block_seqread(dev, bufpos, buflen, pos, fname,
+			if (block_seqread(dsid, bufpos, buflen, pos, fname,
 			    entry.len) != EOK) {
 				(void) ops->destroy(fn);
@@ -148,5 +148,5 @@
 			free(fname);
 			
-			if (!tmpfs_restore_recursion(dev, bufpos, buflen, pos,
+			if (!tmpfs_restore_recursion(dsid, bufpos, buflen, pos,
 			    fn))
 				return false;
@@ -161,5 +161,5 @@
 }
 
-bool tmpfs_restore(devmap_handle_t dev)
+bool tmpfs_restore(service_id_t dsid)
 {
 	libfs_ops_t *ops = &tmpfs_libfs_ops;
@@ -167,5 +167,5 @@
 	int rc;
 
-	rc = block_init(EXCHANGE_SERIALIZE, dev, TMPFS_COMM_SIZE);
+	rc = block_init(EXCHANGE_SERIALIZE, dsid, TMPFS_COMM_SIZE);
 	if (rc != EOK)
 		return false; 
@@ -176,5 +176,5 @@
 	
 	char tag[6];
-	if (block_seqread(dev, &bufpos, &buflen, &pos, tag, 5) != EOK)
+	if (block_seqread(dsid, &bufpos, &buflen, &pos, tag, 5) != EOK)
 		goto error;
 	
@@ -183,16 +183,16 @@
 		goto error;
 	
-	rc = ops->root_get(&fn, dev);
+	rc = ops->root_get(&fn, dsid);
 	if (rc != EOK)
 		goto error;
 
-	if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, fn))
-		goto error;
-		
-	block_fini(dev);
+	if (!tmpfs_restore_recursion(dsid, &bufpos, &buflen, &pos, fn))
+		goto error;
+		
+	block_fini(dsid);
 	return true;
 	
 error:
-	block_fini(dev);
+	block_fini(dsid);
 	return false;
 }
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -69,8 +69,8 @@
 /* Forward declarations of static functions. */
 static int tmpfs_match(fs_node_t **, fs_node_t *, const char *);
-static int tmpfs_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
+static int tmpfs_node_get(fs_node_t **, service_id_t, fs_index_t);
 static int tmpfs_node_open(fs_node_t *);
 static int tmpfs_node_put(fs_node_t *);
-static int tmpfs_create_node(fs_node_t **, devmap_handle_t, int);
+static int tmpfs_create_node(fs_node_t **, service_id_t, int);
 static int tmpfs_destroy_node(fs_node_t *);
 static int tmpfs_link_node(fs_node_t *, fs_node_t *, const char *);
@@ -78,7 +78,7 @@
 
 /* Implementation of helper functions. */
-static int tmpfs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
-{
-	return tmpfs_node_get(rfn, devmap_handle, TMPFS_SOME_ROOT); 
+static int tmpfs_root_get(fs_node_t **rfn, service_id_t service_id)
+{
+	return tmpfs_node_get(rfn, service_id, TMPFS_SOME_ROOT); 
 }
 
@@ -104,9 +104,4 @@
 }
 
-static char tmpfs_plb_get_char(unsigned pos)
-{
-	return tmpfs_reg.plb_ro[pos % PLB_SIZE];
-}
-
 static bool tmpfs_is_directory(fs_node_t *fn)
 {
@@ -119,5 +114,5 @@
 }
 
-static devmap_handle_t tmpfs_device_get(fs_node_t *fn)
+static service_id_t tmpfs_device_get(fs_node_t *fn)
 {
 	return 0;
@@ -139,5 +134,4 @@
 	.size_get = tmpfs_size_get,
 	.lnkcnt_get = tmpfs_lnkcnt_get,
-	.plb_get_char = tmpfs_plb_get_char,
 	.is_directory = tmpfs_is_directory,
 	.is_file = tmpfs_is_file,
@@ -164,7 +158,7 @@
 	switch (keys) {
 	case 1:
-		return (nodep->devmap_handle == key[NODES_KEY_DEV]);
+		return (nodep->service_id == key[NODES_KEY_DEV]);
 	case 2:	
-		return ((nodep->devmap_handle == key[NODES_KEY_DEV]) &&
+		return ((nodep->service_id == key[NODES_KEY_DEV]) &&
 		    (nodep->index == key[NODES_KEY_INDEX]));
 	default:
@@ -208,5 +202,5 @@
 	nodep->bp = NULL;
 	nodep->index = 0;
-	nodep->devmap_handle = 0;
+	nodep->service_id = 0;
 	nodep->type = TMPFS_NONE;
 	nodep->lnkcnt = 0;
@@ -232,10 +226,10 @@
 }
 
-static bool tmpfs_instance_init(devmap_handle_t devmap_handle)
+static bool tmpfs_instance_init(service_id_t service_id)
 {
 	fs_node_t *rfn;
 	int rc;
 	
-	rc = tmpfs_create_node(&rfn, devmap_handle, L_DIRECTORY);
+	rc = tmpfs_create_node(&rfn, service_id, L_DIRECTORY);
 	if (rc != EOK || !rfn)
 		return false;
@@ -244,8 +238,8 @@
 }
 
-static void tmpfs_instance_done(devmap_handle_t devmap_handle)
-{
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle
+static void tmpfs_instance_done(service_id_t service_id)
+{
+	unsigned long key[] = {
+		[NODES_KEY_DEV] = service_id
 	};
 	/*
@@ -276,8 +270,8 @@
 }
 
-int tmpfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
-{
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle,
+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
 	};
@@ -305,5 +299,5 @@
 }
 
-int tmpfs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int lflag)
+int tmpfs_create_node(fs_node_t **rfn, service_id_t service_id, int lflag)
 {
 	fs_node_t *rootfn;
@@ -324,5 +318,5 @@
 	nodep->bp->data = nodep;	/* link the FS and TMPFS nodes */
 
-	rc = tmpfs_root_get(&rootfn, devmap_handle);
+	rc = tmpfs_root_get(&rootfn, service_id);
 	assert(rc == EOK);
 	if (!rootfn)
@@ -330,5 +324,5 @@
 	else
 		nodep->index = tmpfs_next_index++;
-	nodep->devmap_handle = devmap_handle;
+	nodep->service_id = service_id;
 	if (lflag & L_DIRECTORY) 
 		nodep->type = TMPFS_DIRECTORY;
@@ -338,5 +332,5 @@
 	/* Insert the new node into the nodes hash table. */
 	unsigned long key[] = {
-		[NODES_KEY_DEV] = nodep->devmap_handle,
+		[NODES_KEY_DEV] = nodep->service_id,
 		[NODES_KEY_INDEX] = nodep->index
 	};
@@ -354,5 +348,5 @@
 
 	unsigned long key[] = {
-		[NODES_KEY_DEV] = nodep->devmap_handle,
+		[NODES_KEY_DEV] = nodep->service_id,
 		[NODES_KEY_INDEX] = nodep->index
 	};
@@ -433,80 +427,50 @@
 }
 
-void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+/*
+ * Implementation of the VFS_OUT interface.
+ */
+
+static int
+tmpfs_mounted(service_id_t service_id, const char *opts,
+    fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
 	fs_node_t *rootfn;
 	int rc;
 	
-	/* Accept the mount options. */
-	char *opts;
-	rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-
 	/* Check if this device is not already mounted. */
-	rc = tmpfs_root_get(&rootfn, devmap_handle);
+	rc = tmpfs_root_get(&rootfn, service_id);
 	if ((rc == EOK) && (rootfn)) {
 		(void) tmpfs_node_put(rootfn);
-		free(opts);
-		async_answer_0(rid, EEXIST);
-		return;
+		return EEXIST;
 	}
 
 	/* Initialize TMPFS instance. */
-	if (!tmpfs_instance_init(devmap_handle)) {
-		free(opts);
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
-
-	rc = tmpfs_root_get(&rootfn, devmap_handle);
+	if (!tmpfs_instance_init(service_id))
+		return ENOMEM;
+
+	rc = tmpfs_root_get(&rootfn, service_id);
 	assert(rc == EOK);
 	tmpfs_node_t *rootp = TMPFS_NODE(rootfn);
 	if (str_cmp(opts, "restore") == 0) {
-		if (tmpfs_restore(devmap_handle))
-			async_answer_3(rid, EOK, rootp->index, rootp->size,
-			    rootp->lnkcnt);
-		else
-			async_answer_0(rid, ELIMIT);
-	} else {
-		async_answer_3(rid, EOK, rootp->index, rootp->size,
-		    rootp->lnkcnt);
-	}
-	free(opts);
-}
-
-void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_mount(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-
-	tmpfs_instance_done(devmap_handle);
-	async_answer_0(rid, EOK);
-}
-
-void tmpfs_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&tmpfs_libfs_ops, rid, request);
-}
-
-void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+		if (!tmpfs_restore(service_id))
+			return ELIMIT;
+	}
+
+	*index = rootp->index;
+	*size = rootp->size;
+	*lnkcnt = rootp->lnkcnt;
+
+	return EOK;
+}
+
+static int tmpfs_unmounted(service_id_t service_id)
+{
+	tmpfs_instance_done(service_id);
+	return EOK;
+}
+
+static int tmpfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
 	/*
 	 * Lookup the respective TMPFS node.
@@ -514,12 +478,10 @@
 	link_t *hlp;
 	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle,
+		[NODES_KEY_DEV] = service_id,
 		[NODES_KEY_INDEX] = index
 	};
 	hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (!hlp)
+		return ENOENT;
 	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
 	    nh_link);
@@ -532,6 +494,5 @@
 	if (!async_data_read_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -556,6 +517,5 @@
 		if (lnk == NULL) {
 			async_answer_0(callid, ENOENT);
-			async_answer_1(rid, ENOENT, 0);
-			return;
+			return ENOENT;
 		}
 
@@ -567,17 +527,12 @@
 	}
 
-	/*
-	 * Answer the VFS_READ call.
-	 */
-	async_answer_1(rid, EOK, bytes);
-}
-
-void tmpfs_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+	*rbytes = bytes;
+	return EOK;
+}
+
+static int
+tmpfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
 	/*
 	 * Lookup the respective TMPFS node.
@@ -585,12 +540,10 @@
 	link_t *hlp;
 	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle,
+		[NODES_KEY_DEV] = service_id,
 		[NODES_KEY_INDEX] = index
 	};
 	hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (!hlp)
+		return ENOENT;
 	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
 	    nh_link);
@@ -603,6 +556,5 @@
 	if (!async_data_write_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);	
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -612,7 +564,7 @@
 	if (pos + size <= nodep->size) {
 		/* The file size is not changing. */
-		(void) async_data_write_finalize(callid, nodep->data + pos, size);
-		async_answer_2(rid, EOK, size, nodep->size);
-		return;
+		(void) async_data_write_finalize(callid, nodep->data + pos,
+		    size);
+		goto out;
 	}
 	size_t delta = (pos + size) - nodep->size;
@@ -627,6 +579,6 @@
 	if (!newdata) {
 		async_answer_0(callid, ENOMEM);
-		async_answer_2(rid, EOK, 0, nodep->size);
-		return;
+		size = 0;
+		goto out;
 	}
 	/* Clear any newly allocated memory in order to emulate gaps. */
@@ -635,44 +587,35 @@
 	nodep->data = newdata;
 	(void) async_data_write_finalize(callid, nodep->data + pos, size);
-	async_answer_2(rid, EOK, size, nodep->size);
-}
-
-void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t size =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+
+out:
+	*wbytes = size;
+	*nsize = nodep->size;
+	return EOK;
+}
+
+static int tmpfs_truncate(service_id_t service_id, fs_index_t index,
+    aoff64_t size)
+{
 	/*
 	 * Lookup the respective TMPFS node.
 	 */
 	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle,
+		[NODES_KEY_DEV] = service_id,
 		[NODES_KEY_INDEX] = index
 	};
 	link_t *hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
-	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
-	    nh_link);
-	
-	if (size == nodep->size) {
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	if (size > SIZE_MAX) {
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
+	if (!hlp)
+		return ENOENT;
+	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, nh_link);
+	
+	if (size == nodep->size)
+		return EOK;
+	
+	if (size > SIZE_MAX)
+		return ENOMEM;
 	
 	void *newdata = realloc(nodep->data, size);
-	if (!newdata) {
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
+	if (!newdata)
+		return ENOMEM;
 	
 	if (size > nodep->size) {
@@ -683,45 +626,28 @@
 	nodep->size = size;
 	nodep->data = newdata;
-	async_answer_0(rid, EOK);
-}
-
-void tmpfs_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, EOK);
-}
-
-void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	int rc;
-
+	return EOK;
+}
+
+static int tmpfs_close(service_id_t service_id, fs_index_t index)
+{
+	return EOK;
+}
+
+static int tmpfs_destroy(service_id_t service_id, fs_index_t index)
+{
 	link_t *hlp;
 	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle,
+		[NODES_KEY_DEV] = service_id,
 		[NODES_KEY_INDEX] = index
 	};
 	hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (!hlp)
+		return ENOENT;
 	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
 	    nh_link);
-	rc = tmpfs_destroy_node(FS_NODE(nodep));
-	async_answer_0(rid, rc);
-}
-
-void tmpfs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_open_node(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_stat(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_sync(ipc_callid_t rid, ipc_call_t *request)
+	return tmpfs_destroy_node(FS_NODE(nodep));
+}
+
+static int tmpfs_sync(service_id_t service_id, fs_index_t index)
 {
 	/*
@@ -729,8 +655,20 @@
 	 * thus the sync operation is a no-op.
 	 */
-	async_answer_0(rid, EOK);
-}
+	return EOK;
+}
+
+vfs_out_ops_t tmpfs_ops = {
+	.mounted = tmpfs_mounted,
+	.unmounted = tmpfs_unmounted,
+	.read = tmpfs_read,
+	.write = tmpfs_write,
+	.truncate = tmpfs_truncate,
+	.close = tmpfs_close,
+	.destroy = tmpfs_destroy,
+	.sync = tmpfs_sync,
+};
 
 /**
  * @}
  */
+
Index: uspace/srv/hid/console/Makefile
===================================================================
--- uspace/srv/hid/console/Makefile	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/console/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -29,29 +29,31 @@
 
 USPACE_PREFIX = ../../..
+LIBS = $(LIBIMGMAP_PREFIX)/libimgmap.a
+EXTRA_CFLAGS += -I$(LIBIMGMAP_PREFIX)
 BINARY = console
 
-GENERIC_SOURCES = \
+SOURCES = \
 	console.c \
 	keybuffer.c \
+	images.c \
 	gcons.c
 
 IMAGES = \
-	gfx/helenos.ppm \
-	gfx/nameic.ppm \
-	gfx/cons_selected.ppm \
-	gfx/cons_idle.ppm \
-	gfx/cons_has_data.ppm \
-	gfx/cons_kernel.ppm \
-	gfx/anim_1.ppm \
-	gfx/anim_2.ppm \
-	gfx/anim_3.ppm \
-	gfx/anim_4.ppm
+	gfx/helenos.tga \
+	gfx/nameic.tga \
+	gfx/cons_selected.tga \
+	gfx/cons_idle.tga \
+	gfx/cons_has_data.tga \
+	gfx/cons_kernel.tga \
+	gfx/anim_1.tga \
+	gfx/anim_2.tga \
+	gfx/anim_3.tga \
+	gfx/anim_4.tga
 
-SOURCES = \
-	$(GENERIC_SOURCES) \
-	$(IMAGES)
+PRE_DEPEND = images.c images.h
+EXTRA_CLEAN = images.c images.h
 
 include $(USPACE_PREFIX)/Makefile.common
 
-%.o: %.ppm
-	$(OBJCOPY) -I binary -O $(BFD_NAME) -B $(BFD_ARCH) $< $@
+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 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/console/console.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -53,5 +53,5 @@
 #include <sysinfo.h>
 #include <event.h>
-#include <devmap.h>
+#include <loc.h>
 #include <fcntl.h>
 #include <vfs/vfs.h>
@@ -81,5 +81,5 @@
 	size_t index;             /**< Console index */
 	size_t refcount;          /**< Connection reference count */
-	devmap_handle_t devmap_handle;  /**< Device handle */
+	service_id_t service_id;  /**< Service ID */
 	keybuffer_t keybuffer;    /**< Buffer for incoming keys. */
 	screenbuffer_t scr;       /**< Screenbuffer for saving screen
@@ -582,5 +582,5 @@
 			continue;
 		
-		if (consoles[i].devmap_handle == (devmap_handle_t) IPC_GET_ARG1(*icall)) {
+		if (consoles[i].service_id == (service_id_t) IPC_GET_ARG1(*icall)) {
 			cons = &consoles[i];
 			break;
@@ -721,13 +721,13 @@
 }
 
-static async_sess_t *connect_input(const char *dev_path)
+static async_sess_t *connect_input(const char *svc_path)
 {
 	async_sess_t *sess;
 	async_exch_t *exch;
-	devmap_handle_t handle;
-	
-	int rc = devmap_device_get_handle(dev_path, &handle, 0);
+	service_id_t service_id;
+	
+	int rc = loc_service_get_id(svc_path, &service_id, 0);
 	if (rc == EOK) {
-		sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0);
+		sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 0);
 		if (sess == NULL) {
 			printf("%s: Failed to connect to input server\n", NAME);
@@ -773,8 +773,8 @@
 	}
 	
-	/* Register driver */
-	int rc = devmap_driver_register(NAME, client_connection);
+	/* Register server */
+	int rc = loc_server_register(NAME, client_connection);
 	if (rc < 0) {
-		printf("%s: Unable to register driver (%d)\n", NAME, rc);
+		printf("%s: Unable to register server (%d)\n", NAME, rc);
 		return false;
 	}
@@ -820,9 +820,9 @@
 			consoles[i].refcount = 0;
 			
-			char vc[DEVMAP_NAME_MAXLEN + 1];
-			snprintf(vc, DEVMAP_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
+			char vc[LOC_NAME_MAXLEN + 1];
+			snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
 			
-			if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) {
-				printf("%s: Unable to register device %s\n", NAME, vc);
+			if (loc_service_register(vc, &consoles[i].service_id) != EOK) {
+				printf("%s: Unable to register service %s\n", NAME, vc);
 				return false;
 			}
Index: uspace/srv/hid/console/gcons.c
===================================================================
--- uspace/srv/hid/console/gcons.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/console/gcons.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,7 +41,9 @@
 #include <align.h>
 #include <bool.h>
+#include <imgmap.h>
 
 #include "console.h"
 #include "gcons.h"
+#include "images.h"
 
 #define CONSOLE_TOP     66
@@ -58,30 +60,20 @@
 #define COLOR_BACKGROUND  0xffffff
 
-extern char _binary_gfx_helenos_ppm_start[0];
-extern int _binary_gfx_helenos_ppm_size;
-extern char _binary_gfx_nameic_ppm_start[0];
-extern int _binary_gfx_nameic_ppm_size;
-
-extern char _binary_gfx_anim_1_ppm_start[0];
-extern int _binary_gfx_anim_1_ppm_size;
-extern char _binary_gfx_anim_2_ppm_start[0];
-extern int _binary_gfx_anim_2_ppm_size;
-extern char _binary_gfx_anim_3_ppm_start[0];
-extern int _binary_gfx_anim_3_ppm_size;
-extern char _binary_gfx_anim_4_ppm_start[0];
-extern int _binary_gfx_anim_4_ppm_size;
-
-extern char _binary_gfx_cons_selected_ppm_start[0];
-extern int _binary_gfx_cons_selected_ppm_size;
-extern char _binary_gfx_cons_idle_ppm_start[0];
-extern int _binary_gfx_cons_idle_ppm_size;
-extern char _binary_gfx_cons_has_data_ppm_start[0];
-extern int _binary_gfx_cons_has_data_ppm_size;
-extern char _binary_gfx_cons_kernel_ppm_start[0];
-extern int _binary_gfx_cons_kernel_ppm_size;
-
 static bool use_gcons = false;
 static sysarg_t xres;
 static sysarg_t yres;
+
+static imgmap_t *helenos_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 imgmap_t *cons_has_data_img;
+static imgmap_t *cons_idle_img;
+static imgmap_t *cons_kernel_img;
+static imgmap_t *cons_selected_img;
 
 enum butstate {
@@ -101,6 +93,6 @@
 static int fbphone;
 
-/** List of pixmaps identifying these icons */
-static int ic_pixmaps[CONS_LAST] = {-1, -1, -1, -1, -1, -1};
+/** List of image maps identifying these icons */
+static int ic_imgmaps[CONS_LAST] = {-1, -1, -1, -1, -1, -1};
 static int animation = -1;
 
@@ -149,7 +141,7 @@
 	enum butstate state = console_state[index];
 	
-	if (ic_pixmaps[state] != -1)
-		async_obsolete_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[index],
-		    ic_pixmaps[state]);
+	if (ic_imgmaps[state] != -1)
+		async_obsolete_msg_2(fbphone, FB_VP_DRAW_IMGMAP, cstatus_vp[index],
+		    ic_imgmaps[state]);
 	
 	if ((state != CONS_DISCONNECTED) && (state != CONS_KERNEL)
@@ -358,21 +350,23 @@
 }
 
-/** Draw a PPM pixmap to framebuffer
- *
- * @param logo Pointer to PPM data
- * @param size Size of PPM data
- * @param x Coordinate of upper left corner
- * @param y Coordinate of upper left corner
- *
- */
-static void draw_pixmap(char *logo, size_t size, sysarg_t x, sysarg_t y)
-{
+/** Draw an image map to framebuffer
+ *
+ * @param img  Image map
+ * @param x    Coordinate of upper left corner
+ * @param y    Coordinate of upper left corner
+ *
+ */
+static void draw_imgmap(imgmap_t *img, sysarg_t x, sysarg_t y)
+{
+	if (img == NULL)
+		return;
+	
 	/* Create area */
-	char *shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
+	char *shm = mmap(NULL, img->size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
 	    MAP_ANONYMOUS, 0, 0);
 	if (shm == MAP_FAILED)
 		return;
 	
-	memcpy(shm, logo, size);
+	memcpy(shm, img, img->size);
 	
 	/* Send area */
@@ -386,5 +380,5 @@
 	
 	/* Draw logo */
-	async_obsolete_msg_2(fbphone, FB_DRAW_PPM, x, y);
+	async_obsolete_msg_2(fbphone, FB_DRAW_IMGMAP, x, y);
 	
 drop:
@@ -394,5 +388,5 @@
 exit:
 	/* Remove area */
-	munmap(shm, size);
+	munmap(shm, img->size);
 }
 
@@ -406,8 +400,6 @@
 	set_rgb_color(COLOR_MAIN, COLOR_MAIN);
 	clear();
-	draw_pixmap(_binary_gfx_helenos_ppm_start,
-	    (size_t) &_binary_gfx_helenos_ppm_size, xres - 66, 2);
-	draw_pixmap(_binary_gfx_nameic_ppm_start,
-	    (size_t) &_binary_gfx_nameic_ppm_size, 5, 17);
+	draw_imgmap(helenos_img, xres - 66, 2);
+	draw_imgmap(nameic_img, 5, 17);
 	
 	unsigned int i;
@@ -418,23 +410,25 @@
 }
 
-/** Creates a pixmap on framebuffer
- *
- * @param data PPM data
- * @param size PPM data size
- *
- * @return Pixmap identification
- *
- */
-static int make_pixmap(char *data, size_t size)
-{
+/** Create an image map on framebuffer
+ *
+ * @param img Image map.
+ *
+ * @return Image map identification
+ *
+ */
+static int make_imgmap(imgmap_t *img)
+{
+	if (img == NULL)
+		return -1;
+	
 	/* Create area */
-	char *shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
-	    MAP_ANONYMOUS, 0, 0);
+	char *shm = mmap(NULL, img->size, PROTO_READ | PROTO_WRITE,
+	    MAP_SHARED | MAP_ANONYMOUS, 0, 0);
 	if (shm == MAP_FAILED)
 		return -1;
 	
-	memcpy(shm, data, size);
-	
-	int pxid = -1;
+	memcpy(shm, img, img->size);
+	
+	int id = -1;
 	
 	/* Send area */
@@ -447,10 +441,10 @@
 		goto drop;
 	
-	/* Obtain pixmap */
-	rc = async_obsolete_req_0_0(fbphone, FB_SHM2PIXMAP);
+	/* Obtain image map identifier */
+	rc = async_obsolete_req_0_0(fbphone, FB_SHM2IMGMAP);
 	if (rc < 0)
 		goto drop;
 	
-	pxid = rc;
+	id = rc;
 	
 drop:
@@ -460,7 +454,7 @@
 exit:
 	/* Remove area */
-	munmap(shm, size);
-	
-	return pxid;
+	munmap(shm, img->size);
+	
+	return id;
 }
 
@@ -472,19 +466,15 @@
 		return;
 	
-	int pm = make_pixmap(_binary_gfx_anim_1_ppm_start,
-	    (size_t) &_binary_gfx_anim_1_ppm_size);
-	async_obsolete_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
-	
-	pm = make_pixmap(_binary_gfx_anim_2_ppm_start,
-	    (size_t) &_binary_gfx_anim_2_ppm_size);
-	async_obsolete_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
-	
-	pm = make_pixmap(_binary_gfx_anim_3_ppm_start,
-	    (size_t) &_binary_gfx_anim_3_ppm_size);
-	async_obsolete_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
-	
-	pm = make_pixmap(_binary_gfx_anim_4_ppm_start,
-	    (size_t) &_binary_gfx_anim_4_ppm_size);
-	async_obsolete_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
+	int pm = make_imgmap(anim_1_img);
+	async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
+	
+	pm = make_imgmap(anim_2_img);
+	async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
+	
+	pm = make_imgmap(anim_3_img);
+	async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
+	
+	pm = make_imgmap(anim_4_img);
+	async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
 	
 	async_obsolete_msg_1(fbphone, FB_ANIM_START, an);
@@ -504,4 +494,28 @@
 	if ((xres < 800) || (yres < 600))
 		return;
+	
+	/* Create image maps */
+	helenos_img = imgmap_decode_tga((void *) helenos_tga,
+	    helenos_tga_size);
+	nameic_img = imgmap_decode_tga((void *) nameic_tga,
+	    nameic_tga_size);
+	
+	anim_1_img = imgmap_decode_tga((void *) anim_1_tga,
+	    anim_1_tga_size);
+	anim_2_img = imgmap_decode_tga((void *) anim_2_tga,
+	    anim_2_tga_size);
+	anim_3_img = imgmap_decode_tga((void *) anim_3_tga,
+	    anim_3_tga_size);
+	anim_4_img = imgmap_decode_tga((void *) anim_4_tga,
+	    anim_4_tga_size);
+	
+	cons_has_data_img = imgmap_decode_tga((void *) cons_has_data_tga,
+	    cons_has_data_tga_size);
+	cons_idle_img = imgmap_decode_tga((void *) cons_idle_tga,
+	    cons_idle_tga_size);
+	cons_kernel_img = imgmap_decode_tga((void *) cons_kernel_tga,
+	    cons_kernel_tga_size);
+	cons_selected_img = imgmap_decode_tga((void *) cons_selected_tga,
+	    cons_selected_tga_size);
 	
 	/* Create console viewport */
@@ -531,20 +545,10 @@
 	
 	/* Initialize icons */
-	ic_pixmaps[CONS_SELECTED] =
-	    make_pixmap(_binary_gfx_cons_selected_ppm_start,
-	    (size_t) &_binary_gfx_cons_selected_ppm_size);
-	ic_pixmaps[CONS_IDLE] =
-	    make_pixmap(_binary_gfx_cons_idle_ppm_start,
-	    (size_t) &_binary_gfx_cons_idle_ppm_size);
-	ic_pixmaps[CONS_HAS_DATA] =
-	    make_pixmap(_binary_gfx_cons_has_data_ppm_start,
-	    (size_t) &_binary_gfx_cons_has_data_ppm_size);
-	ic_pixmaps[CONS_DISCONNECTED] =
-	    make_pixmap(_binary_gfx_cons_idle_ppm_start,
-	    (size_t) &_binary_gfx_cons_idle_ppm_size);
-	ic_pixmaps[CONS_KERNEL] =
-	    make_pixmap(_binary_gfx_cons_kernel_ppm_start,
-	    (size_t) &_binary_gfx_cons_kernel_ppm_size);
-	ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED];
+	ic_imgmaps[CONS_SELECTED] = make_imgmap(cons_selected_img);
+	ic_imgmaps[CONS_IDLE] = make_imgmap(cons_idle_img);
+	ic_imgmaps[CONS_HAS_DATA] = make_imgmap(cons_has_data_img);
+	ic_imgmaps[CONS_DISCONNECTED] = make_imgmap(cons_idle_img);
+	ic_imgmaps[CONS_KERNEL] = make_imgmap(cons_kernel_img);
+	ic_imgmaps[CONS_DISCONNECTED_SEL] = ic_imgmaps[CONS_SELECTED];
 	
 	make_anim();
Index: pace/srv/hid/console/gfx/anim_1.ppm
===================================================================
--- uspace/srv/hid/console/gfx/anim_1.ppm	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,23 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ääääää÷÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúúúúúúúúúúûûûûûûûûûûûûûûûûûûüüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿööö½½½eeeeee½½½öööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýùùùøøøõõõêêêèèèèèèéééêêêëëëìììíííîîîîîîðððøøøúúúûûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷÷÷ñññáááÞÞÞÞÞÞÜÜÜÞÞÞßßßáááãããäääåååæææçççèèèéééëëëêêêììì÷÷÷úúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿýýýõõõîîî×××ÒÒÒÏÏÏÑÑÑÒÒÒÕÕÕ×××ÚÚÚÜÜÜÞÞÞàààâââãããääääääååååååääääääåååèèèõõõùùùýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿööö½½½eeeddd½½½öööÿÿÿÿÿÿýýýíííÏÏÏÇÇÇÃÃÃÃÃÃÅÅÅÈÈÈËËËÎÎÎÑÑÑÕÕÕØØØÛÛÛÝÝÝßßßàààáááââââââââââââáááßßßÞÞÞßßßâââôôôýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööããããããöööþþþÿÿÿüüüìììÇÇÇ¸¸¸···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÊÊÊÎÎÎÒÒÒÖÖÖÙÙÙÜÜÜÞÞÞàààáááââââââââââââàààßßßÜÜÜÙÙÙ×××ÝÝÝòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüêêêÃÃÃ±±±¯¯¯°°°²²²¶¶¶ººº¾¾¾ÃÃÃÈÈÈÍÍÍÒÒÒÖÖÖÚÚÚÝÝÝßßßáááâââãããääääääãããáááàààÝÝÝÚÚÚÖÖÖÔÔÔÚÚÚòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëëëÁÁÁ­­­©©©©©©«««¯¯¯³³³¹¹¹¾¾¾ÄÄÄÊÊÊÏÏÏÔÔÔØØØÜÜÜßßßâââäääåååæææççççççæææäääâââàààÜÜÜÙÙÙÔÔÔÑÑÑØØØðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýìììÃÃÃ­­­§§§¦¦¦§§§ªªª®®®´´´ºººÁÁÁÇÇÇÍÍÍÓÓÓØØØÜÜÜàààãããæææèèèéééêêêêêêêêêêêêèèèæææäääàààÝÝÝØØØÓÓÓÏÏÏ×××ðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÇÇÇ±±±©©©¦¦¦¦¦¦¨¨¨¬¬¬±±±···¾¾¾ÅÅÅÌÌÌÒÒÒØØØÝÝÝâââåååèèèêêêìììíííîîîîîîîîîîîîìììëëëèèèæææâââÞÞÞØØØÓÓÓÎÎÎÕÕÕðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÏÏÏ¸¸¸¯¯¯©©©§§§¨¨¨«««°°°¶¶¶½½½ÄÄÄËËËÒÒÒÙÙÙÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòòòòñññïïïíííëëëçççãããßßßÙÙÙÓÓÓÎÎÎ×××÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýîîîÇÇÇ···°°°«««ªªª¬¬¬°°°¶¶¶½½½ÄÄÄÌÌÌÓÓÓÙÙÙßßßåååéééìììïïïñññóóóôôôõõõõõõööööööõõõõõõóóóòòòïïïíííéééåååàààÚÚÚÔÔÔÔÔÔðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ØØØÂÂÂ¸¸¸²²²¯¯¯®®®±±±¶¶¶¼¼¼ÄÄÄËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøùùùùùùøøøøøø÷÷÷õõõôôôñññïïïëëëçççáááÛÛÛÕÕÕÜÜÜøøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýòòòÒÒÒÃÃÃ»»»µµµ³³³´´´···½½½ÄÄÄËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúûûûûûûûûûûûûúúúúúúùùù÷÷÷öööóóóðððìììèèèâââÜÜÜÛÛÛóóóýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿùùùààà···yyyEEE777¹¹¹ººº¾¾¾ÄÄÄÌÌÌÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûüüüüüüüüüýýýýýýüüüüüüûûûûûûúúúøøø÷÷÷ôôôñññíííèèèãããÞÞÞãããùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿøøøÝÝÝºººccc   
-
-
-¾¾¾ÁÁÁÅÅÅËËËÓÓÓÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûüüüüüüýýýýýýýýýþþþþþþýýýýýýýýýüüüüüüûûûùùùøøøõõõòòòîîîéééääääääùùùþþþÿÿÿÿÿÿÿÿÿþþþõõõÞÞÞÒÒÒÅÅÅ   
-
-
-ÄÄÄÇÇÇÌÌÌÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûúúúøøøõõõòòòîîîêêêééé÷÷÷þþþþþþÿÿÿÿÿÿûûûéééÜÜÜÕÕÕÍÍÍ   ÊÊÊÍÍÍÒÒÒÙÙÙßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþýýýýýýûûûúúúøøøöööóóóïïïìììîîîûûûþþþÿÿÿÿÿÿúúúèèèÝÝÝ×××ÑÑÑ   ÏÏÏÆÆÆDDD   ZZZáááôôô¯¯¯666MMM666VVVäääþþþþþþ···999GGG???KKKÔÔÔÿÿÿ      '''ÐÐÐZZZªªªùùùöööôôôððððððûûûþþþÿÿÿÿÿÿúúúéééßßßÙÙÙÔÔÔ      ÔÔÔ×××^^^eeeâââîîîóóó¸¸¸üüüööö666þþþÂÂÂÿÿÿþþþXXXâââþþþÆÆÆ   
-
-
-ùùùííí			úúúùùù÷÷÷ôôôôôôüüüþþþÿÿÿÿÿÿûûûêêêáááÜÜÜ×××   !!!ÕÕÕSSS^^^çççìììñññõõõ???ñññüüüýýýCCC   ÿÿÿEEEñññÿÿÿÿÿÿÊÊÊ   qqqÿÿÿþþþ   $$$ÿÿÿþþþþþþ%%%   üüüûûûùùùøøø÷÷÷ýýýþþþÿÿÿÿÿÿûûûëëëãããÞÞÞÚÚÚ   NNNÙÙÙïïïóóó÷÷÷   üüüýýýþþþûûûúúúÿÿÿ
-
-
-ÿÿÿÿÿÿÿÿÿôôô   333ÿÿÿÿÿÿ   '''ÿÿÿÿÿÿþþþ'''   ýýýüüüûûûúúúúúúýýýþþþÿÿÿÿÿÿûûûëëëäääàààÝÝÝ   
-
-
-²²²¨¨¨   UUUñññõõõøøø			ýýýþþþþþþþþþÿÿÿÿÿÿ			   ÿÿÿÿÿÿÿÿÿùùù   111ÿÿÿÿÿÿ   '''ÿÿÿÿÿÿÿÿÿ'''   ýýýýýýüüüüüüûûûþþþþþþÿÿÿÿÿÿûûûìììåååâââßßß   """âââæææ___   ¨¨¨öööùùù>>>èèèþþþþþþÿÿÿöööÿÿÿ>>>ôôôÿÿÿÿÿÿÔÔÔ   gggÿÿÿÿÿÿ   '''ÿÿÿÿÿÿÿÿÿ'''   þþþþþþýýýýýýýýýþþþþþþÿÿÿÿÿÿûûûíííæææãããÖÖÖ   ãããèèèßßßÖÖÖúúú½½½___ûûûÿÿÿîîîUUUôôô¾¾¾ÿÿÿþþþhhhÜÜÜÿÿÿôôô   ÿÿÿÿÿÿÿÿÿ
-
-
-   õõõþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûíííççç···BBB      UUUÎÎÎ   üüü»»»:::///^^^jjjâââÿÿÿÿÿÿ¾¾¾>>>KKKEEEJJJÓÓÓÿÿÿÍÍÍKKK      rrrÿÿÿqqq      NNNÍÍÍþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûîîîçççäääââââââãããæææêêêîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüðððèèèäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøêêêäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúêêêäääââââââãããæææéééîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûíííäääáááàààáááäääèèèìììñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööåååßßßÞÞÞßßßâââæææëëëïïïóóó÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúèèèÞÞÞÜÜÜÝÝÝàààäääèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþõõõßßßÙÙÙÚÚÚÜÜÜàààæææëëëðððôôô÷÷÷úúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøâââ×××ÖÖÖÙÙÙÝÝÝâââèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôÝÝÝÓÓÓÔÔÔØØØÞÞÞãããéééïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýòòòÚÚÚÐÐÐÓÓÓØØØßßßåååëëëðððôôôøøøúúúûûûýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññØØØÏÏÏÓÓÓÙÙÙàààçççìììñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññ×××ÎÎÎÓÓÓÚÚÚáááèèèíííòòòõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÕÕÕÎÎÎÓÓÓÛÛÛâââèèèîîîòòòöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÖÖÖÔÔÔÕÕÕÛÛÛãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüöööðððÜÜÜÛÛÛÞÞÞãããêêêïïïôôô÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþüüü÷÷÷òòòãããäääéééìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýùùùùùù÷÷÷îîîðððôôô÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýûûûûûûüüüüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/anim_2.ppm
===================================================================
--- uspace/srv/hid/console/gfx/anim_2.ppm	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,23 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúúúúúúúúúúûûûûûûûûûûûûûûûûûûüüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ääääää÷÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýùùùøøøõõõêêêèèèèèèéééêêêëëëìììíííîîîîîîðððøøøúúúûûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿööö½½½eeeeee½½½öööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷÷÷ñññáááÞÞÞÞÞÞÜÜÜÞÞÞßßßáááãããäääåååæææçççèèèéééëëëêêêììì÷÷÷úúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýõõõîîî×××ÒÒÒÏÏÏÑÑÑÒÒÒÕÕÕ×××ÚÚÚÜÜÜÞÞÞàààâââãããääääääååååååääääääåååèèèõõõùùùýýýþþþÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÏÏÏÇÇÇÃÃÃÃÃÃÅÅÅÈÈÈËËËÎÎÎÑÑÑÕÕÕØØØÛÛÛÝÝÝßßßàààáááââââââââââââáááßßßÞÞÞßßßâââôôôýýýþþþÿÿÿööö½½½eeeddd½½½öööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüìììÇÇÇ¸¸¸···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÊÊÊÎÎÎÒÒÒÖÖÖÙÙÙÜÜÜÞÞÞàààáááââââââââââââàààßßßÜÜÜÙÙÙ×××ÝÝÝòòòýýýþþþÿÿÿöööããããããöööþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüêêêÃÃÃ±±±¯¯¯°°°²²²¶¶¶ººº¾¾¾ÃÃÃÈÈÈÍÍÍÒÒÒÖÖÖÚÚÚÝÝÝßßßáááâââãããääääääãããáááàààÝÝÝÚÚÚÖÖÖÔÔÔÚÚÚòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëëëÁÁÁ­­­©©©©©©«««¯¯¯³³³¹¹¹¾¾¾ÄÄÄÊÊÊÏÏÏÔÔÔØØØÜÜÜßßßâââäääåååæææççççççæææäääâââàààÜÜÜÙÙÙÔÔÔÑÑÑØØØðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýìììÃÃÃ­­­§§§¦¦¦§§§ªªª®®®´´´ºººÁÁÁÇÇÇÍÍÍÓÓÓØØØÜÜÜàààãããæææèèèéééêêêêêêêêêêêêèèèæææäääàààÝÝÝØØØÓÓÓÏÏÏ×××ðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÇÇÇ±±±©©©¦¦¦¦¦¦¨¨¨¬¬¬±±±···¾¾¾ÅÅÅÌÌÌÒÒÒØØØÝÝÝâââåååèèèêêêìììíííîîîîîîîîîîîîìììëëëèèèæææâââÞÞÞØØØÓÓÓÎÎÎÕÕÕðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÏÏÏ¸¸¸¯¯¯©©©§§§¨¨¨«««°°°¶¶¶½½½ÄÄÄËËËÒÒÒÙÙÙÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòòòòñññïïïíííëëëçççãããßßßÙÙÙÓÓÓÎÎÎ×××÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýîîîÇÇÇ···°°°«««ªªª¬¬¬°°°¶¶¶½½½ÄÄÄÌÌÌÓÓÓÙÙÙßßßåååéééìììïïïñññóóóôôôõõõõõõööööööõõõõõõóóóòòòïïïíííéééåååàààÚÚÚÔÔÔÔÔÔðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ØØØÂÂÂ¸¸¸²²²¯¯¯®®®±±±¶¶¶¼¼¼ÄÄÄËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøùùùùùùøøøøøø÷÷÷õõõôôôñññïïïëëëçççáááÛÛÛÕÕÕÜÜÜøøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýòòòÒÒÒÃÃÃ»»»µµµ³³³´´´···½½½ÄÄÄËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúûûûûûûûûûûûûúúúúúúùùù÷÷÷öööóóóðððìììèèèâââÜÜÜÛÛÛóóóýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿùùùààà···yyyEEE777¹¹¹ººº¾¾¾ÄÄÄÌÌÌÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûüüüüüüüüüýýýýýýüüüüüüûûûûûûúúúøøø÷÷÷ôôôñññíííèèèãããÞÞÞãããùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿøøøÝÝÝºººccc   
-
-
-¾¾¾ÁÁÁÅÅÅËËËÓÓÓÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûüüüüüüýýýýýýýýýþþþþþþýýýýýýýýýüüüüüüûûûùùùøøøõõõòòòîîîéééääääääùùùþþþÿÿÿÿÿÿÿÿÿþþþõõõÞÞÞÒÒÒÅÅÅ   
-
-
-ÄÄÄÇÇÇÌÌÌÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûúúúøøøõõõòòòîîîêêêééé÷÷÷þþþþþþÿÿÿÿÿÿûûûéééÜÜÜÕÕÕÍÍÍ   ÊÊÊÍÍÍÒÒÒÙÙÙßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþýýýýýýûûûúúúøøøöööóóóïïïìììîîîûûûþþþÿÿÿÿÿÿúúúèèèÝÝÝ×××ÑÑÑ   ÏÏÏÆÆÆDDD   ZZZáááôôô¯¯¯666MMM666VVVäääþþþþþþ···999GGG???KKKÔÔÔÿÿÿ      '''ÐÐÐZZZªªªùùùöööôôôððððððûûûþþþÿÿÿÿÿÿúúúéééßßßÙÙÙÔÔÔ      ÔÔÔ×××^^^eeeâââîîîóóó¸¸¸üüüööö666þþþÂÂÂÿÿÿþþþXXXâââþþþÆÆÆ   
-
-
-ùùùííí			úúúùùù÷÷÷ôôôôôôüüüþþþÿÿÿÿÿÿûûûêêêáááÜÜÜ×××   !!!ÕÕÕSSS^^^çççìììñññõõõ???ñññüüüýýýCCC   ÿÿÿEEEñññÿÿÿÿÿÿÊÊÊ   qqqÿÿÿþþþ   $$$ÿÿÿþþþþþþ%%%   üüüûûûùùùøøø÷÷÷ýýýþþþÿÿÿÿÿÿûûûëëëãããÞÞÞÚÚÚ   NNNÙÙÙïïïóóó÷÷÷   üüüýýýþþþûûûúúúÿÿÿ
-
-
-ÿÿÿÿÿÿÿÿÿôôô   333ÿÿÿÿÿÿ   '''ÿÿÿÿÿÿþþþ'''   ýýýüüüûûûúúúúúúýýýþþþÿÿÿÿÿÿûûûëëëäääàààÝÝÝ   
-
-
-²²²¨¨¨   UUUñññõõõøøø			ýýýþþþþþþþþþÿÿÿÿÿÿ			   ÿÿÿÿÿÿÿÿÿùùù   111ÿÿÿÿÿÿ   '''ÿÿÿÿÿÿÿÿÿ'''   ýýýýýýüüüüüüûûûþþþþþþÿÿÿÿÿÿûûûìììåååâââßßß   """âââæææ___   ¨¨¨öööùùù>>>èèèþþþþþþÿÿÿöööÿÿÿ>>>ôôôÿÿÿÿÿÿÔÔÔ   gggÿÿÿÿÿÿ   '''ÿÿÿÿÿÿÿÿÿ'''   þþþþþþýýýýýýýýýþþþþþþÿÿÿÿÿÿûûûíííæææãããÖÖÖ   ãããèèèßßßÖÖÖúúú½½½___ûûûÿÿÿîîîUUUôôô¾¾¾ÿÿÿþþþhhhÜÜÜÿÿÿôôô   ÿÿÿÿÿÿÿÿÿ
-
-
-   õõõþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûíííççç···BBB      UUUÎÎÎ   üüü»»»:::///^^^jjjâââÿÿÿÿÿÿ¾¾¾>>>KKKEEEJJJÓÓÓÿÿÿÍÍÍKKK      rrrÿÿÿqqq      NNNÍÍÍþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûîîîçççäääââââââãããæææêêêîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüðððèèèäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøêêêäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúêêêäääââââââãããæææéééîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûíííäääáááàààáááäääèèèìììñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööåååßßßÞÞÞßßßâââæææëëëïïïóóó÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúèèèÞÞÞÜÜÜÝÝÝàààäääèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþõõõßßßÙÙÙÚÚÚÜÜÜàààæææëëëðððôôô÷÷÷úúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøâââ×××ÖÖÖÙÙÙÝÝÝâââèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôÝÝÝÓÓÓÔÔÔØØØÞÞÞãããéééïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýòòòÚÚÚÐÐÐÓÓÓØØØßßßåååëëëðððôôôøøøúúúûûûýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññØØØÏÏÏÓÓÓÙÙÙàààçççìììñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññ×××ÎÎÎÓÓÓÚÚÚáááèèèíííòòòõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÕÕÕÎÎÎÓÓÓÛÛÛâââèèèîîîòòòöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÖÖÖÔÔÔÕÕÕÛÛÛãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüöööðððÜÜÜÛÛÛÞÞÞãããêêêïïïôôô÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþüüü÷÷÷òòòãããäääéééìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýùùùùùù÷÷÷îîîðððôôô÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýûûûûûûüüüüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/anim_3.ppm
===================================================================
--- uspace/srv/hid/console/gfx/anim_3.ppm	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,23 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúúúúúúúúúúûûûûûûûûûûûûûûûûûûüüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýùùùøøøõõõêêêèèèèèèéééêêêëëëìììíííîîîîîîðððøøøúúúûûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷÷÷ñññáááÞÞÞÞÞÞÜÜÜÞÞÞßßßáááãããäääåååæææçççèèèéééëëëêêêììì÷÷÷úúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýõõõîîî×××ÒÒÒÏÏÏÑÑÑÒÒÒÕÕÕ×××ÚÚÚÜÜÜÞÞÞàààâââãããääääääååååååääääääåååèèèõõõùùùýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÏÏÏÇÇÇÃÃÃÃÃÃÅÅÅÈÈÈËËËÎÎÎÑÑÑÕÕÕØØØÛÛÛÝÝÝßßßàààáááââââââââââââáááßßßÞÞÞßßßâââôôôýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüìììÇÇÇ¸¸¸···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÊÊÊÎÎÎÒÒÒÖÖÖÙÙÙÜÜÜÞÞÞàààáááââââââââââââàààßßßÜÜÜÙÙÙ×××ÝÝÝòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüêêêÃÃÃ±±±¯¯¯°°°²²²¶¶¶ººº¾¾¾ÃÃÃÈÈÈÍÍÍÒÒÒÖÖÖÚÚÚÝÝÝßßßáááâââãããääääääãããáááàààÝÝÝÚÚÚÖÖÖÔÔÔÚÚÚòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëëëÁÁÁ­­­©©©©©©«««¯¯¯³³³¹¹¹¾¾¾ÄÄÄÊÊÊÏÏÏÔÔÔØØØÜÜÜßßßâââäääåååæææççççççæææäääâââàààÜÜÜÙÙÙÔÔÔÑÑÑØØØðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýìììÃÃÃ­­­§§§¦¦¦§§§ªªª®®®´´´ºººÁÁÁÇÇÇÍÍÍÓÓÓØØØÜÜÜàààãããæææèèèéééêêêêêêêêêêêêèèèæææäääàààÝÝÝØØØÓÓÓÏÏÏ×××ðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÇÇÇ±±±©©©¦¦¦¦¦¦¨¨¨¬¬¬±±±···¾¾¾ÅÅÅÌÌÌÒÒÒØØØÝÝÝâââåååèèèêêêìììíííîîîîîîîîîîîîìììëëëèèèæææâââÞÞÞØØØÓÓÓÎÎÎÕÕÕðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÏÏÏ¸¸¸¯¯¯©©©§§§¨¨¨«««°°°¶¶¶½½½ÄÄÄËËËÒÒÒÙÙÙÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòòòòñññïïïíííëëëçççãããßßßÙÙÙÓÓÓÎÎÎ×××÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýîîîÇÇÇ···°°°«««ªªª¬¬¬°°°¶¶¶½½½ÄÄÄÌÌÌÓÓÓÙÙÙßßßåååéééìììïïïñññóóóôôôõõõõõõööööööõõõõõõóóóòòòïïïíííéééåååàààÚÚÚÔÔÔÔÔÔðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ØØØÂÂÂ¸¸¸²²²¯¯¯®®®±±±¶¶¶¼¼¼ÄÄÄËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøùùùùùùøøøøøø÷÷÷õõõôôôñññïïïëëëçççáááÛÛÛÕÕÕÜÜÜøøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýòòòÒÒÒÃÃÃ»»»µµµ³³³´´´···½½½ÄÄÄËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúûûûûûûûûûûûûúúúúúúùùù÷÷÷öööóóóðððìììèèèâââÜÜÜÛÛÛóóóýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿùùùààà···yyyEEE777¹¹¹ººº¾¾¾ÄÄÄÌÌÌÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûüüüüüüüüüýýýýýýüüüüüüûûûûûûúúúøøø÷÷÷ôôôñññíííèèèãããÞÞÞãããùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿøøøÝÝÝºººccc   
-
-
-¾¾¾ÁÁÁÅÅÅËËËÓÓÓÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûüüüüüüýýýýýýýýýþþþþþþýýýýýýýýýüüüüüüûûûùùùøøøõõõòòòîîîéééääääääùùùþþþÿÿÿÿÿÿÿÿÿþþþõõõÞÞÞÒÒÒÅÅÅ   
-
-
-ÄÄÄÇÇÇÌÌÌÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûúúúøøøõõõòòòîîîêêêééé÷÷÷þþþþþþÿÿÿÿÿÿûûûéééÜÜÜÕÕÕÍÍÍ   ÊÊÊÍÍÍÒÒÒÙÙÙßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþýýýýýýûûûúúúøøøöööóóóïïïìììîîîûûûþþþÿÿÿÿÿÿúúúèèèÝÝÝ×××ÑÑÑ   ÏÏÏÆÆÆDDD   ZZZáááôôô¯¯¯666MMM666VVVäääþþþþþþ···999GGG???KKKÔÔÔÿÿÿ      '''ÐÐÐZZZªªªùùùöööôôôððððððûûûþþþÿÿÿÿÿÿúúúéééßßßÙÙÙÔÔÔ      ÔÔÔ×××^^^eeeâââîîîóóó¸¸¸üüüööö666þþþÂÂÂÿÿÿþþþXXXâââþþþÆÆÆ   
-
-
-ùùùííí			úúúùùù÷÷÷ôôôôôôüüüþþþÿÿÿÿÿÿûûûêêêáááÜÜÜ×××   !!!ÕÕÕSSS^^^çççìììñññõõõ???ñññüüüýýýCCC   ÿÿÿEEEñññÿÿÿÿÿÿÊÊÊ   qqqÿÿÿþþþ   $$$ÿÿÿþþþþþþ%%%   üüüûûûùùùøøø÷÷÷ýýýþþþÿÿÿÿÿÿûûûëëëãããÞÞÞÚÚÚ   NNNÙÙÙïïïóóó÷÷÷   üüüýýýþþþûûûúúúÿÿÿ
-
-
-ÿÿÿÿÿÿÿÿÿôôô   333ÿÿÿÿÿÿ   '''ÿÿÿÿÿÿþþþ'''   ýýýüüüûûûúúúúúúýýýþþþÿÿÿÿÿÿûûûëëëäääàààÝÝÝ   
-
-
-²²²¨¨¨   UUUñññõõõøøø			ýýýþþþþþþþþþÿÿÿÿÿÿ			   ÿÿÿÿÿÿÿÿÿùùù   111ÿÿÿÿÿÿ   '''ÿÿÿÿÿÿÿÿÿ'''   ýýýýýýüüüüüüûûûþþþþþþÿÿÿÿÿÿûûûìììåååâââßßß   """âââæææ___   ¨¨¨öööùùù>>>èèèþþþþþþÿÿÿöööÿÿÿ>>>ôôôÿÿÿÿÿÿÔÔÔ   gggÿÿÿÿÿÿ   '''ÿÿÿÿÿÿÿÿÿ'''   þþþþþþýýýýýýýýýþþþþþþÿÿÿÿÿÿûûûíííæææãããÖÖÖ   ãããèèèßßßÖÖÖúúú½½½___ûûûÿÿÿîîîUUUôôô¾¾¾ÿÿÿþþþhhhÜÜÜÿÿÿôôô   ÿÿÿÿÿÿÿÿÿ
-
-
-   õõõþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûíííççç···BBB      UUUÎÎÎ   üüü»»»:::///^^^jjjâââÿÿÿÿÿÿ¾¾¾>>>KKKEEEJJJÓÓÓÿÿÿÍÍÍKKK      rrrÿÿÿqqq      NNNÍÍÍþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûîîîçççäääââââââãããæææêêêîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüðððèèèäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøêêêäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúêêêäääââââââãããæææéééîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûíííäääáááàààáááäääèèèìììñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööåååßßßÞÞÞßßßâââæææëëëïïïóóó÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúèèèÞÞÞÜÜÜÝÝÝàààäääèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþõõõßßßÙÙÙÚÚÚÜÜÜàààæææëëëðððôôô÷÷÷úúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøâââ×××ÖÖÖÙÙÙÝÝÝâââèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôÝÝÝÓÓÓÔÔÔØØØÞÞÞãããéééïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýòòòÚÚÚÐÐÐÓÓÓØØØßßßåååëëëðððôôôøøøúúúûûûýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññØØØÏÏÏÓÓÓÙÙÙàààçççìììñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññ×××ÎÎÎÓÓÓÚÚÚáááèèèíííòòòõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÕÕÕÎÎÎÓÓÓÛÛÛâââèèèîîîòòòöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÖÖÖÔÔÔÕÕÕÛÛÛãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿ÷÷÷ääääää÷÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüöööðððÜÜÜÛÛÛÞÞÞãããêêêïïïôôô÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýýýýýýýþþþþþþþþþÿÿÿÿÿÿööö½½½eeeeee½½½öööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþüüü÷÷÷òòòãããäääéééìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýùùùùùù÷÷÷îîîðððôôô÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýûûûûûûüüüüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿööö½½½eeeddd½½½öööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööããããããöööþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/anim_4.ppm
===================================================================
--- uspace/srv/hid/console/gfx/anim_4.ppm	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,23 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúúúúúúúúúúûûûûûûûûûûûûûûûûûûüüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýùùùøøøõõõêêêèèèèèèéééêêêëëëìììíííîîîîîîðððøøøúúúûûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷÷÷ñññáááÞÞÞÞÞÞÜÜÜÞÞÞßßßáááãããäääåååæææçççèèèéééëëëêêêììì÷÷÷úúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýõõõîîî×××ÒÒÒÏÏÏÑÑÑÒÒÒÕÕÕ×××ÚÚÚÜÜÜÞÞÞàààâââãããääääääååååååääääääåååèèèõõõùùùýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÏÏÏÇÇÇÃÃÃÃÃÃÅÅÅÈÈÈËËËÎÎÎÑÑÑÕÕÕØØØÛÛÛÝÝÝßßßàààáááââââââââââââáááßßßÞÞÞßßßâââôôôýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüìììÇÇÇ¸¸¸···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÊÊÊÎÎÎÒÒÒÖÖÖÙÙÙÜÜÜÞÞÞàààáááââââââââââââàààßßßÜÜÜÙÙÙ×××ÝÝÝòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüêêêÃÃÃ±±±¯¯¯°°°²²²¶¶¶ººº¾¾¾ÃÃÃÈÈÈÍÍÍÒÒÒÖÖÖÚÚÚÝÝÝßßßáááâââãããääääääãããáááàààÝÝÝÚÚÚÖÖÖÔÔÔÚÚÚòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëëëÁÁÁ­­­©©©©©©«««¯¯¯³³³¹¹¹¾¾¾ÄÄÄÊÊÊÏÏÏÔÔÔØØØÜÜÜßßßâââäääåååæææççççççæææäääâââàààÜÜÜÙÙÙÔÔÔÑÑÑØØØðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýìììÃÃÃ­­­§§§¦¦¦§§§ªªª®®®´´´ºººÁÁÁÇÇÇÍÍÍÓÓÓØØØÜÜÜàààãããæææèèèéééêêêêêêêêêêêêèèèæææäääàààÝÝÝØØØÓÓÓÏÏÏ×××ðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÇÇÇ±±±©©©¦¦¦¦¦¦¨¨¨¬¬¬±±±···¾¾¾ÅÅÅÌÌÌÒÒÒØØØÝÝÝâââåååèèèêêêìììíííîîîîîîîîîîîîìììëëëèèèæææâââÞÞÞØØØÓÓÓÎÎÎÕÕÕðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÏÏÏ¸¸¸¯¯¯©©©§§§¨¨¨«««°°°¶¶¶½½½ÄÄÄËËËÒÒÒÙÙÙÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòòòòñññïïïíííëëëçççãããßßßÙÙÙÓÓÓÎÎÎ×××÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýîîîÇÇÇ···°°°«««ªªª¬¬¬°°°¶¶¶½½½ÄÄÄÌÌÌÓÓÓÙÙÙßßßåååéééìììïïïñññóóóôôôõõõõõõööööööõõõõõõóóóòòòïïïíííéééåååàààÚÚÚÔÔÔÔÔÔðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ØØØÂÂÂ¸¸¸²²²¯¯¯®®®±±±¶¶¶¼¼¼ÄÄÄËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøùùùùùùøøøøøø÷÷÷õõõôôôñññïïïëëëçççáááÛÛÛÕÕÕÜÜÜøøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýòòòÒÒÒÃÃÃ»»»µµµ³³³´´´···½½½ÄÄÄËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúûûûûûûûûûûûûúúúúúúùùù÷÷÷öööóóóðððìììèèèâââÜÜÜÛÛÛóóóýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿùùùààà···yyyEEE777¹¹¹ººº¾¾¾ÄÄÄÌÌÌÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûüüüüüüüüüýýýýýýüüüüüüûûûûûûúúúøøø÷÷÷ôôôñññíííèèèãããÞÞÞãããùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿøøøÝÝÝºººccc   
-
-
-¾¾¾ÁÁÁÅÅÅËËËÓÓÓÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûüüüüüüýýýýýýýýýþþþþþþýýýýýýýýýüüüüüüûûûùùùøøøõõõòòòîîîéééääääääùùùþþþÿÿÿÿÿÿÿÿÿþþþõõõÞÞÞÒÒÒÅÅÅ   
-
-
-ÄÄÄÇÇÇÌÌÌÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûúúúøøøõõõòòòîîîêêêééé÷÷÷þþþþþþÿÿÿÿÿÿûûûéééÜÜÜÕÕÕÍÍÍ   ÊÊÊÍÍÍÒÒÒÙÙÙßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþýýýýýýûûûúúúøøøöööóóóïïïìììîîîûûûþþþÿÿÿÿÿÿúúúèèèÝÝÝ×××ÑÑÑ   ÏÏÏÆÆÆDDD   ZZZáááôôô¯¯¯666MMM666VVVäääþþþþþþ···999GGG???KKKÔÔÔÿÿÿ      '''ÐÐÐZZZªªªùùùöööôôôððððððûûûþþþÿÿÿÿÿÿúúúéééßßßÙÙÙÔÔÔ      ÔÔÔ×××^^^eeeâââîîîóóó¸¸¸üüüööö666þþþÂÂÂÿÿÿþþþXXXâââþþþÆÆÆ   
-
-
-ùùùííí			úúúùùù÷÷÷ôôôôôôüüüþþþÿÿÿÿÿÿûûûêêêáááÜÜÜ×××   !!!ÕÕÕSSS^^^çççìììñññõõõ???ñññüüüýýýCCC   ÿÿÿEEEñññÿÿÿÿÿÿÊÊÊ   qqqÿÿÿþþþ   $$$ÿÿÿþþþþþþ%%%   üüüûûûùùùøøø÷÷÷ýýýþþþÿÿÿÿÿÿûûûëëëãããÞÞÞÚÚÚ   NNNÙÙÙïïïóóó÷÷÷   üüüýýýþþþûûûúúúÿÿÿ
-
-
-ÿÿÿÿÿÿÿÿÿôôô   333ÿÿÿÿÿÿ   '''ÿÿÿÿÿÿþþþ'''   ýýýüüüûûûúúúúúúýýýþþþÿÿÿÿÿÿûûûëëëäääàààÝÝÝ   
-
-
-²²²¨¨¨   UUUñññõõõøøø			ýýýþþþþþþþþþÿÿÿÿÿÿ			   ÿÿÿÿÿÿÿÿÿùùù   111ÿÿÿÿÿÿ   '''ÿÿÿÿÿÿÿÿÿ'''   ýýýýýýüüüüüüûûûþþþþþþÿÿÿÿÿÿûûûìììåååâââßßß   """âââæææ___   ¨¨¨öööùùù>>>èèèþþþþþþÿÿÿöööÿÿÿ>>>ôôôÿÿÿÿÿÿÔÔÔ   gggÿÿÿÿÿÿ   '''ÿÿÿÿÿÿÿÿÿ'''   þþþþþþýýýýýýýýýþþþþþþÿÿÿÿÿÿûûûíííæææãããÖÖÖ   ãããèèèßßßÖÖÖúúú½½½___ûûûÿÿÿîîîUUUôôô¾¾¾ÿÿÿþþþhhhÜÜÜÿÿÿôôô   ÿÿÿÿÿÿÿÿÿ
-
-
-   õõõþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûíííççç···BBB      UUUÎÎÎ   üüü»»»:::///^^^jjjâââÿÿÿÿÿÿ¾¾¾>>>KKKEEEJJJÓÓÓÿÿÿÍÍÍKKK      rrrÿÿÿqqq      NNNÍÍÍþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûîîîçççäääââââââãããæææêêêîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüðððèèèäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøêêêäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúêêêäääââââââãããæææéééîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûíííäääáááàààáááäääèèèìììñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööåååßßßÞÞÞßßßâââæææëëëïïïóóó÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúèèèÞÞÞÜÜÜÝÝÝàààäääèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþõõõßßßÙÙÙÚÚÚÜÜÜàààæææëëëðððôôô÷÷÷úúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøâââ×××ÖÖÖÙÙÙÝÝÝâââèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôÝÝÝÓÓÓÔÔÔØØØÞÞÞãããéééïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýòòòÚÚÚÐÐÐÓÓÓØØØßßßåååëëëðððôôôøøøúúúûûûýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññØØØÏÏÏÓÓÓÙÙÙàààçççìììñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññ×××ÎÎÎÓÓÓÚÚÚáááèèèíííòòòõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÕÕÕÎÎÎÓÓÓÛÛÛâââèèèîîîòòòöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ääääää÷÷÷ÿÿÿÿÿÿþþþüüüðððÖÖÖÔÔÔÕÕÕÛÛÛãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿööö½½½eeeeee½½½öööÿÿÿÿÿÿþþþüüüöööðððÜÜÜÛÛÛÞÞÞãããêêêïïïôôô÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿþþþþþþüüü÷÷÷òòòãããäääéééìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýùùùùùù÷÷÷îîîðððôôô÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿööö½½½eeeddd½½½öööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýûûûûûûüüüüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööããããããöööþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/cons_has_data.ppm
===================================================================
--- uspace/srv/hid/console/gfx/cons_has_data.ppm	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,5 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþúúþúúþúúþúúþûûþûûþûûþûûþûûþûûþüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþùùþøøþõõþêêþèèþèèþééþêêþëëþììþííþîîþîîþððþøøþúúþûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþ÷÷þññþááþÞÞþÞÞþÜÜþÞÞþßßþááþããþääþååþææþççþèèþééþëëþêêþììþ÷÷þúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþõõþîîþ××þÒÒþÏÏþÑÑþÒÒþÕÕþ××þÚÚþÜÜþÞÞþààþââþããþääþääþååþååþääþääþååþèèþõõþùùþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþííþÏÏþÇÇþÃÃþÃÃþÅÅþÈÈþËËþÎÎþÑÑþÕÕþØØþÛÛþÝÝþßßþààþááþââþââþââþââþááþßßþÞÞþßßþââþôôþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüüþììþÇÇþ¸¸þ··þ¸¸þ»»þ¾¾þÂÂþÆÆþÊÊþÎÎþÒÒþÖÖþÙÙþÜÜþÞÞþààþááþââþââþââþââþààþßßþÜÜþÙÙþ××þÝÝþòòþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüüþêêþÃÃþ±±þ¯¯þ°°þ²²þ¶¶þººþ¾¾þÃÃþÈÈþÍÍþÒÒþÖÖþÚÚþÝÝþßßþááþââþããþääþääþããþááþààþÝÝþÚÚþÖÖþÔÔþÚÚþòòþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüüþëëþÁÁþ­­þ©©þ©©þ««þ¯¯þ³³þ¹¹þ¾¾þÄÄþÊÊþÏÏþÔÔþØØþÜÜþßßþââþääþååþææþççþççþææþääþââþààþÜÜþÙÙþÔÔþÑÑþØØþððþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþììþÃÃþ­­þ§§þ¦¦þ§§þªªþ®®þ´´þººþÁÁþÇÇþÍÍþÓÓþØØþÜÜþààþããþææþèèþééþêêþêêþêêþêêþèèþææþääþààþÝÝþØØþÓÓþÏÏþ××þððþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþííþÇÇþ±±þ©©þ¦¦þ¦¦þ¨¨þ¬¬þ±±þ··þ¾¾þÅÅþÌÌþÒÒþØØþÝÝþââþååþèèþêêþììþííþîîþîîþîîþîîþììþëëþèèþææþââþÞÞþØØþÓÓþÎÎþÕÕþððþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþööþÏÏþ¸¸þ¯¯þ©©þ§§þ¨¨þ««þ°°þ¶¶þ½½þÄÄþËËþÒÒþÙÙþÞÞþããþççþêêþííþïïþððþññþòòþòòþòòþòòþññþïïþííþëëþççþããþßßþÙÙþÓÓþÎÎþ××þ÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþîîþÇÇþ··þ°°þ««þªªþ¬¬þ°°þ¶¶þ½½þÄÄþÌÌþÓÓþÙÙþßßþååþééþììþïïþññþóóþôôþõõþõõþööþööþõõþõõþóóþòòþïïþííþééþååþààþÚÚþÔÔþÔÔþððþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ÷÷þØØþÂÂþ¸¸þ²²þ¯¯þ®®þ±±þ¶¶þ¼¼þÄÄþËËþÓÓþÚÚþààþææþëëþîîþññþóóþõõþööþ÷÷þøøþøøþùùþùùþøøþøøþ÷÷þõõþôôþññþïïþëëþççþááþÛÛþÕÕþÜÜþøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþòòþÒÒþÃÃþ»»þµµþ³³þ´´þ··þ½½þÄÄþËËþÓÓþÚÚþááþççþììþððþóóþõõþ÷÷þøøþùùþúúþúúþûûþûûþûûþûûþúúþúúþùùþ÷÷þööþóóþððþììþèèþââþÜÜþÛÛþóóþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿþùùþààþÏÏþÅÅþ¾¾þººþ¹¹þººþ¾¾þÄÄþÌÌþÓÓþÚÚþááþèèþííþññþôôþööþøøþùùþúúþûûþüüþüüþüüþýýþýýþüüþüüþûûþûûþúúþøøþ÷÷þôôþññþííþèèþããþÞÞþããþùùþþþÿÿÿÿÿÿÿÿÿÿÿÿþøøþÝÝþÐÐþÈÈþÂÂþ¾¾þ¾¾þÁÁþÅÅþËËþÓÓþÚÚþááþèèþííþññþôôþ÷÷þùùþúúþûûþüüþüüþýýÿýýÿýýÿþþÿþþÿýýÿýýþýýþüüþüüþûûþùùþøøþõõþòòþîîþééþääþääþùùþþþÿÿÿÿÿÿÿÿÿþþþþõõþÞÞþÒÒþËËþÆÆþÃÃþÄÄþÇÇþÌÌþÒÒþÙÙþààþççþííþññþõõþ÷÷þùùþûûþüüþýýþýýÿýýÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿýýþýýþüüþûûþúúþøøþõõþòòþîîþêêþééþ÷÷þþþþþþÿÿÿÿÿÿþûûþééþÜÜþÕÕþÎÎþÊÊþÈÈþÊÊþÍÍþÒÒþÙÙþßßþææþììþññþôôþ÷÷þùùþûûþüüþýýÿýýÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿýýþýýþûûþúúþøøþööþóóþïïþììþîîþûûþþþÿÿÿÿÿÿþúúþèèþÝÝþ××þÑÑþÎÎþÍÍþÏÏþÓÓþØØþÞÞþååþëëþððþôôþ÷÷þùùþûûþüüþýýÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿýýþýýþüüþúúþùùþööþôôþððþððþûûþþþÿÿÿÿÿÿþúúþééþßßþÙÙþÔÔþÒÒþÒÒþÔÔþØØþÝÝþããþééþîîþóóþööþùùþûûþüüþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýþýýþüüþúúþùùþ÷÷þôôþôôþüüþþþÿÿÿÿÿÿþûûþêêþááþÜÜþ××þÖÖþÖÖþØØþÜÜþââþççþììþññþõõþøøþúúþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýþýýþüüþûûþùùþøøþ÷÷þýýþþþÿÿÿÿÿÿþûûþëëþããþÞÞþÚÚþÙÙþÚÚþÜÜþààþååþêêþïïþóóþ÷÷þùùþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýþýýþüüþûûþúúþúúþýýþþþÿÿÿÿÿÿþûûþëëþääþààþÝÝþÜÜþÝÝþßßþããþèèþííþññþõõþøøþúúþüüþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýþüüþüüþûûþþþþþþÿÿÿÿÿÿþûûþììþååþââþßßþÞÞþßßþââþææþêêþïïþóóþööþùùþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿýýþýýþýýþþþþþþÿÿÿÿÿÿþûûþííþææþããþààþààþááþääþèèþììþððþôôþ÷÷þúúþüüþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿþûûþííþççþääþááþááþââþååþééþííþññþõõþøøþúúþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿþûûþîîþççþääþââþââþããþææþêêþîîþòòþõõþøøþúúþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüüþððþèèþääþââþââþääþææþêêþîîþòòþööþùùþûûþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþøøþêêþääþââþââþääþææþêêþîîþòòþööþùùþûûþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþúúþêêþääþââþââþããþææþééþîîþòòþõõþøøþúúþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþûûþííþääþááþààþááþääþèèþììþññþõõþøøþúúþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþööþååþßßþÞÞþßßþââþææþëëþïïþóóþ÷÷þùùþûûþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþúúþèèþÞÞþÜÜþÝÝþààþääþèèþííþòòþööþùùþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþõõþßßþÙÙþÚÚþÜÜþààþææþëëþððþôôþ÷÷þúúþüüþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþøøþââþ××þÖÖþÙÙþÝÝþââþèèþííþòòþööþùùþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþôôþÝÝþÓÓþÔÔþØØþÞÞþããþééþïïþóóþ÷÷þùùþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþýýþòòþÚÚþÐÐþÓÓþØØþßßþååþëëþððþôôþøøþúúþûûþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿüüÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþüüþññþØØþÏÏþÓÓþÙÙþààþççþììþññþõõþøøþúúþüüþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿüüÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþüüþññþ××þÎÎþÓÓþÚÚþááþèèþííþòòþõõþøøþúúþüüþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿüüÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþüüþððþÕÕþÎÎþÓÓþÛÛþââþèèþîîþòòþööþùùþûûþüüþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿüüÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþüüþððþÖÖþÔÔþÕÕþÛÛþããþééþîîþóóþööþùùþûûþüüþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿüüÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþüüþööþððþÜÜþÛÛþÞÞþããþêêþïïþôôþ÷÷þùùþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿýýÿýýÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþüüþ÷÷þòòþããþääþééþììþððþôôþ÷÷þúúþüüþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþýýþùùþùùþ÷÷þîîþððþôôþ÷÷þùùþûûþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþýýþûûþûûþüüþüüþýýþýýþþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/cons_idle.ppm
===================================================================
--- uspace/srv/hid/console/gfx/cons_idle.ppm	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,5 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúúúúúúúúúúûûûûûûûûûûûûûûûûûûüüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýùùùøøøõõõêêêèèèèèèéééêêêëëëìììíííîîîîîîðððøøøúúúûûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷÷÷ñññáááÞÞÞÞÞÞÜÜÜÞÞÞßßßáááãããäääåååæææçççèèèéééëëëêêêììì÷÷÷úúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýõõõîîî×××ÒÒÒÏÏÏÑÑÑÒÒÒÕÕÕ×××ÚÚÚÜÜÜÞÞÞàààâââãããääääääååååååääääääåååèèèõõõùùùýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÏÏÏÇÇÇÃÃÃÃÃÃÅÅÅÈÈÈËËËÎÎÎÑÑÑÕÕÕØØØÛÛÛÝÝÝßßßàààáááââââââââââââáááßßßÞÞÞßßßâââôôôýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüìììÇÇÇ¸¸¸···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÊÊÊÎÎÎÒÒÒÖÖÖÙÙÙÜÜÜÞÞÞàààáááââââââââââââàààßßßÜÜÜÙÙÙ×××ÝÝÝòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüêêêÃÃÃ±±±¯¯¯°°°²²²¶¶¶ººº¾¾¾ÃÃÃÈÈÈÍÍÍÒÒÒÖÖÖÚÚÚÝÝÝßßßáááâââãããääääääãããáááàààÝÝÝÚÚÚÖÖÖÔÔÔÚÚÚòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëëëÁÁÁ­­­©©©©©©«««¯¯¯³³³¹¹¹¾¾¾ÄÄÄÊÊÊÏÏÏÔÔÔØØØÜÜÜßßßâââäääåååæææççççççæææäääâââàààÜÜÜÙÙÙÔÔÔÑÑÑØØØðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýìììÃÃÃ­­­§§§¦¦¦§§§ªªª®®®´´´ºººÁÁÁÇÇÇÍÍÍÓÓÓØØØÜÜÜàààãããæææèèèéééêêêêêêêêêêêêèèèæææäääàààÝÝÝØØØÓÓÓÏÏÏ×××ðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÇÇÇ±±±©©©¦¦¦¦¦¦¨¨¨¬¬¬±±±···¾¾¾ÅÅÅÌÌÌÒÒÒØØØÝÝÝâââåååèèèêêêìììíííîîîîîîîîîîîîìììëëëèèèæææâââÞÞÞØØØÓÓÓÎÎÎÕÕÕðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÏÏÏ¸¸¸¯¯¯©©©§§§¨¨¨«««°°°¶¶¶½½½ÄÄÄËËËÒÒÒÙÙÙÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòòòòñññïïïíííëëëçççãããßßßÙÙÙÓÓÓÎÎÎ×××÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýîîîÇÇÇ···°°°«««ªªª¬¬¬°°°¶¶¶½½½ÄÄÄÌÌÌÓÓÓÙÙÙßßßåååéééìììïïïñññóóóôôôõõõõõõööööööõõõõõõóóóòòòïïïíííéééåååàààÚÚÚÔÔÔÔÔÔðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ØØØÂÂÂ¸¸¸²²²¯¯¯®®®±±±¶¶¶¼¼¼ÄÄÄËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøùùùùùùøøøøøø÷÷÷õõõôôôñññïïïëëëçççáááÛÛÛÕÕÕÜÜÜøøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýòòòÒÒÒÃÃÃ»»»µµµ³³³´´´···½½½ÄÄÄËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúûûûûûûûûûûûûúúúúúúùùù÷÷÷öööóóóðððìììèèèâââÜÜÜÛÛÛóóóýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿùùùàààÏÏÏÅÅÅ¾¾¾ººº¹¹¹ººº¾¾¾ÄÄÄÌÌÌÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûüüüüüüüüüýýýýýýüüüüüüûûûûûûúúúøøø÷÷÷ôôôñññíííèèèãããÞÞÞãããùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿøøøÝÝÝÐÐÐÈÈÈÂÂÂ¾¾¾¾¾¾ÁÁÁÅÅÅËËËÓÓÓÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûüüüüüüýýýýýýýýýþþþþþþýýýýýýýýýüüüüüüûûûùùùøøøõõõòòòîîîéééääääääùùùþþþÿÿÿÿÿÿÿÿÿþþþõõõÞÞÞÒÒÒËËËÆÆÆÃÃÃÄÄÄÇÇÇÌÌÌÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûúúúøøøõõõòòòîîîêêêééé÷÷÷þþþþþþÿÿÿÿÿÿûûûéééÜÜÜÕÕÕÎÎÎÊÊÊÈÈÈÊÊÊÍÍÍÒÒÒÙÙÙßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþýýýýýýûûûúúúøøøöööóóóïïïìììîîîûûûþþþÿÿÿÿÿÿúúúèèèÝÝÝ×××ÑÑÑÎÎÎÍÍÍÏÏÏÓÓÓØØØÞÞÞåååëëëðððôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýýýýüüüúúúùùùöööôôôððððððûûûþþþÿÿÿÿÿÿúúúéééßßßÙÙÙÔÔÔÒÒÒÒÒÒÔÔÔØØØÝÝÝãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüúúúùùù÷÷÷ôôôôôôüüüþþþÿÿÿÿÿÿûûûêêêáááÜÜÜ×××ÖÖÖÖÖÖØØØÜÜÜâââçççìììñññõõõøøøúúúûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüûûûùùùøøø÷÷÷ýýýþþþÿÿÿÿÿÿûûûëëëãããÞÞÞÚÚÚÙÙÙÚÚÚÜÜÜàààåååêêêïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüûûûúúúúúúýýýþþþÿÿÿÿÿÿûûûëëëäääàààÝÝÝÜÜÜÝÝÝßßßãããèèèíííñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüüüüûûûþþþþþþÿÿÿÿÿÿûûûìììåååâââßßßÞÞÞßßßâââæææêêêïïïóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýýýýýýýþþþþþþÿÿÿÿÿÿûûûíííæææãããààààààáááäääèèèìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûíííçççäääááááááâââåååéééíííñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûîîîçççäääââââââãããæææêêêîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüðððèèèäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøêêêäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúêêêäääââââââãããæææéééîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûíííäääáááàààáááäääèèèìììñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööåååßßßÞÞÞßßßâââæææëëëïïïóóó÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúèèèÞÞÞÜÜÜÝÝÝàààäääèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþõõõßßßÙÙÙÚÚÚÜÜÜàààæææëëëðððôôô÷÷÷úúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøâââ×××ÖÖÖÙÙÙÝÝÝâââèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôÝÝÝÓÓÓÔÔÔØØØÞÞÞãããéééïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýòòòÚÚÚÐÐÐÓÓÓØØØßßßåååëëëðððôôôøøøúúúûûûýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññØØØÏÏÏÓÓÓÙÙÙàààçççìììñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññ×××ÎÎÎÓÓÓÚÚÚáááèèèíííòòòõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÕÕÕÎÎÎÓÓÓÛÛÛâââèèèîîîòòòöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÖÖÖÔÔÔÕÕÕÛÛÛãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüöööðððÜÜÜÛÛÛÞÞÞãããêêêïïïôôô÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþüüü÷÷÷òòòãããäääéééìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýùùùùùù÷÷÷îîîðððôôô÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýûûûûûûüüüüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/cons_kernel.ppm
===================================================================
--- uspace/srv/hid/console/gfx/cons_kernel.ppm	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,23 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúúúúúúúúúúûûûûûûûûûûûûûûûûûûüüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýùùùøøøõõõêêêèèèèèèéééêêêëëëìììíííîîîîîîðððøøøúúúûûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷÷÷ñññáááÞÞÞÞÞÞÜÜÜÞÞÞßßßáááãããäääåååæææçççèèèéééëëëêêêììì÷÷÷úúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýõõõîîî×××ÒÒÒÏÏÏÑÑÑÒÒÒÕÕÕ×××ÚÚÚÜÜÜÞÞÞàààâââãããääääääååååååääääääåååèèèõõõùùùýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÏÏÏÇÇÇÃÃÃÃÃÃÅÅÅÈÈÈËËËÎÎÎÑÑÑÕÕÕØØØÛÛÛÝÝÝßßßàààáááââââââââââââáááßßßÞÞÞßßßâââôôôýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüìììÇÇÇ¸¸¸···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÊÊÊÎÎÎÒÒÒÖÖÖÙÙÙÜÜÜÞÞÞàààáááââââââââââââàààßßßÜÜÜÙÙÙ×××ÝÝÝòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüêêêÃÃÃ±±±¯¯¯°°°²²²¶¶¶ººº¾¾¾ÃÃÃÈÈÈÍÍÍÒÒÒÖÖÖÚÚÚÝÝÝßßßáááâââãããääääääãããáááàààÝÝÝÚÚÚÖÖÖÔÔÔÚÚÚòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëëëÁÁÁ­­­©©©©©©«««¯¯¯³³³¹¹¹¾¾¾ÄÄÄÊÊÊÏÏÏÔÔÔØØØÜÜÜßßßâââäääåååæææççççççæææäääâââàààÜÜÜÙÙÙÔÔÔÑÑÑØØØðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýìììÃÃÃ­­­§§§¦¦¦§§§ªªª®®®´´´ºººÁÁÁÇÇÇÍÍÍÓÓÓØØØÜÜÜàààãããæææèèèéééêêêêêêêêêêêêèèèæææäääàààÝÝÝØØØÓÓÓÏÏÏ×××ðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÇÇÇ±±±©©©¦¦¦¦¦¦¨¨¨¬¬¬±±±···¾¾¾ÅÅÅÌÌÌÒÒÒØØØÝÝÝâââåååèèèêêêìììíííîîîîîîîîîîîîìììëëëèèèæææâââÞÞÞØØØÓÓÓÎÎÎÕÕÕðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÏÏÏ¸¸¸¯¯¯©©©§§§¨¨¨«««°°°¶¶¶½½½ÄÄÄËËËÒÒÒÙÙÙÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòòòòñññïïïíííëëëçççãããßßßÙÙÙÓÓÓÎÎÎ×××÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýîîîÇÇÇ···°°°«««ªªª¬¬¬°°°¶¶¶½½½ÄÄÄÌÌÌÓÓÓÙÙÙßßßåååéééìììïïïñññóóóôôôõõõõõõööööööõõõõõõóóóòòòïïïíííéééåååàààÚÚÚÔÔÔÔÔÔðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ØØØÂÂÂ¸¸¸²²²¯¯¯®®®±±±¶¶¶¼¼¼ÄÄÄËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøùùùùùùøøøøøø÷÷÷õõõôôôñññïïïëëëçççáááÛÛÛÕÕÕÜÜÜøøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýòòòÒÒÒÃÃÃ»»»µµµ³³³´´´···½½½ÄÄÄËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúûûûûûûûûûûûûúúúúúúùùù÷÷÷öööóóóðððìììèèèâââÜÜÜÛÛÛóóóýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿùùùààà···yyyEEE777¹¹¹ººº¾¾¾ÄÄÄÌÌÌÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûüüüüüüüüüýýýýýýüüüüüüûûûûûûúúúøøø÷÷÷ôôôñññíííèèèãããÞÞÞãããùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿøøøÝÝÝºººccc   
-
-
-¾¾¾ÁÁÁÅÅÅËËËÓÓÓÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûüüüüüüýýýýýýýýýþþþþþþýýýýýýýýýüüüüüüûûûùùùøøøõõõòòòîîîéééääääääùùùþþþÿÿÿÿÿÿÿÿÿþþþõõõÞÞÞÒÒÒÅÅÅ   
-
-
-ÄÄÄÇÇÇÌÌÌÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûúúúøøøõõõòòòîîîêêêééé÷÷÷þþþþþþÿÿÿÿÿÿûûûéééÜÜÜÕÕÕÍÍÍ   ÊÊÊÍÍÍÒÒÒÙÙÙßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþýýýýýýûûûúúúøøøöööóóóïïïìììîîîûûûþþþÿÿÿÿÿÿúúúèèèÝÝÝ×××ÑÑÑ   ÏÏÏÆÆÆDDD   ZZZáááôôô¯¯¯666MMM666VVVäääþþþþþþ···999GGG???KKKÔÔÔÿÿÿ      '''ÐÐÐZZZªªªùùùöööôôôððððððûûûþþþÿÿÿÿÿÿúúúéééßßßÙÙÙÔÔÔ      ÔÔÔ×××^^^eeeâââîîîóóó¸¸¸üüüööö666þþþÂÂÂÿÿÿþþþXXXâââþþþÆÆÆ   
-
-
-ùùùííí			úúúùùù÷÷÷ôôôôôôüüüþþþÿÿÿÿÿÿûûûêêêáááÜÜÜ×××   !!!ÕÕÕSSS^^^çççìììñññõõõ???ñññüüüýýýCCC   ÿÿÿEEEñññÿÿÿÿÿÿÊÊÊ   qqqÿÿÿþþþ   $$$ÿÿÿþþþþþþ%%%   üüüûûûùùùøøø÷÷÷ýýýþþþÿÿÿÿÿÿûûûëëëãããÞÞÞÚÚÚ   NNNÙÙÙïïïóóó÷÷÷   üüüýýýþþþûûûúúúÿÿÿ
-
-
-ÿÿÿÿÿÿÿÿÿôôô   333ÿÿÿÿÿÿ   '''ÿÿÿÿÿÿþþþ'''   ýýýüüüûûûúúúúúúýýýþþþÿÿÿÿÿÿûûûëëëäääàààÝÝÝ   
-
-
-²²²¨¨¨   UUUñññõõõøøø			ýýýþþþþþþþþþÿÿÿÿÿÿ			   ÿÿÿÿÿÿÿÿÿùùù   111ÿÿÿÿÿÿ   '''ÿÿÿÿÿÿÿÿÿ'''   ýýýýýýüüüüüüûûûþþþþþþÿÿÿÿÿÿûûûìììåååâââßßß   """âââæææ___   ¨¨¨öööùùù>>>èèèþþþþþþÿÿÿöööÿÿÿ>>>ôôôÿÿÿÿÿÿÔÔÔ   gggÿÿÿÿÿÿ   '''ÿÿÿÿÿÿÿÿÿ'''   þþþþþþýýýýýýýýýþþþþþþÿÿÿÿÿÿûûûíííæææãããÖÖÖ   ãããèèèßßßÖÖÖúúú½½½___ûûûÿÿÿîîîUUUôôô¾¾¾ÿÿÿþþþhhhÜÜÜÿÿÿôôô   ÿÿÿÿÿÿÿÿÿ
-
-
-   õõõþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûíííççç···BBB      UUUÎÎÎ   üüü»»»:::///^^^jjjâââÿÿÿÿÿÿ¾¾¾>>>KKKEEEJJJÓÓÓÿÿÿÍÍÍKKK      rrrÿÿÿqqq      NNNÍÍÍþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûîîîçççäääââââââãããæææêêêîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüðððèèèäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøêêêäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúêêêäääââââââãããæææéééîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûíííäääáááàààáááäääèèèìììñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööåååßßßÞÞÞßßßâââæææëëëïïïóóó÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúèèèÞÞÞÜÜÜÝÝÝàààäääèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþõõõßßßÙÙÙÚÚÚÜÜÜàààæææëëëðððôôô÷÷÷úúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøâââ×××ÖÖÖÙÙÙÝÝÝâââèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôÝÝÝÓÓÓÔÔÔØØØÞÞÞãããéééïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýòòòÚÚÚÐÐÐÓÓÓØØØßßßåååëëëðððôôôøøøúúúûûûýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññØØØÏÏÏÓÓÓÙÙÙàààçççìììñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññ×××ÎÎÎÓÓÓÚÚÚáááèèèíííòòòõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÕÕÕÎÎÎÓÓÓÛÛÛâââèèèîîîòòòöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÖÖÖÔÔÔÕÕÕÛÛÛãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüöööðððÜÜÜÛÛÛÞÞÞãããêêêïïïôôô÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþüüü÷÷÷òòòãããäääéééìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýùùùùùù÷÷÷îîîðððôôô÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýûûûûûûüüüüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/cons_selected.ppm
===================================================================
--- uspace/srv/hid/console/gfx/cons_selected.ppm	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,29 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûû÷÷÷ïïïæææÝÝÝ×××ÓÓÓÓÓÓ×××ÝÝÝæææïïï÷÷÷ûûûüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûôôôåååÓÓÓÂÂÂ©©©tttaaaVVVVVVaaattt©©©ÁÁÁÒÒÒåååôôôûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûðððÙÙÙººº]]]LLL___zzz¬¬¬¸¸¸¹¹¹¯¯¯eee```]]]ºººÙÙÙðððûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüôôôÛÛÛ¬¬¬oooFFFfff   ³³³½½½ÈÈÈÒÒÒÛÛÛàààáááÞÞÞØØØÑÑÑÈÈÈÀÀÀ­­­tttdddnnn¬¬¬ÚÚÚôôôüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýúúúèèèºººxxx@@@jjj···ËËËÑÑÑÔÔÔ×××ÚÚÚÜÜÜÞÞÞßßßáááâââââââââáááÝÝÝËËË²²²~~~kkkwww¹¹¹èèèúúúüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüøøøÜÜÜ555NNN¯¯¯ÀÀÀÅÅÅÉÉÉÌÌÌÏÏÏÓÓÓ×××ÙÙÙÜÜÜÞÞÞßßßàààááááááàààßßßÞÞÞÚÚÚÊÊÊªªªggggggÛÛÛ÷÷÷üüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüöööÐÐÐ
-
-
-333www²²²¸¸¸¼¼¼ÀÀÀÅÅÅÉÉÉÍÍÍÑÑÑÔÔÔØØØÛÛÛÝÝÝßßßàààáááááááááàààßßßÜÜÜÚÚÚÓÓÓ½½½uuu
-
-
-ÏÏÏõõõüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüöööËËËxxx000{{{¥¥¥¬¬¬°°°³³³¸¸¸½½½ÂÂÂÇÇÇÌÌÌÑÑÑÕÕÕØØØÜÜÜÞÞÞàààáááâââãããâââáááàààÞÞÞÜÜÜ×××ÔÔÔÉÉÉ{{{xxxËËËõõõüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýøøøÐÐÐxxx///{{{   ¦¦¦¨¨¨¬¬¬²²²···½½½ÃÃÃÈÈÈÎÎÎÓÓÓ×××ÛÛÛÞÞÞáááãããååååååæææååååååãããáááÞÞÞÛÛÛÖÖÖÒÒÒÈÈÈ}}}xxxÐÐÐ÷÷÷üüüýýýýýýýýýýýýýýýýýýýýýýýýúúúÛÛÛ
-
-
-000{{{£££¤¤¤¨¨¨­­­²²²¹¹¹¿¿¿ÆÆÆÌÌÌÒÒÒ×××ÜÜÜàààãããåååçççéééêêêêêêêêêéééçççåååãããàààÜÜÜ×××ÑÑÑÆÆÆ{{{
-
-
-ÛÛÛúúúüüüýýýýýýýýýýýýýýýýýýüüüèèè333{{{   ££££££¦¦¦ªªª¯¯¯¶¶¶½½½ÄÄÄËËËÒÒÒ×××ÝÝÝáááåååèèèêêêìììíííîîîîîîîîîíííìììêêêèèèåååáááÝÝÝØØØÑÑÑÅÅÅuuuèèèûûûüüüýýýýýýýýýýýýýýýôôôººº555www¥¥¥¦¦¦¤¤¤¦¦¦©©©®®®´´´¼¼¼ÃÃÃËËËÒÒÒØØØÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòñññðððïïïíííêêêçççãããÞÞÞØØØÑÑÑÃÃÃgggºººôôôüüüýýýýýýýýýýýýûûûÚÚÚwwwNNN­­­¨¨¨¨¨¨ªªª®®®´´´»»»ÃÃÃËËËÒÒÒÙÙÙßßßäääéééìììïïïñññóóóôôôõõõõõõõõõõõõõõõôôôóóóñññïïïìììéééäääßßßÙÙÙÑÑÑµµµwwwÚÚÚúúúüüüýýýýýýýýýñññ¬¬¬@@@²²²¯¯¯¬¬¬­­­¯¯¯´´´»»»ÃÃÃËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøøøøøøøøøø÷÷÷öööõõõóóóñññîîîëëëæææáááÙÙÙÎÎÎjjj¬¬¬ðððüüüýýýýýýûûûÙÙÙooojjj¯¯¯¸¸¸³³³²²²²²²¶¶¶¼¼¼ÃÃÃËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúúúúúúúúúúúúúúúúùùùøøø÷÷÷õõõóóóðððìììçççâââÚÚÚÃÃÃoooÙÙÙûûûüüüýýýõõõºººFFFÀÀÀ¼¼¼¸¸¸···¹¹¹½½½ÃÃÃËËËÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûûûûûûûüüüüüüüüüûûûûûûûûûúúúùùùøøøöööôôôñññíííèèèâââÙÙÙ¦¦¦eeeºººôôôüüüüüüåååeee¶¶¶ÆÆÆÀÀÀ½½½½½½¿¿¿ÄÄÄËËËÒÒÒÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûûûûüüüüüüýýýýýýýýýýýýýýýüüüüüüûûûûûûúúúùùù÷÷÷õõõñññîîîéééâââÆÆÆåååüüüüüüÓÓÓ]]]ËËËÉÉÉÅÅÅÂÂÂÃÃÃÆÆÆËËËÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùúúúûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûúúúùùù÷÷÷õõõòòòîîîéééßßßÃÃÃ]]]ÒÒÒûûû÷÷÷ÂÂÂKKK³³³ÒÒÒÌÌÌÉÉÉÇÇÇÈÈÈÌÌÌÒÒÒØØØßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûùùùøøøõõõòòòïïïééé¿¿¿___ÂÂÂ÷÷÷ïïïªªª^^^½½½ÕÕÕÏÏÏÍÍÍÌÌÌÎÎÎÒÒÒ×××ÞÞÞäääëëëðððôôô÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûúúúøøøöööóóóïïïÍÍÍvvvªªªïïïæææzzzÈÈÈ×××ÓÓÓÑÑÑÐÐÐÓÓÓ×××ÝÝÝãããéééîîîóóóöööùùùúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûúúúøøøöööôôôÜÜÜæææÞÞÞtttÓÓÓÙÙÙÖÖÖÔÔÔÕÕÕ×××ÜÜÜáááçççìììñññõõõøøøúúúûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûúúúùùù÷÷÷èèè­­­tttÞÞÞ×××aaa«««ÚÚÚÜÜÜÙÙÙØØØØØØÛÛÛßßßåååêêêïïïóóó÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûúúúùùùòòòÁÁÁaaa×××ÔÔÔWWW¸¸¸àààÞÞÞÜÜÜÚÚÚÜÜÜÞÞÞãããèèèíííñññõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûûûûøøøÍÍÍWWWÔÔÔÔÔÔWWW¹¹¹áááßßßÞÞÞÝÝÝÞÞÞáááåååêêêïïïóóóöööùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüùùùÍÍÍWWWÔÔÔ×××aaa¯¯¯ßßßáááßßßßßßàààãããçççìììðððôôô÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýý÷÷÷ÂÂÂaaa×××ÞÞÞtttÙÙÙáááààààààáááäääèèèíííñññõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýððð­­­tttÞÞÞæææÐÐÐâââááááááâââåååéééíííòòòõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýèèèæææïïï©©©eeeÇÇÇâââááááááãããæææéééîîîòòòõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýßßßvvv©©©ïïï÷÷÷ÁÁÁ___¿¿¿âââàààáááâââåååéééíííòòòõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüÖÖÖ___ÁÁÁöööüüüÒÒÒ]]]­­­ÜÜÜßßßàààáááäääèèèíííñññõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýøøøÄÄÄ]]]ÒÒÒûûûüüüåååtttËËËÞÞÞßßßàààãããçççìììðððôôô÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýæææåååüüüüüüôôô¹¹¹eee²²²ÚÚÚÜÜÜÞÞÞáááåååêêêïïïóóóöööùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýúúúÐÐÐeee¹¹¹óóóüüüýýýûûûÙÙÙooo~~~ËËËÙÙÙÜÜÜÞÞÞãããèèèíííñññõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüêêêoooÙÙÙûûûüüüýýýüüüððð«««jjjªªªÔÔÔ×××ÛÛÛßßßåååêêêïïïóóó÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüü÷÷÷ÎÎÎjjj«««ïïïüüüüüüýýýýýýûûûÚÚÚwwwfff¾¾¾ÔÔÔÖÖÖÜÜÜáááçççìììñññõõõøøøúúúûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúäääwwwÚÚÚúúúüüüýýýýýýýýýüüüôôôºººgggÈÈÈÒÒÒ×××ÝÝÝãããéééîîîóóóöööùùùúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûóóóÀÀÀgggºººóóóüüüüüüýýýýýýýýýýýýüüüèèèuuuÈÈÈÑÑÑ×××ÞÞÞäääëëëðððôôô÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûôôôÌÌÌuuuçççûûûüüüýýýýýýýýýýýýýýýüüüùùùÛÛÛ
-
-
-{{{ÆÆÆÑÑÑØØØßßßæææìììñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûõõõÐÐÐ{{{
-
-
-ÛÛÛùùùüüüüüüýýýýýýýýýýýýýýýýýýüüü÷÷÷ÏÏÏxxx}}}ÅÅÅÑÑÑÙÙÙáááçççíííñññõõõøøøúúúûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûôôôÐÐÐ}}}xxxÏÏÏ÷÷÷üüüüüüýýýýýýýýýýýýýýýýýýýýýýýýüüüõõõËËËxxx{{{ÄÄÄÑÑÑÙÙÙâââèèèîîîòòòõõõøøøúúúûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúóóóÌÌÌ{{{xxxËËËõõõüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüüõõõÐÐÐ
-
-
-uuuµµµÏÏÏÚÚÚâââéééîîîòòòöööøøøúúúûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýüüü÷÷÷äääÁÁÁuuu
-
-
-ÏÏÏõõõûûûüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüü÷÷÷ÛÛÛgggÂÂÂÙÙÙâââéééïïïóóóöööøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýúúúêêêÎÎÎgggÚÚÚöööûûûüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüüùùùèèèºººxxxkkk¥¥¥ÅÅÅßßßéééïïïôôô÷÷÷ùùùûûûüüüýýýýýýýýýýýýüüüøøøæææÏÏÏkkkwww¹¹¹çççùùùüüüüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûóóóÚÚÚ¬¬¬ooodddÄÄÄ½½½ÍÍÍÛÛÛèèèòòòøøøùùù÷÷÷ðððçççÞÞÞÖÖÖÄÄÄdddnnn«««ÙÙÙóóóûûûüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüüúúúðððÙÙÙººº]]]```vvv­­­ÂÂÂÍÍÍÍÍÍÂÂÂ­­­vvv```]]]ºººÙÙÙðððúúúüüüüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüüûûûôôôåååÓÓÓÂÂÂ©©©tttaaaVVVVVVaaattt©©©ÁÁÁÒÒÒåååôôôúúúüüüüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüüüüüûûûöööîîîæææÝÝÝ×××ÓÓÓÓÓÓ×××ÝÝÝåååîîîöööûûûûûûüüüüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýý
Index: pace/srv/hid/console/gfx/helenos.ppm
===================================================================
--- uspace/srv/hid/console/gfx/helenos.ppm	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,13 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-64 60
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýøùùñóõîñóïòóö÷÷ûûûþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýþþøùùíñóäêîßèìÞæëÝåêÝåêÞåêäèêðññûûûþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýþþøùùïòôåëïåìðäêîÛàãØÜßÛàâæëîåëîÝåêÛäèÛáåèééúúúþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýþþùùúïóôæìïåìðåëî×Üß½ÄÆµ¼¾ÈÍÏÍÒÓÊÏÑ·¾ÀÃÊÌãçêÝåéÚãçØÛÞçèèûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúðôõèîñäìðçíðÙÞáÁÇÉ´¼¾ÊÏÑèëì÷ùù÷ùúôöøòõ÷ñóôÖÚÜ¹ÀÂÞäæÜâåØÝâÔÕ×ñòòþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþûûûòõöéîñåíñæíñÛáäÄËÎµ¼¾ÈÍÏäæçöøøøúúõ÷ùòõ÷ðóõðóõðóõïòôïòôÒ×Ù¿ÅÈàåéØßäÎÒÕáááûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþûûûóö÷êïòæíñçîñÞãåÇÎÐµ½¿ÅËÍàãäö÷÷ùúûöøùóöøòõ÷ñôöðóõðóõïòôïòôïòôîñóëïñ»ÂÅÛßâÚàåÓÙÞÑÒÓôôôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþûüüôöøëðóçîñèïòßåèËÑÓ¶¾ÀÃÉËÜàáóôõøúû÷ùúô÷øóöøòõ÷òõ÷ñôöðóõðóõïòôïòôîñóîñóìðòìïòÔÙÛÄËÍÞäè×ÞãËÎÐæççüýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþûüüô÷øíñôèîòéïóáçêÍÔÖ¹ÁÃÂÈÊØÜÝñòóøúú÷úûõ÷ùôöøóöøòõ÷òõ÷ñôöñôöðóõðóõïòôîñóîñóíñóìðòëïñëîñåéìºÁÃÞãå×ÞãÐÕÙÕÕÖ÷÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüõøùîòõèïóéðôãéìÑ×Ù»ÂÄÀÆÈÔØÙïðñøùúøúûõøúô÷ùôöøóöøóöøòõ÷òõ÷ñôöðóõðóõïòôïòôîñóîñóìðòìïòëîñëîñêíðéíðÉÏÒÌÒÓÛàäÓÙÞÊÌÏìííþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷ùùðóõèïóéðôåêîÔÚÝ½ÄÇ¿ÆÇÑÖ×ëíîøùùúûüöùúô÷ùô÷ùô÷ùôöøóöøòõ÷òõ÷òõ÷ñôöðóõðóõïòôîñóîñóíñóìðòëïñëîñêîñéíðèìïèìïÝâä»ÂÄÞâåÓÚßËÐÓÛÛÛúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷ùúðôöéðóêðôæìï×ÝßÁÈË¾ÅÇÎÓÔèëëöøøúüü÷úûöùúõ÷ùô÷ùô÷ùô÷ùôöøòõ÷òõ÷òõ÷òõ÷ñôöðóõïòôïòôîñóíñóìðòìïòëîñëîñêíðéíðèìïèìïçëîæêí¿ÆÈÕÚÜÖÜáÐ×ÛÍÏÐððñþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþùúúñõ÷êñôêñõçíñÚàâÃÊÌ¾ÅÆÊÏÑæèéö÷øûüüøúûöùúöùúõøùô÷ùô÷ùô÷ùôöøóöøòõ÷òõ÷òõ÷ñôöðóõïòôïòôîñóîñóíðòìðòìïòëîñëîñêíðéíðèìïçëîçëîæêíåêíÕÛÞ¿ÆÇÝâåÓÙÞÉÍÏâââûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþùûûíóöéñôëñôßäçÆÍÏ¾ÅÇÇÌÎâåæõö÷ûüýùûü÷ùúöùúöùúöùúõøùô÷ùô÷ùô÷ùôöøóöøòõ÷òõ÷òõ÷ñôöðóõïòôïòôîñóÛÞà±²´´µ¶ÛÝàëîñêîñéíðèìïèìïçëîçëîæêíåéìäéìáæèºÁÃÙÝßÓÙÝÍÓÖÑÒÓôõõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùúúèðôêñõíñóÃÉËÂÈÊßâãóôõûüýúûýøúü÷ùûöùúöùúöùúõøùô÷ùô÷ùô÷ùôöøôöøòõ÷òõ÷òõ÷òõ÷ñôöïòôïòôîñóîñóÜÞá~~ooptsuÛÞáéíðèìïèìïçëîæêíåêíäéìäéëãèêãèêËÒÔÅËÍØÞáÏÖÚÈËÍèèèýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëðôçðôóöø½ÄÆ×ÚÜúûûûüýøúüøúü÷úûöùúöùúöùúöùúõ÷ùô÷ùô÷ùôöøôöøóöøòõ÷òõ÷òõ÷ñôöðóõïòôïòôîñóîñóíñó¯±³poq{{|º»½çëîçëîçëîæêíåéìäéìãèëãèêâçéáæèÛàâ¸¿ÁÛßâÐ×ÚËÐÒ×××÷øøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïððäíñðöøÔÙÛÍÒÓûüýùûüøúüøúü÷úûöùúöùúöùúõøùõ÷ùô÷ùô÷ùôöøôöøóöøòõ÷òõ÷ñôöðóõïòôïòôïòôîñóîñóíðòìðò«¬®yyz¢¢£«ª«­®¯áåèçëîæêíäéìäèëãèêâçéâçéáæèàåçßäçÁÈÊÌÒÔÓÙÜÎÓÖÊÌÍíîîþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýþþÝàáâëð÷úûºÁÃðòóùûüøúüøúü÷ùûöùúöùúöùúõøùô÷ùô÷ùôöøôöøôöøòõ÷òõ÷òõ÷ñôöðóõïòôïòôîñóîñóîñóìðòìðòëîñÑÓÕ³³´½¼½µµ¶ÑÔ×æêíåéìãèêãèêâçéâçéàåçßäçÞãæÝâåÓØÛºÀÃÙÞáÎÔØÆÊÍÝÝÞúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÍÑÒáêïøúüºÁÃ÷øùøúüøúü÷ùûöùúöùúöùúõ÷ùô÷ùô÷ùôöøôöøóöøòõ÷òõ÷ëîðæéëîñóïòôïòôîñóîñóíñóìðòìïòëîñêîñéìï  ¡¸·¹ÁÀÂ¾½¿ÀÁÂâæéãèêâçéâçéáæèàåçßäçÞãæÝâåÜáäÚßãºÁÄÔÙÛÎÕØËÐÔÍÎÏòòòþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûû¶¸¹Ýåêóöù»ÂÄðòò÷úûöùúöùúöùúõøùõ÷ùô÷ùôöøôöøôöøóöøòõ÷ñôöÎÐÒ°±³èëíîñóîñóíñóìðòìïòëîñêíðéíðèìïÂÄÆ³³´À¿ÁÀÀÁ¹¹ºÙÝÞâçéâçéàåçßäçßäçÝâåÜáäÛàäÛàäÚßãËÑÔ½ÄÆ×ÜßÌÓ×ÆÉËäääüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûº»»½ÄÈëñôÏÔÖÕÙÛöùúöùúöùúõøùô÷ùô÷ùôöøôöøôöøóõ÷òõ÷ñôößâä~~qpqxxz¹º»îñóìðòìðòëîñëîñêíðéíðèìïèìïàäç««¬½¼¾ÂÁÃ½¼¾ÇÈÉàåçàåçßäçÞãæÝâåÜáäÛàäÚßãÚßãÙÞâÕÚÞ¶¾ÀÕÚÞËÒÖÈÎÑÒÒÒöööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýýÙÙÙàéíèíï»ÁÃóö÷öùúõøùô÷ùôöøôöøôöøóöøòõ÷òõ÷ñôöðóõÇÉÊqpq~~~£¤¥æêëìïòëîñêíðéíðèìïèìïçëîçëîæêí±³µ¡¡¢··¸ÁÀÂÀ¿Áºº¼ÚßáßäçÞãæÜáåÛàäÛàäÚßãÚÞâØÝáØÝáÖÛàÁÈËÇÌÎÑ×ÚÊÐÔÇÉËéêêýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþéééÌÔØíóõ¿ÆÈâæèõ÷ùô÷ùôöøôöøôöøóõ÷òõ÷ñôöñôöðóõïòôÔÖØ|}}¦¥¦³²³°°±ÒÕ×ëîñêíðéíðèìïèìïçëîæêíæêíåéìÍÐÓ°¯±¿¾ÀÂÁÃ»º»ÌÐÒÝâåÜáäÛàäÚßãÚßãÙÞâØÝá×ÜàÖÛàÕÚßÏÕÙ¶½¿ØÜÞÊÐÔÆÊÌØØÙùùùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôõõº»¼¢§ª¶¼¾¡¡¤¥ðòôôöøôöøóöøòõ÷òõ÷ñôöñôöðóõïòôïòôèëí²±³¿¾À½¼¾ÀÀÂéìïèìïèìïçëîçëîæêíæêíÞáäÂÅÇ¨¨©»»½ÂÁÃ¾¾À¾¿ÁÙÞáÛàäÚßãÚÞâÙÝáØÝáÖÛàÖÛàÕÚÞÕÚÝÓØÜ»ÁÄÎÓÕÌÒÖÉÎÒÉÊËïïïþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüàààehi444444ÇÇÈôöøóõ÷òõ÷ñôöñôöñôöðóõïòôïòôîñóíñóÁÂÄ²±³À¿ÁÁÀÂ»º¼ÜßáçëîçëîæêíäèëØÛÞ¬®°onowxy¦¦§º¹ºÂÁÃÁÀÂ¸¸¹ÐÔ×ÚßãÚÞâØÝá×ÜàÖÛàÕÚßÕÚÞÔÙÝÓØÛÒ×ÚÊÏÒ·¾ÀÖÚÝÊÐÔÅÈËßßßûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþïïïªª¬|??@222||}ðòôòõ÷ñôöñôöðóõðóõïòôîñóîñóíðòìðòàâå««¬½¼¾ÁÁÂ¼¼½ÈÊÌæêíâåèÉËÍuuvppqvvw}~~®®¯¼¼½ÂÁÃÂÁÃ½½¾ÂÄÆÙÝá×ÜáÖÛàÖÛàÕÚßÔÙÝÔÙÝÓØÛÒ×ÚÑÖÙÏÕØ¶½ÀÔÙÛÊÐÔÈÍÑÌÍÎóóóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùùùÐÐÐ
-XYY333AAAÜßàñôöñôöðóõðóõïòôîñóíñóìðòìïòëîñêíð´µ·¡¡¢¸¸¹ÁÀÂÀÀÁº¹»ÅÈÊsstrrsyyz¥¥¦±°±º¹»À¿ÁÃÂÄÃÂÄÀ¿Á¹¹»ÒÖÚÖÛàÖÛßÕÚÞÔÙÝÓØÜÒ×ÚÒ×ÚÑÖÙÐÖÙÐÖÙÃÉÌ¾ÄÆÓØÛÊÐÔÅÈÊæææüýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýééérvx999222 ¡¢ñôöðóõïòôîñóîñóíðòìðòìïñëîñêíðéíðÓÖØ°°±¾¾¿ÁÀÂ»º»¨¨©
-
- ªª«³²´º¹»ÂÁÃÊÌÎÂÁÃÂÁÃÂÁÃÂÁÃ»»¼ÆÈËÕÚßÔÙÝÔÙÝÓØÛÒ×ÚÒ×ÚÐÖÙÐÖÙÏÕØÏÕØËÑÕ³»½ÖÙÜÊÐÔÇÍÐÓÓÓ÷÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôôô»¼½JJK222]]]çéëïòôîñóíðòìðòìïñëîñêîðêíðéíðèìïãæé¥¦§¦¦§»º¼ÂÁÃ¿¾Àµ´¶§§¨  ¢¥¥¥®®¯¶¶¸¼¼½ÆÇÉÒÕ×ÚÞâÚßãÃÄÆ¼»½À¿ÁÂÁÃ¿¾À¼¼¾Ò×ÚÔÙÜÓØÛÒ×ÚÑ×ÚÐÖÙÐÖÙÏÕØÏÔØÍÓ×ÍÓ×ºÂÄÈÎÐÍÓ×ÉÏÓÆÈÉìììýþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûüüàààfij555444ÆÆÇîñóíðòìðòìïñëîñêíðêíðéìïèìïçëîçëîÄÇÈ´´µÀ¿ÁÂÁÃ¾½¿¹¸º·¶¸º¹ºÀÀÁÌÎÐØÜßÛàäÚßãÚßãÚÞâÉÌÏ®®¯¹¸ºÀÀÁÁÀÂ¹¹ºÉÍÏÒ×ÚÒ×ÚÑÖÙÐÖÙÐÖÙÏÕØÏÔØÍÓ×ÍÓ×ÌÒÖÈÎÒ³»½×ÛÞÊÐÔÅÉËÚÛÛúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþïïï©«¬|AAB222{||ìïðìðòìîñëîñêíðêíðèìïèìïçëîæêíæêíÜàâ««¬½¼¾ÂÁÃÂÁÃÂÁÃÆÇÉÓÖØÜàãÝâåÛàäÚßãÚÞâÚÞâØÝáÔØÜ¡¡£¬¬­¼¼½ÁÀÂ½¼¾¾¿ÁÑÖÙÐÖÙÐÖÙÏÕØÏÕØÎÔØÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕµ½ÀÐÔÖËÐÔÉÏÒÉÊËðññþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷øøÍÍÎY[\333CCCÙÛÜëîñêîðêíðéìïèìïçëîçëîæêíåéìåéìãèê²´µ  ¡·¶·ÁÁÂÃÂÄÅÄÆÛßâÝâåÜáäÚßãÚßãÚÞâÙÝá×ÜàÖÛàÖÛà°²´ ·¶·ÁÀÂÀÀÁ¹¹»ÌÑÓÐÖÙÏÕØÏÔØÎÓ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÃÊÍ·¾ÀÕÚÝÊÐÔÄÇÉáááüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýççèsxy:::222 ¡¢ìïòêíðéìïèìïçëîçëîæêíåéìåéìäèëâçéÑÕÖ¯¯°¾¾¿ÃÂÄÂÁÃÐÓÖÛàäÚßãÚÞâÚÞâØÝá×ÜàÖÛàÖÛßÔÙÝÇËÎ®­®¾½¾ÂÁÃ»»¼ÃÇÉÏÕØÏÔØÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕËÑÕÊÐÔÉÏÓ³º½ÔØÛÊÐÔÈÎÑÍÎÎôôõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóôô¹ººLMN222^^^ãåçèìïèìïçëîæêíæêíåéìäèëãèêâçéâçéÞãä¥§¨¥¥¦º¹»ÂÁÃÂÁÃÁÁÄÙÞáÚÞâÙÝáØÝáÖÛàÖÛàÕÚÞÔÙÝÓØÛÒ×Ú¢£¤¤¤¥¹¹ºÁÀÂ¿¾ÀÆÈËÎÔØÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔ¾ÅÇÀÆÉÐÕÙÊÐÔÅÈÉçèèýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûÝÝÝhjl666666ÃÄÅèìïçëîæêíåéìåéìäèëãçêâçéáæèáæèàåçÂÅÇ³³´À¿ÁÂÁÃ¼»½ÎÒÕÙÝá×ÜàÖÛàÕÚßÕÚÞÓØÜÓØÛÒ×ÚÒ×ÚÀÃÆ²±²À¿ÁÃÃÅÌÐÔÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÇÎÑ±¸»ÖÚÝÊÐÔÆËÏÔÔÔøøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþîîï§¨ª{BBC222|}}éìîæêíåéìäèëãèêâçéâçéáæèàåèßäçÞãæÖÚÝªª«¼¼½ÂÁÃ¾½¿ÀÁÃ×ÜàÖÛàÕÚÞÔÙÝÓØÛÓØÛÒ×ÚÒ×ÚÑÖÙÐÕØÃÈÊ¼¾ÀÅÇÉÌÐÔÍÓ×ÌÒÖÌÒÖËÑÕËÑÕËÑÕÊÐÔÊÐÔÈÏÒ¸¾Á¾ÄÇËÑÕÊÐÔ¹ÀÃÌÑÓÌÒÖÊÏÓÆÇÈíîîþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷øøËËË[]^344EEEÖØÙåéìäèëâçéâçéáæèáæèàåçßäæÝâåÝâåÛàä³µ·  ¶¶·ÁÀÂÀÀÁ¸¸ºÑÕÙÕÚÞÔÙÜÓØÛÓØÛÒ×ÚÒ×ÚÐÖÙÐÖÙÏÕØÏÕØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔ£ª¬{ÐÔ×ÊÐÔÄÊÎºÁÃÚÞáÊÐÔÄÈÊÜÜÜúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýçççswy;;;222 ¡¢æêíâçéáæèáæèàåèßäçÞãæÝâåÜáäÛàäÚßãÍÐÓ®®¯¾¾¿ÂÁÃ»»¼ÄÆÉÓØÜÓØÛÒ×ÚÒ×ÚÑ×ÚÐÖÙÐÖÙÏÕØÏÔØÎÓ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔ®³µ¤«­ÊÐÒâäæÊÐÔÇÍÑ¹ÀÂäæéÊÐÔÉÏÒÉÉÊóóóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóôô¸¹¹MNO222___áãåáæèáæèàåçßäçÞãæÝâåÜáäÛàäÚßãÚÞâ×ÚÞ¥¦¨¤¤¥º¹»ÁÀÂ¿¾À¾¿ÁÓØÛÒ×ÚÒ×ÚÑÖÙÐÖÙÏÕØÏÕØÏÔØÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÌÒÖàãåèëìÑÖÚÊÐÔÂÈË¿ÅÇæèêÊÐÔÉÏÓ¼¾¿êêêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúûûÛÛÛhlm666666½¾¿âçéàåçßäæÝâåÜáäÜáäÚßãÚÞâÙÝáÙÝá×Üà¿ÂÅ³²³À¿ÁÂÁÃÆÈÊÒ×ÚÒ×ÚÑÖÙÐÖÙÏÕØÏÕØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔËÐÔËÑÕÊÐÔÉÏÓ³»½ÙÝÞÜàãÊÐÔÉÏÓ³´µäääÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþîîî§¨©{DEE222wxxäèêÞãæÝâåÜáäÛàäÚßãÚÞâÙÝáØÜáÖÛàÕÚßÒ×Û±³µ¬«­¼¼½ÆÆÈÐÔ×Ò×ÚÐÖÙÐÖÙÏÕØÏÔØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÈÎÒ¶¾Á½ÄÅñóôÍÓ×ÊÐÔÃÉÌ¬¬­äääÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ÊÊÊ\^_444EEEÒÔÕÝâåÜáäÛàãÚßãÙÝáÙÝá×ÜàÖÛàÕÚßÔÙÝÔÙÝÒ×ÚÌÐÒÎÒÔÑÖØÑÖÙÐÖÙÏÕØÏÕØÏÔØÍÓ×ÍÓ×ÌÒÖÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÉÏÓÃÊÎ¸ÀÃ±¹»ÇÍÏïñòØÜßÊÐÔÉÏÓ³³´éêêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýææçsxy<<<222áåèÚßãÚÞâÙÝáØÝá×ÜàÖÛßÕÚÞÔÙÝÓØÜÓØÛÓØÛÒ×ÚÒ×ÚÑÖÙÐÖÙÏÕØÏÕØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÅËÎ»ÃÅ²º½ºÀÂÑÖ×éëìêíîÔÙÜÊÐÔÉÏÓnooÂÂÃñòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóóô¸¸¹
-OQQ222\\\ÝàâÚÞâÙÝá×ÜáÖÛàÕÚßÔÙÞÔÙÝÓØÜÓØÛÒ×ÚÒ×ÚÒ×ÚÐÖÙÐÖÙÏÕØÏÔØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÆÌÐ¾ÄÇ²º¼¸¿ÀËÐÑæèéëíîáåçÓØÛËÑÕÇÍÑ®²µxyzKKKÖÖÖøøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúúúÚÚÚiln667777¼½¾Ûàä×ÜàÖÛßÕÚÞÔÙÝÔÙÜÓØÛÓØÛÒ×ÚÒ×ÚÑÖÙÐÖÙÏÕØÏÕØÏÔØÍÓ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÇÍÑÀÆÊµ¼¿µ¼¾ÇÌÎáäåìîïäèêÕÚÝÌÒÖÈÎÒ´º½`abAABCCD¼»¼êêêýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþîîî¥§¨zDEF333¥¥¦àãæÖÛßÔÙÞÔÙÝÓØÜÓØÛÓØÛÒ×ÚÒ×ÚÑÖÙÐÖÙÏÕØÏÕØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÈÎÒÁÈËµ½Àµ¼¾ÁÇÉÞáâëíîèêìØÜßÍÓ×ÉÏÓ¹¾ÂgjkHIJ;;;FGGaab¶¶·ßààøøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ÈÈÉ]__\\]ÐÒÓÛßâÔÙÝÔÙÝÓØÜÓØÛÈÍÐÀÄÇÍÒÔÐÖÙÐÖÙÏÕØÏÔØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÉÏÓÃÉÍ¸¿Â³»½½ÃÅØÜÝêìíëíîÚÞáÏÔØÊÐÓ½ÂÆ¡¥¨qstOOO===DDDZ[[www«««ÇÇÈäää÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýæææ}ÂÃÄÂÉËÎÓÕÖÛßÓØÛÓØÛÍÒÕ~
-¤¨ªÚÞáÏÕØÏÔØÎÓ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÉÏÓÅËÏºÂÅ³»¾¹ÀÂÓ×ØèêëìîïÝáäÐÖÙÊÐÔÀÆÊ¨¬¯|UVV>>>CCDTTUppq¥¥¦»»¼ÐÐÐâââñññúúúþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóóô·¸¸ÑÕØÊÐÓºÀÂÚÞáÓØÛÒ×ÚÎÓÕ¢¥§¹ÀÂÕ×ØÝáãÏÔØÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÅÌÏ¾ÄÇ³»½·¾ÀÍÒÓåèèïðñàäæÓØÛËÑÔÃÈÌ°µ¸
-\^_CCDCDDQQQjkk
- µµ¶ËËÌÞÞÞìììöööüüüþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúúúÙÙÙ·¼¿ÎÔØ·¾ÀÔÙÜÓØÛÒ×ÚÐÖÙÙÝàçêëæéêÐÕÙÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕÈÎÒÀÇÉ´»¾´»½ÇÌÎâåæîðñäçéÔÙÜËÑÕÆÌÐ´º½cdeGGGCDDNOOddd~°°±ÆÆÇÚÚÚéééôôôûûûþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþíîîÌÒÕÆÌÎ»ÂÄÔÙÜÐÖÙÐÖÙÏÕØÏÔØÎÓ×ÍÓ×ÍÓ×ÌÒÖÉÏÓÃÉÍ¶¾À³»½ÁÈÉÞáâïññæéë×ÜßËÑÕÇÍÑº¿ÂknoKLMDEFKLL_``yzz«««ÁÁÁÕÕÖæççòòóùúúýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ÆÇÇuwx¾ÄÈÏÔ×¹ÁÃºÂÄËÑÔÏÕØÏÔØÍÓ×ÍÓ×ËÑÕÅËÏ¸ÀÃ´»½»ÁÃÛÞßíîïëíïÚÞàÍÓ×ÈÎÒ½ÃÇ£¦qsuPQRDEEIJKZ[\uuv¦¦§½½½ÑÑÑáââïïðøøøýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýýåææ£¥ÌÒÖÎÔ×¾ÅÈ²º¼ºÁÄÁÈËÂÉÌºÁÄ³»½¸¿ÁÓ×ØëííîðñÝáãÏÔØÊÏÓÁÆÊ§¬¯x{}RTUCDEGHIUUWoop¡¡¢¸·¸ÍÍÎßààíîî÷÷÷üüüþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóóô²²²uxyÃÉÍÍÓÖÐÖÙÕÙÜÒ×ØÇÍÏÉÎÐ×ÚÜæéêñòóàãæÐÖÚÊÐÔÃÉÍ­²µ
-Z\]DEFEFGPPQhii²²³ÈÈÈÜÜÜëëëõööûûûþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúúúØØØopqÈÎÑÌÒÖÍÓ×ÎÔØÖÛßÛßâÚÞáÒ×ÛÊÐÔÅËÏ¶¼¿`bdGHIGHINOPbcd}}~¬¬­ÃÃÄ××ØèèèóóóúúúþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþíîîXYZ½ÂÆÉÏÓËÑÕËÑÕÊÐÔÇÍÑ»ÀÄhklKLMGHIKLM]^_vww§§¨¾½¾ÒÓÔåååñññùùùýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷øøÔÔÕ{||RTU\^_|qstQRRHIJLMNYZZqqq¢¢£¹¹¹ÏÏÐáááîîî÷÷÷üüüþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýïïïÅÅÅ~UWXPQROPQNOOMNNNOOWXYklm´³´ÊÊÊÝÝÝìííö÷÷üüüþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûüüêëëÊÊÊ z{{jkkhhhnoo®®¯ÅÅÅÙÚÚéééóôôûûûþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûüüðððÛÜÜÇÇÇ··¸²²²¶¶¶ÃÃÄÕÕÕæææòóóúúúýþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/nameic.ppm
===================================================================
--- uspace/srv/hid/console/gfx/nameic.ppm	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,14 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-100 26
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿããã»»»¤¤¤¿¿¿êêêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñññÄÄÄ¦¦¦¢¢¢ÅÅÅððñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËËË___444222222222222222666rrsÞÞÞÿÿÿÿÿÿÿÿÿññò;;;222222222222222999òòòÿÿÿÿÿÿ~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯¯°888222222222222222222222222222AAAÈÈÈÿÿÿïïïbbb222222222222222222222222222VVWïïïÿÿÿ~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖÖÖ;;;222222222222222222222222222222222UUUììì222222222222222222222222222222222~~~ÿÿÿ~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿzzz222222222222222IIIeef???222222222222222NNN222222222222???hhhLLL222222222222444ççè~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööBBB222222222222VVVëëëÿÿÿÔÔÔAAA222222222222AAA444222222222CCCàááÿÿÿñññWWW222222222333®®®~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÞÞ;;;222222222222ÿÿÿÿÿÿýýýaaa222222222222222222222222222\\\ÿÿÿÿÿÿþþþ222222222222
-
-
-~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýààà¿¿¿´´´ÀÀÀßßßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëëëÈÈÈ´´´ºººÔÔÕúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñññÇÇÇ´´´¿¿¿ÝÝÝÿÿÿÿÿÿÿÿÿÿÿÿÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222222222222222222GGGëëëÿÿÿÿÿÿ£££222222222222ttt~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿúúú°°±PPP222222222222333\\\ÑÑÑÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÏÏÏggg666222222222222GHH¬¬¬ûûûÿÿÿÿÿÿâââMMMNNN¤¤¤ùùú;;;222222222222WXXËËËÿÿÿÿÿÿÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222222222222222222222uuuôôôÿÿÿòòòãããããããããäääëëë~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿôôôzz{222222222222222222222222777¼¼¼ÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿ§§§999222222222222222222222444ùùùÿÿÿÞÞÞ222222222222222222222222222555ÄÄÄÿÿÿÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222BBBHHH222222222222222YYYÇÇÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿúúú222222BBBÛÛÛãããÏÏÏ
-
-
-5552229::ãããÿÿÿÿÿÿVVV222IIIòòòÿÿÿ¶¶¶888222666ÏÏÏäääÙÙÙ  ¡EEE222555ªªªÿÿÿÞÞÞ222222CCD222KKK¨¨©ÞÞÞãããÂÃÃ]]]222222RRRúúúÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222OOOooo222222222222222222555wwwçççÿÿÿÿÿÿÿÿÿÿÿÿ~~~222222QQQhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhEEE222222«««ÿÿÿÆÆÆ666222NNNÝÝÝÿÿÿÿÿÿÿÿÿÿÿÿþþþ­¬­222222þþþÿÿÿVVV222IIIòòòïïïLLL222999µµµþþþÿÿÿÿÿÿÿÿÿÿÿÿÖÖÖFFF222RRRîîîÞÞÞ222222222WWWìììÿÿÿÿÿÿÿÿÿÿÿÿóóóFFF222222ÕÕÕÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222RRRÓÓÓKKK222222222222222222222===üüüÿÿÿÿÿÿ~~~222222222222222222222222222222222222222222222222222«««ûûûuuu222<<<ÆÆÆÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûû__`222899óóóÿÿÿVVV222IIIòòò¬¬¬444222ýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ222555¸¸¸ÞÞÞ222222:::ÆÆÆÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ222222²²²ÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222RRRïïïÔÔÔPPP222222222222222222222333nnnùùùÿÿÿ~~~222222222222222222222222222222222222222222222222222«««æææKKK222[[[úúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§¨¨222222¾¾¾ÿÿÿVVV222IIIòòòppp222999ÝÝÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚÚÚ>>>222ÞÞÞ222222SSSúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°°°222222¬¬¬ÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222RRRïïïÿÿÿìììzzz222222222222222222222333ÿÿÿ~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ËËË222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÊÊÊ222222ÿÿÿVVV222IIIêêêEEE222WWWðððÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêêêQQQ222]]]ÞÞÞ222222wwwÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222RRRïïïÿÿÿÿÿÿýýýÁÁÁRRR222222222222222222444ááá~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««³³³222222222222222222222222222222222222222222~~~þþþVVV222IIIÖÖÖ@@@222222222222222222222222222222222222222NNNÎÎÎ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222RRRïïïÿÿÿÿÿÿÿÿÿÿÿÿõõõ777222222222222222~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««¥¥¥222222222222222222222222222222222222222222zzzþþþVVV222IIIËËË===222222222222222222222222222222222222222MMMÌÌÌ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222BBB¤¤¤´´´´´´´´´ÚÚÚÿÿÿþþþÆÆÆ===222222222222{{{~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««¨¨¨222222tttÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏàààÿÿÿVVV222IIIÎÎÎ>>>222PPPÄÄÄÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÕÕÕÙÙÙ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222222222222222222ÿÿÿÿÿÿþþþ222222222222iii~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÁÁÁ222222|||ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIáááCCC222PPPíííÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÞÞ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÞÞÞ;;;222222222222£££ÿÿÿÿÿÿÿÿÿmmm222222222222222222222222222ÿÿÿÿÿÿÿÿÿ£££222222222222iii~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ßßßAAA222SSSøøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÏÏ}}}}}}ÊÊÊÿÿÿVVV222IIIòòò___222555×××ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëëë}}}¢¢¢ÞÞÞ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ööö>>>222222222222tttûûûÿÿÿîîïQQQ222222222222222222222222222pqqÿÿÿÿÿÿüüü222222222222~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««øøøjij222888¸¸¸ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüülll222222áááÿÿÿVVV222IIIòòò  ¡333222ûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§¨¨222222£££ÞÞÞ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÿÿÿiii222222222222777ÌÌÌ555222222222222\\\222222222222999ÎÎÎ¤¤¤;;;222222222333®®®~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÃÃÃ666222IIIÔÔÔÿÿÿÿÿÿÿÿÿÿÿÿøøø222222vvvþþþÿÿÿVVV222IIIòòòìììKKK222677¬¬¬ûûûÿÿÿÿÿÿÿÿÿýýýºººAAA222OOOçççÞÞÞ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÿÿÿ¬¬¬444222222222222222222222222222222222===£££:::222222222222222222222222222222222;;;îîï~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿûûû222222777www©©©³³³TTT222222HHHçççÿÿÿÿÿÿVVV222IIIòòòÿÿÿ¿¿¿:::222222aaa´´´§§§kkl555222;;;¶¶¶ÿÿÿÞÞÞ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÿÿÿóóó\\\222222222222222222222222222222222
-úúú222222222222222222222222222222333 ÿÿÿ~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿøøø777222222222222222222222TTTáááÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿ»»¼DDD222222222222222222222BBBµµµÿÿÿÿÿÿÞÞÞ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÿÿÿÿÿÿæææbbb333222222222222222222222444~~ôôôÿÿÿ÷÷÷444222222222222222222222444ÿÿÿÿÿÿ¿¿¿ÔÔÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¾¾¾ÕÕÕÿÿÿÿÿÿÿÿÿþþþ×ØØ
-
-SSS555333EEEeef­­­ùùùÿÿÿÿÿÿÿÿÿÿÿÿ«««¤¤¤ùùùÿÿÿÿÿÿÿÿÿëëë__`;;;222===YYZèèèÿÿÿÿÿÿÿÿÿîîîÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÙÙÕÕÕÿÿÿÿÿÿÿÿÿüüüÁÁÁzzzTUU666222:::XYYÐÐÐýýýÿÿÿÿÿÿÿÿÿþþþÕÕÕZZ[<<<222888[[[ÝÝÝÿÿÿÿÿÿÿÿÿ
Index: uspace/srv/hid/fb/Makefile
===================================================================
--- uspace/srv/hid/fb/Makefile	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/fb/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -40,6 +40,5 @@
 
 SOURCES = \
-	main.c \
-	ppm.c
+	main.c
 
 ifneq ($(UARCH),ia64)
@@ -86,5 +85,6 @@
 endif
 
-EXTRA_CFLAGS += -D$(UARCH)
+LIBS = $(LIBIMGMAP_PREFIX)/libimgmap.a
+EXTRA_CFLAGS += -I$(LIBIMGMAP_PREFIX) -D$(UARCH)
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/fb/ega.c
===================================================================
--- uspace/srv/hid/fb/ega.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/fb/ega.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -56,5 +56,5 @@
 
 // FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 
 #define MAX_SAVED_SCREENS  256
@@ -414,12 +414,12 @@
 			retval = 0;
 			break;
-		case FB_VP_DRAW_PIXMAP:
+		case FB_VP_DRAW_IMGMAP:
 			scr = IPC_GET_ARG2(call);
 			retval = print_screen(scr);
 			break;
-		case FB_VP2PIXMAP:
+		case FB_VP2IMGMAP:
 			retval = save_screen();
 			break;
-		case FB_DROP_PIXMAP:
+		case FB_DROP_IMGMAP:
 			scr = IPC_GET_ARG1(call);
 			
Index: uspace/srv/hid/fb/fb.c
===================================================================
--- uspace/srv/hid/fb/fb.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/fb/fb.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -49,6 +49,6 @@
 #include <ipc/ns.h>
 #include <ipc/services.h>
-#include <kernel/errno.h>
-#include <kernel/genarch/fb/visuals.h>
+#include <errno.h>
+#include <abi/fb/visuals.h>
 #include <io/color.h>
 #include <io/style.h>
@@ -59,13 +59,13 @@
 #include <byteorder.h>
 #include <io/screenbuffer.h>
+#include <imgmap.h>
 #include "font-8x16.h"
 #include "fb.h"
 #include "main.h"
-#include "ppm.h"
 #include "pointer.xbm"
 #include "pointer_mask.xbm"
 
 // FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 
 #define DEFAULT_BGCOLOR  0xf0f0f0
@@ -76,5 +76,5 @@
 #define MAX_ANIM_LEN    8
 #define MAX_ANIMATIONS  4
-#define MAX_PIXMAPS     256  /**< Maximum number of saved pixmaps */
+#define MAX_IMGMAPS     256  /**< Maximum number of saved image maps */
 #define MAX_VIEWPORTS   128  /**< Viewport is a rectangular area on the screen */
 
@@ -160,5 +160,5 @@
 	unsigned int pos;
 	unsigned int animlen;
-	unsigned int pixmaps[MAX_ANIM_LEN];
+	unsigned int imgmaps[MAX_ANIM_LEN];
 } animation_t;
 
@@ -166,11 +166,5 @@
 static bool anims_enabled;
 
-typedef struct {
-	unsigned int width;
-	unsigned int height;
-	uint8_t *data;
-} pixmap_t;
-
-static pixmap_t pixmaps[MAX_PIXMAPS];
+static imgmap_t *imgmaps[MAX_IMGMAPS];
 static viewport_t viewports[128];
 
@@ -212,5 +206,4 @@
 static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col,
     unsigned int row);
-
 
 #define RED(x, bits)                 (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
@@ -875,5 +868,4 @@
 }
 
-
 /** Show cursor if cursor showing is enabled
  *
@@ -888,5 +880,4 @@
 }
 
-
 /** Invert cursor, if it is enabled
  *
@@ -899,5 +890,4 @@
 		cursor_show(vport);
 }
-
 
 /** Draw character at given position relative to viewport
@@ -981,18 +971,7 @@
 }
 
-
-static void putpixel_pixmap(void *data, unsigned int x, unsigned int y, uint32_t color)
-{
-	int pm = *((int *) data);
-	pixmap_t *pmap = &pixmaps[pm];
-	unsigned int pos = (y * pmap->width + x) * screen.pixelbytes;
-	
-	screen.rgb_conv(&pmap->data[pos], color);
-}
-
-
-static void putpixel(void *data, unsigned int x, unsigned int y, uint32_t color)
-{
-	viewport_t *vport = (viewport_t *) data;
+static void putpixel(viewport_t *vport, unsigned int x, unsigned int y,
+    uint32_t color)
+{
 	unsigned int dx = vport->x + x;
 	unsigned int dy = vport->y + y;
@@ -1001,14 +980,50 @@
 }
 
-
-/** Return first free pixmap
- *
- */
-static int find_free_pixmap(void)
+/** Draw image map
+ *
+ * @param[in] img       Image map.
+ * @param[in] sx        Coordinate of upper left corner.
+ * @param[in] sy        Coordinate of upper left corner.
+ * @param[in] maxwidth  Maximum allowed width for picture.
+ * @param[in] maxheight Maximum allowed height for picture.
+ * @param[in] vport     Viewport.
+ *
+ * @return EOK on success.
+ *
+ */
+static int imgmap_draw(imgmap_t *img, unsigned int sx, unsigned int sy,
+    unsigned int maxwidth, unsigned int maxheight, void *vport)
+{
+	if (img->visual != VISUAL_BGR_8_8_8)
+		return EINVAL;
+	
+	uint8_t *data = (uint8_t *) img->data;
+	
+	for (sysarg_t y = 0; y < img->height; y++) {
+		for (sysarg_t x = 0; x < img->width; x++) {
+			if ((x > maxwidth) || (y > maxheight)) {
+				data += 3;
+				continue;
+			}
+			
+			uint32_t color = (data[2] << 16) + (data[1] << 8) + data[0];
+			
+			putpixel(vport, sx + x, sy + y, color);
+			data += 3;
+		}
+	}
+	
+	return EOK;
+}
+
+/** Return first free image map
+ *
+ */
+static int find_free_imgmap(void)
 {
 	unsigned int i;
 	
-	for (i = 0; i < MAX_PIXMAPS; i++)
-		if (!pixmaps[i].data)
+	for (i = 0; i < MAX_IMGMAPS; i++)
+		if (!imgmaps[i])
 			return i;
 	
@@ -1016,38 +1031,28 @@
 }
 
-
-/** Create a new pixmap and return appropriate ID
- *
- */
-static int shm2pixmap(unsigned char *shm, size_t size)
-{
-	int pm;
-	pixmap_t *pmap;
-	
-	pm = find_free_pixmap();
-	if (pm == -1)
+/** Create a new image map and return appropriate ID
+ *
+ */
+static int shm2imgmap(imgmap_t *shm, size_t size)
+{
+	int im = find_free_imgmap();
+	if (im == -1)
 		return ELIMIT;
 	
-	pmap = &pixmaps[pm];
-	
-	if (ppm_get_data(shm, size, &pmap->width, &pmap->height))
-		return EINVAL;
-	
-	pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes);
-	if (!pmap->data)
+	imgmap_t *imap = malloc(size);
+	if (!imap)
 		return ENOMEM;
 	
-	ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, putpixel_pixmap, (void *) &pm);
-	
-	return pm;
-}
-
+	memcpy(imap, shm, size);
+	imgmaps[im] = imap;
+	return im;
+}
 
 /** Handle shared memory communication calls
  *
- * Protocol for drawing pixmaps:
+ * Protocol for drawing image maps:
  * - FB_PREPARE_SHM(client shm identification)
  * - IPC_M_AS_AREA_SEND
- * - FB_DRAW_PPM(startx, starty)
+ * - FB_DRAW_IMGMAP(startx, starty)
  * - FB_DROP_SHM
  *
@@ -1071,5 +1076,5 @@
 	static size_t intersize = 0;
 	
-	static unsigned char *shm = NULL;
+	static imgmap_t *shm = NULL;
 	static sysarg_t shm_id = 0;
 	static size_t shm_size;
@@ -1093,9 +1098,6 @@
 				return false;
 			}
+			
 			shm = dest;
-			
-			if (shm[0] != 'P')
-				return false;
-			
 			return true;
 		} else {
@@ -1107,8 +1109,7 @@
 		if (shm_id)
 			retval = EBUSY;
-		else 
+		else
 			shm_id = IPC_GET_ARG1(*call);
 		break;
-		
 	case FB_DROP_SHM:
 		if (shm) {
@@ -1118,17 +1119,17 @@
 		shm_id = 0;
 		break;
-		
-	case FB_SHM2PIXMAP:
+	case FB_SHM2IMGMAP:
 		if (!shm) {
 			retval = EINVAL;
 			break;
 		}
-		retval = shm2pixmap(shm, shm_size);
-		break;
-	case FB_DRAW_PPM:
+		retval = shm2imgmap(shm, shm_size);
+		break;
+	case FB_DRAW_IMGMAP:
 		if (!shm) {
 			retval = EINVAL;
 			break;
 		}
+		
 		x = IPC_GET_ARG1(*call);
 		y = IPC_GET_ARG2(*call);
@@ -1139,6 +1140,6 @@
 		}
 		
-		ppm_draw(shm, shm_size, IPC_GET_ARG1(*call),
-		    IPC_GET_ARG2(*call), vport->width - x, vport->height - y, putpixel, (void *) vport);
+		imgmap_draw(shm, IPC_GET_ARG1(*call), IPC_GET_ARG2(*call),
+		    vport->width - x, vport->height - y, vport);
 		break;
 	case FB_DRAW_TEXT_DATA:
@@ -1167,9 +1168,9 @@
 	if (handled)
 		async_answer_0(callid, retval);
+	
 	return handled;
 }
 
-
-static void copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap)
+static void copy_vp_to_imgmap(viewport_t *vport, imgmap_t *imap)
 {
 	unsigned int width = vport->width;
@@ -1178,9 +1179,10 @@
 	if (width + vport->x > screen.xres)
 		width = screen.xres - vport->x;
+	
 	if (height + vport->y > screen.yres)
 		height = screen.yres - vport->y;
 	
-	unsigned int realwidth = pmap->width <= width ? pmap->width : width;
-	unsigned int realheight = pmap->height <= height ? pmap->height : height;
+	unsigned int realwidth = imap->width <= width ? imap->width : width;
+	unsigned int realheight = imap->height <= height ? imap->height : height;
 	
 	unsigned int srcrowsize = vport->width * screen.pixelbytes;
@@ -1190,44 +1192,44 @@
 	for (y = 0; y < realheight; y++) {
 		unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
-		memcpy(pmap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize);
-	}
-}
-
-
-/** Save viewport to pixmap
- *
- */
-static int save_vp_to_pixmap(viewport_t *vport)
-{
-	int pm;
-	pixmap_t *pmap;
-	
-	pm = find_free_pixmap();
-	if (pm == -1)
+		memcpy(imap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize);
+	}
+}
+
+/** Save viewport to image map
+ *
+ */
+static int save_vp_to_imgmap(viewport_t *vport)
+{
+	int im = find_free_imgmap();
+	if (im == -1)
 		return ELIMIT;
 	
-	pmap = &pixmaps[pm];
-	pmap->data = malloc(screen.pixelbytes * vport->width * vport->height);
-	if (!pmap->data)
+	size_t size = screen.pixelbytes * vport->width * vport->height;
+	imgmap_t *imap = malloc(sizeof(imgmap_t) + size);
+	if (!imap)
 		return ENOMEM;
 	
-	pmap->width = vport->width;
-	pmap->height = vport->height;
-	
-	copy_vp_to_pixmap(vport, pmap);
-	
-	return pm;
-}
-
-
-/** Draw pixmap on screen
- *
- * @param vp Viewport to draw on
- * @param pm Pixmap identifier
- *
- */
-static int draw_pixmap(int vp, int pm)
-{
-	pixmap_t *pmap = &pixmaps[pm];
+	imap->size = sizeof(imgmap_t) + size;
+	imap->width = vport->width;
+	imap->height = vport->height;
+	imap->visual = (visual_t) -1;
+	
+	copy_vp_to_imgmap(vport, imap);
+	imgmaps[im] = imap;
+	return im;
+}
+
+/** Draw image map to screen
+ *
+ * @param vp Viewport to draw to
+ * @param im Image map identifier
+ *
+ */
+static int draw_imgmap(int vp, int im)
+{
+	imgmap_t *imap = imgmaps[im];
+	if (!imap)
+		return EINVAL;
+	
 	viewport_t *vport = &viewports[vp];
 	
@@ -1237,25 +1239,25 @@
 	if (width + vport->x > screen.xres)
 		width = screen.xres - vport->x;
+	
 	if (height + vport->y > screen.yres)
 		height = screen.yres - vport->y;
 	
-	if (!pmap->data)
-		return EINVAL;
-	
-	unsigned int realwidth = pmap->width <= width ? pmap->width : width;
-	unsigned int realheight = pmap->height <= height ? pmap->height : height;
-	
-	unsigned int srcrowsize = vport->width * screen.pixelbytes;
-	unsigned int realrowsize = realwidth * screen.pixelbytes;
-	
-	unsigned int y;
-	for (y = 0; y < realheight; y++) {
-		unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
-		memcpy(screen.fb_addr + tmp, pmap->data + y * srcrowsize, realrowsize);
-	}
+	unsigned int realwidth = imap->width <= width ? imap->width : width;
+	unsigned int realheight = imap->height <= height ? imap->height : height;
+	
+	if (imap->visual == (visual_t) -1) {
+		unsigned int srcrowsize = vport->width * screen.pixelbytes;
+		unsigned int realrowsize = realwidth * screen.pixelbytes;
+		
+		unsigned int y;
+		for (y = 0; y < realheight; y++) {
+			unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
+			memcpy(screen.fb_addr + tmp, imap->data + y * srcrowsize, realrowsize);
+		}
+	} else
+		imgmap_draw(imap, 0, 0, realwidth, realheight, vport);
 	
 	return EOK;
 }
-
 
 /** Tick animation one step forward
@@ -1277,5 +1279,5 @@
 			continue;
 		
-		draw_pixmap(animations[i].vp, animations[i].pixmaps[animations[i].pos]);
+		draw_imgmap(animations[i].vp, animations[i].imgmaps[animations[i].pos]);
 		animations[i].pos = (animations[i].pos + 1) % animations[i].animlen;
 	}
@@ -1287,5 +1289,5 @@
 static bool pointer_shown, pointer_enabled;
 static int pointer_vport = -1;
-static int pointer_pixmap = -1;
+static int pointer_imgmap = -1;
 
 
@@ -1310,8 +1312,8 @@
 	}
 	
-	if (pointer_pixmap == -1)
-		pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]);
+	if (pointer_imgmap == -1)
+		pointer_imgmap = save_vp_to_imgmap(&viewports[pointer_vport]);
 	else
-		copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]);
+		copy_vp_to_imgmap(&viewports[pointer_vport], imgmaps[pointer_imgmap]);
 	
 	/* Draw mouse pointer. */
@@ -1338,5 +1340,5 @@
 	/* Restore image under the pointer. */
 	if (pointer_shown) {
-		draw_pixmap(pointer_vport, pointer_pixmap);
+		draw_imgmap(pointer_vport, pointer_imgmap);
 		pointer_shown = 0;
 	}
@@ -1393,5 +1395,5 @@
 		animations[i].initialized = 0;
 		break;
-	case FB_ANIM_ADDPIXMAP:
+	case FB_ANIM_ADDIMGMAP:
 		i = IPC_GET_ARG1(*call);
 		if (i >= MAX_ANIMATIONS || i < 0 ||
@@ -1405,10 +1407,10 @@
 		}
 		newval = IPC_GET_ARG2(*call);
-		if (newval < 0 || newval > MAX_PIXMAPS ||
-			!pixmaps[newval].data) {
+		if (newval < 0 || newval > MAX_IMGMAPS ||
+			!imgmaps[newval]) {
 			retval = EINVAL;
 			break;
 		}
-		animations[i].pixmaps[animations[i].animlen++] = newval;
+		animations[i].imgmaps[animations[i].animlen++] = newval;
 		break;
 	case FB_ANIM_CHGVP:
@@ -1449,9 +1451,8 @@
 }
 
-
-/** Handler for messages concerning pixmap handling
- *
- */
-static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
+/** Handler for messages concerning image map handling
+ *
+ */
+static int imgmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
 {
 	bool handled = true;
@@ -1460,36 +1461,43 @@
 	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case FB_VP_DRAW_PIXMAP:
+	case FB_VP_DRAW_IMGMAP:
 		nvp = IPC_GET_ARG1(*call);
 		if (nvp == -1)
 			nvp = vp;
+		
 		if (nvp < 0 || nvp >= MAX_VIEWPORTS ||
-			!viewports[nvp].initialized) {
+		    !viewports[nvp].initialized) {
 			retval = EINVAL;
 			break;
 		}
+		
 		i = IPC_GET_ARG2(*call);
-		retval = draw_pixmap(nvp, i);
-		break;
-	case FB_VP2PIXMAP:
+		retval = draw_imgmap(nvp, i);
+		break;
+	case FB_VP2IMGMAP:
 		nvp = IPC_GET_ARG1(*call);
 		if (nvp == -1)
 			nvp = vp;
+		
 		if (nvp < 0 || nvp >= MAX_VIEWPORTS ||
-			!viewports[nvp].initialized)
+		    !viewports[nvp].initialized) {
 			retval = EINVAL;
-		else
-			retval = save_vp_to_pixmap(&viewports[nvp]);
-		break;
-	case FB_DROP_PIXMAP:
+			break;
+		}
+		
+		retval = save_vp_to_imgmap(&viewports[nvp]);
+		break;
+	case FB_DROP_IMGMAP:
 		i = IPC_GET_ARG1(*call);
-		if (i >= MAX_PIXMAPS) {
+		if (i >= MAX_IMGMAPS) {
 			retval = EINVAL;
 			break;
 		}
-		if (pixmaps[i].data) {
-			free(pixmaps[i].data);
-			pixmaps[i].data = NULL;
-		}
+		
+		if (imgmaps[i]) {
+			free(imgmaps[i]);
+			imgmaps[i] = NULL;
+		}
+		
 		break;
 	default:
@@ -1616,5 +1624,5 @@
 			continue;
 		
-		if (pixmap_handle(callid, &call, vp))
+		if (imgmap_handle(callid, &call, vp))
 			continue;
 		
Index: uspace/srv/hid/fb/fb.h
===================================================================
--- uspace/srv/hid/fb/fb.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/fb/fb.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,6 +39,4 @@
 #include <stdint.h>
 
-typedef void (* putpixel_cb_t)(void *, unsigned int, unsigned int, uint32_t);
-
 extern int fb_init(void);
 
Index: pace/srv/hid/fb/ppm.c
===================================================================
--- uspace/srv/hid/fb/ppm.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,130 +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.
- */
-
-#include <sys/types.h>
-#include <errno.h>
-
-#include "ppm.h"
-
-static void skip_whitespace(unsigned char **data)
-{
-retry:
-	while (**data == ' ' || **data == '\t' || **data == '\n' ||
-	    **data == '\r')
-		(*data)++;
-	if (**data == '#') {
-		while (1) {
-			if (**data == '\n' || **data == '\r')
-				break;
-			(*data)++;
-		}
-		goto retry;
-	}
-}
-
-static void read_num(unsigned char **data, unsigned int *num)
-{
-	*num = 0;
-	while (**data >= '0' && **data <= '9') {
-		*num *= 10;
-		*num += **data - '0';
-		(*data)++;
-	}
-}
-
-int ppm_get_data(unsigned char *data, size_t dtsz, unsigned int *width,
-    unsigned int *height)
-{
-	/* Read magic */
-	if (data[0] != 'P' || data[1] != '6')
-		return EINVAL;
-
-	data+=2;
-	skip_whitespace(&data);
-	read_num(&data, width);
-	skip_whitespace(&data);
-	read_num(&data,height);
-
-	return 0;
-}
-
-/** Draw PPM pixmap
- *
- * @param data Pointer to PPM data
- * @param datasz Maximum data size
- * @param sx Coordinate of upper left corner
- * @param sy Coordinate of upper left corner
- * @param maxwidth Maximum allowed width for picture
- * @param maxheight Maximum allowed height for picture
- * @param putpixel Putpixel function used to print bitmap
- */
-int ppm_draw(unsigned char *data, size_t datasz, unsigned int sx,
-    unsigned int sy, unsigned int maxwidth, unsigned int maxheight,
-    putpixel_cb_t putpixel, void *vport)
-{
-	unsigned int width, height;
-	unsigned int maxcolor;
-	unsigned int i;
-	unsigned int color;
-	unsigned int coef;
-	
-	/* Read magic */
-	if ((data[0] != 'P') || (data[1] != '6'))
-		return EINVAL;
-	
-	data += 2;
-	skip_whitespace(&data);
-	read_num(&data, &width);
-	skip_whitespace(&data);
-	read_num(&data, &height);
-	skip_whitespace(&data);
-	read_num(&data, &maxcolor);
-	data++;
-	
-	if ((maxcolor == 0) || (maxcolor > 255) || (width * height > datasz))
-		return EINVAL;
-	
-	coef = 255 / maxcolor;
-	if (coef * maxcolor > 255)
-		coef -= 1;
-	
-	for (i = 0; i < width * height; i++) {
-		/* Crop picture if we don't fit into region */
-		if (i % width > maxwidth || i / width > maxheight) {
-			data += 3;
-			continue;
-		}
-		color = ((data[0] * coef) << 16) + ((data[1] * coef) << 8) +
-		    data[2] * coef;
-		
-		(*putpixel)(vport, sx + (i % width), sy + (i / width), color);
-		data += 3;
-	}
-	
-	return 0;
-}
Index: pace/srv/hid/fb/ppm.h
===================================================================
--- uspace/srv/hid/fb/ppm.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,39 +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.
- */
-
-#ifndef FB_PPM_H_
-#define FB_PPM_H_
-
-#include "fb.h"
-#include <sys/types.h>
-
-extern int ppm_draw(unsigned char *, size_t, unsigned int, unsigned int, 
-    unsigned int, unsigned int, putpixel_cb_t, void *);
-extern int ppm_get_data(unsigned char *, size_t, unsigned int *, unsigned int *);
-
-#endif
Index: uspace/srv/hid/fb/serial_console.c
===================================================================
--- uspace/srv/hid/fb/serial_console.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/fb/serial_console.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -53,5 +53,5 @@
 
 // FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 
 #define MAX_CONTROL 20
Index: uspace/srv/hid/input/ctl/kbdev.c
===================================================================
--- uspace/srv/hid/input/ctl/kbdev.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/input/ctl/kbdev.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -48,7 +48,8 @@
 #include <kbd_ctl.h>
 #include <kbd_port.h>
+#include <loc.h>
 #include <stdlib.h>
 #include <vfs/vfs_sess.h>
-
+#include <sys/typefmt.h>
 
 static int kbdev_ctl_init(kbd_dev_t *);
@@ -70,7 +71,4 @@
 	/** Session with kbdev device */
 	async_sess_t *sess;
-
-	/** File descriptor of open kbdev device */
-	int fd;
 } kbdev_t;
 
@@ -84,5 +82,4 @@
 
 	kbdev->kbd_dev = kdev;
-	kbdev->fd = -1;
 
 	return kbdev;
@@ -93,6 +90,4 @@
 	if (kbdev->sess != NULL)
 		async_hangup(kbdev->sess);
-	if (kbdev->fd >= 0)
-		close(kbdev->fd);
 	free(kbdev);
 }
@@ -100,22 +95,13 @@
 static int kbdev_ctl_init(kbd_dev_t *kdev)
 {
-	const char *pathname;
 	async_sess_t *sess;
 	async_exch_t *exch;
 	kbdev_t *kbdev;
-	int fd;
 	int rc;
 
-	pathname = kdev->dev_path;
-
-	fd = open(pathname, O_RDWR);
-	if (fd < 0) {
-		return -1;
-	}
-
-	sess = fd_session(EXCHANGE_SERIALIZE, fd);
+	sess = loc_service_connect(EXCHANGE_SERIALIZE, kdev->svc_id, 0);
 	if (sess == NULL) {
-		printf("%s: Failed starting session with '%s'\n", NAME, pathname);
-		close(fd);
+		printf("%s: Failed starting session with '%s.'\n", NAME,
+		    kdev->svc_name);
 		return -1;
 	}
@@ -124,14 +110,14 @@
 	if (kbdev == NULL) {
 		printf("%s: Failed allocating device structure for '%s'.\n",
-		    NAME, pathname);
+		    NAME, kdev->svc_name);
 		return -1;
 	}
 
-	kbdev->fd = fd;
 	kbdev->sess = sess;
 
 	exch = async_exchange_begin(sess);
 	if (exch == NULL) {
-		printf("%s: Failed starting exchange with '%s'.\n", NAME, pathname);
+		printf("%s: Failed starting exchange with '%s'.\n", NAME,
+		    kdev->svc_name);
 		kbdev_destroy(kbdev);
 		return -1;
@@ -141,5 +127,5 @@
 	if (rc != EOK) {
 		printf("%s: Failed creating callback connection from '%s'.\n",
-		    NAME, pathname);
+		    NAME, kdev->svc_name);
 		async_exchange_end(exch);
 		kbdev_destroy(kbdev);
Index: uspace/srv/hid/input/ctl/stty.c
===================================================================
--- uspace/srv/hid/input/ctl/stty.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/input/ctl/stty.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -34,4 +34,6 @@
  * @file
  * @brief Serial TTY-like keyboard controller driver.
+ *
+ * Keyboard emulation on a serial terminal.
  */
 
@@ -63,4 +65,9 @@
 #include <stdio.h>
 
+/**
+ * Sequnece definitions are primarily for Xterm. Additionally we define
+ * sequences that are unique to Gnome terminal -- most are the same but
+ * some differ.
+ */
 static int seq_defs[] = {
 	/* Not shifted */
@@ -81,4 +88,5 @@
 	0,	KC_MINUS,	0x2d, GSP_END,
 	0,	KC_EQUALS,	0x3d, GSP_END,
+
 	0,	KC_BACKSPACE,	0x08, GSP_END,
 
@@ -216,4 +224,11 @@
 	0,	KC_RIGHT,	0x1b, 0x5b, 0x43, GSP_END,
 
+	/*
+	 * Sequences specific to Gnome terminal
+	 */
+	0,	KC_BACKSPACE,	0x7f, GSP_END, /* ASCII DEL */
+	0,	KC_HOME,	0x1b, 0x4f, 0x48, GSP_END,
+	0,	KC_END,		0x1b, 0x4f, 0x46, GSP_END,
+
 	0,	0
 };
Index: uspace/srv/hid/input/generic/gsp.c
===================================================================
--- uspace/srv/hid/input/generic/gsp.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/input/generic/gsp.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -104,5 +104,5 @@
 		if (key == 0) break;
 
-		/* Insert one sequence. */		
+		/* Insert one sequence. */
 		rc = gsp_insert_seq(p, dp, mods, key);
 		if (rc != 0)
@@ -197,5 +197,6 @@
 
 	if (t == NULL) {
-		printf("gsp_step: not found\n");
+		printf("gsp_step: not found, state=%d, input=0x%x\n",
+		    state, input);
 		*mods = 0;
 		*key = 0;
@@ -205,4 +206,5 @@
 	*mods = t->out_mods;
 	*key = t->out_key;
+
 	return t->new_state;
 }
Index: uspace/srv/hid/input/generic/input.c
===================================================================
--- uspace/srv/hid/input/generic/input.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/input/generic/input.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,4 +38,5 @@
 
 #include <adt/list.h>
+#include <bool.h>
 #include <ipc/services.h>
 #include <ipc/input.h>
@@ -53,5 +54,5 @@
 #include <io/console.h>
 #include <io/keycode.h>
-#include <devmap.h>
+#include <loc.h>
 #include <input.h>
 #include <kbd.h>
@@ -63,8 +64,5 @@
 
 // FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
-
-/* In microseconds */
-#define DISCOVERY_POLL_INTERVAL  (10 * 1000 * 1000)
+#include <abi/ipc/methods.h>
 
 #define NUM_LAYOUTS  3
@@ -275,5 +273,5 @@
 	kdev->port_ops = port;
 	kdev->ctl_ops = ctl;
-	kdev->dev_path = NULL;
+	kdev->svc_id = 0;
 	
 	/* Initialize port driver. */
@@ -303,5 +301,5 @@
 	mdev->port_ops = port;
 	mdev->proto_ops = proto;
-	mdev->dev_path = NULL;
+	mdev->svc_id = 0;
 	
 	/* Initialize port driver. */
@@ -324,8 +322,8 @@
 /** Add new kbdev device.
  *
- * @param dev_path Filesystem path to the device (/dev/class/...)
+ * @param service_id	Service ID of the keyboard device
  *
  */
-static int kbd_add_kbdev(const char *dev_path)
+static int kbd_add_kbdev(service_id_t service_id, kbd_dev_t **kdevp)
 {
 	kbd_dev_t *kdev = kbd_dev_new();
@@ -333,8 +331,14 @@
 		return -1;
 	
-	kdev->dev_path = dev_path;
+	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) {
@@ -343,7 +347,10 @@
 	
 	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;
@@ -352,8 +359,8 @@
 /** Add new mousedev device.
  *
- * @param dev_path Filesystem path to the device (/dev/class/...)
+ * @param service_id	Service ID of the mouse device
  *
  */
-static int mouse_add_mousedev(const char *dev_path)
+static int mouse_add_mousedev(service_id_t service_id, mouse_dev_t **mdevp)
 {
 	mouse_dev_t *mdev = mouse_dev_new();
@@ -361,8 +368,14 @@
 		return -1;
 	
-	mdev->dev_path = dev_path;
+	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) {
@@ -371,4 +384,5 @@
 	
 	list_append(&mdev->mouse_devs, &mouse_devs);
+	*mdevp = mdev;
 	return EOK;
 	
@@ -410,5 +424,5 @@
 #endif
 #if defined(MACHINE_msim)
-	kbd_add_dev(&msim_port, &pc_ctl);
+	kbd_add_dev(&msim_port, &stty_ctl);
 #endif
 #if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)
@@ -480,70 +494,143 @@
 }
 
-/** Periodically check for new input devices.
- *
- * Looks under /dev/class/keyboard and /dev/class/mouse.
- *
- * @param arg Ignored
- *
- */
-static int dev_discovery_fibril(void *arg)
-{
-	char *dev_path;
-	size_t kbd_id = 1;
-	size_t mouse_id = 1;
+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;
 	
-	while (true) {
-		async_usleep(DISCOVERY_POLL_INTERVAL);
-		
-		/*
-		 * Check for new keyboard device
-		 */
-		rc = asprintf(&dev_path, "/dev/class/keyboard\\%zu", kbd_id);
-		if (rc < 0)
-			continue;
-		
-		if (kbd_add_kbdev(dev_path) == EOK) {
-			printf("%s: Connected keyboard device '%s'\n",
-			    NAME, dev_path);
-			
-			/* XXX Handle device removal */
-			++kbd_id;
+	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;
+			}
 		}
 		
-		free(dev_path);
-		
-		/*
-		 * Check for new mouse device
-		 */
-		rc = asprintf(&dev_path, "/dev/class/mouse\\%zu", mouse_id);
-		if (rc < 0)
-			continue;
-		
-		if (mouse_add_mousedev(dev_path) == EOK) {
-			printf("%s: Connected mouse device '%s'\n",
-			    NAME, dev_path);
-			
-			/* XXX Handle device removal */
-			++mouse_id;
+		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(dev_path);
-	}
+	}
+	
+	free(svcs);
+	
+	/* XXX Handle device removal */
 	
 	return EOK;
 }
 
-/** Start a fibril for discovering new devices. */
-static void input_start_dev_discovery(void)
-{
-	fid_t fid = fibril_create(dev_discovery_fibril, NULL);
-	if (!fid) {
-		printf("%s: Failed to create device discovery fibril.\n",
+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;
-	}
-	
-	fibril_add_ready(fid);
+		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;
+	
+	rc = dev_check_new_kbdevs();
+	if (rc != EOK)
+		return rc;
+	
+	rc = dev_check_new_mousedevs();
+	if (rc != EOK)
+		return rc;
+
+	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();
 }
 
@@ -572,16 +659,16 @@
 	
 	/* Register driver */
-	int rc = devmap_driver_register(NAME, client_connection);
+	int rc = loc_server_register(NAME, client_connection);
 	if (rc < 0) {
-		printf("%s: Unable to register driver (%d)\n", NAME, rc);
+		printf("%s: Unable to register server (%d)\n", NAME, rc);
 		return -1;
 	}
 	
-	char kbd[DEVMAP_NAME_MAXLEN + 1];
-	snprintf(kbd, DEVMAP_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
-	
-	devmap_handle_t devmap_handle;
-	if (devmap_device_register(kbd, &devmap_handle) != EOK) {
-		printf("%s: Unable to register device %s\n", NAME, kbd);
+	char kbd[LOC_NAME_MAXLEN + 1];
+	snprintf(kbd, LOC_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
+	
+	service_id_t service_id;
+	if (loc_service_register(kbd, &service_id) != EOK) {
+		printf("%s: Unable to register service %s\n", NAME, kbd);
 		return -1;
 	}
Index: uspace/srv/hid/input/include/kbd.h
===================================================================
--- uspace/srv/hid/input/include/kbd.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/input/include/kbd.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -40,4 +40,5 @@
 
 #include <adt/list.h>
+#include <ipc/loc.h>
 
 struct kbd_port_ops;
@@ -49,6 +50,9 @@
 	link_t kbd_devs;
 
-	/** Path to the device (only for kbdev devices) */
-	const char *dev_path;
+	/** Service ID (only for kbdev devices) */
+	service_id_t svc_id;
+
+	/** Device service name (only for kbdev devices) */
+	char *svc_name;
 
 	/** Port ops */
Index: uspace/srv/hid/input/include/mouse.h
===================================================================
--- uspace/srv/hid/input/include/mouse.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/input/include/mouse.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,4 +39,5 @@
 
 #include <adt/list.h>
+#include <ipc/loc.h>
 
 struct mouse_port_ops;
@@ -47,6 +48,9 @@
 	link_t mouse_devs;
 	
-	/** Path to the device (only for mouseev devices) */
-	const char *dev_path;
+	/** Service ID (only for mousedev devices) */
+	service_id_t svc_id;
+	
+	/** Device service name (only for mousedev devices) */
+	char *svc_name;
 	
 	/** Port ops */
Index: uspace/srv/hid/input/port/adb.c
===================================================================
--- uspace/srv/hid/input/port/adb.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/input/port/adb.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -43,5 +43,5 @@
 #include <fcntl.h>
 #include <errno.h>
-#include <devmap.h>
+#include <loc.h>
 
 static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg);
@@ -66,5 +66,5 @@
 {
 	const char *dev = "adb/kbd";
-	devmap_handle_t handle;
+	service_id_t service_id;
 	async_exch_t *exch;
 	int rc;
@@ -72,9 +72,9 @@
 	kbd_dev = kdev;
 	
-	rc = devmap_device_get_handle(dev, &handle, 0);
+	rc = loc_service_get_id(dev, &service_id, 0);
 	if (rc != EOK)
 		return rc;
 	
-	dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0);
+	dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 0);
 	if (dev_sess == NULL) {
 		printf("%s: Failed to connect to device\n", NAME);
Index: uspace/srv/hid/input/port/adb_mouse.c
===================================================================
--- uspace/srv/hid/input/port/adb_mouse.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/input/port/adb_mouse.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -41,5 +41,6 @@
 #include <mouse.h>
 #include <errno.h>
-#include <devmap.h>
+#include <loc.h>
+#include <stdio.h>
 
 static mouse_dev_t *mouse_dev;
@@ -78,10 +79,10 @@
 	mouse_dev = mdev;
 	
-	devmap_handle_t handle;
-	int rc = devmap_device_get_handle(dev, &handle, 0);
+	service_id_t service_id;
+	int rc = loc_service_get_id(dev, &service_id, 0);
 	if (rc != EOK)
 		return rc;
 	
-	dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0);
+	dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 0);
 	if (dev_sess == NULL) {
 		printf("%s: Failed to connect to device\n", NAME);
Index: uspace/srv/hid/input/port/chardev.c
===================================================================
--- uspace/srv/hid/input/port/chardev.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/input/port/chardev.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -40,5 +40,5 @@
 #include <kbd_port.h>
 #include <kbd.h>
-#include <devmap.h>
+#include <loc.h>
 #include <errno.h>
 #include <stdio.h>
@@ -71,5 +71,5 @@
 static int chardev_port_init(kbd_dev_t *kdev)
 {
-	devmap_handle_t handle;
+	service_id_t service_id;
 	async_exch_t *exch;
 	unsigned int i;
@@ -79,5 +79,5 @@
 	
 	for (i = 0; i < num_devs; i++) {
-		rc = devmap_device_get_handle(in_devs[i], &handle, 0);
+		rc = loc_service_get_id(in_devs[i], &service_id, 0);
 		if (rc == EOK)
 			break;
@@ -89,5 +89,5 @@
 	}
 	
-	dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle,
+	dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id,
 	    IPC_FLAG_BLOCKING);
 	if (dev_sess == NULL) {
Index: uspace/srv/hid/input/port/chardev_mouse.c
===================================================================
--- uspace/srv/hid/input/port/chardev_mouse.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/input/port/chardev_mouse.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,5 @@
 #include <async.h>
 #include <errno.h>
-#include <devmap.h>
+#include <loc.h>
 #include <input.h>
 #include <mouse_port.h>
@@ -82,5 +82,5 @@
 static int chardev_port_init(mouse_dev_t *mdev)
 {
-	devmap_handle_t handle;
+	service_id_t service_id;
 	unsigned int i;
 	int rc;
@@ -89,5 +89,5 @@
 	
 	for (i = 0; i < num_devs; i++) {
-		rc = devmap_device_get_handle(in_devs[i], &handle, 0);
+		rc = loc_service_get_id(in_devs[i], &service_id, 0);
 		if (rc == EOK)
 			break;
@@ -99,5 +99,5 @@
 	}
 	
-	dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle,
+	dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id,
 	    IPC_FLAG_BLOCKING);
 	if (dev_sess == NULL) {
Index: uspace/srv/hid/input/proto/mousedev.c
===================================================================
--- uspace/srv/hid/input/proto/mousedev.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/input/proto/mousedev.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -44,7 +44,9 @@
 #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>
 
 /** Mousedev softstate */
@@ -55,7 +57,4 @@
 	/** Session to mouse device */
 	async_sess_t *sess;
-	
-	/** File descriptor of open mousedev device */
-	int fd;
 } mousedev_t;
 
@@ -67,5 +66,4 @@
 	
 	mousedev->mouse_dev = mdev;
-	mousedev->fd = -1;
 	
 	return mousedev;
@@ -76,7 +74,4 @@
 	if (mousedev->sess != NULL)
 		async_hangup(mousedev->sess);
-	
-	if (mousedev->fd >= 0)
-		close(mousedev->fd);
 	
 	free(mousedev);
@@ -122,14 +117,9 @@
 static int mousedev_proto_init(mouse_dev_t *mdev)
 {
-	const char *pathname = mdev->dev_path;
-	
-	int fd = open(pathname, O_RDWR);
-	if (fd < 0)
-		return -1;
-	
-	async_sess_t *sess = fd_session(EXCHANGE_SERIALIZE, fd);
+	async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE,
+	    mdev->svc_id, 0);
 	if (sess == NULL) {
-		printf("%s: Failed starting session with '%s'\n", NAME, pathname);
-		close(fd);
+		printf("%s: Failed starting session with '%s'\n", NAME,
+		    mdev->svc_name);
 		return -1;
 	}
@@ -138,14 +128,14 @@
 	if (mousedev == NULL) {
 		printf("%s: Failed allocating device structure for '%s'.\n",
-		    NAME, pathname);
+		    NAME, mdev->svc_name);
 		return -1;
 	}
 	
-	mousedev->fd = fd;
 	mousedev->sess = sess;
 	
 	async_exch_t *exch = async_exchange_begin(sess);
 	if (exch == NULL) {
-		printf("%s: Failed starting exchange with '%s'.\n", NAME, pathname);
+		printf("%s: Failed starting exchange with '%s'.\n", NAME,
+		    mdev->svc_name);
 		mousedev_destroy(mousedev);
 		return -1;
@@ -157,5 +147,5 @@
 	if (rc != EOK) {
 		printf("%s: Failed creating callback connection from '%s'.\n",
-		    NAME, pathname);
+		    NAME, mdev->svc_name);
 		mousedev_destroy(mousedev);
 		return -1;
Index: uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c
===================================================================
--- uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,5 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
-#include <devmap.h>
+#include <loc.h>
 #include <io/console.h>
 #include <vfs/vfs.h>
@@ -54,5 +54,5 @@
 
 // FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 
 #define NAME "s3c24ser"
@@ -90,5 +90,5 @@
 	printf(NAME ": S3C24xx touchscreen driver\n");
 
-	rc = devmap_driver_register(NAME, s3c24xx_ts_connection);
+	rc = loc_server_register(NAME, s3c24xx_ts_connection);
 	if (rc < 0) {
 		printf(NAME ": Unable to register driver.\n");
@@ -103,5 +103,5 @@
 		return -1;
 
-	rc = devmap_device_register(NAMESPACE "/mouse", &ts->devmap_handle);
+	rc = loc_service_register(NAMESPACE "/mouse", &ts->service_id);
 	if (rc != EOK) {
 		printf(NAME ": Unable to register device %s.\n",
Index: uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.h
===================================================================
--- uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -124,6 +124,6 @@
 	int client_phone;
 
-	/** Device handle */
-	devmap_handle_t devmap_handle;
+	/** Service ID */
+	service_id_t service_id;
 
 	/** Device/driver state */
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.c
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -43,5 +43,5 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sysinfo.h>
 #include <errno.h>
@@ -53,5 +53,5 @@
 
 // FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 
 #define NAME "cuda_adb"
@@ -147,5 +147,5 @@
 int main(int argc, char *argv[])
 {
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 	int rc;
 	int i;
@@ -155,29 +155,29 @@
 	for (i = 0; i < ADB_MAX_ADDR; ++i) {
 		adb_dev[i].client_phone = -1;
-		adb_dev[i].devmap_handle = 0;
-	}
-
-	rc = devmap_driver_register(NAME, cuda_connection);
+		adb_dev[i].service_id = 0;
+	}
+
+	rc = loc_server_register(NAME, cuda_connection);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver.\n");
+		printf(NAME ": Unable to register server.\n");
 		return rc;
 	}
 
-	rc = devmap_device_register("adb/kbd", &devmap_handle);
+	rc = loc_service_register("adb/kbd", &service_id);
 	if (rc != EOK) {
-		printf(NAME ": Unable to register device %s.\n", "adb/kdb");
+		printf(NAME ": Unable to register service %s.\n", "adb/kdb");
 		return rc;
 	}
 
-	adb_dev[2].devmap_handle = devmap_handle;
-	adb_dev[8].devmap_handle = devmap_handle;
-
-	rc = devmap_device_register("adb/mouse", &devmap_handle);
+	adb_dev[2].service_id = service_id;
+	adb_dev[8].service_id = service_id;
+
+	rc = loc_service_register("adb/mouse", &service_id);
 	if (rc != EOK) {
-		printf(NAME ": Unable to register device %s.\n", "adb/mouse");
+		printf(NAME ": Unable to register servise %s.\n", "adb/mouse");
 		return rc;
 	}
 
-	adb_dev[9].devmap_handle = devmap_handle;
+	adb_dev[9].service_id = service_id;
 
 	if (cuda_init() < 0) {
@@ -198,15 +198,15 @@
 	ipc_call_t call;
 	sysarg_t method;
-	devmap_handle_t dh;
+	service_id_t dsid;
 	int retval;
 	int dev_addr, i;
 
 	/* Get the device handle. */
-	dh = IPC_GET_ARG1(*icall);
+	dsid = IPC_GET_ARG1(*icall);
 
 	/* Determine which disk device is the client connecting to. */
 	dev_addr = -1;
 	for (i = 0; i < ADB_MAX_ADDR; i++) {
-		if (adb_dev[i].devmap_handle == dh)
+		if (adb_dev[i].service_id == dsid)
 			dev_addr = i;
 	}
@@ -242,5 +242,5 @@
 			 */
 			for (i = 0; i < ADB_MAX_ADDR; ++i) {
-				if (adb_dev[i].devmap_handle == dh) {
+				if (adb_dev[i].service_id == dsid) {
 					adb_dev[i].client_phone = IPC_GET_ARG5(call);
 				}
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.h
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,5 +38,5 @@
 
 #include <sys/types.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 #include <fibril_synch.h>
 
@@ -104,5 +104,5 @@
 
 typedef struct {
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 	int client_phone;
 } adb_dev_t;
Index: uspace/srv/hw/char/i8042/i8042.c
===================================================================
--- uspace/srv/hw/char/i8042/i8042.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hw/char/i8042/i8042.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,5 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
-#include <devmap.h>
+#include <loc.h>
 #include <async.h>
 #include <async_obsolete.h>
@@ -50,5 +50,5 @@
 
 // FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 
 #define NAME "i8042"
@@ -135,7 +135,7 @@
 	printf(NAME ": i8042 PS/2 port driver\n");
 
-	rc = devmap_driver_register(NAME, i8042_connection);
+	rc = loc_server_register(NAME, i8042_connection);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver.\n");
+		printf(NAME ": Unable to register server.\n");
 		return rc;
 	}
@@ -148,5 +148,5 @@
 
 		snprintf(name, 16, "%s/ps2%c", NAMESPACE, dchar[i]);
-		rc = devmap_device_register(name, &i8042_port[i].devmap_handle);
+		rc = loc_service_register(name, &i8042_port[i].service_id);
 		if (rc != EOK) {
 			printf(NAME ": Unable to register device %s.\n", name);
@@ -221,5 +221,5 @@
 	ipc_call_t call;
 	sysarg_t method;
-	devmap_handle_t dh;
+	service_id_t dsid;
 	int retval;
 	int dev_id, i;
@@ -228,10 +228,10 @@
 
 	/* Get the device handle. */
-	dh = IPC_GET_ARG1(*icall);
+	dsid = IPC_GET_ARG1(*icall);
 
 	/* Determine which disk device is the client connecting to. */
 	dev_id = -1;
 	for (i = 0; i < MAX_DEVS; i++) {
-		if (i8042_port[i].devmap_handle == dh)
+		if (i8042_port[i].service_id == dsid)
 			dev_id = i;
 	}
Index: uspace/srv/hw/char/i8042/i8042.h
===================================================================
--- uspace/srv/hw/char/i8042/i8042.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hw/char/i8042/i8042.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -52,5 +52,5 @@
 /** Softstate structure, one for each serial port (primary and aux). */
 typedef struct {
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 	int client_phone;
 } i8042_port_t;
Index: uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c
===================================================================
--- uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,5 +39,5 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
-#include <devmap.h>
+#include <loc.h>
 #include <ipc/char.h>
 #include <async.h>
@@ -52,5 +52,5 @@
 
 // FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
+#include <abi/ipc/methods.h>
 
 #define NAME "s3c24ser"
@@ -83,7 +83,7 @@
 	printf(NAME ": S3C24xx on-chip UART driver\n");
 
-	rc = devmap_driver_register(NAME, s3c24xx_uart_connection);
+	rc = loc_server_register(NAME, s3c24xx_uart_connection);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver.\n");
+		printf(NAME ": Unable to register server.\n");
 		return -1;
 	}
@@ -96,5 +96,5 @@
 		return -1;
 
-	rc = devmap_device_register(NAMESPACE "/" NAME, &uart->devmap_handle);
+	rc = loc_service_register(NAMESPACE "/" NAME, &uart->service_id);
 	if (rc != EOK) {
 		printf(NAME ": Unable to register device %s.\n",
Index: uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.h
===================================================================
--- uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -87,6 +87,6 @@
 	int client_phone;
 
-	/** Device handle */
-	devmap_handle_t devmap_handle;
+	/** Service ID */
+	service_id_t service_id;
 } s3c24xx_uart_t;
 
Index: uspace/srv/hw/irc/apic/apic.c
===================================================================
--- uspace/srv/hw/irc/apic/apic.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hw/irc/apic/apic.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -42,20 +42,114 @@
 #include <as.h>
 #include <ddi.h>
-#include <libarch/ddi.h>
-#include <align.h>
 #include <bool.h>
 #include <errno.h>
 #include <async.h>
-#include <align.h>
-#include <async.h>
 #include <stdio.h>
-#include <ipc/devmap.h>
 
 #define NAME  "apic"
 
+#define APIC_MAX_IRQ	15
+
+#define IOREGSEL  (0x00U / sizeof(uint32_t))
+#define IOWIN     (0x10U / sizeof(uint32_t))
+
+#define IOREDTBL   0x10U
+
+/** I/O Register Select Register. */
+typedef union {
+	uint32_t value;
+	struct {
+		uint8_t reg_addr;	/**< APIC Register Address. */
+		unsigned int : 24;	/**< Reserved. */
+	} __attribute__ ((packed));
+} io_regsel_t;
+
+/** I/O Redirection Register. */
+typedef struct io_redirection_reg {
+	union {
+		uint32_t lo;
+		struct {
+			uint8_t intvec;			/**< Interrupt Vector. */
+			unsigned int delmod : 3;	/**< Delivery Mode. */
+			unsigned int destmod : 1;	/**< Destination mode. */
+			unsigned int delivs : 1;	/**< Delivery status (RO). */
+			unsigned int intpol : 1;	/**< Interrupt Input Pin Polarity. */
+			unsigned int irr : 1;		/**< Remote IRR (RO). */
+			unsigned int trigger_mode : 1;	/**< Trigger Mode. */
+			unsigned int masked : 1;	/**< Interrupt Mask. */
+			unsigned int : 15;		/**< Reserved. */
+		} __attribute__ ((packed));
+	};
+	union {
+		uint32_t hi;
+		struct {
+			unsigned int : 24;	/**< Reserved. */
+			uint8_t dest : 8;  	/**< Destination Field. */
+		} __attribute__ ((packed));
+	};
+} __attribute__ ((packed)) io_redirection_reg_t;
+
+// FIXME: get the address from the kernel
+#define IO_APIC_BASE	0xfec00000UL
+#define IO_APIC_SIZE	20
+
+ioport32_t *io_apic = NULL;
+
+/** Read from IO APIC register.
+ *
+ * @param address IO APIC register address.
+ *
+ * @return Content of the addressed IO APIC register.
+ *
+ */
+static uint32_t io_apic_read(uint8_t address)
+{
+	io_regsel_t regsel;
+
+	regsel.value = io_apic[IOREGSEL];
+	regsel.reg_addr = address;
+	io_apic[IOREGSEL] = regsel.value;
+	return io_apic[IOWIN];
+}
+
+/** Write to IO APIC register.
+ *
+ * @param address IO APIC register address.
+ * @param val     Content to be written to the addressed IO APIC register.
+ *
+ */
+static void io_apic_write(uint8_t address, uint32_t val)
+{
+	io_regsel_t regsel;
+
+	regsel.value = io_apic[IOREGSEL];
+	regsel.reg_addr = address;
+	io_apic[IOREGSEL] = regsel.value;
+	io_apic[IOWIN] = val;
+}
+
+static int irq_to_pin(int irq)
+{
+	// FIXME: get the map from the kernel, even though this may work
+	//	  for simple cases
+	return irq;
+}
+
 static int apic_enable_irq(sysarg_t irq)
 {
-	// FIXME: TODO
-	return ENOTSUP;
+	io_redirection_reg_t reg;
+
+	if (irq > APIC_MAX_IRQ)
+		return ELIMIT;
+
+	int pin = irq_to_pin(irq);
+ 	if (pin == -1)
+		return ENOENT;
+
+	reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
+	reg.masked = false;
+	io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo);
+
+	return EOK;
 }
 
@@ -111,4 +205,8 @@
 		return false;
 	}
+
+	if (pio_enable((void *) IO_APIC_BASE, IO_APIC_SIZE,
+	    (void **) &io_apic) != EOK)
+		return false;	
 	
 	async_set_client_connection(apic_connection);
Index: uspace/srv/hw/irc/i8259/i8259.c
===================================================================
--- uspace/srv/hw/irc/i8259/i8259.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hw/irc/i8259/i8259.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -50,5 +50,5 @@
 #include <async.h>
 #include <stdio.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 
 #define NAME  "i8259"
Index: uspace/srv/hw/irc/obio/obio.c
===================================================================
--- uspace/srv/hw/irc/obio/obio.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/hw/irc/obio/obio.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -55,5 +55,5 @@
 #include <async.h>
 #include <stdio.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 
 #define NAME "obio"
Index: uspace/srv/loader/Makefile
===================================================================
--- uspace/srv/loader/Makefile	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/loader/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -39,6 +39,4 @@
 LINKER_SCRIPT = $(LIBC_PREFIX)/arch/$(UARCH)/_link-loader.ld
 
-EXTRA_CFLAGS = -Iinclude
-
 BINARY = loader
 STATIC_ONLY = y
@@ -46,5 +44,4 @@
 GENERIC_SOURCES = \
 	main.c \
-	elf_load.c \
 	interp.s
 
Index: pace/srv/loader/elf_load.c
===================================================================
--- uspace/srv/loader/elf_load.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,482 +1,0 @@
-/*
- * Copyright (c) 2006 Sergey Bondari
- * Copyright (c) 2006 Jakub Jermar
- * 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 generic	
- * @{
- */
-
-/**
- * @file
- * @brief	Userspace ELF loader.
- *
- * This module allows loading ELF binaries (both executables and
- * shared objects) from VFS. The current implementation allocates
- * anonymous memory, fills it with segment data and then adjusts
- * the memory areas' flags to the final value. In the future,
- * the segments will be mapped directly from the file.
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <align.h>
-#include <assert.h>
-#include <as.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <smc.h>
-#include <loader/pcb.h>
-#include <entry_point.h>
-
-#include "elf.h"
-#include "elf_load.h"
-
-#define DPRINTF(...)
-
-static const char *error_codes[] = {
-	"no error",
-	"invalid image",
-	"address space error",
-	"incompatible image",
-	"unsupported image type",
-	"irrecoverable error"
-};
-
-static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
-static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
-static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
-static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
-
-/** Read until the buffer is read in its entirety. */
-static int my_read(int fd, void *buf, size_t len)
-{
-	int cnt = 0;
-	do {
-		buf += cnt;
-		len -= cnt;
-		cnt = read(fd, buf, len);
-	} while ((cnt > 0) && ((len - cnt) > 0));
-
-	return cnt;
-}
-
-/** Load ELF binary from a file.
- *
- * Load an ELF binary from the specified file. If the file is
- * an executable program, it is loaded unbiased. If it is a shared
- * object, it is loaded with the bias @a so_bias. Some information
- * extracted from the binary is stored in a elf_info_t structure
- * pointed to by @a info.
- *
- * @param file_name Path to the ELF file.
- * @param so_bias   Bias to use if the file is a shared object.
- * @param info      Pointer to a structure for storing information
- *                  extracted from the binary.
- *
- * @return EOK on success or negative error code.
- *
- */
-int elf_load_file(const char *file_name, size_t so_bias, eld_flags_t flags,
-    elf_info_t *info)
-{
-	elf_ld_t elf;
-
-	int fd;
-	int rc;
-	
-	fd = open(file_name, O_RDONLY);
-	if (fd < 0) {
-		DPRINTF("failed opening file\n");
-		return -1;
-	}
-
-	elf.fd = fd;
-	elf.info = info;
-	elf.flags = flags;
-
-	rc = elf_load(&elf, so_bias);
-
-	close(fd);
-
-	return rc;
-}
-
-/** Create the program control block (PCB).
- *
- * Fills the program control block @a pcb with information from
- * @a info.
- *
- * @param info	Program info structure
- * @return EOK on success or negative error code
- */
-void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
-{
-	pcb->entry = info->entry;
-	pcb->dynamic = info->dynamic;
-	pcb->rtld_runtime = NULL;
-}
-
-
-/** Load an ELF binary.
- *
- * The @a elf structure contains the loader state, including
- * an open file, from which the binary will be loaded,
- * a pointer to the @c info structure etc.
- *
- * @param elf		Pointer to loader state buffer.
- * @param so_bias	Bias to use if the file is a shared object.
- * @return EE_OK on success or EE_xx error code.
- */
-static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
-{
-	elf_header_t header_buf;
-	elf_header_t *header = &header_buf;
-	int i, rc;
-
-	rc = my_read(elf->fd, header, sizeof(elf_header_t));
-	if (rc < 0) {
-		DPRINTF("Read error.\n"); 
-		return EE_INVALID;
-	}
-
-	elf->header = header;
-
-	/* Identify ELF */
-	if (header->e_ident[EI_MAG0] != ELFMAG0 ||
-	    header->e_ident[EI_MAG1] != ELFMAG1 || 
-	    header->e_ident[EI_MAG2] != ELFMAG2 ||
-	    header->e_ident[EI_MAG3] != ELFMAG3) {
-		DPRINTF("Invalid header.\n");
-		return EE_INVALID;
-	}
-	
-	/* Identify ELF compatibility */
-	if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
-	    header->e_machine != ELF_MACHINE || 
-	    header->e_ident[EI_VERSION] != EV_CURRENT ||
-	    header->e_version != EV_CURRENT ||
-	    header->e_ident[EI_CLASS] != ELF_CLASS) {
-		DPRINTF("Incompatible data/version/class.\n");
-		return EE_INCOMPATIBLE;
-	}
-
-	if (header->e_phentsize != sizeof(elf_segment_header_t)) {
-		DPRINTF("e_phentsize:%d != %d\n", header->e_phentsize,
-		    sizeof(elf_segment_header_t));
-		return EE_INCOMPATIBLE;
-	}
-
-	if (header->e_shentsize != sizeof(elf_section_header_t)) {
-		DPRINTF("e_shentsize:%d != %d\n", header->e_shentsize,
-		    sizeof(elf_section_header_t));
-		return EE_INCOMPATIBLE;
-	}
-
-	/* Check if the object type is supported. */
-	if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
-		DPRINTF("Object type %d is not supported\n", header->e_type);
-		return EE_UNSUPPORTED;
-	}
-
-	/* Shared objects can be loaded with a bias */
-	if (header->e_type == ET_DYN)
-		elf->bias = so_bias;
-	else
-		elf->bias = 0;
-
-	elf->info->interp = NULL;
-	elf->info->dynamic = NULL;
-
-	/* Walk through all segment headers and process them. */
-	for (i = 0; i < header->e_phnum; i++) {
-		elf_segment_header_t segment_hdr;
-
-		/* Seek to start of segment header */
-		lseek(elf->fd, header->e_phoff
-		        + i * sizeof(elf_segment_header_t), SEEK_SET);
-
-		rc = my_read(elf->fd, &segment_hdr,
-		    sizeof(elf_segment_header_t));
-		if (rc < 0) {
-			DPRINTF("Read error.\n");
-			return EE_INVALID;
-		}
-
-		rc = segment_header(elf, &segment_hdr);
-		if (rc != EE_OK)
-			return rc;
-	}
-
-	DPRINTF("Parse sections.\n");
-
-	/* Inspect all section headers and proccess them. */
-	for (i = 0; i < header->e_shnum; i++) {
-		elf_section_header_t section_hdr;
-
-		/* Seek to start of section header */
-		lseek(elf->fd, header->e_shoff
-		    + i * sizeof(elf_section_header_t), SEEK_SET);
-
-		rc = my_read(elf->fd, &section_hdr,
-		    sizeof(elf_section_header_t));
-		if (rc < 0) {
-			DPRINTF("Read error.\n");
-			return EE_INVALID;
-		}
-
-		rc = section_header(elf, &section_hdr);
-		if (rc != EE_OK)
-			return rc;
-	}
-
-	elf->info->entry =
-	    (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
-
-	DPRINTF("Done.\n");
-
-	return EE_OK;
-}
-
-/** Print error message according to error code.
- *
- * @param rc Return code returned by elf_load().
- *
- * @return NULL terminated description of error.
- */
-const char *elf_error(unsigned int rc)
-{
-	assert(rc < sizeof(error_codes) / sizeof(char *));
-
-	return error_codes[rc];
-}
-
-/** Process segment header.
- *
- * @param entry	Segment header.
- *
- * @return EE_OK on success, error code otherwise.
- */
-static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
-{
-	switch (entry->p_type) {
-	case PT_NULL:
-	case PT_PHDR:
-	case PT_NOTE:
-		break;
-	case PT_LOAD:
-		return load_segment(elf, entry);
-		break;
-	case PT_INTERP:
-		/* Assume silently interp == "/app/dload" */
-		elf->info->interp = "/app/dload";
-		break;
-	case PT_DYNAMIC:
-		/* Record pointer to dynamic section into info structure */
-		elf->info->dynamic =
-		    (void *)((uint8_t *)entry->p_vaddr + elf->bias);
-		DPRINTF("dynamic section found at 0x%x\n",
-			(uintptr_t)elf->info->dynamic);
-		break;
-	case 0x70000000:
-		/* FIXME: MIPS reginfo */
-		break;
-	case PT_SHLIB:
-//	case PT_LOPROC:
-//	case PT_HIPROC:
-	default:
-		DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
-		return EE_UNSUPPORTED;
-		break;
-	}
-	return EE_OK;
-}
-
-/** Load segment described by program header entry.
- *
- * @param elf	Loader state.
- * @param entry Program header entry describing segment to be loaded.
- *
- * @return EE_OK on success, error code otherwise.
- */
-int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
-{
-	void *a;
-	int flags = 0;
-	uintptr_t bias;
-	uintptr_t base;
-	void *seg_ptr;
-	uintptr_t seg_addr;
-	size_t mem_sz;
-	int rc;
-
-	bias = elf->bias;
-
-	seg_addr = entry->p_vaddr + bias;
-	seg_ptr = (void *) seg_addr;
-
-	DPRINTF("Load segment at addr %p, size 0x%x\n", (void *) seg_addr,
-		entry->p_memsz);
-
-	if (entry->p_align > 1) {
-		if ((entry->p_offset % entry->p_align) !=
-		    (seg_addr % entry->p_align)) {
-			DPRINTF("Align check 1 failed offset%%align=%d, "
-			    "vaddr%%align=%d\n",
-			    entry->p_offset % entry->p_align,
-			    seg_addr % entry->p_align
-			);
-			return EE_INVALID;
-		}
-	}
-
-	/* Final flags that will be set for the memory area */
-
-	if (entry->p_flags & PF_X)
-		flags |= AS_AREA_EXEC;
-	if (entry->p_flags & PF_W)
-		flags |= AS_AREA_WRITE;
-	if (entry->p_flags & PF_R)
-		flags |= AS_AREA_READ;
-	flags |= AS_AREA_CACHEABLE;
-	
-	base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
-	mem_sz = entry->p_memsz + (entry->p_vaddr - base);
-
-	DPRINTF("Map to seg_addr=%p-%p.\n", (void *) seg_addr,
-	    (void *) (entry->p_vaddr + bias +
-	    ALIGN_UP(entry->p_memsz, PAGE_SIZE)));
-
-	/*
-	 * For the course of loading, the area needs to be readable
-	 * and writeable.
-	 */
-	a = as_area_create((uint8_t *)base + bias, mem_sz,
-	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
-	if (a == (void *)(-1)) {
-		DPRINTF("memory mapping failed (0x%x, %d)\n",
-			base+bias, mem_sz);
-		return EE_MEMORY;
-	}
-
-	DPRINTF("as_area_create(%p, %#zx, %d) -> %p\n",
-	    (void *) (base + bias), mem_sz, flags, (void *) a);
-
-	/*
-	 * Load segment data
-	 */
-	rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
-	if (rc < 0) {
-		printf("seek error\n");
-		return EE_INVALID;
-	}
-
-/*	rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
-	if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
-
-	/* Long reads are not possible yet. Load segment piecewise. */
-
-	unsigned left, now;
-	uint8_t *dp;
-
-	left = entry->p_filesz;
-	dp = seg_ptr;
-
-	while (left > 0) {
-		now = 16384;
-		if (now > left) now = left;
-
-		rc = my_read(elf->fd, dp, now);
-
-		if (rc < 0) { 
-			DPRINTF("Read error.\n");
-			return EE_INVALID;
-		}
-
-		left -= now;
-		dp += now;
-	}
-
-	/*
-	 * The caller wants to modify the segments first. He will then
-	 * need to set the right access mode and ensure SMC coherence.
-	 */
-	if ((elf->flags & ELDF_RW) != 0) return EE_OK;
-
-//	printf("set area flags to %d\n", flags);
-	rc = as_area_change_flags(seg_ptr, flags);
-	if (rc != 0) {
-		DPRINTF("Failed to set memory area flags.\n");
-		return EE_MEMORY;
-	}
-
-	if (flags & AS_AREA_EXEC) {
-		/* Enforce SMC coherence for the segment */
-		if (smc_coherence(seg_ptr, entry->p_filesz))
-			return EE_MEMORY;
-	}
-
-	return EE_OK;
-}
-
-/** Process section header.
- *
- * @param elf	Loader state.
- * @param entry Segment header.
- *
- * @return EE_OK on success, error code otherwise.
- */
-static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
-{
-	switch (entry->sh_type) {
-	case SHT_PROGBITS:
-		if (entry->sh_flags & SHF_TLS) {
-			/* .tdata */
-		}
-		break;
-	case SHT_NOBITS:
-		if (entry->sh_flags & SHF_TLS) {
-			/* .tbss */
-		}
-		break;
-	case SHT_DYNAMIC:
-		/* Record pointer to dynamic section into info structure */
-		elf->info->dynamic =
-		    (void *)((uint8_t *)entry->sh_addr + elf->bias);
-		DPRINTF("Dynamic section found at %p.\n",
-		    (void *) elf->info->dynamic);
-		break;
-	default:
-		break;
-	}
-	
-	return EE_OK;
-}
-
-/** @}
- */
Index: pace/srv/loader/include/elf.h
===================================================================
--- uspace/srv/loader/include/elf.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,344 +1,0 @@
-/*
- * Copyright (c) 2006 Sergey Bondari
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING 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 ELF_H_
-#define ELF_H_
-
-#include <arch/elf.h>
-#include <sys/types.h>
-
-/**
- * current ELF version
- */
-#define	EV_CURRENT	1
-
-/** 
- * ELF types 
- */
-#define ET_NONE		0	/* No type */
-#define ET_REL		1	/* Relocatable file */
-#define ET_EXEC		2	/* Executable */
-#define ET_DYN		3	/* Shared object */
-#define ET_CORE		4	/* Core */
-#define ET_LOPROC	0xff00	/* Processor specific */
-#define ET_HIPROC	0xffff	/* Processor specific */
-
-/** 
- * ELF machine types
- */
-#define EM_NO		0	/* No machine */
-#define EM_SPARC	2	/* SPARC */
-#define EM_386		3	/* i386 */
-#define EM_MIPS		8	/* MIPS RS3000 */
-#define EM_MIPS_RS3_LE	10	/* MIPS RS3000 LE */
-#define EM_PPC		20	/* PPC32 */
-#define EM_PPC64	21	/* PPC64 */
-#define EM_ARM		40	/* ARM */
-#define EM_SPARCV9	43	/* SPARC64 */
-#define EM_IA_64	50	/* IA-64 */
-#define EM_X86_64	62	/* AMD64/EMT64 */
-
-/**
- * ELF identification indexes
- */
-#define EI_MAG0		0
-#define EI_MAG1		1
-#define EI_MAG2		2
-#define EI_MAG3		3
-#define EI_CLASS	4		/* File class */
-#define EI_DATA		5		/* Data encoding */
-#define EI_VERSION	6		/* File version */
-#define EI_OSABI	7
-#define EI_ABIVERSION	8
-#define EI_PAD		9		/* Start of padding bytes */
-#define EI_NIDENT	16		/* ELF identification table size */
-
-/**
- * ELF magic number
- */
-#define ELFMAG0		0x7f
-#define ELFMAG1		'E'
-#define ELFMAG2		'L'
-#define ELFMAG3		'F'
-
-/**
- * ELF file classes
- */
-#define ELFCLASSNONE	0
-#define ELFCLASS32	1
-#define ELFCLASS64	2
-
-/**
- * ELF data encoding types
- */
-#define ELFDATANONE	0
-#define ELFDATA2LSB	1		/* Least significant byte first (little endian) */
-#define ELFDATA2MSB	2		/* Most signigicant byte first (big endian) */
-
-/**
- * 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_IRRECOVERABLE	5
-
-/**
- * ELF section types
- */
-#define SHT_NULL		0
-#define SHT_PROGBITS		1
-#define SHT_SYMTAB		2
-#define SHT_STRTAB		3
-#define SHT_RELA		4
-#define SHT_HASH		5
-#define SHT_DYNAMIC		6
-#define SHT_NOTE		7
-#define SHT_NOBITS		8
-#define SHT_REL			9
-#define SHT_SHLIB		10
-#define SHT_DYNSYM		11
-#define SHT_LOOS		0x60000000
-#define SHT_HIOS		0x6fffffff
-#define SHT_LOPROC		0x70000000
-#define SHT_HIPROC		0x7fffffff
-#define SHT_LOUSER		0x80000000
-#define SHT_HIUSER		0xffffffff
-
-/**
- * ELF section flags
- */
-#define SHF_WRITE		0x1 
-#define SHF_ALLOC		0x2
-#define SHF_EXECINSTR		0x4
-#define SHF_TLS			0x400
-#define SHF_MASKPROC		0xf0000000
-
-/**
- * Symbol binding
- */
-#define STB_LOCAL		0
-#define STB_GLOBAL		1
-#define STB_WEAK		2
-#define STB_LOPROC		13
-#define STB_HIPROC		15
-
-/**
- * Symbol types
- */
-#define STT_NOTYPE		0
-#define STT_OBJECT		1
-#define STT_FUNC		2
-#define STT_SECTION		3
-#define STT_FILE		4
-#define STT_LOPROC		13
-#define STT_HIPROC		15
-
-/**
- * Program segment types
- */
-#define PT_NULL			0
-#define PT_LOAD			1
-#define PT_DYNAMIC		2
-#define PT_INTERP		3
-#define PT_NOTE			4
-#define PT_SHLIB		5
-#define PT_PHDR			6
-#define PT_LOPROC		0x70000000
-#define PT_HIPROC		0x7fffffff
-
-/**
- * Program segment attributes.
- */
-#define PF_X	1
-#define PF_W	2
-#define PF_R	4
-
-/**
- * ELF data types
- *
- * These types are found to be identical in both 32-bit and 64-bit
- * ELF object file specifications. They are the only types used
- * in ELF header.
- */
-typedef uint64_t elf_xword;
-typedef int64_t elf_sxword;
-typedef uint32_t elf_word;
-typedef int32_t elf_sword;
-typedef uint16_t elf_half;
-
-/**
- * 32-bit ELF data types.
- *
- * These types are specific for 32-bit format.
- */
-typedef uint32_t elf32_addr;
-typedef uint32_t elf32_off;
-
-/**
- * 64-bit ELF data types.
- *
- * These types are specific for 64-bit format.
- */
-typedef uint64_t elf64_addr;
-typedef uint64_t elf64_off;
-
-/** ELF header */
-struct elf32_header {
-	uint8_t e_ident[EI_NIDENT];
-	elf_half e_type;
-	elf_half e_machine;
-	elf_word e_version;
-	elf32_addr e_entry;
-	elf32_off e_phoff;
-	elf32_off e_shoff;
-	elf_word e_flags;
-	elf_half e_ehsize;
-	elf_half e_phentsize;
-	elf_half e_phnum;
-	elf_half e_shentsize;
-	elf_half e_shnum;
-	elf_half e_shstrndx;
-};
-struct elf64_header {
-	uint8_t e_ident[EI_NIDENT];
-	elf_half e_type;
-	elf_half e_machine;
-	elf_word e_version;
-	elf64_addr e_entry;
-	elf64_off e_phoff;
-	elf64_off e_shoff;
-	elf_word e_flags;
-	elf_half e_ehsize;
-	elf_half e_phentsize;
-	elf_half e_phnum;
-	elf_half e_shentsize;
-	elf_half e_shnum;
-	elf_half e_shstrndx;
-};
-
-/*
- * ELF segment header.
- * Segments headers are also known as program headers.
- */
-struct elf32_segment_header {
-	elf_word p_type;
-	elf32_off p_offset;
-	elf32_addr p_vaddr;
-	elf32_addr p_paddr;
-	elf_word p_filesz;
-	elf_word p_memsz;
-	elf_word p_flags;
-	elf_word p_align;
-};
-struct elf64_segment_header {
-	elf_word p_type;
-	elf_word p_flags;
-	elf64_off p_offset;
-	elf64_addr p_vaddr;
-	elf64_addr p_paddr;
-	elf_xword p_filesz;
-	elf_xword p_memsz;
-	elf_xword p_align;
-};
-
-/*
- * ELF section header
- */
-struct elf32_section_header {
-	elf_word sh_name;
-	elf_word sh_type;
-	elf_word sh_flags;
-	elf32_addr sh_addr;
-	elf32_off sh_offset;
-	elf_word sh_size;
-	elf_word sh_link;
-	elf_word sh_info;
-	elf_word sh_addralign;
-	elf_word sh_entsize;
-};
-struct elf64_section_header {
-	elf_word sh_name;
-	elf_word sh_type;
-	elf_xword sh_flags;
-	elf64_addr sh_addr;
-	elf64_off sh_offset;
-	elf_xword sh_size;
-	elf_word sh_link;
-	elf_word sh_info;
-	elf_xword sh_addralign;
-	elf_xword sh_entsize;
-};
-
-/*
- * ELF symbol table entry
- */
-struct elf32_symbol {
-	elf_word st_name;
-	elf32_addr st_value;
-	elf_word st_size;
-	uint8_t st_info;
-	uint8_t st_other;
-	elf_half st_shndx;
-};
-struct elf64_symbol {
-	elf_word st_name;
-	uint8_t st_info;
-	uint8_t st_other;
-	elf_half st_shndx;
-	elf64_addr st_value;
-	elf_xword st_size;
-};
-
-#ifdef __32_BITS__ 
-typedef struct elf32_header elf_header_t;
-typedef struct elf32_segment_header elf_segment_header_t;
-typedef struct elf32_section_header elf_section_header_t;
-typedef struct elf32_symbol elf_symbol_t;
-#endif
-#ifdef __64_BITS__
-typedef struct elf64_header elf_header_t;
-typedef struct elf64_segment_header elf_segment_header_t;
-typedef struct elf64_section_header elf_section_header_t;
-typedef struct elf64_symbol elf_symbol_t;
-#endif
-
-extern const char *elf_error(unsigned int rc);
-
-#endif
-
-/** @}
- */
Index: pace/srv/loader/include/elf_load.h
===================================================================
--- uspace/srv/loader/include/elf_load.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ 	(revision )
@@ -1,91 +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.
- */
-
-/** @addtogroup generic
- * @{
- */
-/** @file
- * @brief ELF loader structures and public functions.
- */
-
-#ifndef ELF_LOAD_H_
-#define ELF_LOAD_H_
-
-#include <arch/elf.h>
-#include <sys/types.h>
-#include <loader/pcb.h>
-
-#include "elf.h"
-
-typedef enum {
-	/** Leave all segments in RW access mode. */
-	ELDF_RW = 1
-} eld_flags_t;
-
-/**
- * Some data extracted from the headers are stored here
- */
-typedef struct {
-	/** Entry point */
-	entry_point_t entry;
-
-	/** ELF interpreter name or NULL if statically-linked */
-	const char *interp;
-
-	/** Pointer to the dynamic section */
-	void *dynamic;
-} elf_info_t;
-
-/**
- * Holds information about an ELF binary being loaded.
- */
-typedef struct {
-	/** Filedescriptor of the file from which we are loading */
-	int fd;
-
-	/** Difference between run-time addresses and link-time addresses */
-	uintptr_t bias;
-
-	/** Flags passed to the ELF loader. */
-	eld_flags_t flags;
-
-	/** A copy of the ELF file header */
-	elf_header_t *header;
-
-	/** Store extracted info here */
-	elf_info_t *info;
-} elf_ld_t;
-
-int elf_load_file(const char *file_name, size_t so_bias, eld_flags_t flags,
-    elf_info_t *info);
-void elf_create_pcb(elf_info_t *info, pcb_t *pcb);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/loader/main.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -59,6 +59,7 @@
 #include <str.h>
 #include <as.h>
-#include <elf.h>
-#include <elf_load.h>
+#include <elf/elf.h>
+#include <elf/elf_load.h>
+#include <vfs/vfs.h>
 
 #ifdef CONFIG_RTLD
@@ -89,9 +90,5 @@
 
 /** Number of preset files */
-static int filc = 0;
-/** Preset files vector */
-static fdi_node_t **filv = NULL;
-/** Buffer holding all preset files */
-static fdi_node_t *fil_buf = NULL;
+static unsigned int filc = 0;
 
 static elf_info_t prog_info;
@@ -239,45 +236,23 @@
 static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
 {
-	fdi_node_t *buf;
-	size_t buf_size;
-	int rc = async_data_write_accept((void **) &buf, false, 0, 0,
-	    sizeof(fdi_node_t), &buf_size);
-	
-	if (rc == EOK) {
-		int count = buf_size / sizeof(fdi_node_t);
-		
-		/*
-		 * Allocate new filv
-		 */
-		fdi_node_t **_filv = (fdi_node_t **) calloc(count + 1, sizeof(fdi_node_t *));
-		if (_filv == NULL) {
-			free(buf);
-			async_answer_0(rid, ENOMEM);
-			return;
+	size_t count = IPC_GET_ARG1(*request);
+
+	async_exch_t *vfs_exch = vfs_exchange_begin();
+
+	for (filc = 0; filc < count; filc++) {
+		ipc_callid_t callid;
+		int fd;
+
+		if (!async_state_change_receive(&callid, NULL, NULL, NULL)) {
+			async_answer_0(callid, EINVAL);
+			break;
 		}
-		
-		/*
-		 * Fill the new filv with argument pointers
-		 */
-		int i;
-		for (i = 0; i < count; i++)
-			_filv[i] = &buf[i];
-		
-		_filv[count] = NULL;
-		
-		/*
-		 * Copy temporary data to global variables
-		 */
-		if (fil_buf != NULL)
-			free(fil_buf);
-		
-		if (filv != NULL)
-			free(filv);
-		
-		filc = count;
-		fil_buf = buf;
-		filv = _filv;
-	}
-	
+		async_state_change_finalize(callid, vfs_exch);
+		fd = fd_wait();
+		assert(fd == (int) filc);
+	}
+
+	vfs_exchange_end(vfs_exch);
+
 	async_answer_0(rid, EOK);
 }
@@ -308,5 +283,4 @@
 	
 	pcb.filc = filc;
-	pcb.filv = filv;
 	
 	if (prog_info.interp == NULL) {
@@ -348,6 +322,6 @@
 
 	/* Initialize list of loaded modules */
-	list_initialize(&runtime_env->modules_head);
-	list_append(&prog_mod.modules_link, &runtime_env->modules_head);
+	list_initialize(&runtime_env->modules);
+	list_append(&prog_mod.modules_link, &runtime_env->modules);
 
 	/* Pointer to program module. Used as root of the module graph. */
Index: uspace/srv/loc/Makefile
===================================================================
--- uspace/srv/loc/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/srv/loc/Makefile	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+BINARY = loc
+STATIC_NEEDED = y
+
+SOURCES = \
+	category.c \
+	loc.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/loc/category.c
===================================================================
--- uspace/srv/loc/category.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/srv/loc/category.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,213 @@
+/*
+ * 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 loc
+ * @{
+ */
+/** @file Categories for location service.
+ */
+
+#include <adt/list.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+
+#include "category.h"
+#include "loc.h"
+
+/** Initialize category directory. */
+void categ_dir_init(categ_dir_t *cdir)
+{
+	fibril_mutex_initialize(&cdir->mutex);
+	list_initialize(&cdir->categories);
+}
+
+/** Add new category to directory. */
+void categ_dir_add_cat(categ_dir_t *cdir, category_t *cat)
+{
+	list_append(&cat->cat_list, &cdir->categories);
+}
+
+/** Get list of categories. */
+int categ_dir_get_categories(categ_dir_t *cdir, category_id_t *id_buf,
+    size_t buf_size, size_t *act_size)
+{
+	size_t act_cnt;
+	size_t buf_cnt;
+
+	assert(fibril_mutex_is_locked(&cdir->mutex));
+
+	buf_cnt = buf_size / sizeof(category_id_t);
+
+	act_cnt = list_count(&cdir->categories);
+	*act_size = act_cnt * sizeof(category_id_t);
+
+	if (buf_size % sizeof(category_id_t) != 0)
+		return EINVAL;
+
+	size_t pos = 0;
+	list_foreach(cdir->categories, item) {
+		category_t *cat =
+		    list_get_instance(item, category_t, cat_list);
+
+		if (pos < buf_cnt)
+			id_buf[pos] = cat->id;
+		pos++;
+	}
+
+	return EOK;
+}
+
+
+/** Initialize category structure. */
+static void category_init(category_t *cat, const char *name)
+{
+	fibril_mutex_initialize(&cat->mutex);
+	cat->name = str_dup(name);
+	cat->id = loc_create_id();
+	link_initialize(&cat->cat_list);
+	list_initialize(&cat->svc_memb);
+}
+
+/** Allocate new category. */
+category_t *category_new(const char *name)
+{
+	category_t *cat;
+
+	cat = malloc(sizeof(category_t));
+	if (cat == NULL)
+		return NULL;
+
+	category_init(cat, name);
+	return cat;
+}
+
+/** Add service to category. */
+int category_add_service(category_t *cat, loc_service_t *svc)
+{
+	assert(fibril_mutex_is_locked(&cat->mutex));
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+
+	/* Verify that category does not contain this service yet. */
+	list_foreach(cat->svc_memb, item) {
+		svc_categ_t *memb = list_get_instance(item, svc_categ_t,
+		    cat_link);
+		if (memb->svc == svc) {
+			return EEXIST;
+		}
+	}
+
+	svc_categ_t *nmemb = malloc(sizeof(svc_categ_t));
+	if (nmemb == NULL)
+		return ENOMEM;
+
+	nmemb->svc = svc;
+	nmemb->cat = cat;
+
+	list_append(&nmemb->cat_link, &cat->svc_memb);
+	list_append(&nmemb->svc_link, &svc->cat_memb);
+
+	return EOK;
+}
+
+/** Remove service from category. */
+void category_remove_service(svc_categ_t *memb)
+{
+	assert(fibril_mutex_is_locked(&memb->cat->mutex));
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+
+	list_remove(&memb->cat_link);
+	list_remove(&memb->svc_link);
+
+	free(memb);
+}
+
+/** Get category by ID. */
+category_t *category_get(categ_dir_t *cdir, catid_t catid)
+{
+	assert(fibril_mutex_is_locked(&cdir->mutex));
+
+	list_foreach(cdir->categories, item) {
+		category_t *cat = list_get_instance(item, category_t,
+		    cat_list);
+		if (cat->id == catid)
+			return cat;
+	}
+
+	return NULL;
+}
+
+/** Find category by name. */
+category_t *category_find_by_name(categ_dir_t *cdir, const char *name)
+{
+	assert(fibril_mutex_is_locked(&cdir->mutex));
+
+	list_foreach(cdir->categories, item) {
+		category_t *cat = list_get_instance(item, category_t,
+		    cat_list);
+		if (str_cmp(cat->name, name) == 0)
+			return cat;
+	}
+
+	return NULL;
+}
+
+/** Get list of services in category. */
+int category_get_services(category_t *cat, service_id_t *id_buf,
+    size_t buf_size, size_t *act_size)
+{
+	size_t act_cnt;
+	size_t buf_cnt;
+
+	assert(fibril_mutex_is_locked(&cat->mutex));
+
+	buf_cnt = buf_size / sizeof(service_id_t);
+
+	act_cnt = list_count(&cat->svc_memb);
+	*act_size = act_cnt * sizeof(service_id_t);
+
+	if (buf_size % sizeof(service_id_t) != 0)
+		return EINVAL;
+
+	size_t pos = 0;
+	list_foreach(cat->svc_memb, item) {
+		svc_categ_t *memb =
+		    list_get_instance(item, svc_categ_t, cat_link);
+
+		if (pos < buf_cnt)
+			id_buf[pos] = memb->svc->id;
+		pos++;
+	}
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/loc/category.h
===================================================================
--- uspace/srv/loc/category.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/srv/loc/category.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,98 @@
+/*
+ * 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 loc
+ * @{
+ */
+/** @file Categories for location service.
+ */
+
+#ifndef CATEGORY_H_
+#define CATEGORY_H_
+
+#include <adt/list.h>
+#include "loc.h"
+
+typedef sysarg_t catid_t;
+
+/** Service category */
+typedef struct {
+	/** Protects this structure, list of services */
+	fibril_mutex_t mutex;
+
+	/** Identifier */
+	catid_t id;
+
+	/** Category name */
+	const char *name;
+
+	/** Link to list of categories (categ_dir_t.categories) */
+	link_t cat_list;
+
+	/** List of service memberships in this category (svc_categ_t) */
+	list_t svc_memb;
+} category_t;
+
+/** Service directory ogranized by categories (yellow pages) */
+typedef struct {
+	/** Protects this structure, list of categories */
+	fibril_mutex_t mutex;
+	/** List of all categories (category_t) */
+	list_t categories;
+} categ_dir_t;
+
+/** Service in category membership. */
+typedef struct {
+	/** Link to category_t.svc_memb list */
+	link_t cat_link;
+	/** Link to loc_service_t.cat_memb list */
+	link_t svc_link;
+	
+	/** Category */
+	category_t *cat;
+	/** Service */
+	loc_service_t *svc;
+} svc_categ_t;
+
+extern void categ_dir_init(categ_dir_t *);
+extern void categ_dir_add_cat(categ_dir_t *, category_t *);
+extern int categ_dir_get_categories(categ_dir_t *, service_id_t *, size_t,
+    size_t *);
+extern category_t *category_new(const char *);
+extern int category_add_service(category_t *, loc_service_t *);
+extern void category_remove_service(svc_categ_t *);
+extern category_t *category_get(categ_dir_t *, catid_t);
+extern category_t *category_find_by_name(categ_dir_t *, const char *);
+extern int category_get_services(category_t *, service_id_t *, size_t,
+    size_t *);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/loc/loc.c
===================================================================
--- uspace/srv/loc/loc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/srv/loc/loc.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,1457 @@
+/*
+ * Copyright (c) 2007 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.
+ */
+
+/**
+ * @defgroup loc Location Service.
+ * @brief HelenOS location service.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <ipc/services.h>
+#include <ns.h>
+#include <async.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <macros.h>
+#include <stdlib.h>
+#include <str.h>
+#include <ipc/loc.h>
+#include <assert.h>
+
+#include "category.h"
+#include "loc.h"
+
+#define NAME          "loc"
+#define NULL_SERVICES  256
+
+LIST_INITIALIZE(services_list);
+LIST_INITIALIZE(namespaces_list);
+LIST_INITIALIZE(servers_list);
+
+/* Locking order:
+ *  servers_list_mutex
+ *  services_list_mutex
+ *  (loc_server_t *)->services_mutex
+ *  create_id_mutex
+ **/
+
+FIBRIL_MUTEX_INITIALIZE(services_list_mutex);
+static FIBRIL_CONDVAR_INITIALIZE(services_list_cv);
+static FIBRIL_MUTEX_INITIALIZE(servers_list_mutex);
+static FIBRIL_MUTEX_INITIALIZE(create_id_mutex);
+static FIBRIL_MUTEX_INITIALIZE(null_services_mutex);
+
+static service_id_t last_id = 0;
+static loc_service_t *null_services[NULL_SERVICES];
+
+/*
+ * Dummy list for null services. This is necessary so that null services can
+ * be used just as any other services, e.g. in loc_service_unregister_core().
+ */
+static LIST_INITIALIZE(dummy_null_services);
+
+/** Service directory ogranized by categories (yellow pages) */
+static categ_dir_t cdir;
+
+static FIBRIL_MUTEX_INITIALIZE(callback_sess_mutex);
+static async_sess_t *callback_sess = NULL;
+
+service_id_t loc_create_id(void)
+{
+	/* TODO: allow reusing old ids after their unregistration
+	 * and implement some version of LRU algorithm, avoid overflow
+	 */
+	
+	fibril_mutex_lock(&create_id_mutex);
+	last_id++;
+	fibril_mutex_unlock(&create_id_mutex);
+	
+	return last_id;
+}
+
+/** Convert fully qualified service name to namespace and service name.
+ *
+ * A fully qualified service name can be either a plain service name
+ * (then the namespace is considered to be an empty string) or consist
+ * of two components separated by a slash. No more than one slash
+ * is allowed.
+ *
+ */
+static bool loc_fqsn_split(const char *fqsn, char **ns_name, char **name)
+{
+	size_t cnt = 0;
+	size_t slash_offset = 0;
+	size_t slash_after = 0;
+	
+	size_t offset = 0;
+	size_t offset_prev = 0;
+	wchar_t c;
+	
+	while ((c = str_decode(fqsn, &offset, STR_NO_LIMIT)) != 0) {
+		if (c == '/') {
+			cnt++;
+			slash_offset = offset_prev;
+			slash_after = offset;
+		}
+		offset_prev = offset;
+	}
+	
+	/* More than one slash */
+	if (cnt > 1)
+		return false;
+	
+	/* No slash -> namespace is empty */
+	if (cnt == 0) {
+		*ns_name = str_dup("");
+		if (*ns_name == NULL)
+			return false;
+		
+		*name = str_dup(fqsn);
+		if (*name == NULL) {
+			free(*ns_name);
+			return false;
+		}
+		
+		if (str_cmp(*name, "") == 0) {
+			free(*name);
+			free(*ns_name);
+			return false;
+		}
+		
+		return true;
+	}
+	
+	/* Exactly one slash */
+	*ns_name = str_ndup(fqsn, slash_offset);
+	if (*ns_name == NULL)
+		return false;
+	
+	*name = str_dup(fqsn + slash_after);
+	if (*name == NULL) {
+		free(*ns_name);
+		return false;
+	}
+	
+	if (str_cmp(*name, "") == 0) {
+		free(*name);
+		free(*ns_name);
+		return false;
+	}
+	
+	return true;
+}
+
+/** Find namespace with given name. */
+static loc_namespace_t *loc_namespace_find_name(const char *name)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+	
+	list_foreach(namespaces_list, item) {
+		loc_namespace_t *namespace =
+		    list_get_instance(item, loc_namespace_t, namespaces);
+		if (str_cmp(namespace->name, name) == 0)
+			return namespace;
+	}
+	
+	return NULL;
+}
+
+/** Find namespace with given ID.
+ *
+ * @todo: use hash table
+ *
+ */
+static loc_namespace_t *loc_namespace_find_id(service_id_t id)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+	
+	list_foreach(namespaces_list, item) {
+		loc_namespace_t *namespace =
+		    list_get_instance(item, loc_namespace_t, namespaces);
+		if (namespace->id == id)
+			return namespace;
+	}
+	
+	return NULL;
+}
+
+/** Find service with given name. */
+static loc_service_t *loc_service_find_name(const char *ns_name,
+    const char *name)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+	
+	list_foreach(services_list, item) {
+		loc_service_t *service =
+		    list_get_instance(item, loc_service_t, services);
+		if ((str_cmp(service->namespace->name, ns_name) == 0)
+		    && (str_cmp(service->name, name) == 0))
+			return service;
+	}
+	
+	return NULL;
+}
+
+/** Find service with given ID.
+ *
+ * @todo: use hash table
+ *
+ */
+static loc_service_t *loc_service_find_id(service_id_t id)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+	
+	list_foreach(services_list, item) {
+		loc_service_t *service =
+		    list_get_instance(item, loc_service_t, services);
+		if (service->id == id)
+			return service;
+	}
+	
+	return NULL;
+}
+
+/** Create a namespace (if not already present). */
+static loc_namespace_t *loc_namespace_create(const char *ns_name)
+{
+	loc_namespace_t *namespace;
+	
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+	
+	namespace = loc_namespace_find_name(ns_name);
+	if (namespace != NULL)
+		return namespace;
+	
+	namespace = (loc_namespace_t *) malloc(sizeof(loc_namespace_t));
+	if (namespace == NULL)
+		return NULL;
+	
+	namespace->name = str_dup(ns_name);
+	if (namespace->name == NULL) {
+		free(namespace);
+		return NULL;
+	}
+	
+	namespace->id = loc_create_id();
+	namespace->refcnt = 0;
+	
+	/*
+	 * Insert new namespace into list of registered namespaces
+	 */
+	list_append(&(namespace->namespaces), &namespaces_list);
+	
+	return namespace;
+}
+
+/** Destroy a namespace (if it is no longer needed). */
+static void loc_namespace_destroy(loc_namespace_t *namespace)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+
+	if (namespace->refcnt == 0) {
+		list_remove(&(namespace->namespaces));
+		
+		free(namespace->name);
+		free(namespace);
+	}
+}
+
+/** Increase namespace reference count by including service. */
+static void loc_namespace_addref(loc_namespace_t *namespace,
+    loc_service_t *service)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+
+	service->namespace = namespace;
+	namespace->refcnt++;
+}
+
+/** Decrease namespace reference count. */
+static void loc_namespace_delref(loc_namespace_t *namespace)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+
+	namespace->refcnt--;
+	loc_namespace_destroy(namespace);
+}
+
+/** Unregister service and free it. */
+static void loc_service_unregister_core(loc_service_t *service)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+	assert(fibril_mutex_is_locked(&cdir.mutex));
+	
+	loc_namespace_delref(service->namespace);
+	list_remove(&(service->services));
+	list_remove(&(service->server_services));
+	
+	/* Remove service from all categories. */
+	while (!list_empty(&service->cat_memb)) {
+		link_t *link = list_first(&service->cat_memb);
+		svc_categ_t *memb = list_get_instance(link, svc_categ_t,
+		    svc_link);
+		fibril_mutex_lock(&memb->cat->mutex);
+		category_remove_service(memb);
+		fibril_mutex_unlock(&memb->cat->mutex);
+	}
+	
+	free(service->name);
+	free(service);
+}
+
+/**
+ * Read info about new server and add it into linked list of registered
+ * servers.
+ */
+static loc_server_t *loc_server_register(void)
+{
+	ipc_call_t icall;
+	ipc_callid_t iid = async_get_call(&icall);
+	
+	if (IPC_GET_IMETHOD(icall) != LOC_SERVER_REGISTER) {
+		async_answer_0(iid, EREFUSED);
+		return NULL;
+	}
+	
+	loc_server_t *server =
+	    (loc_server_t *) malloc(sizeof(loc_server_t));
+	if (server == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return NULL;
+	}
+	
+	/*
+	 * Get server name
+	 */
+	int rc = async_data_write_accept((void **) &server->name, true, 0,
+	    LOC_NAME_MAXLEN, 0, NULL);
+	if (rc != EOK) {
+		free(server);
+		async_answer_0(iid, rc);
+		return NULL;
+	}
+	
+	/*
+	 * Create connection to the server
+	 */
+	server->sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (!server->sess) {
+		free(server->name);
+		free(server);
+		async_answer_0(iid, ENOTSUP);
+		return NULL;
+	}
+	
+	/*
+	 * Initialize mutex for list of services
+	 * supplied by this server
+	 */
+	fibril_mutex_initialize(&server->services_mutex);
+	
+	/*
+	 * Initialize list of supplied services
+	 */
+	list_initialize(&server->services);
+
+	link_initialize(&server->servers);
+	
+	fibril_mutex_lock(&servers_list_mutex);
+	
+	/* TODO:
+	 * Check that no server with name equal to
+	 * server->name is registered
+	 */
+	
+	/*
+	 * Insert new server into list of registered servers
+	 */
+	list_append(&(server->servers), &servers_list);
+	fibril_mutex_unlock(&servers_list_mutex);
+	
+	async_answer_0(iid, EOK);
+	
+	return server;
+}
+
+/**
+ * Unregister server, unregister all its services and free server
+ * structure.
+ *
+ */
+static int loc_server_unregister(loc_server_t *server)
+{
+	if (server == NULL)
+		return EEXISTS;
+	
+	fibril_mutex_lock(&servers_list_mutex);
+	
+	if (server->sess)
+		async_hangup(server->sess);
+	
+	/* Remove it from list of servers */
+	list_remove(&(server->servers));
+	
+	/* Unregister all its services */
+	fibril_mutex_lock(&services_list_mutex);
+	fibril_mutex_lock(&server->services_mutex);
+	fibril_mutex_lock(&cdir.mutex);
+	
+	while (!list_empty(&server->services)) {
+		loc_service_t *service = list_get_instance(
+		    list_first(&server->services), loc_service_t,
+		    server_services);
+		loc_service_unregister_core(service);
+	}
+	
+	fibril_mutex_unlock(&cdir.mutex);
+	fibril_mutex_unlock(&server->services_mutex);
+	fibril_mutex_unlock(&services_list_mutex);
+	fibril_mutex_unlock(&servers_list_mutex);
+	
+	/* Free name and server */
+	if (server->name != NULL)
+		free(server->name);
+	
+	free(server);
+	
+	return EOK;
+}
+
+/** Register service
+ *
+ */
+static void loc_service_register(ipc_callid_t iid, ipc_call_t *icall,
+    loc_server_t *server)
+{
+	if (server == NULL) {
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	/* Create new service entry */
+	loc_service_t *service =
+	    (loc_service_t *) malloc(sizeof(loc_service_t));
+	if (service == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	/* Set the interface, if any. */
+	service->forward_interface = IPC_GET_ARG1(*icall);
+
+	/* Get fqsn */
+	char *fqsn;
+	int rc = async_data_write_accept((void **) &fqsn, true, 0,
+	    LOC_NAME_MAXLEN, 0, NULL);
+	if (rc != EOK) {
+		free(service);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	char *ns_name;
+	if (!loc_fqsn_split(fqsn, &ns_name, &service->name)) {
+		free(fqsn);
+		free(service);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	free(fqsn);
+	
+	fibril_mutex_lock(&services_list_mutex);
+	
+	loc_namespace_t *namespace = loc_namespace_create(ns_name);
+	free(ns_name);
+	if (namespace == NULL) {
+		fibril_mutex_unlock(&services_list_mutex);
+		free(service->name);
+		free(service);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	link_initialize(&service->services);
+	link_initialize(&service->server_services);
+	list_initialize(&service->cat_memb);
+	
+	/* Check that service is not already registered */
+	if (loc_service_find_name(namespace->name, service->name) != NULL) {
+		printf("%s: Service '%s/%s' already registered\n", NAME,
+		    namespace->name, service->name);
+		loc_namespace_destroy(namespace);
+		fibril_mutex_unlock(&services_list_mutex);
+		free(service->name);
+		free(service);
+		async_answer_0(iid, EEXISTS);
+		return;
+	}
+	
+	/* Get unique service ID */
+	service->id = loc_create_id();
+
+	loc_namespace_addref(namespace, service);
+	service->server = server;
+	
+	/* Insert service into list of all services  */
+	list_append(&service->services, &services_list);
+	
+	/* Insert service into list of services supplied by one server */
+	fibril_mutex_lock(&service->server->services_mutex);
+	
+	list_append(&service->server_services, &service->server->services);
+	
+	fibril_mutex_unlock(&service->server->services_mutex);
+	fibril_condvar_broadcast(&services_list_cv);
+	fibril_mutex_unlock(&services_list_mutex);
+	
+	async_answer_1(iid, EOK, service->id);
+}
+
+/**
+ *
+ */
+static void loc_service_unregister(ipc_callid_t iid, ipc_call_t *icall, 
+    loc_server_t *server)
+{
+	loc_service_t *svc;
+	
+	fibril_mutex_lock(&services_list_mutex);
+	svc = loc_service_find_id(IPC_GET_ARG1(*icall));
+	if (svc == NULL) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	fibril_mutex_lock(&cdir.mutex);
+	loc_service_unregister_core(svc);
+	fibril_mutex_unlock(&cdir.mutex);
+	fibril_mutex_unlock(&services_list_mutex);
+	async_answer_0(iid, EOK);
+}
+
+static void loc_category_get_name(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	category_t *cat;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	fibril_mutex_lock(&cdir.mutex);
+	
+	cat = category_get(&cdir, IPC_GET_ARG1(*icall));
+	if (cat == NULL) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	act_size = str_size(cat->name);
+	if (act_size > size) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, EOVERFLOW);
+		async_answer_0(iid, EOVERFLOW);
+		return;
+	}
+	
+	sysarg_t retval = async_data_read_finalize(callid, cat->name,
+	    min(size, act_size));
+	
+	fibril_mutex_unlock(&cdir.mutex);
+	
+	async_answer_0(iid, retval);
+}
+
+static void loc_service_get_name(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	loc_service_t *svc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	fibril_mutex_lock(&services_list_mutex);
+	
+	svc = loc_service_find_id(IPC_GET_ARG1(*icall));
+	if (svc == NULL) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	act_size = str_size(svc->name);
+	if (act_size > size) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, EOVERFLOW);
+		async_answer_0(iid, EOVERFLOW);
+		return;
+	}
+	
+	sysarg_t retval = async_data_read_finalize(callid, svc->name,
+	    min(size, act_size));
+	
+	fibril_mutex_unlock(&services_list_mutex);
+	
+	async_answer_0(iid, retval);
+}
+
+/** Connect client to the service.
+ *
+ * Find server supplying requested service and forward
+ * the message to it.
+ *
+ */
+static void loc_forward(ipc_callid_t callid, ipc_call_t *call)
+{
+	fibril_mutex_lock(&services_list_mutex);
+	
+	/*
+	 * Get ID from request
+	 */
+	service_id_t id = IPC_GET_ARG2(*call);
+	loc_service_t *svc = loc_service_find_id(id);
+	
+	if ((svc == NULL) || (svc->server == NULL) || (!svc->server->sess)) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	async_exch_t *exch = async_exchange_begin(svc->server->sess);
+	
+	if (svc->forward_interface == 0)
+		async_forward_fast(callid, exch, svc->id, 0, 0, IPC_FF_NONE);
+	else
+		async_forward_fast(callid, exch, svc->forward_interface,
+		    svc->id, 0, IPC_FF_NONE);
+	
+	async_exchange_end(exch);
+	
+	fibril_mutex_unlock(&services_list_mutex);
+}
+
+/** Find ID for service identified by name.
+ *
+ * In answer will be send EOK and service ID in arg1 or a error
+ * code from errno.h.
+ *
+ */
+static void loc_service_get_id(ipc_callid_t iid, ipc_call_t *icall)
+{
+	char *fqsn;
+	
+	/* Get fqsn */
+	int rc = async_data_write_accept((void **) &fqsn, true, 0,
+	    LOC_NAME_MAXLEN, 0, NULL);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	char *ns_name;
+	char *name;
+	if (!loc_fqsn_split(fqsn, &ns_name, &name)) {
+		free(fqsn);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	free(fqsn);
+	
+	fibril_mutex_lock(&services_list_mutex);
+	const loc_service_t *svc;
+	
+recheck:
+	
+	/*
+	 * Find service name in the list of known services.
+	 */
+	svc = loc_service_find_name(ns_name, name);
+	
+	/*
+	 * Device was not found.
+	 */
+	if (svc == NULL) {
+		if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
+			/* Blocking lookup */
+			fibril_condvar_wait(&services_list_cv,
+			    &services_list_mutex);
+			goto recheck;
+		}
+		
+		async_answer_0(iid, ENOENT);
+		free(ns_name);
+		free(name);
+		fibril_mutex_unlock(&services_list_mutex);
+		return;
+	}
+	
+	async_answer_1(iid, EOK, svc->id);
+	
+	fibril_mutex_unlock(&services_list_mutex);
+	free(ns_name);
+	free(name);
+}
+
+/** Find ID for namespace identified by name.
+ *
+ * In answer will be send EOK and service ID in arg1 or a error
+ * code from errno.h.
+ *
+ */
+static void loc_namespace_get_id(ipc_callid_t iid, ipc_call_t *icall)
+{
+	char *name;
+	
+	/* Get service name */
+	int rc = async_data_write_accept((void **) &name, true, 0,
+	    LOC_NAME_MAXLEN, 0, NULL);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_mutex_lock(&services_list_mutex);
+	const loc_namespace_t *namespace;
+	
+recheck:
+	
+	/*
+	 * Find namespace name in the list of known namespaces.
+	 */
+	namespace = loc_namespace_find_name(name);
+	
+	/*
+	 * Namespace was not found.
+	 */
+	if (namespace == NULL) {
+		if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
+			/* Blocking lookup */
+			fibril_condvar_wait(&services_list_cv,
+			    &services_list_mutex);
+			goto recheck;
+		}
+		
+		async_answer_0(iid, ENOENT);
+		free(name);
+		fibril_mutex_unlock(&services_list_mutex);
+		return;
+	}
+	
+	async_answer_1(iid, EOK, namespace->id);
+	
+	fibril_mutex_unlock(&services_list_mutex);
+	free(name);
+}
+
+/** Find ID for category specified by name.
+ *
+ * On success, answer will contain EOK int retval and service ID in arg1.
+ * On failure, error code will be sent in retval.
+ *
+ */
+static void loc_callback_create(ipc_callid_t iid, ipc_call_t *icall)
+{
+	async_sess_t *cb_sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (cb_sess == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	fibril_mutex_lock(&callback_sess_mutex);
+	if (callback_sess != NULL) {
+		fibril_mutex_unlock(&callback_sess_mutex);
+		async_answer_0(iid, EEXIST);
+		return;
+	}
+	
+	callback_sess = cb_sess;
+	fibril_mutex_unlock(&callback_sess_mutex);
+	
+	async_answer_0(iid, EOK);
+}
+
+void loc_category_change_event(void)
+{
+	fibril_mutex_lock(&callback_sess_mutex);
+
+	if (callback_sess != NULL) {
+		async_exch_t *exch = async_exchange_begin(callback_sess);
+		async_msg_0(exch, LOC_EVENT_CAT_CHANGE);
+		async_exchange_end(exch);
+	}
+
+	fibril_mutex_unlock(&callback_sess_mutex);
+}
+
+/** Find ID for category specified by name.
+ *
+ * On success, answer will contain EOK int retval and service ID in arg1.
+ * On failure, error code will be sent in retval.
+ *
+ */
+static void loc_category_get_id(ipc_callid_t iid, ipc_call_t *icall)
+{
+	char *name;
+	category_t *cat;
+	
+	/* Get service name */
+	int rc = async_data_write_accept((void **) &name, true, 0,
+	    LOC_NAME_MAXLEN, 0, NULL);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_mutex_lock(&cdir.mutex);
+
+	cat = category_find_by_name(&cdir, name);
+	if (cat == NULL) {
+		/* Category not found */
+		async_answer_0(iid, ENOENT);
+		goto cleanup;
+	}
+	
+	async_answer_1(iid, EOK, cat->id);
+cleanup:
+	fibril_mutex_unlock(&cdir.mutex);
+	free(name);
+}
+
+static void loc_id_probe(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fibril_mutex_lock(&services_list_mutex);
+	
+	loc_namespace_t *namespace =
+	    loc_namespace_find_id(IPC_GET_ARG1(*icall));
+	if (namespace == NULL) {
+		loc_service_t *svc =
+		    loc_service_find_id(IPC_GET_ARG1(*icall));
+		if (svc == NULL)
+			async_answer_1(iid, EOK, LOC_OBJECT_NONE);
+		else
+			async_answer_1(iid, EOK, LOC_OBJECT_SERVICE);
+	} else
+		async_answer_1(iid, EOK, LOC_OBJECT_NAMESPACE);
+	
+	fibril_mutex_unlock(&services_list_mutex);
+}
+
+static void loc_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fibril_mutex_lock(&services_list_mutex);
+	async_answer_1(iid, EOK, list_count(&namespaces_list));
+	fibril_mutex_unlock(&services_list_mutex);
+}
+
+static void loc_get_service_count(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fibril_mutex_lock(&services_list_mutex);
+	
+	loc_namespace_t *namespace =
+	    loc_namespace_find_id(IPC_GET_ARG1(*icall));
+	if (namespace == NULL)
+		async_answer_0(iid, EEXISTS);
+	else
+		async_answer_1(iid, EOK, namespace->refcnt);
+	
+	fibril_mutex_unlock(&services_list_mutex);
+}
+
+static void loc_get_categories(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	int rc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	category_id_t *id_buf = (category_id_t *) malloc(size);
+	if (id_buf == NULL) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	fibril_mutex_lock(&cdir.mutex);
+	
+	rc = categ_dir_get_categories(&cdir, id_buf, size, &act_size);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_mutex_unlock(&cdir.mutex);
+	
+	sysarg_t retval = async_data_read_finalize(callid, id_buf, size);
+	free(id_buf);
+	
+	async_answer_1(iid, retval, act_size);
+}
+
+static void loc_get_namespaces(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, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	if ((size % sizeof(loc_sdesc_t)) != 0) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	fibril_mutex_lock(&services_list_mutex);
+	
+	size_t count = size / sizeof(loc_sdesc_t);
+	if (count != list_count(&namespaces_list)) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, EOVERFLOW);
+		async_answer_0(iid, EOVERFLOW);
+		return;
+	}
+	
+	loc_sdesc_t *desc = (loc_sdesc_t *) malloc(size);
+	if (desc == NULL) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	size_t pos = 0;
+	list_foreach(namespaces_list, item) {
+		loc_namespace_t *namespace =
+		    list_get_instance(item, loc_namespace_t, namespaces);
+		
+		desc[pos].id = namespace->id;
+		str_cpy(desc[pos].name, LOC_NAME_MAXLEN, namespace->name);
+		pos++;
+	}
+	
+	sysarg_t retval = async_data_read_finalize(callid, desc, size);
+	
+	free(desc);
+	fibril_mutex_unlock(&services_list_mutex);
+	
+	async_answer_0(iid, retval);
+}
+
+static void loc_get_services(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/* FIXME: Use faster algorithm which can make better use
+	   of namespaces */
+	
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	if ((size % sizeof(loc_sdesc_t)) != 0) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	fibril_mutex_lock(&services_list_mutex);
+	
+	loc_namespace_t *namespace =
+	    loc_namespace_find_id(IPC_GET_ARG1(*icall));
+	if (namespace == NULL) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	size_t count = size / sizeof(loc_sdesc_t);
+	if (count != namespace->refcnt) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, EOVERFLOW);
+		async_answer_0(iid, EOVERFLOW);
+		return;
+	}
+	
+	loc_sdesc_t *desc = (loc_sdesc_t *) malloc(size);
+	if (desc == NULL) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	size_t pos = 0;
+	list_foreach(services_list, item) {
+		loc_service_t *service =
+		    list_get_instance(item, loc_service_t, services);
+		
+		if (service->namespace == namespace) {
+			desc[pos].id = service->id;
+			str_cpy(desc[pos].name, LOC_NAME_MAXLEN, service->name);
+			pos++;
+		}
+	}
+	
+	sysarg_t retval = async_data_read_finalize(callid, desc, size);
+	
+	free(desc);
+	fibril_mutex_unlock(&services_list_mutex);
+	
+	async_answer_0(iid, retval);
+}
+
+static void loc_category_get_svcs(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	int rc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	fibril_mutex_lock(&cdir.mutex);
+	
+	category_t *cat = category_get(&cdir, IPC_GET_ARG1(*icall));
+	if (cat == NULL) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	category_id_t *id_buf = (category_id_t *) malloc(size);
+	if (id_buf == NULL) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	fibril_mutex_lock(&cat->mutex);
+	
+	rc = category_get_services(cat, id_buf, size, &act_size);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&cat->mutex);
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_mutex_unlock(&cat->mutex);
+	fibril_mutex_unlock(&cdir.mutex);
+	
+	sysarg_t retval = async_data_read_finalize(callid, id_buf, size);
+	free(id_buf);
+	
+	async_answer_1(iid, retval, act_size);
+}
+
+
+static void loc_null_create(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fibril_mutex_lock(&null_services_mutex);
+	
+	unsigned int i;
+	bool fnd = false;
+	
+	for (i = 0; i < NULL_SERVICES; i++) {
+		if (null_services[i] == NULL) {
+			fnd = true;
+			break;
+		}
+	}
+	
+	if (!fnd) {
+		fibril_mutex_unlock(&null_services_mutex);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	char null[LOC_NAME_MAXLEN];
+	snprintf(null, LOC_NAME_MAXLEN, "%u", i);
+	
+	char *dev_name = str_dup(null);
+	if (dev_name == NULL) {
+		fibril_mutex_unlock(&null_services_mutex);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	loc_service_t *service =
+	    (loc_service_t *) malloc(sizeof(loc_service_t));
+	if (service == NULL) {
+		fibril_mutex_unlock(&null_services_mutex);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	fibril_mutex_lock(&services_list_mutex);
+	
+	loc_namespace_t *namespace = loc_namespace_create("null");
+	if (namespace == NULL) {
+		fibril_mutex_lock(&services_list_mutex);
+		fibril_mutex_unlock(&null_services_mutex);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	link_initialize(&service->services);
+	link_initialize(&service->server_services);
+	
+	/* Get unique service ID */
+	service->id = loc_create_id();
+	service->server = NULL;
+	
+	loc_namespace_addref(namespace, service);
+	service->name = dev_name;
+	
+	/*
+	 * Insert service into list of all services and into null services array.
+	 * Insert service into a dummy list of null server's services so that it
+	 * can be safely removed later.
+	 */
+	list_append(&service->services, &services_list);
+	list_append(&service->server_services, &dummy_null_services);
+	null_services[i] = service;
+	
+	fibril_mutex_unlock(&services_list_mutex);
+	fibril_mutex_unlock(&null_services_mutex);
+	
+	async_answer_1(iid, EOK, (sysarg_t) i);
+}
+
+static void loc_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
+{
+	sysarg_t i = IPC_GET_ARG1(*icall);
+	if (i >= NULL_SERVICES) {
+		async_answer_0(iid, ELIMIT);
+		return;
+	}
+	
+	fibril_mutex_lock(&null_services_mutex);
+	
+	if (null_services[i] == NULL) {
+		fibril_mutex_unlock(&null_services_mutex);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	fibril_mutex_lock(&services_list_mutex);
+	fibril_mutex_lock(&cdir.mutex);
+	loc_service_unregister_core(null_services[i]);
+	fibril_mutex_unlock(&cdir.mutex);
+	fibril_mutex_unlock(&services_list_mutex);
+	
+	null_services[i] = NULL;
+	
+	fibril_mutex_unlock(&null_services_mutex);
+	async_answer_0(iid, EOK);
+}
+
+static void loc_service_add_to_cat(ipc_callid_t iid, ipc_call_t *icall)
+{
+	category_t *cat;
+	loc_service_t *svc;
+	catid_t cat_id;
+	service_id_t svc_id;
+	sysarg_t retval;
+	
+	svc_id = IPC_GET_ARG1(*icall);
+	cat_id = IPC_GET_ARG2(*icall);
+	
+	fibril_mutex_lock(&services_list_mutex);
+	fibril_mutex_lock(&cdir.mutex);
+	
+	cat = category_get(&cdir, cat_id);
+	svc = loc_service_find_id(svc_id);
+	
+	fibril_mutex_lock(&cat->mutex);
+	retval = category_add_service(cat, svc);
+
+	fibril_mutex_unlock(&cat->mutex);
+	fibril_mutex_unlock(&cdir.mutex);
+	fibril_mutex_unlock(&services_list_mutex);
+
+	async_answer_0(iid, retval);
+
+	loc_category_change_event();
+}
+
+
+/** Initialize location service.
+ *
+ *
+ */
+static bool loc_init(void)
+{
+	unsigned int i;
+	category_t *cat;
+
+	for (i = 0; i < NULL_SERVICES; i++)
+		null_services[i] = NULL;
+	
+	categ_dir_init(&cdir);
+
+	cat = category_new("bd");
+	categ_dir_add_cat(&cdir, cat);
+
+	cat = category_new("keyboard");
+	categ_dir_add_cat(&cdir, cat);
+
+	cat = category_new("mouse");
+	categ_dir_add_cat(&cdir, cat);
+
+	cat = category_new("serial");
+	categ_dir_add_cat(&cdir, cat);
+
+	cat = category_new("usbhc");
+	categ_dir_add_cat(&cdir, cat);
+
+	cat = category_new("virtual");
+	categ_dir_add_cat(&cdir, cat);
+
+	return true;
+}
+
+/** Handle connection on supplier port.
+ *
+ */
+static void loc_connection_supplier(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/* Accept connection */
+	async_answer_0(iid, EOK);
+	
+	loc_server_t *server = loc_server_register();
+	if (server == NULL)
+		return;
+	
+	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 LOC_SERVER_UNREGISTER:
+			if (server == NULL)
+				async_answer_0(callid, ENOENT);
+			else
+				async_answer_0(callid, EOK);
+			break;
+		case LOC_SERVICE_ADD_TO_CAT:
+			/* Add service to category */
+			loc_service_add_to_cat(callid, &call);
+			break;
+		case LOC_SERVICE_REGISTER:
+			/* Register one service */
+			loc_service_register(callid, &call, server);
+			break;
+		case LOC_SERVICE_UNREGISTER:
+			/* Remove one service */
+			loc_service_unregister(callid, &call, server);
+			break;
+		case LOC_SERVICE_GET_ID:
+			loc_service_get_id(callid, &call);
+			break;
+		case LOC_NAMESPACE_GET_ID:
+			loc_namespace_get_id(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOENT);
+		}
+	}
+	
+	if (server != NULL) {
+		/*
+		 * Unregister the server and all its services.
+		 */
+		loc_server_unregister(server);
+		server = NULL;
+	}
+}
+
+/** Handle connection on consumer port.
+ *
+ */
+static void loc_connection_consumer(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/* Accept 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))
+			break;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case LOC_SERVICE_GET_ID:
+			loc_service_get_id(callid, &call);
+			break;
+		case LOC_SERVICE_GET_NAME:
+			loc_service_get_name(callid, &call);
+			break;
+		case LOC_NAMESPACE_GET_ID:
+			loc_namespace_get_id(callid, &call);
+			break;
+		case LOC_CALLBACK_CREATE:
+			loc_callback_create(callid, &call);
+			break;
+		case LOC_CATEGORY_GET_ID:
+			loc_category_get_id(callid, &call);
+			break;
+		case LOC_CATEGORY_GET_NAME:
+			loc_category_get_name(callid, &call);
+			break;
+		case LOC_CATEGORY_GET_SVCS:
+			loc_category_get_svcs(callid, &call);
+			break;
+		case LOC_ID_PROBE:
+			loc_id_probe(callid, &call);
+			break;
+		case LOC_NULL_CREATE:
+			loc_null_create(callid, &call);
+			break;
+		case LOC_NULL_DESTROY:
+			loc_null_destroy(callid, &call);
+			break;
+		case LOC_GET_NAMESPACE_COUNT:
+			loc_get_namespace_count(callid, &call);
+			break;
+		case LOC_GET_SERVICE_COUNT:
+			loc_get_service_count(callid, &call);
+			break;
+		case LOC_GET_CATEGORIES:
+			loc_get_categories(callid, &call);
+			break;
+		case LOC_GET_NAMESPACES:
+			loc_get_namespaces(callid, &call);
+			break;
+		case LOC_GET_SERVICES:
+			loc_get_services(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOENT);
+		}
+	}
+}
+
+/** Function for handling connections to location service
+ *
+ */
+static void loc_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Select interface */
+	switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
+	case LOC_PORT_SUPPLIER:
+		loc_connection_supplier(iid, icall);
+		break;
+	case LOC_PORT_CONSUMER:
+		loc_connection_consumer(iid, icall);
+		break;
+	case LOC_CONNECT_TO_SERVICE:
+		/* Connect client to selected service */
+		loc_forward(iid, icall);
+		break;
+	default:
+		/* No such interface */
+		async_answer_0(iid, ENOENT);
+	}
+}
+
+/**
+ *
+ */
+int main(int argc, char *argv[])
+{
+	printf("%s: HelenOS Location Service\n", NAME);
+	
+	if (!loc_init()) {
+		printf("%s: Error while initializing service\n", NAME);
+		return -1;
+	}
+	
+	/* Set a handler of incomming connections */
+	async_set_client_connection(loc_connection);
+	
+	/* Register location service at naming service */
+	if (service_register(SERVICE_LOC) != EOK)
+		return -1;
+	
+	printf("%s: Accepting connections\n", NAME);
+	async_manager();
+	
+	/* Never reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/loc/loc.h
===================================================================
--- uspace/srv/loc/loc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
+++ uspace/srv/loc/loc.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -0,0 +1,114 @@
+/*
+ * 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 loc
+ * @{
+ */
+/** @file HelenOS location service.
+ */
+
+#ifndef LOC_H_
+#define LOC_H_
+
+#include <ipc/loc.h>
+#include <async.h>
+#include <fibril_synch.h>
+#include <sys/types.h>
+
+/** Representation of server (supplier).
+ *
+ * Each server supplies a set of services.
+ *
+ */
+typedef struct {
+	/** Link to servers_list */
+	link_t servers;
+	
+	/** List of services supplied by this server */
+	list_t services;
+	
+	/** Session asociated with this server */
+	async_sess_t *sess;
+	
+	/** Server name */
+	char *name;
+	
+	/** Fibril mutex for list of services owned by this server */
+	fibril_mutex_t services_mutex;
+} loc_server_t;
+
+/** Info about registered namespaces
+ *
+ */
+typedef struct {
+	/** Link to namespaces_list */
+	link_t namespaces;
+	
+	/** Unique namespace identifier */
+	service_id_t id;
+	
+	/** Namespace name */
+	char *name;
+	
+	/** Reference count */
+	size_t refcnt;
+} loc_namespace_t;
+
+/** Info about registered service
+ *
+ */
+typedef struct {
+	/** Link to global list of services (services_list) */
+	link_t services;
+	/** Link to server list of services (loc_server_t.services) */
+	link_t server_services;
+	/** Link to list of services in category (category_t.services) */
+	link_t cat_services;
+	/** List of category memberships (svc_categ_t) */
+	list_t cat_memb;
+	/** Unique service identifier */
+	service_id_t id;
+	/** Service namespace */
+	loc_namespace_t *namespace;
+	/** Service name */
+	char *name;
+	/** Supplier of this service */
+	loc_server_t *server;
+	/** Use this interface when forwarding to server. */
+	sysarg_t forward_interface;
+} loc_service_t;
+
+extern fibril_mutex_t services_list_mutex;
+
+extern service_id_t loc_create_id(void);
+extern void loc_category_change_event(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/vfs/vfs.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -36,5 +36,8 @@
  */
 
+#include <vfs/vfs.h>
 #include <ipc/services.h>
+#include <abi/ipc/event.h>
+#include <event.h>
 #include <ns.h>
 #include <async.h>
@@ -45,7 +48,12 @@
 #include <as.h>
 #include <atomic.h>
+#include <macros.h>
 #include "vfs.h"
 
 #define NAME  "vfs"
+
+enum {
+	VFS_TASK_STATE_CHANGE
+};
 
 static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
@@ -80,7 +88,4 @@
 			vfs_open(callid, &call);
 			break;
-		case VFS_IN_OPEN_NODE:
-			vfs_open_node(callid, &call);
-			break;
 		case VFS_IN_CLOSE:
 			vfs_close(callid, &call);
@@ -118,4 +123,8 @@
 		case VFS_IN_DUP:
 			vfs_dup(callid, &call);
+			break;
+		case VFS_IN_WAIT_HANDLE:
+			vfs_wait_handle(callid, &call);
+			break;
 		default:
 			async_answer_0(callid, ENOTSUP);
@@ -128,4 +137,19 @@
 	 * connection fibril terminates.
 	 */
+}
+
+static void notification_received(ipc_callid_t callid, ipc_call_t *call)
+{
+	switch (IPC_GET_IMETHOD(*call)) {
+	case VFS_TASK_STATE_CHANGE:
+		if (IPC_GET_ARG1(*call) == VFS_PASS_HANDLE)
+			vfs_pass_handle(
+			    (task_id_t) MERGE_LOUP32(IPC_GET_ARG4(*call),
+			    IPC_GET_ARG5(*call)), call->in_task_id,
+			    (int) IPC_GET_ARG2(*call));
+		break;
+	default:
+		break;
+	}
 }
 
@@ -170,4 +194,10 @@
 
 	/*
+	 * Set notification handler and subscribe to notifications.
+	 */
+	async_set_interrupt_received(notification_received);
+	event_task_subscribe(EVENT_TASK_STATE_CHANGE, VFS_TASK_STATE_CHANGE);
+
+	/*
 	 * Register at the naming service.
 	 */
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/vfs/vfs.h	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -38,7 +38,8 @@
 #include <fibril_synch.h>
 #include <sys/types.h>
-#include <devmap.h>
+#include <loc.h>
 #include <bool.h>
 #include <ipc/vfs.h>
+#include <task.h>
 
 #ifndef dprintf
@@ -61,5 +62,5 @@
 #define VFS_PAIR \
 	fs_handle_t fs_handle; \
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 
 /**
@@ -67,5 +68,5 @@
  * doesn't contain any state. For a stateful structure, see vfs_node_t.
  *
- * @note	fs_handle, devmap_handle and index are meant to be returned in one
+ * @note	fs_handle, service_id and index are meant to be returned in one
  *		IPC reply.
  */
@@ -175,5 +176,4 @@
 extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *,
     vfs_pair_t *, ...);
-extern int vfs_open_node_internal(vfs_lookup_res_t *);
 
 extern bool vfs_nodes_init(void);
@@ -181,5 +181,5 @@
 extern void vfs_node_put(vfs_node_t *);
 extern void vfs_node_forget(vfs_node_t *);
-extern unsigned vfs_nodes_refcount_sum_get(fs_handle_t, devmap_handle_t);
+extern unsigned vfs_nodes_refcount_sum_get(fs_handle_t, service_id_t);
 
 
@@ -188,4 +188,7 @@
 extern void *vfs_client_data_create(void);
 extern void vfs_client_data_destroy(void *);
+
+extern void vfs_pass_handle(task_id_t, task_id_t, int);
+extern int vfs_wait_handle_internal(void);
 
 extern vfs_file_t *vfs_file_get(int);
@@ -197,4 +200,5 @@
 extern void vfs_node_addref(vfs_node_t *);
 extern void vfs_node_delref(vfs_node_t *);
+extern int vfs_open_node_remote(vfs_node_t *);
 
 extern void vfs_register(ipc_callid_t, ipc_call_t *);
@@ -202,5 +206,4 @@
 extern void vfs_unmount(ipc_callid_t, ipc_call_t *);
 extern void vfs_open(ipc_callid_t, ipc_call_t *);
-extern void vfs_open_node(ipc_callid_t, ipc_call_t *);
 extern void vfs_sync(ipc_callid_t, ipc_call_t *);
 extern void vfs_dup(ipc_callid_t, ipc_call_t *);
@@ -215,4 +218,5 @@
 extern void vfs_unlink(ipc_callid_t, ipc_call_t *);
 extern void vfs_rename(ipc_callid_t, ipc_call_t *);
+extern void vfs_wait_handle(ipc_callid_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/vfs/vfs_file.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -43,4 +43,6 @@
 #include <fibril.h>
 #include <fibril_synch.h>
+#include <adt/list.h>
+#include <task.h>
 #include "vfs.h"
 
@@ -50,38 +52,57 @@
 typedef struct {
 	fibril_mutex_t lock;
+	fibril_condvar_t cv;
+	list_t passed_handles;
 	vfs_file_t **files;
 } vfs_client_data_t;
 
+typedef struct {
+	link_t link;
+	int handle;
+} vfs_boxed_handle_t;
+
+static int _vfs_fd_free(vfs_client_data_t *, int);
+
 /** Initialize the table of open files. */
-static bool vfs_files_init(void)
-{
-	fibril_mutex_lock(&VFS_DATA->lock);
-	if (!FILES) {
-		FILES = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
-		if (!FILES) {
-			fibril_mutex_unlock(&VFS_DATA->lock);
+static bool vfs_files_init(vfs_client_data_t *vfs_data)
+{
+	fibril_mutex_lock(&vfs_data->lock);
+	if (!vfs_data->files) {
+		vfs_data->files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
+		if (!vfs_data->files) {
+			fibril_mutex_unlock(&vfs_data->lock);
 			return false;
 		}
-		memset(FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
-	}
-	fibril_mutex_unlock(&VFS_DATA->lock);
+		memset(vfs_data->files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
+	}
+	fibril_mutex_unlock(&vfs_data->lock);
 	return true;
 }
 
 /** Cleanup the table of open files. */
-static void vfs_files_done(void)
+static void vfs_files_done(vfs_client_data_t *vfs_data)
 {
 	int i;
 
-	if (!FILES)
+	if (!vfs_data->files)
 		return;
 
 	for (i = 0; i < MAX_OPEN_FILES; i++) {
-		if (FILES[i]) {
-			(void) vfs_fd_free(i);
-		}
-	}
-	
-	free(FILES);
+		if (vfs_data->files[i])
+			(void) _vfs_fd_free(vfs_data, i);
+	}
+	
+	free(vfs_data->files);
+
+	while (!list_empty(&vfs_data->passed_handles)) {
+		link_t *lnk;
+		vfs_boxed_handle_t *bh;
+		
+		lnk = list_first(&vfs_data->passed_handles);
+		list_remove(lnk);
+
+		bh = list_get_instance(lnk, vfs_boxed_handle_t, link);
+		free(bh);
+	}
 }
 
@@ -93,4 +114,6 @@
 	if (vfs_data) {
 		fibril_mutex_initialize(&vfs_data->lock);
+		fibril_condvar_initialize(&vfs_data->cv);
+		list_initialize(&vfs_data->passed_handles);
 		vfs_data->files = NULL;
 	}
@@ -103,5 +126,5 @@
 	vfs_client_data_t *vfs_data = (vfs_client_data_t *) data;
 
-	vfs_files_done();
+	vfs_files_done(vfs_data);
 	free(vfs_data);
 }
@@ -115,5 +138,5 @@
 	
 	ipc_call_t answer;
-	aid_t msg = async_send_2(exch, VFS_OUT_CLOSE, file->node->devmap_handle,
+	aid_t msg = async_send_2(exch, VFS_OUT_CLOSE, file->node->service_id,
 	    file->node->index, &answer);
 	
@@ -131,7 +154,7 @@
  *			incremented.
  */
-static void vfs_file_addref(vfs_file_t *file)
-{
-	assert(fibril_mutex_is_locked(&VFS_DATA->lock));
+static void vfs_file_addref(vfs_client_data_t *vfs_data, vfs_file_t *file)
+{
+	assert(fibril_mutex_is_locked(&vfs_data->lock));
 
 	file->refcnt++;
@@ -143,9 +166,9 @@
  *			decremented.
  */
-static int vfs_file_delref(vfs_file_t *file)
+static int vfs_file_delref(vfs_client_data_t *vfs_data, vfs_file_t *file)
 {
 	int rc = EOK;
 
-	assert(fibril_mutex_is_locked(&VFS_DATA->lock));
+	assert(fibril_mutex_is_locked(&vfs_data->lock));
 
 	if (file->refcnt-- == 1) {
@@ -162,16 +185,7 @@
 }
 
-
-/** Allocate a file descriptor.
- *
- * @param desc If true, look for an available file descriptor
- *             in a descending order.
- *
- * @return First available file descriptor or a negative error
- *         code.
- */
-int vfs_fd_alloc(bool desc)
-{
-	if (!vfs_files_init())
+static int _vfs_fd_alloc(vfs_client_data_t *vfs_data, bool desc)
+{
+	if (!vfs_files_init(vfs_data))
 		return ENOMEM;
 	
@@ -182,17 +196,17 @@
 		i = 0;
 	
-	fibril_mutex_lock(&VFS_DATA->lock);
+	fibril_mutex_lock(&vfs_data->lock);
 	while (true) {
-		if (!FILES[i]) {
-			FILES[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
-			if (!FILES[i]) {
-				fibril_mutex_unlock(&VFS_DATA->lock);
+		if (!vfs_data->files[i]) {
+			vfs_data->files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
+			if (!vfs_data->files[i]) {
+				fibril_mutex_unlock(&vfs_data->lock);
 				return ENOMEM;
 			}
 			
-			memset(FILES[i], 0, sizeof(vfs_file_t));
-			fibril_mutex_initialize(&FILES[i]->lock);
-			vfs_file_addref(FILES[i]);
-			fibril_mutex_unlock(&VFS_DATA->lock);
+			memset(vfs_data->files[i], 0, sizeof(vfs_file_t));
+			fibril_mutex_initialize(&vfs_data->files[i]->lock);
+			vfs_file_addref(vfs_data, vfs_data->files[i]);
+			fibril_mutex_unlock(&vfs_data->lock);
 			return (int) i;
 		}
@@ -210,7 +224,40 @@
 		}
 	}
-	fibril_mutex_unlock(&VFS_DATA->lock);
+	fibril_mutex_unlock(&vfs_data->lock);
 	
 	return EMFILE;
+}
+
+/** Allocate a file descriptor.
+ *
+ * @param desc If true, look for an available file descriptor
+ *             in a descending order.
+ *
+ * @return First available file descriptor or a negative error
+ *         code.
+ */
+int vfs_fd_alloc(bool desc)
+{
+	return _vfs_fd_alloc(VFS_DATA, desc);
+}
+
+static int _vfs_fd_free(vfs_client_data_t *vfs_data, int fd)
+{
+	int rc;
+
+	if (!vfs_files_init(vfs_data))
+		return ENOMEM;
+
+	fibril_mutex_lock(&vfs_data->lock);	
+	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || !vfs_data->files[fd]) {
+		fibril_mutex_unlock(&vfs_data->lock);
+		return EBADF;
+	}
+	
+	rc = vfs_file_delref(vfs_data, vfs_data->files[fd]);
+	vfs_data->files[fd] = NULL;
+	fibril_mutex_unlock(&vfs_data->lock);
+	
+	return rc;
 }
 
@@ -224,20 +271,5 @@
 int vfs_fd_free(int fd)
 {
-	int rc;
-
-	if (!vfs_files_init())
-		return ENOMEM;
-
-	fibril_mutex_lock(&VFS_DATA->lock);	
-	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] == NULL)) {
-		fibril_mutex_unlock(&VFS_DATA->lock);
-		return EBADF;
-	}
-	
-	rc = vfs_file_delref(FILES[fd]);
-	FILES[fd] = NULL;
-	fibril_mutex_unlock(&VFS_DATA->lock);
-	
-	return rc;
+	return _vfs_fd_free(VFS_DATA, fd);
 }
 
@@ -253,5 +285,5 @@
 int vfs_fd_assign(vfs_file_t *file, int fd)
 {
-	if (!vfs_files_init())
+	if (!vfs_files_init(VFS_DATA))
 		return ENOMEM;
 
@@ -263,5 +295,5 @@
 	
 	FILES[fd] = file;
-	vfs_file_addref(FILES[fd]);
+	vfs_file_addref(VFS_DATA, FILES[fd]);
 	fibril_mutex_unlock(&VFS_DATA->lock);
 	
@@ -269,29 +301,41 @@
 }
 
-/** Find VFS file structure for a given file descriptor.
- *
- * @param fd		File descriptor.
- *
- * @return		VFS file structure corresponding to fd.
- */
-vfs_file_t *vfs_file_get(int fd)
-{
-	if (!vfs_files_init())
+static vfs_file_t *_vfs_file_get(vfs_client_data_t *vfs_data, int fd)
+{
+	if (!vfs_files_init(vfs_data))
 		return NULL;
 	
-	fibril_mutex_lock(&VFS_DATA->lock);
+	fibril_mutex_lock(&vfs_data->lock);
 	if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
-		vfs_file_t *file = FILES[fd];
+		vfs_file_t *file = vfs_data->files[fd];
 		if (file != NULL) {
-			vfs_file_addref(file);
-			fibril_mutex_unlock(&VFS_DATA->lock);
+			vfs_file_addref(vfs_data, file);
+			fibril_mutex_unlock(&vfs_data->lock);
 			return file;
 		}
 	}
-	fibril_mutex_unlock(&VFS_DATA->lock);
+	fibril_mutex_unlock(&vfs_data->lock);
 	
 	return NULL;
 }
 
+/** Find VFS file structure for a given file descriptor.
+ *
+ * @param fd		File descriptor.
+ *
+ * @return		VFS file structure corresponding to fd.
+ */
+vfs_file_t *vfs_file_get(int fd)
+{
+	return _vfs_file_get(VFS_DATA, fd);
+}
+
+static void _vfs_file_put(vfs_client_data_t *vfs_data, vfs_file_t *file)
+{
+	fibril_mutex_lock(&vfs_data->lock);
+	vfs_file_delref(vfs_data, file);
+	fibril_mutex_unlock(&vfs_data->lock);
+}
+
 /** Stop using a file structure.
  *
@@ -300,7 +344,90 @@
 void vfs_file_put(vfs_file_t *file)
 {
-	fibril_mutex_lock(&VFS_DATA->lock);
-	vfs_file_delref(file);
-	fibril_mutex_unlock(&VFS_DATA->lock);
+	_vfs_file_put(VFS_DATA, file);
+}
+
+void vfs_pass_handle(task_id_t donor_id, task_id_t acceptor_id, int donor_fd)
+{
+	vfs_client_data_t *donor_data = NULL;
+	vfs_client_data_t *acceptor_data = NULL;
+	vfs_file_t *donor_file = NULL;
+	vfs_file_t *acceptor_file = NULL;
+	vfs_boxed_handle_t *bh;
+	int acceptor_fd;
+
+	acceptor_data = async_get_client_data_by_id(acceptor_id);
+	if (!acceptor_data)
+		return;
+
+	bh = malloc(sizeof(vfs_boxed_handle_t));
+	assert(bh);
+
+	link_initialize(&bh->link);
+	bh->handle = -1;
+
+	donor_data = async_get_client_data_by_id(donor_id);
+	if (!donor_data)
+		goto out;
+
+	donor_file = _vfs_file_get(donor_data, donor_fd);
+	if (!donor_file)
+		goto out;
+
+	acceptor_fd = _vfs_fd_alloc(acceptor_data, false);
+	if (acceptor_fd < 0)
+		goto out;
+
+	bh->handle = acceptor_fd;
+
+	/*
+	 * Add a new reference to the underlying VFS node.
+	 */
+	vfs_node_addref(donor_file->node);
+	(void) vfs_open_node_remote(donor_file->node);
+
+	acceptor_file = _vfs_file_get(acceptor_data, acceptor_fd);
+	assert(acceptor_file);
+
+	/*
+	 * Inherit attributes from the donor.
+	 */
+	acceptor_file->node = donor_file->node;
+	acceptor_file->append = donor_file->append;
+	acceptor_file->pos = donor_file->pos;
+
+out:
+	fibril_mutex_lock(&acceptor_data->lock);
+	list_append(&bh->link, &acceptor_data->passed_handles);
+	fibril_condvar_broadcast(&acceptor_data->cv);
+	fibril_mutex_unlock(&acceptor_data->lock);
+
+	if (donor_data)
+		async_put_client_data_by_id(donor_id);
+	if (acceptor_data)
+		async_put_client_data_by_id(acceptor_id);
+	if (donor_file)
+		_vfs_file_put(donor_data, donor_file);
+	if (acceptor_file)
+		_vfs_file_put(acceptor_data, acceptor_file);
+
+}
+
+int vfs_wait_handle_internal(void)
+{
+	vfs_client_data_t *vfs_data = VFS_DATA;	
+	int fd;
+	
+	fibril_mutex_lock(&vfs_data->lock);
+	while (list_empty(&vfs_data->passed_handles))
+		fibril_condvar_wait(&vfs_data->cv, &vfs_data->lock);
+	link_t *lnk = list_first(&vfs_data->passed_handles);
+	list_remove(lnk);
+	fibril_mutex_unlock(&vfs_data->lock);
+
+	vfs_boxed_handle_t *bh = list_get_instance(lnk, vfs_boxed_handle_t, link);
+	fd = bh->handle;
+	free(bh);
+
+	return fd;
 }
 
Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/vfs/vfs_lookup.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -162,5 +162,5 @@
 	aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first,
 	    (sysarg_t) (first + len - 1) % PLB_SIZE,
-	    (sysarg_t) root->devmap_handle, (sysarg_t) lflag, (sysarg_t) index,
+	    (sysarg_t) root->service_id, (sysarg_t) lflag, (sysarg_t) index,
 	    &answer);
 	
@@ -185,5 +185,5 @@
 	
 	result->triplet.fs_handle = (fs_handle_t) rc;
-	result->triplet.devmap_handle = (devmap_handle_t) IPC_GET_ARG1(answer);
+	result->triplet.service_id = (service_id_t) IPC_GET_ARG1(answer);
 	result->triplet.index = (fs_index_t) IPC_GET_ARG2(answer);
 	result->size =
@@ -201,37 +201,4 @@
 }
 
-/** Perform a node open operation.
- *
- * @return EOK on success or an error code from errno.h.
- *
- */
-int vfs_open_node_internal(vfs_lookup_res_t *result)
-{
-	async_exch_t *exch = vfs_exchange_grab(result->triplet.fs_handle);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(exch, VFS_OUT_OPEN_NODE,
-	    (sysarg_t) result->triplet.devmap_handle,
-	    (sysarg_t) result->triplet.index, &answer);
-	
-	sysarg_t rc;
-	async_wait_for(req, &rc);
-	vfs_exchange_release(exch);
-	
-	if (rc == EOK) {
-		result->size =
-		    MERGE_LOUP32(IPC_GET_ARG1(answer), IPC_GET_ARG2(answer));
-		result->lnkcnt = (unsigned int) IPC_GET_ARG3(answer);
-		if (IPC_GET_ARG4(answer) & L_FILE)
-			result->type = VFS_NODE_FILE;
-		else if (IPC_GET_ARG4(answer) & L_DIRECTORY)
-			result->type = VFS_NODE_DIRECTORY;
-		else
-			result->type = VFS_NODE_UNKNOWN;
-	}
-	
-	return rc;
-}
-
 /**
  * @}
Index: uspace/srv/vfs/vfs_node.c
===================================================================
--- uspace/srv/vfs/vfs_node.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/vfs/vfs_node.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -116,5 +116,5 @@
 		unsigned long key[] = {
 			[KEY_FS_HANDLE] = node->fs_handle,
-			[KEY_DEV_HANDLE] = node->devmap_handle,
+			[KEY_DEV_HANDLE] = node->service_id,
 			[KEY_INDEX] = node->index
 		};
@@ -138,5 +138,5 @@
 		async_exch_t *exch = vfs_exchange_grab(node->fs_handle);
 		sysarg_t rc = async_req_2_0(exch, VFS_OUT_DESTROY,
-		    (sysarg_t) node->devmap_handle, (sysarg_t)node->index);
+		    (sysarg_t) node->service_id, (sysarg_t)node->index);
 		
 		assert(rc == EOK);
@@ -160,5 +160,5 @@
 	unsigned long key[] = {
 		[KEY_FS_HANDLE] = node->fs_handle,
-		[KEY_DEV_HANDLE] = node->devmap_handle,
+		[KEY_DEV_HANDLE] = node->service_id,
 		[KEY_INDEX] = node->index
 	};
@@ -184,5 +184,5 @@
 	unsigned long key[] = {
 		[KEY_FS_HANDLE] = result->triplet.fs_handle,
-		[KEY_DEV_HANDLE] = result->triplet.devmap_handle,
+		[KEY_DEV_HANDLE] = result->triplet.service_id,
 		[KEY_INDEX] = result->triplet.index
 	};
@@ -200,5 +200,5 @@
 		memset(node, 0, sizeof(vfs_node_t));
 		node->fs_handle = result->triplet.fs_handle;
-		node->devmap_handle = result->triplet.devmap_handle;
+		node->service_id = result->triplet.service_id;
 		node->index = result->triplet.index;
 		node->size = result->size;
@@ -252,5 +252,5 @@
 	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->devmap_handle == key[KEY_DEV_HANDLE]) &&
+	    (node->service_id == key[KEY_DEV_HANDLE]) &&
 	    (node->index == key[KEY_INDEX]);
 }
@@ -264,5 +264,5 @@
 	unsigned refcnt;
 	fs_handle_t fs_handle;
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 };
 
@@ -273,15 +273,15 @@
 
 	if ((node->fs_handle == rd->fs_handle) &&
-	    (node->devmap_handle == rd->devmap_handle))
+	    (node->service_id == rd->service_id))
 		rd->refcnt += node->refcnt;
 }
 
 unsigned
-vfs_nodes_refcount_sum_get(fs_handle_t fs_handle, devmap_handle_t devmap_handle)
+vfs_nodes_refcount_sum_get(fs_handle_t fs_handle, service_id_t service_id)
 {
 	struct refcnt_data rd = {
 		.refcnt = 0,
 		.fs_handle = fs_handle,
-		.devmap_handle = devmap_handle
+		.service_id = service_id
 	};
 
@@ -291,4 +291,26 @@
 
 	return rd.refcnt;
+}
+
+
+/** Perform a remote node open operation.
+ *
+ * @return EOK on success or an error code from errno.h.
+ *
+ */
+int vfs_open_node_remote(vfs_node_t *node)
+{
+	async_exch_t *exch = vfs_exchange_grab(node->fs_handle);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, VFS_OUT_OPEN_NODE,
+	    (sysarg_t) node->service_id, (sysarg_t) node->index, &answer);
+	
+	vfs_exchange_release(exch);
+
+	sysarg_t rc;
+	async_wait_for(req, &rc);
+	
+	return rc;
 }
 
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/vfs/vfs_ops.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -54,5 +54,5 @@
 
 /* Forward declarations of static functions. */
-static int vfs_truncate_internal(fs_handle_t, devmap_handle_t, fs_index_t,
+static int vfs_truncate_internal(fs_handle_t, service_id_t, fs_index_t,
     aoff64_t);
 
@@ -65,8 +65,8 @@
 vfs_pair_t rootfs = {
 	.fs_handle = 0,
-	.devmap_handle = 0
+	.service_id = 0
 };
 
-static void vfs_mount_internal(ipc_callid_t rid, devmap_handle_t devmap_handle,
+static void vfs_mount_internal(ipc_callid_t rid, service_id_t service_id,
     fs_handle_t fs_handle, char *mp, char *opts)
 {
@@ -76,5 +76,5 @@
 	vfs_node_t *mr_node;
 	fs_index_t rindex;
-	size_t rsize;
+	aoff64_t rsize;
 	unsigned rlnkcnt;
 	async_exch_t *exch;
@@ -125,5 +125,5 @@
 			exch = vfs_exchange_grab(fs_handle);
 			msg = async_send_1(exch, VFS_OUT_MOUNTED,
-			    (sysarg_t) devmap_handle, &answer);
+			    (sysarg_t) service_id, &answer);
 			/* Send the mount options */
 			rc = async_data_write_start(exch, (void *)opts,
@@ -146,9 +146,9 @@
 
 			rindex = (fs_index_t) IPC_GET_ARG1(answer);
-			rsize = (size_t) IPC_GET_ARG2(answer);
-			rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
+			rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer), IPC_GET_ARG3(answer));
+			rlnkcnt = (unsigned) IPC_GET_ARG4(answer);
 			
 			mr_res.triplet.fs_handle = fs_handle;
-			mr_res.triplet.devmap_handle = devmap_handle;
+			mr_res.triplet.service_id = service_id;
 			mr_res.triplet.index = rindex;
 			mr_res.size = rsize;
@@ -157,5 +157,5 @@
 			
 			rootfs.fs_handle = fs_handle;
-			rootfs.devmap_handle = devmap_handle;
+			rootfs.service_id = service_id;
 			
 			/* Add reference to the mounted root. */
@@ -178,6 +178,6 @@
 	
 	/*
-	 * At this point, we have all necessary pieces: file system and device
-	 * handles, and we know the mount point VFS node.
+	 * At this point, we have all necessary pieces: file system handle
+	 * and service ID, and we know the mount point VFS node.
 	 */
 	
@@ -187,8 +187,8 @@
 	exch = vfs_exchange_grab(mp_res.triplet.fs_handle);
 	msg = async_send_4(exch, VFS_OUT_MOUNT,
-	    (sysarg_t) mp_res.triplet.devmap_handle,
+	    (sysarg_t) mp_res.triplet.service_id,
 	    (sysarg_t) mp_res.triplet.index,
 	    (sysarg_t) fs_handle,
-	    (sysarg_t) devmap_handle, &answer);
+	    (sysarg_t) service_id, &answer);
 	
 	/* Send connection */
@@ -229,9 +229,10 @@
 	if (rc == EOK) {
 		rindex = (fs_index_t) IPC_GET_ARG1(answer);
-		rsize = (size_t) IPC_GET_ARG2(answer);
-		rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
+		rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer),
+		    IPC_GET_ARG3(answer));
+		rlnkcnt = (unsigned) IPC_GET_ARG4(answer);
 		
 		mr_res.triplet.fs_handle = fs_handle;
-		mr_res.triplet.devmap_handle = devmap_handle;
+		mr_res.triplet.service_id = service_id;
 		mr_res.triplet.index = rindex;
 		mr_res.size = rsize;
@@ -254,5 +255,5 @@
 void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
 {
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 
 	/*
@@ -261,5 +262,5 @@
 	 * in the request.
 	 */
-	devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+	service_id = (service_id_t) IPC_GET_ARG1(*request);
 	
 	/*
@@ -349,5 +350,5 @@
 	
 	/* Do the mount */
-	vfs_mount_internal(rid, devmap_handle, fs_handle, mp, opts);
+	vfs_mount_internal(rid, service_id, fs_handle, mp, opts);
 	free(mp);
 	free(fs_name);
@@ -408,5 +409,5 @@
 	 */
 	if (vfs_nodes_refcount_sum_get(mr_node->fs_handle,
-	    mr_node->devmap_handle) != 2) {
+	    mr_node->service_id) != 2) {
 		fibril_rwlock_write_unlock(&namespace_rwlock);
 		vfs_node_put(mr_node);
@@ -429,5 +430,5 @@
 		exch = vfs_exchange_grab(mr_node->fs_handle);
 		rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED,
-		    mr_node->devmap_handle);
+		    mr_node->service_id);
 		vfs_exchange_release(exch);
 		
@@ -440,5 +441,5 @@
 		
 		rootfs.fs_handle = 0;
-		rootfs.devmap_handle = 0;
+		rootfs.service_id = 0;
 	} else {
 		
@@ -469,5 +470,5 @@
 		exch = vfs_exchange_grab(mp_node->fs_handle);
 		rc = async_req_2_0(exch, VFS_OUT_UNMOUNT,
-		    mp_node->devmap_handle, mp_node->index);
+		    mp_node->service_id, mp_node->index);
 		vfs_exchange_release(exch);
 		
@@ -574,5 +575,5 @@
 		if (node->size) {
 			rc = vfs_truncate_internal(node->fs_handle,
-			    node->devmap_handle, node->index, 0);
+			    node->service_id, node->index, 0);
 			if (rc) {
 				fibril_rwlock_write_unlock(&node->contents_rwlock);
@@ -617,77 +618,4 @@
 }
 
-void vfs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	// FIXME: check for sanity of the supplied fs, dev and index
-	
-	/*
-	 * The interface is open_node(fs, dev, index, oflag).
-	 */
-	vfs_lookup_res_t lr;
-	
-	lr.triplet.fs_handle = IPC_GET_ARG1(*request);
-	lr.triplet.devmap_handle = IPC_GET_ARG2(*request);
-	lr.triplet.index = IPC_GET_ARG3(*request);
-	int oflag = IPC_GET_ARG4(*request);
-	
-	fibril_rwlock_read_lock(&namespace_rwlock);
-	
-	int rc = vfs_open_node_internal(&lr);
-	if (rc != EOK) {
-		fibril_rwlock_read_unlock(&namespace_rwlock);
-		async_answer_0(rid, rc);
-		return;
-	}
-	
-	vfs_node_t *node = vfs_node_get(&lr);
-	fibril_rwlock_read_unlock(&namespace_rwlock);
-	
-	/* Truncate the file if requested and if necessary. */
-	if (oflag & O_TRUNC) {
-		fibril_rwlock_write_lock(&node->contents_rwlock);
-		if (node->size) {
-			rc = vfs_truncate_internal(node->fs_handle,
-			    node->devmap_handle, node->index, 0);
-			if (rc) {
-				fibril_rwlock_write_unlock(&node->contents_rwlock);
-				vfs_node_put(node);
-				async_answer_0(rid, rc);
-				return;
-			}
-			node->size = 0;
-		}
-		fibril_rwlock_write_unlock(&node->contents_rwlock);
-	}
-	
-	/*
-	 * Get ourselves a file descriptor and the corresponding vfs_file_t
-	 * structure.
-	 */
-	int fd = vfs_fd_alloc((oflag & O_DESC) != 0);
-	if (fd < 0) {
-		vfs_node_put(node);
-		async_answer_0(rid, fd);
-		return;
-	}
-	vfs_file_t *file = vfs_file_get(fd);
-	file->node = node;
-	if (oflag & O_APPEND)
-		file->append = true;
-	
-	/*
-	 * The following increase in reference count is for the fact that the
-	 * file is being opened and that a file structure is pointing to it.
-	 * It is necessary so that the file will not disappear when
-	 * vfs_node_put() is called. The reference will be dropped by the
-	 * respective VFS_IN_CLOSE.
-	 */
-	vfs_node_addref(node);
-	vfs_node_put(node);
-	vfs_file_put(file);
-	
-	/* Success! Return the new file descriptor to the client. */
-	async_answer_1(rid, EOK, fd);
-}
-
 void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
 {
@@ -711,5 +639,5 @@
 	aid_t msg;
 	ipc_call_t answer;
-	msg = async_send_2(fs_exch, VFS_OUT_SYNC, file->node->devmap_handle,
+	msg = async_send_2(fs_exch, VFS_OUT_SYNC, file->node->service_id,
 	    file->node->index, &answer);
 	
@@ -795,14 +723,14 @@
 	ipc_call_t answer;
 	if (read) {
-		rc = async_data_read_forward_3_1(fs_exch, VFS_OUT_READ,
-		    file->node->devmap_handle, file->node->index, file->pos,
-		    &answer);
+		rc = async_data_read_forward_4_1(fs_exch, VFS_OUT_READ,
+		    file->node->service_id, file->node->index,
+		    LOWER32(file->pos), UPPER32(file->pos), &answer);
 	} else {
 		if (file->append)
 			file->pos = file->node->size;
 		
-		rc = async_data_write_forward_3_1(fs_exch, VFS_OUT_WRITE,
-		    file->node->devmap_handle, file->node->index, file->pos,
-		    &answer);
+		rc = async_data_write_forward_4_1(fs_exch, VFS_OUT_WRITE,
+		    file->node->service_id, file->node->index,
+		    LOWER32(file->pos), UPPER32(file->pos), &answer);
 	}
 	
@@ -821,5 +749,6 @@
 		/* Update the cached version of node's size. */
 		if (rc == EOK)
-			file->node->size = IPC_GET_ARG2(answer); 
+			file->node->size = MERGE_LOUP32(IPC_GET_ARG2(answer),
+			    IPC_GET_ARG3(answer));
 		fibril_rwlock_write_unlock(&file->node->contents_rwlock);
 	}
@@ -933,10 +862,10 @@
 }
 
-int vfs_truncate_internal(fs_handle_t fs_handle, devmap_handle_t devmap_handle,
+int vfs_truncate_internal(fs_handle_t fs_handle, service_id_t service_id,
     fs_index_t index, aoff64_t size)
 {
 	async_exch_t *exch = vfs_exchange_grab(fs_handle);
 	sysarg_t rc = async_req_4_0(exch, VFS_OUT_TRUNCATE,
-	    (sysarg_t) devmap_handle, (sysarg_t) index, LOWER32(size),
+	    (sysarg_t) service_id, (sysarg_t) index, LOWER32(size),
 	    UPPER32(size));
 	vfs_exchange_release(exch);
@@ -961,5 +890,5 @@
 	fibril_rwlock_write_lock(&file->node->contents_rwlock);
 	rc = vfs_truncate_internal(file->node->fs_handle,
-	    file->node->devmap_handle, file->node->index, size);
+	    file->node->service_id, file->node->index, size);
 	if (rc == EOK)
 		file->node->size = size;
@@ -995,5 +924,5 @@
 	
 	aid_t msg;
-	msg = async_send_3(exch, VFS_OUT_STAT, file->node->devmap_handle,
+	msg = async_send_3(exch, VFS_OUT_STAT, file->node->service_id,
 	    file->node->index, true, NULL);
 	async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
@@ -1048,5 +977,5 @@
 	
 	aid_t msg;
-	msg = async_send_3(exch, VFS_OUT_STAT, node->devmap_handle,
+	msg = async_send_3(exch, VFS_OUT_STAT, node->service_id,
 	    node->index, false, NULL);
 	async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
@@ -1225,5 +1154,5 @@
 	/* Check whether linking to the same file system instance. */
 	if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
-	    (old_node->devmap_handle != new_par_lr.triplet.devmap_handle)) {
+	    (old_node->service_id != new_par_lr.triplet.service_id)) {
 		fibril_rwlock_write_unlock(&namespace_rwlock);
 		vfs_node_put(old_node);
@@ -1347,4 +1276,10 @@
 }
 
+void vfs_wait_handle(ipc_callid_t rid, ipc_call_t *request)
+{
+	int fd = vfs_wait_handle_internal();
+	async_answer_1(rid, EOK, fd);
+}
+
 /**
  * @}
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 86a34d3e4d287b5a98f96a5b7e0a0a001d5529f8)
+++ uspace/srv/vfs/vfs_register.c	(revision bd5f3b795b75802e7f957c9589605a904f7667df)
@@ -306,5 +306,5 @@
 	list_foreach(fs_list, cur) {
 		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
-		if (str_cmp(fs->vfs_info.name, name) == 0) { 
+		if (str_cmp(fs->vfs_info.name, name) == 0) {
 			handle = fs->fs_handle;
 			break;
