Index: fb/Makefile
===================================================================
--- fb/Makefile	(revision 0861786211b07e36eb56c905f6086530ef2f1604)
+++ fb/Makefile	(revision 90f5d6412912019a8e1263bdb33fdd4742b17e76)
@@ -50,5 +50,6 @@
 	main.c \
 	sysio.c \
-	ega.c
+	ega.c \
+	ppm.c
 
 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
Index: fb/ega.c
===================================================================
--- fb/ega.c	(revision 0861786211b07e36eb56c905f6086530ef2f1604)
+++ fb/ega.c	(revision 90f5d6412912019a8e1263bdb33fdd4742b17e76)
@@ -111,5 +111,5 @@
 			intersize = IPC_GET_ARG2(call);
 			if (intersize >= scr_width*scr_height*sizeof(*interbuf)) {
-				receive_comm_area(callid,&call,(void **)&interbuf, scr_width*scr_height*sizeof(*interbuf));
+				receive_comm_area(callid,&call,(void **)&interbuf);
 				continue;
 			}
Index: fb/fb.c
===================================================================
--- fb/fb.c	(revision 0861786211b07e36eb56c905f6086530ef2f1604)
+++ fb/fb.c	(revision 90f5d6412912019a8e1263bdb33fdd4742b17e76)
@@ -47,4 +47,5 @@
 #include "main.h"
 #include "../console/screenbuffer.h"
+#include "ppm.h"
 
 #define DEFAULT_BGCOLOR                0x000080
@@ -475,4 +476,86 @@
 }
 
+static int shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
+{
+	static keyfield_t *interbuffer = NULL;
+	static size_t intersize = 0;
+
+	static char *pixmap = NULL;
+	static ipcarg_t pixmap_id = 0;
+	static size_t pixmap_size;
+
+	int handled = 1;
+	int retval = 0;
+	viewport_t *vport = &viewports[vp];
+	unsigned int x,y;
+
+	switch (IPC_GET_METHOD(*call)) {
+	case IPC_M_AS_AREA_SEND:
+		/* We accept one area for data interchange */
+		if (IPC_GET_ARG1(*call) == pixmap_id) {
+			void *dest = as_get_mappable_page(IPC_GET_ARG2(*call));
+			pixmap_size = IPC_GET_ARG2(*call);
+			if (!ipc_answer_fast(callid, 0, (sysarg_t)dest, 0)) 
+				pixmap = dest;
+			else
+				pixmap_id = 0;
+			if (pixmap[0] != 'P')
+				while (1)
+					;
+			return 1;
+		} else {
+			intersize = IPC_GET_ARG2(*call);
+			receive_comm_area(callid,call,(void **)&interbuffer);
+		}
+		return 1;
+	case FB_PREPARE_SHM:
+		if (pixmap_id)
+			retval = EBUSY;
+		else 
+			pixmap_id = IPC_GET_ARG1(*call);
+		break;
+		
+	case FB_DROP_SHM:
+		if (pixmap) {
+			as_area_destroy(pixmap);
+			pixmap = NULL;
+		}
+		pixmap_id = 0;
+		break;
+		
+	case FB_DRAW_PPM:
+		if (!pixmap) {
+			retval = EINVAL;
+			break;
+		}
+		x = IPC_GET_ARG1(*call);
+		y = IPC_GET_ARG2(*call);
+		if (x > vport->width || y > vport->height) {
+			retval = EINVAL;
+			break;
+		}
+		
+		draw_ppm(pixmap, pixmap_size, IPC_GET_ARG1(*call), IPC_GET_ARG2(*call),
+			 vport->width - x, vport->height - y, putpixel, vp);
+		break;
+	case FB_DRAW_TEXT_DATA:
+		if (!interbuffer) {
+			retval = EINVAL;
+			break;
+		}
+		if (intersize < vport->cols*vport->rows*sizeof(*interbuffer)) {
+			retval = EINVAL;
+			break;
+		}
+		draw_text_data(vp, interbuffer);
+		break;
+	default:
+		handled = 0;
+	}
+	
+	if (handled)
+		ipc_answer_fast(callid, retval, 0, 0);
+	return handled;
+}
 
 /** Function for handling connections to FB
@@ -487,6 +570,4 @@
 	unsigned int row,col;
 	char c;
-	keyfield_t *interbuffer = NULL;
-	size_t intersize = 0;
 
 	int vp = 0;
@@ -506,4 +587,7 @@
 			continue;
 		}
+		if (shm_handle(callid, &call, vp))
+			continue;
+
  		switch (IPC_GET_METHOD(call)) {
 		case IPC_M_PHONE_HUNGUP:
@@ -514,23 +598,5 @@
 			ipc_answer_fast(callid,0,0,0);
 			return; /* Exit thread */
