Index: uspace/lib/c/generic/ddi.c
===================================================================
--- uspace/lib/c/generic/ddi.c	(revision bd88bee745abe1948dac683975e4b015ecdfaf39)
+++ uspace/lib/c/generic/ddi.c	(revision b243da3434115a8101e3ebac364a0a3b75aaf102)
@@ -42,4 +42,7 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
+#include <device/hw_res.h>
+#include <device/hw_res_parsed.h>
+#include <device/pio_window.h>
 #include <libc.h>
 #include <task.h>
@@ -134,4 +137,56 @@
 	
 	return __SYSCALL1(SYS_IOSPACE_ENABLE, (sysarg_t) &arg);
+}
+
+/** Enable PIO for specified address range.
+ *
+ * @param range I/O range to be enable.
+ * @param virt  Virtual address for application's PIO operations. 
+ */
+int pio_enable_range(addr_range_t *range, void **virt)
+{
+	return pio_enable(RNGABSPTR(*range), RNGSZ(*range), virt);
+}
+
+/** Enable PIO for specified HW resource wrt. to the PIO window.
+ *
+ * @param win      PIO window. May be NULL if the resources are known to be
+ *                 absolute.
+ * @param res      Resources specifying the I/O range wrt. to the PIO window.
+ * @param virt     Virtual address for application's PIO operations.
+ *
+ * @return EOK on success.
+ * @return Negative error code on failure.
+ *
+ */
+int pio_enable_resource(pio_window_t *win, hw_resource_t *res, void **virt)
+{
+	uintptr_t addr;
+	size_t size;
+
+	switch (res->type) {
+	case IO_RANGE:
+		addr = res->res.io_range.address;
+		if (res->res.io_range.relative) {
+			if (!win)
+				return EINVAL;
+			addr += win->io.base;
+		}
+		size = res->res.io_range.size;
+		break;
+	case MEM_RANGE:
+		addr = res->res.mem_range.address;
+		if (res->res.mem_range.relative) {
+			if (!win)
+				return EINVAL;
+			addr += win->mem.base;
+		}
+		size = res->res.mem_range.size;
+		break;
+	default:
+		return EINVAL;
+	}
+
+	return pio_enable((void *) addr, size, virt);	
 }
 
Index: uspace/lib/c/generic/device/hw_res_parsed.c
===================================================================
--- uspace/lib/c/generic/device/hw_res_parsed.c	(revision bd88bee745abe1948dac683975e4b015ecdfaf39)
+++ uspace/lib/c/generic/device/hw_res_parsed.c	(revision b243da3434115a8101e3ebac364a0a3b75aaf102)
@@ -80,12 +80,36 @@
 }
 
+static uint64_t absolutize(uint64_t addr, bool relative, uint64_t base)
+{
+	if (!relative)
+		return addr;
+	else
+		return addr + base;
+}
+
+static uint64_t relativize(uint64_t addr, bool relative, uint64_t base)
+{
+	if (relative)
+		return addr;
+	else
+		return addr - base;
+}
+
 static void hw_res_parse_add_io_range(hw_res_list_parsed_t *out,
-    const hw_resource_t *res, int flags)
-{
+    const pio_window_t *win, const hw_resource_t *res, int flags)
+{
+	endianness_t endianness;
+	uint64_t absolute;
+	uint64_t relative;
+	size_t size;
+
 	assert(res && (res->type == IO_RANGE));
 	
-	uint64_t address = res->res.io_range.address;
-	endianness_t endianness = res->res.io_range.endianness;
-	size_t size = res->res.io_range.size;
+	absolute = absolutize(res->res.io_range.address,
+	    res->res.io_range.relative, win->io.base);
+	relative = relativize(res->res.io_range.address,
+	    res->res.io_range.relative, win->io.base);
+	size = res->res.io_range.size;
+	endianness = res->res.io_range.endianness;
 	
 	if ((size == 0) && (!(flags & HW_RES_KEEP_ZERO_AREA)))
@@ -97,26 +121,38 @@
 	if (!keep_duplicit) {
 		for (size_t i = 0; i < count; i++) {
-			uint64_t s_address = out->io_ranges.ranges[i].address;
-			size_t s_size = out->io_ranges.ranges[i].size;
+			uint64_t s_address;
+			size_t s_size;
+
+			s_address = RNGABS(out->io_ranges.ranges[i]);
+			s_size = RNGSZ(out->io_ranges.ranges[i]);
 			
-			if ((address == s_address) && (size == s_size))
-				return;
-		}
-	}
-	
-	out->io_ranges.ranges[count].address = address;
+			if ((absolute == s_address) && (size == s_size))
+				return;
+		}
+	}
+	
+	RNGABS(out->io_ranges.ranges[count]) = absolute;
+	RNGREL(out->io_ranges.ranges[count]) = relative;
+	RNGSZ(out->io_ranges.ranges[count]) = size;
 	out->io_ranges.ranges[count].endianness = endianness;
