Index: uspace/srv/console/console.c
===================================================================
--- uspace/srv/console/console.c	(revision 3ad953cc9f7b18ae008470e72a5abd43e4142cbd)
+++ uspace/srv/console/console.c	(revision 7122bc7ffe00d5531336885cabe3467b25ade0d9)
@@ -41,5 +41,4 @@
 #include <errno.h>
 #include <key_buffer.h>
-#include <console.h>
 #include <ipc/console.h>
 #include <unistd.h>
@@ -51,4 +50,5 @@
 #include <sysinfo.h>
 
+#include "console.h"
 #include "gcons.h"
 
@@ -125,13 +125,35 @@
 }
 
-static void set_style(style_t *style)
-{
-	async_msg_2(fb_info.phone, FB_SET_STYLE, style->fg_color,
-	    style->bg_color); 
-}
-
-static void set_style_col(int fgcolor, int bgcolor)
-{
-	async_msg_2(fb_info.phone, FB_SET_STYLE, fgcolor, bgcolor); 
+static void set_style(int style)
+{
+	async_msg_1(fb_info.phone, FB_SET_STYLE, style); 
+}
+
+static void set_color(int fgcolor, int bgcolor, int flags)
+{
+	async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
+}
+
+static void set_rgb_color(int fgcolor, int bgcolor)
+{
+	async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); 
+}
+
+static void set_attrs(attrs_t *attrs)
+{
+	switch (attrs->t) {
+	case at_style:
+		set_style(attrs->a.s.style);
+		break;
+
+	case at_idx:
+		set_color(attrs->a.i.fg_color, attrs->a.i.bg_color,
+		    attrs->a.i.flags);
+		break;
+
+	case at_rgb:
+		set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color);
+		break;
+	}
 }
 
@@ -199,5 +221,5 @@
 	int i, j, rc;
 	keyfield_t *field;
-	style_t *style;
+	attrs_t *attrs;
 	
 	if (newcons == active_console)
@@ -227,5 +249,5 @@
 		conn = &connections[active_console];
 		