-		case IPC_M_AS_AREA_SEND:
-			/* We accept one area for data interchange */
-			intersize = IPC_GET_ARG2(call);
-			receive_comm_area(callid,&call,(void **)&interbuffer,
-					  sizeof(*interbuffer)*viewports[0].cols*viewports[0].rows);
-			continue;
-
-		case FB_DRAW_TEXT_DATA:
-			if (!interbuffer) {
-				retval = EINVAL;
-				break;
-			}
-			if (intersize < vport->cols*vport->rows*sizeof(*interbuffer)) {
-				retval = EINVAL;
-				break;
-			}
-			draw_text_data(vp, interbuffer);
-			retval = 0;
-			break;
+
 		case FB_PUTCHAR:
 			c = IPC_GET_ARG1(call);
Index: fb/main.c
===================================================================
--- fb/main.c	(revision 0861786211b07e36eb56c905f6086530ef2f1604)
+++ fb/main.c	(revision 90f5d6412912019a8e1263bdb33fdd4742b17e76)
@@ -40,21 +40,14 @@
 #include "main.h"
 
-void receive_comm_area(ipc_callid_t callid, ipc_call_t *call, void **area,
-		       size_t maxsize)
+void receive_comm_area(ipc_callid_t callid, ipc_call_t *call, void **area)
 {
 	void *dest;
 
-	if (*area) {
-		ipc_answer_fast(callid, ELIMIT, 0, 0);
-		return;
+	dest = as_get_mappable_page(IPC_GET_ARG2(*call));
+	if (ipc_answer_fast(callid, 0, (sysarg_t)dest, 0) == 0) {
+		if (*area)
+			as_area_destroy(*area);
+		*area = dest;
 	}
-	if (IPC_GET_ARG2(*call) > ALIGN_UP(maxsize, PAGE_SIZE)) {
-		ipc_answer_fast(callid, EINVAL, 0, 0);
-		return;
-	}
-	
-	dest = as_get_mappable_page(maxsize);
-	if (ipc_answer_fast(callid, 0, (sysarg_t)dest, 0) == 0)
-		*area = dest;
 }
 
Index: fb/main.h
===================================================================
--- fb/main.h	(revision 0861786211b07e36eb56c905f6086530ef2f1604)
+++ fb/main.h	(revision 90f5d6412912019a8e1263bdb33fdd4742b17e76)
@@ -30,6 +30,5 @@
 #define __MAIN_H_
 
-void receive_comm_area(ipc_callid_t callid, ipc_call_t *call, void **area,
-		       size_t maxsize);
+void receive_comm_area(ipc_callid_t callid, ipc_call_t *call, void **area);
 
 #endif
Index: fb/ppm.c
===================================================================
--- fb/ppm.c	(revision 90f5d6412912019a8e1263bdb33fdd4742b17e76)
+++ fb/ppm.c	(revision 90f5d6412912019a8e1263bdb33fdd4742b17e76)
@@ -0,0 +1,112 @@
+/*
+ * 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 <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)++;
+	}
+}
+
+/** Draw PPM pixmap
+ *
+ * @param data Pointer to PPM data
+ * @param datasz Maximum data size
+ * @param x Coordinate of upper left corner
+ * @param y 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 draw_ppm(unsigned char *data, size_t datasz, unsigned int sx, 
+	     unsigned int sy, 
+	     unsigned int maxwidth, unsigned int maxheight,
+	     void (*putpixel)(int,unsigned int, unsigned int, int),int vp)
+{
+	unsigned int width, height;
+	unsigned int maxcolor;
+	int i;
+	void *maxdatap = data + datasz;
+	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[0]*coef;
+		
+		(*putpixel)(vp, sx+(i % width), sy+(i / width), color);
+		data += 3;
+	}
+}
Index: fb/ppm.h
===================================================================
--- fb/ppm.h	(revision 90f5d6412912019a8e1263bdb33fdd4742b17e76)
+++ fb/ppm.h	(revision 90f5d6412912019a8e1263bdb33fdd4742b17e76)
@@ -0,0 +1,37 @@
+/*
+ * 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 _PPM_H_
+#define _PPM_H_
+
+int draw_ppm(unsigned char *data, size_t datasz, unsigned int sx, 
+	     unsigned int sy, 
+	     unsigned int maxwidth, unsigned int maxheight,
+	     void (*putpixel)(int,unsigned int, unsigned int, int),int vp);
+
+#endif
