Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 12fc04200ab5196e5112eb5d4529b585cba8878b)
+++ uspace/srv/fs/fat/fat_ops.c	(revision b3105ff6d7483bc6e5d9bf19f64b6178a15304ea)
@@ -40,4 +40,6 @@
 #include <libfs.h>
 #include <ipc/ipc.h>
+#include <ipc/services.h>
+#include <ipc/devmap.h>
 #include <async.h>
 #include <errno.h>
@@ -48,4 +50,5 @@
 #include <assert.h>
 #include <futex.h>
+#include <sys/mman.h>
 
 #define BS_BLOCK		0
@@ -96,17 +99,49 @@
 }
 
+static int dev_phone = -1;		/* FIXME */
+static void *dev_buffer = NULL;		/* FIXME */
+
 /* TODO move somewhere else */
 typedef struct {
 	void *data;
+	size_t size;
 } block_t;
 
 static block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs)
 {
-	return NULL;	/* TODO */
+	/* FIXME */
+	block_t *b;
+	off_t bufpos = 0;
+	size_t buflen = 0;
+
+	assert(dev_phone != -1);
+	assert(dev_buffer);
+
+	b = malloc(sizeof(block_t));
+	if (!b)
+		return NULL;
+	
+	b->data = malloc(bs);
+	if (!b->data) {
+		free(b);
+		return NULL;
+	}
+	b->size = bs;
+
+	if (!libfs_blockread(dev_phone, dev_buffer, &bufpos, &buflen, &offset,
+	    b->data, bs, bs)) {
+		free(b->data);
+		free(b);
+		return NULL;
+	}
+
+	return b;
 }
 
 static void block_put(block_t *block)
 {
-	/* TODO */
+	/* FIXME */
+	free(block->data);
+	free(block);
 }
 
@@ -569,14 +604,54 @@
 	dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
 	block_t *bb;
+	uint16_t bps;
 	uint16_t rde;
 	int rc;
 
+	/*
+	 * For now, we don't bother to remember dev_handle, dev_phone or
+	 * dev_buffer in some data structure. We use global variables because we
+	 * know there will be at most one mount on this file system.
+	 * Of course, this is a huge TODO item.
+	 */
+	dev_buffer = mmap(NULL, BS_SIZE, PROTO_READ | PROTO_WRITE,
+	    MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
+	
+	if (!dev_buffer) {
+		ipc_answer_0(rid, ENOMEM);
+		return;
+	}
+
+	dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
+	    DEVMAP_CONNECT_TO_DEVICE, dev_handle);
+
+	if (dev_phone < 0) {
+		munmap(dev_buffer, BS_SIZE);
+		ipc_answer_0(rid, dev_phone);
+		return;
+	}
+
+	rc = ipc_share_out_start(dev_phone, dev_buffer,
+	    AS_AREA_READ | AS_AREA_WRITE);
+	if (rc != EOK) {
+	    	munmap(dev_buffer, BS_SIZE);
+		ipc_answer_0(rid, rc);
+		return;
+	}
+
 	/* Read the number of root directory entries. */
 	bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
+	bps = uint16_t_le2host(FAT_BS(bb)->bps);
 	rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max);
 	block_put(bb);
 
+	if (bps != BS_SIZE) {
+		munmap(dev_buffer, BS_SIZE);
+		ipc_answer_0(rid, ENOTSUP);
+		return;
+	}
+
 	rc = fat_idx_init_by_dev_handle(dev_handle);
 	if (rc != EOK) {
+	    	munmap(dev_buffer, BS_SIZE);
 		ipc_answer_0(rid, rc);
 		return;
@@ -586,4 +661,5 @@
 	fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
 	if (!rootp) {
+	    	munmap(dev_buffer, BS_SIZE);
 		fat_idx_fini_by_dev_handle(dev_handle);
 		ipc_answer_0(rid, ENOMEM);
@@ -594,4 +670,5 @@
 	fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0);
 	if (!ridxp) {
+	    	munmap(dev_buffer, BS_SIZE);
 		free(rootp);
 		fat_idx_fini_by_dev_handle(dev_handle);