-		set_style(&conn->screenbuffer.style);
+		set_attrs(&conn->screenbuffer.attrs);
 		curs_visibility(false);
 		if (interbuffer) {
@@ -243,19 +265,19 @@
 		
 		if ((!interbuffer) || (rc != 0)) {
-			set_style(&conn->screenbuffer.style);
+			set_attrs(&conn->screenbuffer.attrs);
 			clrscr();
-			style = &conn->screenbuffer.style;
+			attrs = &conn->screenbuffer.attrs;
 			
 			for (j = 0; j < conn->screenbuffer.size_y; j++)
 				for (i = 0; i < conn->screenbuffer.size_x; i++) {
 					field = get_field_at(&conn->screenbuffer, i, j);
-					if (!style_same(*style, field->style))
-						set_style(&field->style);
-					style = &field->style;
+					if (!attrs_same(*attrs, field->attrs))
+						set_attrs(&field->attrs);
+					attrs = &field->attrs;
 					if ((field->character == ' ') &&
-					    (style_same(field->style,
-					    conn->screenbuffer.style)))
+					    (attrs_same(field->attrs,
+					    conn->screenbuffer.attrs)))
 						continue;
-					
+
 					prtchr(field->character, j, i);
 				}
@@ -342,5 +364,5 @@
 	ipc_call_t call;
 	int consnum;
-	ipcarg_t arg1, arg2;
+	ipcarg_t arg1, arg2, arg3;
 	connection_t *conn;
 	
@@ -410,9 +432,24 @@
 		case CONSOLE_SET_STYLE:
 			arg1 = IPC_GET_ARG1(call);
+			screenbuffer_set_style(&conn->screenbuffer, arg1);
+			if (consnum == active_console)
+				set_style(arg1);
+			break;
+		case CONSOLE_SET_COLOR:
+			arg1 = IPC_GET_ARG1(call);
 			arg2 = IPC_GET_ARG2(call);
-			screenbuffer_set_style(&conn->screenbuffer, arg1,
+			arg3 = IPC_GET_ARG3(call);
+			screenbuffer_set_color(&conn->screenbuffer, arg1,
+			    arg2, arg3);
+			if (consnum == active_console)
+				set_color(arg1, arg2, arg3);
+			break;
+		case CONSOLE_SET_RGB_COLOR:
+			arg1 = IPC_GET_ARG1(call);
+			arg2 = IPC_GET_ARG2(call);
+			screenbuffer_set_rgb_color(&conn->screenbuffer, arg1,
 			    arg2);
 			if (consnum == active_console)
-				set_style_col(arg1, arg2);
+				set_rgb_color(arg1, arg2);
 			break;
 		case CONSOLE_CURSOR_VISIBILITY:
@@ -488,5 +525,5 @@
 	async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.rows,
 	    &fb_info.cols); 
-	set_style_col(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
+	set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
 	clrscr();
 	
Index: uspace/srv/console/gcons.c
===================================================================
--- uspace/srv/console/gcons.c	(revision 3ad953cc9f7b18ae008470e72a5abd43e4142cbd)
+++ uspace/srv/console/gcons.c	(revision 7122bc7ffe00d5531336885cabe3467b25ade0d9)
@@ -98,7 +98,7 @@
 }
 
-static void set_style(int fgcolor, int bgcolor)
-{
-	async_msg_2(fbphone, FB_SET_STYLE, fgcolor, bgcolor);
+static void set_rgb_color(int fgcolor, int bgcolor)
+{
+	async_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
 }
 
@@ -347,5 +347,5 @@
 	
 	vp_switch(0);
-	set_style(MAIN_COLOR, MAIN_COLOR);
+	set_rgb_color(MAIN_COLOR, MAIN_COLOR);
 	clear();
 	draw_pixmap(_binary_helenos_ppm_start,
@@ -482,5 +482,5 @@
 			return;
 		vp_switch(cstatus_vp[i]);
-		set_style(0x202020, 0xffffff);
+		set_rgb_color(0x202020, 0xffffff);
 	}
 	
Index: uspace/srv/console/screenbuffer.c
===================================================================
--- uspace/srv/console/screenbuffer.c	(revision 3ad953cc9f7b18ae008470e72a5abd43e4142cbd)
+++ uspace/srv/console/screenbuffer.c	(revision 7122bc7ffe00d5531336885cabe3467b25ade0d9)
@@ -34,4 +34,5 @@
 
 #include <screenbuffer.h>
+#include <console/style.h>
 #include <malloc.h>
 #include <unistd.h>
@@ -50,5 +51,5 @@
 
 	field->character = c;
-	field->style = scr->style;
+	field->attrs = scr->attrs;
 }
 
@@ -68,6 +69,6 @@
 	scr->size_x = size_x;
 	scr->size_y = size_y;
-	scr->style.fg_color = DEFAULT_FOREGROUND;
-	scr->style.bg_color = DEFAULT_BACKGROUND;
+	scr->attrs.t = at_style;
+	scr->attrs.a.s.style = STYLE_NORMAL;
 	scr->is_cursor_visible = 1;
 	
@@ -86,5 +87,5 @@
 	for (i = 0; i < (scr->size_x * scr->size_y); i++) {
 		scr->buffer[i].character = ' ';
-		scr->buffer[i].style = scr->style;
+		scr->buffer[i].attrs = scr->attrs;
 	}
 
@@ -104,5 +105,5 @@
 	for (i = 0; i < scr->size_x; i++) {
 		scr->buffer[i + line * scr->size_x].character = ' ';
-		scr->buffer[i + line * scr->size_x].style = scr->style;
+		scr->buffer[i + line * scr->size_x].attrs = scr->attrs;
 	}
 }
@@ -137,8 +138,33 @@
  * @param bg_color
  */
-void screenbuffer_set_style(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color)
+void screenbuffer_set_style(screenbuffer_t *scr, int style)
 {
-	scr->style.fg_color = fg_color;
-	scr->style.bg_color = bg_color;
+	scr->attrs.t = at_style;
+	scr->attrs.a.s.style = style;
+}
+
+/** Set new color.
+ * @param scr
+ * @param fg_color
+ * @param bg_color
+ */
+void screenbuffer_set_color(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color, unsigned int flags)
+{
+	scr->attrs.t = at_idx;
+	scr->attrs.a.i.fg_color = fg_color;
+	scr->attrs.a.i.bg_color = bg_color;
+	scr->attrs.a.i.flags = flags;
+}
+
+/** Set new RGB color.
+ * @param scr
+ * @param fg_color
+ * @param bg_color
+ */
+void screenbuffer_set_rgb_color(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color)
+{
+	scr->attrs.t = at_rgb;
+	scr->attrs.a.r.fg_color = fg_color;
+	scr->attrs.a.r.bg_color = bg_color;
 }
 