-	out->io_ranges.ranges[count].size = size;
 	out->io_ranges.count++;
 }
 
 static void hw_res_parse_add_mem_range(hw_res_list_parsed_t *out,
-    const hw_resource_t *res, int flags)
-{
+    const pio_window_t *win, const hw_resource_t *res, int flags)
+{
+	endianness_t endianness;
+	uint64_t absolute;
+	uint64_t relative;
+	size_t size;
+	
 	assert(res && (res->type == MEM_RANGE));
 	
-	uint64_t address = res->res.mem_range.address;
-	endianness_t endianness = res->res.mem_range.endianness;
-	size_t size = res->res.mem_range.size;
+	absolute = absolutize(res->res.mem_range.address,
+	    res->res.mem_range.relative, win->mem.base);
+	relative = relativize(res->res.mem_range.address,
+	    res->res.mem_range.relative, win->mem.base);
+	size = res->res.mem_range.size;
+	endianness = res->res.mem_range.endianness;
 	
 	if ((size == 0) && (!(flags & HW_RES_KEEP_ZERO_AREA)))
@@ -128,15 +164,19 @@
 	if (!keep_duplicit) {
 		for (size_t i = 0; i < count; ++i) {
-			uint64_t s_address = out->mem_ranges.ranges[i].address;
-			size_t s_size = out->mem_ranges.ranges[i].size;
+			uint64_t s_address;
+			size_t s_size;
+
+			s_address = RNGABS(out->mem_ranges.ranges[i]);;
+			s_size = RNGSZ(out->mem_ranges.ranges[i]);
 			
-			if ((address == s_address) && (size == s_size))
-				return;
-		}
-	}
-	
-	out->mem_ranges.ranges[count].address = address;
+			if ((absolute == s_address) && (size == s_size))
+				return;
+		}
+	}
+	
+	RNGABS(out->mem_ranges.ranges[count]) = absolute;
+	RNGREL(out->mem_ranges.ranges[count]) = relative;
+	RNGSZ(out->mem_ranges.ranges[count]) = size;
 	out->mem_ranges.ranges[count].endianness = endianness;
-	out->mem_ranges.ranges[count].size = size;
 	out->mem_ranges.count++;
 }
@@ -144,21 +184,21 @@
 /** Parse list of hardware resources
  *
- * @param      hw_resources Original structure resource
- * @param[out] out          Output parsed resources
- * @param      flags        Flags of the parsing.
- *                          HW_RES_KEEP_ZERO_AREA for keeping
- *                          zero-size areas, HW_RES_KEEP_DUPLICITIES
- *                          for keep duplicit areas
+ * @param      win          PIO window.
+ * @param      res          Original structure resource.
+ * @param[out] out          Output parsed resources.
+ * @param      flags        Flags of the parsing:
+ *                          HW_RES_KEEP_ZERO_AREA for keeping zero-size areas,
+ *                          HW_RES_KEEP_DUPLICITIES to keep duplicit areas.
  *
  * @return EOK if succeed, error code otherwise.
  *
  */