Index: uspace/srv/console/screenbuffer.h
===================================================================
--- uspace/srv/console/screenbuffer.h	(revision 3ad953cc9f7b18ae008470e72a5abd43e4142cbd)
+++ uspace/srv/console/screenbuffer.h	(revision 7122bc7ffe00d5531336885cabe3467b25ade0d9)
@@ -42,12 +42,35 @@
 
 typedef struct {
+	uint8_t style;
+} attr_style_t;
+
+typedef struct {
+	uint8_t fg_color;
+	uint8_t bg_color;
+	uint8_t flags;
+} attr_idx_t;
+
+typedef struct {
 	uint32_t bg_color;      /**< background color */
 	uint32_t fg_color;      /**< foreground color */
-} style_t;
+} attr_rgb_t;
+
+typedef struct {
+	enum {
+		at_style,
+		at_idx,
+		at_rgb
+	} t;
+	union {
+		attr_style_t s;
+		attr_idx_t i;
+		attr_rgb_t r;
+	} a; 
+} attrs_t;
 
 /** One field on screen. It contain one character and its attributes. */
 typedef struct {
 	char character;			/**< Character itself */
-	style_t style;			/**< Character`s attributes */
+	attrs_t attrs;			/**< Character`s attributes */
 } keyfield_t;
 
@@ -55,8 +78,8 @@
  */
 typedef struct {
-	keyfield_t *buffer;			/**< Screen content - characters and its style. Used as cyclyc buffer. */
+	keyfield_t *buffer;			/**< Screen content - characters and their attributes. Used as a circular buffer. */
 	unsigned int size_x, size_y;		/**< Number of columns and rows */
 	unsigned int position_x, position_y;	/**< Coordinates of last printed character for determining cursor position */
-	style_t style;				/**< Current style */
+	attrs_t attrs;				/**< Current attributes. */
 	unsigned int top_line;			/**< Points to buffer[][] line that will be printed at screen as the first line */
 	unsigned char is_cursor_visible;	/**< Cursor state - default is visible */
@@ -74,12 +97,21 @@
 }
 
-/** Compares two styles.
+/** Compares two sets of attributes.
  * @param s1 first style
  * @param s2 second style
  * @return nonzero on equality
  */
-static inline int style_same(style_t s1, style_t s2)
+static inline int attrs_same(attrs_t a1, attrs_t a2)
 {
-	return s1.fg_color == s2.fg_color && s1.bg_color == s2.bg_color;
+	if (a1.t != a2.t) return 0;
+
+	switch (a1.t) {
+	case at_style: return a1.a.s.style == a2.a.s.style;
+	case at_idx: return a1.a.i.fg_color == a2.a.i.fg_color &&
+	    a1.a.i.bg_color == a2.a.i.bg_color &&
+	    a1.a.i.flags == a2.a.i.flags;
+	case at_rgb: return a1.a.r.fg_color == a2.a.r.fg_color &&
+	    a1.a.r.bg_color == a2.a.r.bg_color;
+	}
 }
 
@@ -92,5 +124,9 @@
 void screenbuffer_copy_buffer(screenbuffer_t *scr, keyfield_t *dest);
 void screenbuffer_goto(screenbuffer_t *scr, unsigned int x, unsigned int y);
-void screenbuffer_set_style(screenbuffer_t *scr, unsigned int fg_color, unsigned int bg_color);
+void screenbuffer_set_style(screenbuffer_t *scr, int style);
+void screenbuffer_set_color(screenbuffer_t *scr, unsigned int fg_color,
+    unsigned int bg_color, unsigned int attr);
+void screenbuffer_set_rgb_color(screenbuffer_t *scr, unsigned int fg_color,
+    unsigned int bg_color);
 
 #endif
Index: uspace/srv/fb/ega.c
===================================================================
--- uspace/srv/fb/ega.c	(revision 3ad953cc9f7b18ae008470e72a5abd43e4142cbd)
+++ uspace/srv/fb/ega.c	(revision 7122bc7ffe00d5531336885cabe3467b25ade0d9)
@@ -50,4 +50,6 @@
 #include <ipc/services.h>
 #include <libarch/ddi.h>
+#include <console/style.h>
+#include <console/color.h>
 
 #include "ega.h"
@@ -65,6 +67,6 @@
 #define EGA_IO_SIZE 2
 
-int ega_normal_color=0x0f;
-int ega_inverted_color=0xf0;
+int ega_normal_color = 0x0f;
+int ega_inverted_color = 0xf0;
 
 #define NORMAL_COLOR		ega_normal_color       
@@ -155,6 +157,8 @@
 	for (i = 0; i < scr_width * scr_height; i++) {
 		scr_addr[i * 2] = data[i].character;
+		/* FIXME
 		scr_addr[i * 2 + 1] = EGA_STYLE(data[i].style.fg_color,
 		    data[i].style.bg_color);
+		*/
 	}
 }
@@ -276,4 +280,20 @@
 			break;
 		case FB_SET_STYLE:
+			retval = 0;
+			switch (IPC_GET_ARG1(call)) {
+			case STYLE_NORMAL: style = INVERTED_COLOR; break;
+			case STYLE_EMPHASIS: style = INVERTED_COLOR | 4; break;
+			default: retval = EINVAL;
+			}
+			break;
+		case FB_SET_COLOR:
+			fgcolor = IPC_GET_ARG1(call);
+			bgcolor = IPC_GET_ARG2(call);
+			style = (fgcolor & 7) | ((bgcolor & 7) << 4);
+			if (IPC_GET_ARG3(call) & CATTR_BRIGHT)
+				style = style | 0x08;
+			retval = 0;
+			break;
+		case FB_SET_RGB_COLOR:
 			fgcolor = IPC_GET_ARG1(call);
 			bgcolor = IPC_GET_ARG2(call);
@@ -318,6 +338,6 @@
 	if(sysinfo_value("fb.blinking"))
 	{
-			ega_normal_color&=0x77;
-			ega_inverted_color&=0x77;
+			ega_normal_color &= 0x77;
+			ega_inverted_color &= 0x77;
 	}
 	style = NORMAL_COLOR;
Index: uspace/srv/fb/fb.c
===================================================================
--- uspace/srv/fb/fb.c	(revision 3ad953cc9f7b18ae008470e72a5abd43e4142cbd)
+++ uspace/srv/fb/fb.c	(revision 7122bc7ffe00d5531336885cabe3467b25ade0d9)
@@ -52,4 +52,6 @@
 #include <kernel/errno.h>
 #include <kernel/genarch/fb/visuals.h>
+#include <console/color.h>
+#include <console/style.h>
 #include <async.h>
 #include <bool.h>
@@ -93,4 +95,11 @@
 	rgb_conv_t rgb_conv;
 } screen;
+
+/** Backbuffer character cell. */
+typedef struct {
+	uint8_t glyph;
+	uint32_t fg_color;
+	uint32_t bg_color;
+} bb_cell_t;
 
 typedef struct {
@@ -109,6 +118,6 @@
 	 */
 
-	/** Current style. */
-	style_t style;
+	/** Current attributes. */
+	attr_rgb_t attr;
 
 	/** Pre-rendered mask for rendering glyphs. Different viewports
@@ -129,6 +138,6 @@
 	
 	/* Back buffer */
+	bb_cell_t *backbuf;
 	unsigned int bbsize;
-	uint8_t *backbuf;
 } viewport_t;
 
@@ -156,4 +165,31 @@
 
 static bool client_connected = false;  /**< Allow only 1 connection */
+
+static uint32_t color_table[16] = {
+	[COLOR_BLACK]		= 0x000000,
+	[COLOR_BLUE]		= 0x0000f0,
+	[COLOR_GREEN]		= 0x00f000,
+	[COLOR_CYAN]		= 0x00f0f0,
+	[COLOR_RED]		= 0xf00000,
+	[COLOR_MAGENTA]		= 0xf000f0,
+	[COLOR_YELLOW]		= 0xf0f000,
+	[COLOR_WHITE]		= 0xf0f0f0,
+
+	[8 + COLOR_BLACK]	= 0x000000,
+	[8 + COLOR_BLUE]	= 0x0000ff,
+	[8 + COLOR_GREEN]	= 0x00ff00,
+	[8 + COLOR_CYAN]	= 0x00ffff,
+	[8 + COLOR_RED]		= 0xff0000,
+	[8 + COLOR_MAGENTA]	= 0xff00ff,
+	[8 + COLOR_YELLOW]	= 0xffff00,
+	[8 + COLOR_WHITE]	= 0xffffff,
+};
+
+static int rgb_from_style(attr_rgb_t *rgb, int style);
+static int rgb_from_idx(attr_rgb_t *rgb, ipcarg_t fg_color,
+    ipcarg_t bg_color, ipcarg_t flags);
+
+static int fb_set_color(viewport_t *vport, ipcarg_t fg_color,
+    ipcarg_t bg_color, ipcarg_t attr);
 
 static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor,