-int hw_res_list_parse(const hw_resource_list_t *hw_resources,
-    hw_res_list_parsed_t *out, int flags)
-{
-	if ((!hw_resources) || (!out))
+int hw_res_list_parse(const pio_window_t *win,
+    const hw_resource_list_t *res, hw_res_list_parsed_t *out, int flags)
+{
+	if (!res || !out)
 		return EINVAL;
 	
-	size_t res_count = hw_resources->count;
+	size_t res_count = res->count;
 	hw_res_list_parsed_clean(out);
 	
@@ -174,5 +214,5 @@
 	
 	for (size_t i = 0; i < res_count; ++i) {
-		const hw_resource_t *resource = &(hw_resources->resources[i]);
+		const hw_resource_t *resource = &res->resources[i];
 		
 		switch (resource->type) {
@@ -181,8 +221,8 @@
 			break;
 		case IO_RANGE:
-			hw_res_parse_add_io_range(out, resource, flags);
+			hw_res_parse_add_io_range(out, win, resource, flags);
 			break;
 		case MEM_RANGE:
-			hw_res_parse_add_mem_range(out, resource, flags);
+			hw_res_parse_add_mem_range(out, win, resource, flags);
 			break;
 		case DMA_CHANNEL_8:
@@ -216,4 +256,7 @@
     hw_res_list_parsed_t *hw_res_parsed, int flags)
 {
+	pio_window_t pio_window;
+	int rc;
+
 	if (!hw_res_parsed)
 		return EBADMEM;
@@ -222,10 +265,15 @@
 	hw_res_list_parsed_clean(hw_res_parsed);
 	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
-	
-	int rc = hw_res_get_resource_list(sess, &hw_resources);
+
+	rc = pio_window_get(sess, &pio_window);
+	if (rc != EOK)
+		return rc; 
+	
+	rc = hw_res_get_resource_list(sess, &hw_resources);
 	if (rc != EOK)
 		return rc;
-	
-	rc = hw_res_list_parse(&hw_resources, hw_res_parsed, flags);
+
+	rc = hw_res_list_parse(&pio_window, &hw_resources, hw_res_parsed,
+	    flags);
 	hw_res_clean_resource_list(&hw_resources);
 	
Index: uspace/lib/c/generic/io/asprintf.c
===================================================================
--- uspace/lib/c/generic/io/asprintf.c	(revision bd88bee745abe1948dac683975e4b015ecdfaf39)
+++ uspace/lib/c/generic/io/asprintf.c	(revision b243da3434115a8101e3ebac364a0a3b75aaf102)
@@ -50,4 +50,25 @@
 }
 
+int vprintf_size(const char *fmt, va_list args)
+{
+	printf_spec_t ps = {
+		asprintf_str_write,
+		asprintf_wstr_write,
+		NULL
+	};
+	
+	return printf_core(fmt, &ps, args);
+}
+
+int printf_size(const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	int ret = vprintf_size(fmt, args);
+	va_end(args);
+	
+	return ret;
+}
+
 /** Allocate and print to string.
  *
@@ -61,14 +82,7 @@
 int asprintf(char **strp, const char *fmt, ...)
 {
-	printf_spec_t ps = {
-		asprintf_str_write,
-		asprintf_wstr_write,
-		NULL
-	};
-	
 	va_list args;
 	va_start(args, fmt);
-	
-	int ret = printf_core(fmt, &ps, args);
+	int ret = vprintf_size(fmt, args);
 	va_end(args);
 	
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision bd88bee745abe1948dac683975e4b015ecdfaf39)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision b243da3434115a8101e3ebac364a0a3b75aaf102)
@@ -893,41 +893,28 @@
 }
 
-int statfs(const char *path, struct statfs *statfs)
-{
-	sysarg_t rc;
-	sysarg_t rc_orig;
+int statfs(const char *path, struct statfs *st)
+{
+	sysarg_t rc, rc_orig;
 	aid_t req;
 	size_t pa_size;
-	
+
 	char *pa = absolutize(path, &pa_size);
 	if (!pa)
 		return ENOMEM;
-	async_exch_t *exch = vfs_exchange_begin();
-	
+
+	async_exch_t *exch = vfs_exchange_begin();
+
 	req = async_send_0(exch, VFS_IN_STATFS, NULL);
 	rc = async_data_write_start(exch, pa, pa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(exch);
-		free(pa);
-		async_wait_for(req, &rc_orig);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	rc = async_data_read_start(exch, (void *) statfs, sizeof(struct statfs));
-	if (rc != EOK) {
-		vfs_exchange_end(exch);
-		free(pa);
-		async_wait_for(req, &rc_orig);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
+	if (rc != EOK)
+		goto exit;
+
+	rc = async_data_read_start(exch, (void *) st, sizeof(*st));
+
+exit:
 	vfs_exchange_end(exch);
 	free(pa);
-	async_wait_for(req, &rc);
-	return rc;
+	async_wait_for(req, &rc_orig);
+	return (int) (rc_orig != EOK ? rc_orig : rc);
 }
 
Index: uspace/lib/c/include/ddi.h
===================================================================
--- uspace/lib/c/include/ddi.h	(revision bd88bee745abe1948dac683975e4b015ecdfaf39)
+++ uspace/lib/c/include/ddi.h	(revision b243da3434115a8101e3ebac364a0a3b75aaf102)
@@ -40,4 +40,7 @@
 #include <sys/time.h>
 #include <abi/ddi/irq.h>
+#include <device/hw_res.h>
+#include <device/hw_res_parsed.h>
+#include <device/pio_window.h>
 #include <task.h>
 
@@ -55,4 +58,6 @@
 extern int dmamem_unmap_anonymous(void *);
 
+extern int pio_enable_range(addr_range_t *, void **);
+extern int pio_enable_resource(pio_window_t *, hw_resource_t *, void **);
 extern int pio_enable(void *, size_t, void **);
 
Index: uspace/lib/c/include/device/hw_res.h
===================================================================
--- uspace/lib/c/include/device/hw_res.h	(revision bd88bee745abe1948dac683975e4b015ecdfaf39)
+++ uspace/lib/c/include/device/hw_res.h	(revision b243da3434115a8101e3ebac364a0a3b75aaf102)
@@ -76,12 +76,14 @@
 		struct {
 			uint64_t address;
+			size_t size;
+			bool relative;
 			endianness_t endianness;
-			size_t size;
 		} mem_range;
 		
 		struct {
 			uint64_t address;
+			size_t size;
+			bool relative;
 			endianness_t endianness;
-			size_t size;
 		} io_range;
 		
Index: uspace/lib/c/include/device/hw_res_parsed.h
===================================================================
--- uspace/lib/c/include/device/hw_res_parsed.h	(revision bd88bee745abe1948dac683975e4b015ecdfaf39)
+++ uspace/lib/c/include/device/hw_res_parsed.h	(revision b243da3434115a8101e3ebac364a0a3b75aaf102)
@@ -37,4 +37,5 @@
 
 #include <device/hw_res.h>
+#include <device/pio_window.h>
 #include <str.h>
 
@@ -45,14 +46,28 @@
 #define HW_RES_KEEP_DUPLICIT   0x2
 
+
+#define RNGABS(rng)	(rng).address.absolute
+#define RNGREL(rng)	(rng).address.relative
+#define RNGSZ(rng)	(rng).size
+
+#define RNGABSPTR(rng)	((void *) ((uintptr_t) RNGABS((rng))))
+
+typedef struct address64 {
+	/** Aboslute address. */ 
+	uint64_t absolute;
+	/** PIO window base relative address. */
+	uint64_t relative; 
+} address64_t;
+
 /** Address range structure */
 typedef struct addr_range {
 	/** Start address */
-	uint64_t address;
-	
-	/** Endianness */
-	endianness_t endianness;
+	address64_t address;
 	
 	/** Area size */
 	size_t size;
+
+	/** Endianness */
+	endianness_t endianness;
 } addr_range_t;
 
@@ -139,5 +154,5 @@
 }
 
-extern int hw_res_list_parse(const hw_resource_list_t *,
+extern int hw_res_list_parse(const pio_window_t *, const hw_resource_list_t *,
     hw_res_list_parsed_t *, int);
 extern int hw_res_get_list_parsed(async_sess_t *, hw_res_list_parsed_t *, int);
Index: uspace/lib/c/include/stdio.h
===================================================================
--- uspace/lib/c/include/stdio.h	(revision bd88bee745abe1948dac683975e4b015ecdfaf39)
+++ uspace/lib/c/include/stdio.h	(revision b243da3434115a8101e3ebac364a0a3b75aaf102)
@@ -124,4 +124,8 @@
 extern int vsnprintf(char *, size_t, const char *, va_list);
 
+extern int printf_size(const char *, ...)
+    PRINTF_ATTRIBUTE(1, 2);
+extern int vprintf_size(const char *, va_list);
+
 /* File stream functions */
 extern FILE *fopen(const char *, const char *);