@@ -300,5 +336,5 @@
 		    vport->x + COL2X(vport->cols), vport->y,
 		    vport->x + vport->width, vport->y + vport->height,
-		    vport->style.bg_color);
+		    vport->attr.bg_color);
 	}
 
@@ -307,8 +343,19 @@
 		    vport->x, vport->y + ROW2Y(vport->rows),
 		    vport->x + vport->width, vport->y + vport->height,
-		    vport->style.bg_color);
-	}
-}
-
+		    vport->attr.bg_color);
+	}
+}
+
+static void backbuf_clear(bb_cell_t *backbuf, size_t len, uint32_t fg_color,
+    uint32_t bg_color)
+{
+	unsigned i;
+
+	for (i = 0; i < len; i++) {
+		backbuf[i].glyph = 0;
+		backbuf[i].fg_color = fg_color;
+		backbuf[i].bg_color = bg_color;
+	}
+}
 
 /** Clear viewport.
@@ -319,5 +366,6 @@
 static void vport_clear(viewport_t *vport)
 {
-	memset(vport->backbuf, 0, vport->bbsize);
+	backbuf_clear(vport->backbuf, vport->cols * vport->rows,
+	    vport->attr.fg_color, vport->attr.bg_color);
 	vport_redraw(vport);
 }
@@ -334,4 +382,7 @@
 	unsigned int x, y;
 	uint8_t glyph;
+	uint32_t fg_color;
+	uint32_t bg_color;
+	bb_cell_t *bbp, *xbp;
 
 	/*
@@ -344,7 +395,14 @@
 		for (col = 0; col < vport->cols; col++) {
 			if ((row + lines >= 0) && (row + lines < vport->rows)) {
-				glyph = vport->backbuf[BB_POS(vport, col, row + lines)];
-
-				if (vport->backbuf[BB_POS(vport, col, row)] == glyph) {
+				xbp = &vport->backbuf[BB_POS(vport, col, row + lines)];
+				bbp = &vport->backbuf[BB_POS(vport, col, row)];
+
+				glyph = xbp->glyph;
+				fg_color = xbp->fg_color;
+				bg_color = xbp->bg_color;
+
+				if (bbp->glyph == glyph &&
+				    bbp->fg_color == xbp->fg_color &&
+				    bbp->bg_color == xbp->bg_color) {
 					x += FONT_WIDTH;
 					continue;
@@ -352,8 +410,10 @@
 			} else {
 				glyph = 0;
+				fg_color = vport->attr.fg_color;
+				bg_color = vport->attr.bg_color;
 			}
 
 			(*vport->dglyph)(x, y, false, vport->glyphs, glyph,
-			    vport->style.fg_color, vport->style.bg_color);
+			    fg_color, bg_color);
 			x += FONT_WIDTH;
 		}
@@ -367,11 +427,12 @@
 	if (lines > 0) {
 		memmove(vport->backbuf, vport->backbuf + vport->cols * lines,
-		    vport->cols * (vport->rows - lines));
-		memset(&vport->backbuf[BB_POS(vport, 0, vport->rows - lines)],
-		    0, vport->cols * lines);
+		    vport->cols * (vport->rows - lines) * sizeof(bb_cell_t));
+		backbuf_clear(&vport->backbuf[BB_POS(vport, 0, vport->rows - lines)],
+		    vport->cols * lines, vport->attr.fg_color, vport->attr.bg_color);
 	} else {
 		memmove(vport->backbuf - vport->cols * lines, vport->backbuf,
-		    vport->cols * (vport->rows + lines));
-		memset(vport->backbuf, 0, - vport->cols * lines);
+		    vport->cols * (vport->rows + lines) * sizeof(bb_cell_t));
+		backbuf_clear(vport->backbuf, - vport->cols * lines,
+		    vport->attr.fg_color, vport->attr.bg_color);
 	}
 }
@@ -407,5 +468,5 @@
 	}
 	
-	screen.rgb_conv(vport->bgpixel, vport->style.bg_color);
+	screen.rgb_conv(vport->bgpixel, vport->attr.bg_color);
 }
 
@@ -435,9 +496,9 @@
 	unsigned int cols = width / FONT_WIDTH;
 	unsigned int rows = height / FONT_SCANLINES;
-	unsigned int bbsize = cols * rows;
+	unsigned int bbsize = cols * rows * sizeof(bb_cell_t);
 	unsigned int glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes;
 	unsigned int word_size = sizeof(unsigned long);
 	
-	uint8_t *backbuf = (uint8_t *) malloc(bbsize);
+	bb_cell_t *backbuf = (bb_cell_t *) malloc(bbsize);
 	if (!backbuf)
 		return ENOMEM;
@@ -455,6 +516,6 @@
 		return ENOMEM;
 	}
-	
-	memset(backbuf, 0, bbsize);
+
+	backbuf_clear(backbuf, cols * rows, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR);
 	memset(glyphs, 0, glyphsize);
 	memset(bgpixel, 0, screen.pixelbytes);
@@ -468,6 +529,6 @@
 	viewports[i].rows = rows;
 	
-	viewports[i].style.bg_color = DEFAULT_BGCOLOR;
-	viewports[i].style.fg_color = DEFAULT_FGCOLOR;
+	viewports[i].attr.bg_color = DEFAULT_BGCOLOR;
+	viewports[i].attr.fg_color = DEFAULT_FGCOLOR;
 	
 	viewports[i].glyphs = glyphs;
@@ -708,10 +769,15 @@
 	unsigned int x = vport->x + COL2X(col);
 	unsigned int y = vport->y + ROW2Y(row);
+
 	uint8_t glyph;
-	
-	glyph = vport->backbuf[BB_POS(vport, col, row)];
+	uint32_t fg_color;
+	uint32_t bg_color;
+	
+	glyph = vport->backbuf[BB_POS(vport, col, row)].glyph;
+	fg_color = vport->backbuf[BB_POS(vport, col, row)].fg_color;
+	bg_color = vport->backbuf[BB_POS(vport, col, row)].bg_color;
 
 	(*vport->dglyph)(x, y, cursor, vport->glyphs, glyph,
-	    vport->style.fg_color, vport->style.bg_color);
+	    fg_color, bg_color);
 }
 
@@ -763,10 +829,16 @@
 static void draw_char(viewport_t *vport, uint8_t c, unsigned int col, unsigned int row)
 {
+	bb_cell_t *bbp;
+
 	/* Do not hide cursor if we are going to overwrite it */
 	if ((vport->cursor_active) && (vport->cursor_shown) &&
 	    ((vport->cur_col != col) || (vport->cur_row != row)))
 		cursor_hide(vport);
-	
-	vport->backbuf[BB_POS(vport, col, row)] = c;
+
+	bbp = &vport->backbuf[BB_POS(vport, col, row)];
+	bbp->glyph = c;
+	bbp->fg_color = vport->attr.fg_color;
+	bbp->bg_color = vport->attr.bg_color;
+
 	draw_vp_glyph(vport, false, col, row);
 	
@@ -795,4 +867,7 @@
 {
 	unsigned int i;
+	bb_cell_t *bbp;
+	attrs_t *a;
+	attr_rgb_t rgb;
 	
 	for (i = 0; i < vport->cols * vport->rows; i++) {
@@ -800,10 +875,27 @@
 		unsigned int row = i / vport->cols;
 		
-		uint8_t glyph = vport->backbuf[BB_POS(vport, col, row)];
-		
-		// TODO: use data[i].style
-		
+		bbp = &vport->backbuf[BB_POS(vport, col, row)];
+		uint8_t glyph = bbp->glyph;
+
 		if (glyph != data[i].character) {
-			vport->backbuf[BB_POS(vport, col, row)] = data[i].character;
+			bbp->glyph = data[i].character;
+			a = &data[i].attrs;
+
+			switch (a->t) {
+			case at_style:
+				rgb_from_style(&rgb, a->a.s.style);
+				break;
+			case at_idx:
+				rgb_from_idx(&rgb, a->a.i.fg_color,
+				    a->a.i.bg_color, a->a.i.flags);
+				break;
+			case at_rgb:
+				rgb = a->a.r;
+				break;
+			}
+
+			bbp->fg_color = rgb.fg_color;
+			bbp->bg_color = rgb.bg_color;
+
 			draw_vp_glyph(vport, false, col, row);
 		}
@@ -1321,4 +1413,45 @@
 	return handled;
 	
+}
+
+static int rgb_from_style(attr_rgb_t *rgb, int style)
+{
+	switch (style) {
+	case STYLE_NORMAL:
+		rgb->fg_color = color_table[COLOR_BLACK];
+		rgb->bg_color = color_table[COLOR_WHITE];
+		break;
+	case STYLE_EMPHASIS:
+		rgb->fg_color = color_table[COLOR_RED];
+		rgb->bg_color = color_table[COLOR_WHITE];
+		break;
+	default:
+		return EINVAL;
+	}
+
+	return EOK;
+}
+
+static int rgb_from_idx(attr_rgb_t *rgb, ipcarg_t fg_color,
+    ipcarg_t bg_color, ipcarg_t flags)
+{
+	fg_color = (fg_color & 7) | ((flags & CATTR_BRIGHT) ? 8 : 0);
+	bg_color = (bg_color & 7) | ((flags & CATTR_BRIGHT) ? 8 : 0);
+
+	rgb->fg_color = color_table[fg_color];
+	rgb->bg_color = color_table[bg_color];
+
+	return EOK;
+}
+
+static int fb_set_style(viewport_t *vport, ipcarg_t style)
+{
+	return rgb_from_style(&vport->attr, (int) style);
+}
+
+static int fb_set_color(viewport_t *vport, ipcarg_t fg_color,
+    ipcarg_t bg_color, ipcarg_t flags)
+{
+	return rgb_from_idx(&vport->attr, fg_color, bg_color, flags);
 }
 
@@ -1479,6 +1612,13 @@
 			break;
 		case FB_SET_STYLE:
-			vport->style.fg_color = IPC_GET_ARG1(call);
-			vport->style.bg_color = IPC_GET_ARG2(call);
+			retval = fb_set_style(vport, IPC_GET_ARG1(call));
+			break;
+		case FB_SET_COLOR:
+			retval = fb_set_color(vport, IPC_GET_ARG1(call),
+			    IPC_GET_ARG2(call), IPC_GET_ARG3(call));
+			break;
+		case FB_SET_RGB_COLOR:
+			vport->attr.fg_color = IPC_GET_ARG1(call);
+			vport->attr.bg_color = IPC_GET_ARG2(call);
 			retval = EOK;
 			break;
Index: uspace/srv/fb/serial_console.c
===================================================================
--- uspace/srv/fb/serial_console.c	(revision 3ad953cc9f7b18ae008470e72a5abd43e4142cbd)
+++ uspace/srv/fb/serial_console.c	(revision 7122bc7ffe00d5531336885cabe3467b25ade0d9)
@@ -44,4 +44,5 @@
 #include <bool.h>
 #include <errno.h>
+#include <console/style.h>
 
 #include "serial_console.h"
@@ -90,5 +91,6 @@
 }
 
-void serial_set_style(const unsigned int mode)
+/** ECMA-48 Set Graphics Rendition. */
+static void serial_sgr(const unsigned int mode)
 {
 	char control[MAX_CONTROL];
@@ -137,4 +139,5 @@
 	int fgcolor;
 	int bgcolor;
+	int style;
 	int i;
 	
@@ -187,10 +190,27 @@
 			break;
 		case FB_SET_STYLE:
+			style =  IPC_GET_ARG1(call);
+			if (style == STYLE_EMPHASIS)
+				serial_sgr(1);
+			else
+				serial_sgr(0);
+			retval = 0;
+			break;
+		case FB_SET_COLOR:
 			fgcolor = IPC_GET_ARG1(call);
 			bgcolor = IPC_GET_ARG2(call);
 			if (fgcolor < bgcolor)
-				serial_set_style(0);
-			else
-				serial_set_style(7);
+				serial_sgr(0);
+			else
+				serial_sgr(7);
+			retval = 0;
+			break;
+		case FB_SET_RGB_COLOR:
+			fgcolor = IPC_GET_ARG1(call);
+			bgcolor = IPC_GET_ARG2(call);
+			if (fgcolor < bgcolor)
+				serial_sgr(0);
+			else
+				serial_sgr(7);
 			retval = 0;
 			break;
