Index: uspace/app/bdsh/cmds/modules/cat/cat.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/bdsh/cmds/modules/cat/cat.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -52,6 +52,6 @@
 #define CAT_VERSION "0.0.1"
 #define CAT_DEFAULT_BUFLEN 1024
-
-static const char *cat_oops = "That option is not yet supported\n";
+#define CAT_FULL_FILE 0
+
 static const char *hexchars = "0123456789abcdef";
 
@@ -163,10 +163,12 @@
 }
 
-static unsigned int cat_file(const char *fname, size_t blen, bool hex)
+static unsigned int cat_file(const char *fname, size_t blen, bool hex,
+    off64_t head, off64_t tail, bool tail_first)
 {
 	int fd, bytes = 0, count = 0, reads = 0;
 	char *buff = NULL;
 	int i;
-	size_t offset = 0;
+	size_t offset = 0, copied_bytes = 0;
+	off64_t file_size = 0, length = 0;
 
 	fd = open(fname, O_RDONLY);
@@ -183,8 +185,34 @@
 	}
 
+	if (tail != CAT_FULL_FILE) {
+		file_size = lseek(fd, 0, SEEK_END);
+		if (head == CAT_FULL_FILE) {
+			head = file_size;
+			length = tail;
+		} else if (tail_first) {
+			length = head;
+		} else {
+			if (tail > head)
+				tail = head;
+			length = tail;
+		}
+
+		if (tail_first) {
+			lseek(fd, (tail >= file_size) ? 0 : (file_size - tail), SEEK_SET);
+		} else {
+			lseek(fd, ((head - tail) >= file_size) ? 0 : (head - tail), SEEK_SET);
+		}
+	} else
+		length = head;
+
 	do {
-		bytes = read(fd, buff, blen);
+		bytes = read(fd, buff + copied_bytes, (
+			(length != CAT_FULL_FILE && length - (off64_t)count <= (off64_t)(blen - copied_bytes)) ?
+			(size_t)(length - count) :
+			(blen - copied_bytes) ) );
+		bytes += copied_bytes;
+		copied_bytes = 0;
+
 		if (bytes > 0) {
-			count += bytes;
 			buff[bytes] = '\0';
 			offset = 0;
@@ -193,4 +221,5 @@
 					paged_char(hexchars[((uint8_t)buff[i])/16]);
 					paged_char(hexchars[((uint8_t)buff[i])%16]);
+					paged_char(((count+i+1) & 0xf) == 0 ? '\n' : ' ');
 				}
 				else {
@@ -199,4 +228,10 @@
 						/* Reached end of string */
 						break;
+					} else if (c == U_SPECIAL && offset + 2 >= (size_t)bytes) {
+						/* If an extended character is cut off due to the size of the buffer,
+						   we will copy it over to the next buffer so it can be read correctly. */
+						copied_bytes = bytes - offset + 1;
+						memcpy(buff, buff + offset - 1, copied_bytes);
+						break;
 					}
 					paged_char(c);
@@ -204,7 +239,8 @@
 				
 			}
+			count += bytes;
 			reads++;
 		}
-	} while (bytes > 0 && !should_quit);
+	} while (bytes > 0 && !should_quit && (count < length || length == CAT_FULL_FILE));
 
 	close(fd);
@@ -223,8 +259,11 @@
 int cmd_cat(char **argv)
 {
-	unsigned int argc, i, ret = 0, buffer = 0;
+	unsigned int argc, i, ret = 0;
+	size_t buffer = 0;
 	int c, opt_ind;
+	aoff64_t head = CAT_FULL_FILE, tail = CAT_FULL_FILE;
 	bool hex = false;
 	bool more = false;
+	bool tailFirst = false;
 	sysarg_t rows, cols;
 	int rc;
@@ -254,11 +293,22 @@
 			return CMD_SUCCESS;
 		case 'H':
-			printf("%s", cat_oops);
-			return CMD_FAILURE;
+			if (!optarg || str_uint64_t(optarg, NULL, 10, false, &head) != EOK ) {
+				puts("Invalid head size\n");
+				return CMD_FAILURE;
+			}
+			break;
 		case 't':
-			printf("%s", cat_oops);
-			return CMD_FAILURE;
+			if (!optarg || str_uint64_t(optarg, NULL, 10, false, &tail) != EOK ) {
+				puts("Invalid tail size\n");
+				return CMD_FAILURE;
+			}
+			if (head == CAT_FULL_FILE)
+				tailFirst = true;
+			break;
 		case 'b':
-			printf("%s", cat_oops);
+			if (!optarg || str_size_t(optarg, NULL, 10, false, &buffer) != EOK ) {
+				puts("Invalid buffer size\n");
+				return CMD_FAILURE;
+			}
 			break;
 		case 'm':
@@ -279,5 +329,5 @@
 	}
 
-	if (buffer <= 0)
+	if (buffer < 4)
 		buffer = CAT_DEFAULT_BUFLEN;
 	
@@ -295,5 +345,5 @@
 
 	for (i = optind; argv[i] != NULL && !should_quit; i++)
-		ret += cat_file(argv[i], buffer, hex);
+		ret += cat_file(argv[i], buffer, hex, head, tail, tailFirst);
 
 	if (ret)
Index: uspace/app/bdsh/cmds/modules/cat/cat.h
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.h	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/bdsh/cmds/modules/cat/cat.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -4,5 +4,5 @@
 /* Prototypes for the cat command, excluding entry points */
 
-static unsigned int cat_file(const char *, size_t, bool);
+static unsigned int cat_file(const char *, size_t, bool, off64_t, off64_t, bool);
 
 #endif /* CAT_H */
Index: uspace/app/bdsh/cmds/modules/ls/ls.c
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/bdsh/cmds/modules/ls/ls.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -42,4 +42,5 @@
 #include <sort.h>
 
+#include "ls.h"
 #include "errors.h"
 #include "config.h"
@@ -48,26 +49,30 @@
 #include "cmds.h"
 
-/* Various values that can be returned by ls_scope() */
-#define LS_BOGUS 0
-#define LS_FILE  1
-#define LS_DIR   2
-
-/** Structure to represent a directory entry.
- *
- * Useful to keep together important information
- * for sorting directory entries.
- */
-struct dir_elem_t {
-	char *name;
-	struct stat s;
-};
-
 static const char *cmdname = "ls";
+
+static ls_job_t ls;
 
 static struct option const long_options[] = {
 	{ "help", no_argument, 0, 'h' },
 	{ "unsort", no_argument, 0, 'u' },
+	{ "recursive", no_argument, 0, 'r' },
 	{ 0, 0, 0, 0 }
 };
+
+/* Prototypes for the ls command, excluding entry points. */
+static unsigned int ls_start(ls_job_t *);
+static void ls_print(struct dir_elem_t *);
+static int ls_cmp(void *, void *, void *);
+static signed int ls_scan_dir(const char *, DIR *, struct dir_elem_t **);
+static unsigned int ls_recursive(const char *, DIR *);
+static unsigned int ls_scope(const char *, struct dir_elem_t *);
+
+static unsigned int ls_start(ls_job_t *ls)
+{
+	ls->recursive = 0;
+	ls->sort = 1;
+
+	return 1;
+}
 
 /** Print an entry.
@@ -92,5 +97,4 @@
 }
 
-
 /** Compare 2 directory elements.
  *
@@ -127,5 +131,6 @@
  *				0 otherwise.
  */
-static void ls_scan_dir(const char *d, DIR *dirp, int sort)
+static signed int ls_scan_dir(const char *d, DIR *dirp, 
+    struct dir_elem_t **dir_list_ptr)
 {
 	int alloc_blocks = 20;
@@ -140,10 +145,10 @@
 	
 	if (!dirp)
-		return;
+		return -1;
 
 	buff = (char *) malloc(PATH_MAX);
 	if (!buff) {
 		cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
-		return;
+		return -1;
 	}
 	
@@ -152,5 +157,5 @@
 		cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
 		free(buff);
-		return;
+		return -1;
 	}
 	
@@ -187,5 +192,5 @@
 	}
 	
-	if (sort) {
+	if (ls.sort) {
 		if (!qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t),
 		    ls_cmp, NULL)) {
@@ -196,4 +201,23 @@
 	for (i = 0; i < nbdirs; i++)
 		ls_print(&tosort[i]);
+
+	/* Populate the directory list. */
+	if (ls.recursive) {
+		tmp = (struct dir_elem_t *) realloc(*dir_list_ptr, 
+		    nbdirs * sizeof(struct dir_elem_t));
+		if (!tmp) {
+			cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
+			goto out;
+		} 
+		*dir_list_ptr = tmp;
+
+		for (i = 0; i < nbdirs; i++) {
+			(*dir_list_ptr)[i].name = str_dup(tosort[i].name);
+			if (!(*dir_list_ptr)[i].name) {
+				cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
+				goto out;
+			}
+		}
+	}
 	
 out:
@@ -202,4 +226,103 @@
 	free(tosort);
 	free(buff);
+
+	return nbdirs;
+}
+
+/** Visit a directory recursively.
+ *
+ * ls_recursive visits all the subdirectories recursively and
+ * prints the files and directories in them.
+ *
+ * @param path	Path the current directory being visited.
+ * @param dirp	Directory stream.
+ */
+static unsigned int ls_recursive(const char *path, DIR *dirp)
+{
+	int i, nbdirs, ret;
+	unsigned int scope;
+	char *subdir_path;
+	DIR *subdirp;
+	struct dir_elem_t *dir_list;
+	
+	const char * const trailing_slash = "/";
+
+	nbdirs = 0;
+	dir_list = (struct dir_elem_t *) malloc(sizeof(struct dir_elem_t));
+
+	printf("\n%s:\n", path);
+
+	subdir_path = (char *) malloc(PATH_MAX);
+	if (!subdir_path) {
+		ret = CMD_FAILURE;
+		goto out;
+	}
+
+	nbdirs = ls_scan_dir(path, dirp, &dir_list); 
+	if (nbdirs == -1) {
+		ret = CMD_FAILURE;
+		goto out;
+	}
+
+	for (i = 0; i < nbdirs; ++i) {
+		memset(subdir_path, 0, PATH_MAX);
+
+		if (str_size(subdir_path) + str_size(path) + 1 <= PATH_MAX)
+			str_append(subdir_path, PATH_MAX, path);
+		if (path[str_size(path)-1] != '/' &&
+		    str_size(subdir_path) + str_size(trailing_slash) + 1 <= PATH_MAX)
+			str_append(subdir_path, PATH_MAX, trailing_slash);
+		if (str_size(subdir_path) +
+		    str_size(dir_list[i].name) + 1 <= PATH_MAX)
+			str_append(subdir_path, PATH_MAX, dir_list[i].name);
+
+		scope = ls_scope(subdir_path, &dir_list[i]);
+		switch (scope) {
+		case LS_FILE:
+			break;
+		case LS_DIR:
+			subdirp = opendir(subdir_path);
+			if (!subdirp) {
+				/* May have been deleted between scoping it and opening it */
+				cli_error(CL_EFAIL, "Could not stat %s", dir_list[i].name);
+				ret = CMD_FAILURE;
+				goto out;
+			}
+
+			ret = ls_recursive(subdir_path, subdirp);
+			closedir(subdirp);
+			if (ret == CMD_FAILURE)
+				goto out;
+			break;
+		case LS_BOGUS:
+			ret = CMD_FAILURE;
+			goto out;
+		}	
+	}
+   
+	ret = CMD_SUCCESS; 
+
+out:
+	for (i = 0; i < nbdirs; i++)
+		free(dir_list[i].name);
+	free(dir_list);
+	free(subdir_path);
+
+	return ret;
+}
+
+static unsigned int ls_scope(const char *path, struct dir_elem_t *de)
+{
+	if (stat(path, &de->s)) {
+		cli_error(CL_ENOENT, path);
+		return LS_BOGUS;
+	}
+
+	if (de->s.is_file)
+		return LS_FILE;
+	else if (de->s.is_directory)
+		return LS_DIR;
+
+	return LS_BOGUS;
 }
 
@@ -215,5 +338,6 @@
 		"Options:\n"
 		"  -h, --help       A short option summary\n"
-		"  -u, --unsort     Do not sort directory entries\n",
+		"  -u, --unsort     Do not sort directory entries\n"
+		"  -r, --recursive  List subdirectories recursively\n",
 		cmdname);
 	}
@@ -228,10 +352,16 @@
 	DIR *dirp;
 	int c, opt_ind;
-	int sort = 1;
+	int ret = 0;
+	unsigned int scope;
+
+	if (!ls_start(&ls)) {
+		cli_error(CL_EFAIL, "%s: Could not initialize", cmdname);
+		return CMD_FAILURE;
+	}
 
 	argc = cli_count_args(argv);
 	
 	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
-		c = getopt_long(argc, argv, "hu", long_options, &opt_ind);
+		c = getopt_long(argc, argv, "hur", long_options, &opt_ind);
 		switch (c) {
 		case 'h':
@@ -239,5 +369,8 @@
 			return CMD_SUCCESS;
 		case 'u':
-			sort = 0;
+			ls.sort = 0;
+			break;
+		case 'r':
+			ls.recursive = 1;
 			break;
 		}
@@ -251,5 +384,5 @@
 		return CMD_FAILURE;
 	}
-	memset(de.name, 0, sizeof(PATH_MAX));
+	memset(de.name, 0, PATH_MAX);
 	
 	if (argc == 0)
@@ -257,14 +390,11 @@
 	else
 		str_cpy(de.name, PATH_MAX, argv[optind]);
-	
-	if (stat(de.name, &de.s)) {
-		cli_error(CL_ENOENT, de.name);
-		free(de.name);
-		return CMD_FAILURE;
-	}
-
-	if (de.s.is_file) {
+
+	scope = ls_scope(de.name, &de);
+	switch (scope) {
+	case LS_FILE:
 		ls_print(&de);
-	} else {
+		break;
+	case LS_DIR:
 		dirp = opendir(de.name);
 		if (!dirp) {
@@ -274,11 +404,21 @@
 			return CMD_FAILURE;
 		}
-		ls_scan_dir(de.name, dirp, sort);
+		if (ls.recursive)
+			ret = ls_recursive(de.name, dirp);
+		else  
+			ret = ls_scan_dir(de.name, dirp, NULL);
+
 		closedir(dirp);
+		break;
+	case LS_BOGUS:
+		return CMD_FAILURE;
 	}
 
 	free(de.name);
 
-	return CMD_SUCCESS;
-}
-
+	if (ret == -1 || ret == CMD_FAILURE)
+		return CMD_FAILURE;
+	else
+		return CMD_SUCCESS;
+}
+
Index: uspace/app/bdsh/cmds/modules/ls/ls.h
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
+++ uspace/app/bdsh/cmds/modules/ls/ls.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -0,0 +1,26 @@
+#ifndef LS_H
+#define LS_H
+
+/* Various values that can be returned by ls_scope() */
+#define LS_BOGUS 0
+#define LS_FILE  1
+#define LS_DIR   2
+
+typedef struct {
+	/* Options set at runtime. */
+	unsigned int recursive;
+	unsigned int sort;
+
+} ls_job_t;
+
+/** Structure to represent a directory entry.
+ *
+ * Useful to keep together important information
+ * for sorting directory entries.
+ */
+struct dir_elem_t {
+	char *name;
+	struct stat s;
+};
+
+#endif
Index: uspace/app/bdsh/cmds/modules/touch/entry.h
===================================================================
--- uspace/app/bdsh/cmds/modules/touch/entry.h	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/bdsh/cmds/modules/touch/entry.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -7,3 +7,2 @@
 
 #endif /* TOUCH_ENTRY_H */
-
Index: uspace/app/bdsh/cmds/modules/touch/touch.c
===================================================================
--- uspace/app/bdsh/cmds/modules/touch/touch.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/bdsh/cmds/modules/touch/touch.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -27,6 +27,8 @@
  */
 
-/* TODO: Options that people would expect, such as not creating the file if
- * it doesn't exist, specifying the access time, etc */
+/*
+ * TODO: Options that people would expect, such as specifying the access time,
+ * etc.
+ */
 
 #include <stdio.h>
@@ -37,4 +39,7 @@
 #include <sys/types.h>
 #include <str.h>
+#include <getopt.h>
+#include <sys/stat.h>
+#include <errno.h>
 
 #include "config.h"
@@ -47,15 +52,24 @@
 static const char *cmdname = "touch";
 
+static struct option const long_options[] = {
+	{ "no-create", no_argument, 0, 'c' },
+	{ 0, 0, 0, 0 }
+};
+
 /* Dispays help for touch in various levels */
 void help_cmd_touch(unsigned int level)
 {
 	if (level == HELP_SHORT) {
-		printf("`%s' updates access times for files\n", cmdname);
+		printf("`%s' updates access times of files\n", cmdname);
 	} else {
 		help_cmd_touch(HELP_SHORT);
-		printf("  `%s' <file>, if the file does not exist it will be "
-				"created\n", cmdname);
+		printf("Usage: `%s' [-c|--no-create] <file>...\n\n"
+		    "If the file does not exist it will be created empty,\n"
+		    "unless -c (--no-create) is supplied.\n\n"
+		    "Options:\n"
+		    "   -c, --no-create  Do not create new files\n",
+		    cmdname);
 	}
-
+	
 	return;
 }
@@ -64,39 +78,65 @@
 int cmd_touch(char **argv)
 {
-	unsigned int argc, i = 0, ret = 0;
-	int fd;
+	unsigned int argc = cli_count_args(argv);
+	unsigned int i = 0;
+	unsigned int ret = 0;
+	int c;
+	int longind;
+	bool no_create = false;
+	struct stat file_stat;
+	int fd = -1;
 	char *buff = NULL;
-
+	
 	DIR *dirp;
-
-	argc = cli_count_args(argv);
-
-	if (argc == 1) {
-		printf("%s - incorrect number of arguments. Try `help %s extended'\n",
-			cmdname, cmdname);
+	
+	for (c = 0, optind = 0, longind = 0; c != -1; ) {
+		c = getopt_long(argc, argv, "c", long_options, &longind);
+		switch (c) {
+		case 'c':
+			no_create = true;
+			break;
+		}
+	}
+	
+	if (argc - optind < 1) {
+		printf("%s: Incorrect number of arguments. Try `help %s extended'\n",
+		    cmdname, cmdname);
 		return CMD_FAILURE;
 	}
-
-	for (i = 1; i < argc; i ++) {
+	
+	for (i = optind; argv[i] != NULL; i++) {
 		buff = str_dup(argv[i]);
+		if (buff == NULL) {
+			cli_error(CL_ENOMEM, "Out of memory");
+			ret++;
+			continue;
+		}
+		
 		dirp = opendir(buff);
 		if (dirp) {
-			cli_error(CL_ENOTSUP, "%s is a directory", buff);
+			cli_error(CL_ENOTSUP, "`%s' is a directory", buff);
 			closedir(dirp);
-			ret ++;
+			free(buff);
+			ret++;
 			continue;
 		}
-
-		fd = open(buff, O_RDWR | O_CREAT);
+		
+		/* Check whether file exists if -c (--no-create) option is given */
+		if ((!no_create) || ((no_create) && (stat(buff, &file_stat) == EOK)))
+			fd = open(buff, O_RDWR | O_CREAT);
+		
 		if (fd < 0) {
-			cli_error(CL_EFAIL, "Could not update / create %s ", buff);
-			ret ++;
+			cli_error(CL_EFAIL, "Could not update or create `%s'", buff);
+			free(buff);
+			ret++;
 			continue;
-		} else
+		} else {
 			close(fd);
-
+			fd = -1;
+		}
+		
 		free(buff);
 	}
-
+	
 	if (ret)
 		return CMD_FAILURE;
@@ -104,3 +144,2 @@
 		return CMD_SUCCESS;
 }
-
Index: uspace/app/bdsh/cmds/modules/touch/touch.h
===================================================================
--- uspace/app/bdsh/cmds/modules/touch/touch.h	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/bdsh/cmds/modules/touch/touch.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -4,5 +4,3 @@
 /* Prototypes for the touch command, excluding entry points */
 
-
 #endif /* TOUCH_H */
-
Index: uspace/app/bdsh/cmds/modules/touch/touch_def.h
===================================================================
--- uspace/app/bdsh/cmds/modules/touch/touch_def.h	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/bdsh/cmds/modules/touch/touch_def.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -5,3 +5,2 @@
 	&help_cmd_touch,
 },
-
Index: uspace/app/binutils/Makefile
===================================================================
--- uspace/app/binutils/Makefile	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/binutils/Makefile	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -112,5 +112,5 @@
 endif
 ifeq ($(PLATFORM),arm32)
-TARGET = arm-linux-gnu
+TARGET = arm-linux-gnueabi
 endif
 ifeq ($(PLATFORM),ia32)
Index: uspace/app/getterm/Makefile
===================================================================
--- uspace/app/getterm/Makefile	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/getterm/Makefile	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -29,5 +29,5 @@
 
 USPACE_PREFIX = ../..
-DEFS = -DRELEASE=$(RELEASE) "-DNAME=$(NAME)"
+DEFS = -DRELEASE=$(RELEASE) "-DCOPYRIGHT=$(COPYRIGHT)" "-DNAME=$(NAME)"
 BINARY = getterm
 
Index: uspace/app/getterm/version.c
===================================================================
--- uspace/app/getterm/version.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/getterm/version.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -40,4 +40,5 @@
 #include "version.h"
 
+static const char *copyright = STRING(COPYRIGHT);
 static const char *release = STRING(RELEASE);
 static const char *name = STRING(NAME);
@@ -61,5 +62,5 @@
 	printf("HelenOS release %s (%s)%s%s\n", release, name, revision, timestamp);
 	printf("Running on %s (%s)\n", arch, term);
-	printf("Copyright (c) 2001-2011 HelenOS project\n\n");
+	printf("%s\n\n", copyright);
 }
 
Index: uspace/app/mkexfat/Makefile
===================================================================
--- uspace/app/mkexfat/Makefile	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
+++ uspace/app/mkexfat/Makefile	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2012 Maurizio Lombardi
+# 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 = $(LIBBLOCK_PREFIX)/libblock.a
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX)
+BINARY = mkexfat
+
+SOURCES = \
+	mkexfat.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/mkexfat/exfat.h
===================================================================
--- uspace/app/mkexfat/exfat.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
+++ uspace/app/mkexfat/exfat.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2008 Jakub Jermar
+ * Copyright (c) 2011 Oleg Romanenko
+ * 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
+ * @{
+ */
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <bool.h>
+
+#define EXFAT_FILENAME_LEN	255
+#define EXFAT_NAME_PART_LEN	15
+
+#define EXFAT_TYPE_UNUSED	0x00
+#define EXFAT_TYPE_USED		0x80
+#define EXFAT_TYPE_VOLLABEL	0x83
+#define EXFAT_TYPE_BITMAP	0x81
+#define EXFAT_TYPE_UCTABLE	0x82
+#define EXFAT_TYPE_GUID		0xA0
+#define EXFAT_TYPE_FILE		0x85
+#define EXFAT_TYPE_STREAM	0xC0
+#define EXFAT_TYPE_NAME		0xC1
+
+#define EXFAT_ATTR_RDONLY	0x01
+#define EXFAT_ATTR_HIDDEN	0x02
+#define EXFAT_ATTR_SYSTEM	0x04
+#define EXFAT_ATTR_SUBDIR	0x10
+#define EXFAT_ATTR_ARCHIVE	0x20
+
+
+/* All dentry structs should have 31 byte size */
+typedef struct {
+	uint8_t 	size;
+	uint16_t 	label[11];
+	uint8_t 	_reserved[8];
+} __attribute__ ((packed)) exfat_vollabel_dentry_t;
+
+typedef struct {
+	uint8_t 	flags;
+	uint8_t 	_reserved[18];
+	uint32_t 	firstc;
+	uint64_t 	size;
+} __attribute__ ((packed)) exfat_bitmap_dentry_t;
+
+typedef struct {
+	uint8_t 	_reserved1[3];
+	uint32_t 	checksum;
+	uint8_t 	_reserved2[12];
+	uint32_t 	firstc;
+	uint64_t 	size;
+} __attribute__ ((packed)) exfat_uctable_dentry_t;
+
+typedef struct {
+	uint8_t 	count; /* Always zero */ 
+	uint16_t 	checksum;
+	uint16_t 	flags;
+	uint8_t 	guid[16];
+	uint8_t 	_reserved[10];
+} __attribute__ ((packed)) exfat_guid_dentry_t;
+
+typedef struct {
+	uint8_t 	count;
+	uint16_t 	checksum;
+	uint16_t 	attr;
+	uint8_t 	_reserved1[2];
+	uint32_t 	ctime;
+	uint32_t 	mtime;
+	uint32_t 	atime;
+	uint8_t 	ctime_fine;
+	uint8_t 	mtime_fine;
+	uint8_t 	ctime_tz;
+	uint8_t 	mtime_tz;
+	uint8_t 	atime_tz;
+	uint8_t 	_reserved2[7];
+} __attribute__ ((packed)) exfat_file_dentry_t;
+
+typedef struct {
+	uint8_t 	flags;
+	uint8_t 	_reserved1[1];
+	uint8_t 	name_size;
+	uint16_t 	hash;
+	uint8_t 	_reserved2[2];
+	uint64_t 	valid_data_size;
+	uint8_t 	_reserved3[4];
+	uint32_t 	firstc;
+	uint64_t 	data_size;
+} __attribute__ ((packed)) exfat_stream_dentry_t;
+
+typedef struct {
+	uint8_t 	flags;
+	uint16_t 	name[EXFAT_NAME_PART_LEN];
+} __attribute__ ((packed)) exfat_name_dentry_t;
+
+
+typedef struct {
+	uint8_t type;
+	union {
+		exfat_vollabel_dentry_t	vollabel;
+		exfat_bitmap_dentry_t 	bitmap;
+		exfat_uctable_dentry_t 	uctable;
+		exfat_guid_dentry_t 	guid;
+		exfat_file_dentry_t 	file;
+		exfat_stream_dentry_t 	stream;
+		exfat_name_dentry_t 	name;
+	};
+} __attribute__ ((packed)) exfat_dentry_t;
+
+
+typedef enum {
+	EXFAT_DENTRY_SKIP,
+	EXFAT_DENTRY_LAST,
+	EXFAT_DENTRY_FREE,
+	EXFAT_DENTRY_VOLLABEL,
+	EXFAT_DENTRY_BITMAP,
+	EXFAT_DENTRY_UCTABLE,
+	EXFAT_DENTRY_GUID,
+	EXFAT_DENTRY_FILE,
+	EXFAT_DENTRY_STREAM,
+	EXFAT_DENTRY_NAME
+} exfat_dentry_clsf_t;
+
+
+typedef struct exfat_bs {
+	uint8_t jump[3];            /* 0x00 jmp and nop instructions */
+	uint8_t oem_name[8];        /* 0x03 "EXFAT   " */
+	uint8_t	__reserved[53];     /* 0x0B always 0 */
+	uint64_t volume_start;      /* 0x40 partition first sector */
+	uint64_t volume_count;      /* 0x48 partition sectors count */
+	uint32_t fat_sector_start;  /* 0x50 FAT first sector */
+	uint32_t fat_sector_count;  /* 0x54 FAT sectors count */
+	uint32_t data_start_sector; /* 0x58 Data region first cluster sector */
+	uint32_t data_clusters;     /* 0x5C total clusters count */
+	uint32_t rootdir_cluster;   /* 0x60 first cluster of the root dir */
+	uint32_t volume_serial;     /* 0x64 volume serial number */
+	struct {                    /* 0x68 FS version */
+		uint8_t minor;
+		uint8_t major;
+	} __attribute__ ((packed)) version;
+	uint16_t volume_flags;     /* 0x6A volume state flags */
+	uint8_t bytes_per_sector;  /* 0x6C sector size as (1 << n) */
+	uint8_t sec_per_cluster;   /* 0x6D sectors per cluster as (1 << n) */
+	uint8_t fat_count;         /* 0x6E always 1 */
+	uint8_t drive_no;          /* 0x6F always 0x80 */
+	uint8_t allocated_percent; /* 0x70 percentage of allocated space */
+	uint8_t _reserved2[7];     /* 0x71 reserved */
+	uint8_t bootcode[390];     /* Boot code */
+	uint16_t signature;        /* the value of 0xAA55 */
+} __attribute__((__packed__)) exfat_bs_t;
+
+/**
+ * @}
+ */
Index: uspace/app/mkexfat/mkexfat.c
===================================================================
--- uspace/app/mkexfat/mkexfat.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
+++ uspace/app/mkexfat/mkexfat.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -0,0 +1,952 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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	mkexfat.c
+ * @brief	Tool for creating new exFAT file systems.
+ *
+ */
+
+#include <stdio.h>
+#include <libblock.h>
+#include <assert.h>
+#include <errno.h>
+#include <malloc.h>
+#include <byteorder.h>
+#include <align.h>
+#include <sys/types.h>
+#include <sys/typefmt.h>
+#include <bool.h>
+#include <str.h>
+#include <getopt.h>
+#include "exfat.h"
+#include "upcase.h"
+
+#define NAME    "mkexfat"
+
+/** First sector of the FAT */
+#define FAT_SECTOR_START 128
+
+/** First sector of the Main Extended Boot Region */
+#define EBS_SECTOR_START 1
+
+/** First sector of the Main Extended Boot Region Backup */
+#define EBS_BACKUP_SECTOR_START 13
+
+/** First sector of the Main Boot Sector */
+#define MBS_SECTOR 0
+
+/** First sector of the Main Boot Sector Backup */
+#define MBS_BACKUP_SECTOR 12
+
+/** VBR Checksum sector */
+#define VBR_CHECKSUM_SECTOR 11
+
+/** VBR Backup Checksum sector */
+#define VBR_BACKUP_CHECKSUM_SECTOR 23
+
+/** Size of the Main Extended Boot Region */
+#define EBS_SIZE 8
+
+/** Divide and round up. */
+#define div_round_up(a, b) (((a) + (b) - 1) / (b))
+
+/** The default size of each cluster is 4096 byte */
+#define DEFAULT_CLUSTER_SIZE 4096
+
+/** Index of the first free cluster on the device */
+#define FIRST_FREE_CLUSTER   2
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+
+typedef struct exfat_cfg {
+	aoff64_t volume_start;
+	aoff64_t volume_count;
+	unsigned long fat_sector_count;
+	unsigned long data_start_sector;
+	unsigned long rootdir_cluster;
+	unsigned long upcase_table_cluster;
+	unsigned long bitmap_cluster;
+	unsigned long total_clusters;
+	unsigned long allocated_clusters;
+	size_t   bitmap_size;
+	size_t   sector_size;
+	size_t   cluster_size;
+} exfat_cfg_t;
+
+
+static unsigned log2(unsigned n);
+
+static uint32_t
+vbr_checksum_start(void const *octets, size_t nbytes);
+
+static void
+vbr_checksum_update(void const *octets, size_t nbytes, uint32_t *checksum);
+
+static int
+ebs_write(service_id_t service_id, exfat_cfg_t *cfg,
+    int base, uint32_t *chksum);
+
+static int
+bitmap_write(service_id_t service_id, exfat_cfg_t *cfg);
+
+static uint32_t
+upcase_table_checksum(void const *data, size_t nbytes);
+
+static struct option const long_options[] = {
+	{"help", no_argument, 0, 'h'},
+	{"cluster-size", required_argument, 0, 'c'},
+	{"fs-size", required_argument, 0, 's'},
+};
+
+static void usage(void)
+{
+	printf("Usage: mkexfat [options] <device>\n"
+	    "-c, --cluster-size ## Specify the cluster size (Kb)\n"
+	    "-s, --fs-size ##      Specify the filesystem size (sectors)\n");
+}
+
+/** Initialize the exFAT params structure.
+ *
+ * @param cfg Pointer to the exFAT params structure to initialize.
+ */
+static void
+cfg_params_initialize(exfat_cfg_t *cfg)
+{
+	unsigned long fat_bytes;
+	unsigned long fat_cls;
+	aoff64_t const volume_bytes = (cfg->volume_count - FAT_SECTOR_START) *
+	    cfg->sector_size;
+
+	if (cfg->cluster_size != 0) {
+		/* The user already choose the cluster size he wants */
+		cfg->total_clusters = volume_bytes / cfg->cluster_size;
+		goto skip_cluster_size_set;
+	}
+
+	cfg->total_clusters = volume_bytes / DEFAULT_CLUSTER_SIZE;
+	cfg->cluster_size = DEFAULT_CLUSTER_SIZE;
+
+	/* Compute the required cluster size to index
+	 * the entire storage device and to keep the FAT
+	 * size less or equal to 64 Mb.
+	 */
+	while (cfg->total_clusters > 16000000ULL &&
+	    (cfg->cluster_size < 32 * 1024 * 1024)) {
+
+		cfg->cluster_size <<= 1;
+		cfg->total_clusters = volume_bytes / cfg->cluster_size;
+	}
+
+skip_cluster_size_set:
+
+	/* Compute the FAT size in sectors */
+	fat_bytes = (cfg->total_clusters + 3) * sizeof(uint32_t);
+	cfg->fat_sector_count = div_round_up(fat_bytes, cfg->sector_size);
+
+	/* Compute the number of the first data sector */
+	cfg->data_start_sector = ROUND_UP(FAT_SECTOR_START +
+	    cfg->fat_sector_count, cfg->cluster_size / cfg->sector_size);
+
+	/* Subtract the FAT space from the total
+	 * number of available clusters.
+	 */
+	fat_cls = div_round_up((cfg->data_start_sector -
+	    FAT_SECTOR_START) * cfg->sector_size,
+	    cfg->cluster_size);
+	if (fat_cls >= cfg->total_clusters) {
+		/* Insufficient disk space on device */
+		cfg->total_clusters = 0;
+		return;
+	}
+	cfg->total_clusters -= fat_cls;
+
+	/* Compute the bitmap size */
+	cfg->bitmap_size = div_round_up(cfg->total_clusters, 8);
+
+	/* Compute the number of clusters reserved to the bitmap */
+	cfg->allocated_clusters = div_round_up(cfg->bitmap_size,
+	    cfg->cluster_size);
+
+	/* This account for the root directory */
+	cfg->allocated_clusters++;
+
+	/* Compute the number of clusters reserved to the upcase table */
+	cfg->allocated_clusters += div_round_up(sizeof(upcase_table),
+	    cfg->cluster_size);
+
+	/* Will be set later */
+	cfg->rootdir_cluster = 0;
+
+	/* Bitmap always starts at the first free cluster */
+	cfg->bitmap_cluster = FIRST_FREE_CLUSTER;
+
+	/* The first sector of the partition is zero */
+	cfg->volume_start = 0;
+}
+
+/** Prints the exFAT structure values
+ *
+ * @param cfg Pointer to the exfat_cfg_t structure.
+ */
+static void
+cfg_print_info(exfat_cfg_t *cfg)
+{
+	printf("Sector size:           %lu\n",
+	    (unsigned long) cfg->sector_size);
+	printf("Cluster size:          %lu\n",
+	    (unsigned long) cfg->cluster_size);
+	printf("FAT size in sectors:   %lu\n", cfg->fat_sector_count);
+	printf("Data start sector:     %lu\n", cfg->data_start_sector);
+	printf("Total num of clusters: %lu\n", cfg->total_clusters);
+	printf("Total used clusters:   %lu\n", cfg->allocated_clusters);
+	printf("Bitmap size:           %lu\n", (unsigned long)
+	    div_round_up(cfg->bitmap_size, cfg->cluster_size));
+	printf("Upcase table size:     %lu\n", (unsigned long)
+	    div_round_up(sizeof(upcase_table), cfg->cluster_size));
+}
+
+/** Initialize the Main Boot Sector fields.
+ *
+ * @param mbs Pointer to the Main Boot Sector structure.
+ * @param cfg Pointer to the exFAT configuration structure.
+ * @return    Initial checksum value.
+ */
+static uint32_t
+vbr_initialize(exfat_bs_t *mbs, exfat_cfg_t *cfg)
+{
+	/* Fill the structure with zeroes */
+	memset(mbs, 0, sizeof(exfat_bs_t));
+
+	/* Init Jump Boot section */
+	mbs->jump[0] = 0xEB;
+	mbs->jump[1] = 0x76;
+	mbs->jump[2] = 0x90;
+
+	/* Set the filesystem name */
+	memcpy(mbs->oem_name, "EXFAT   ", sizeof(mbs->oem_name));
+
+	mbs->volume_start = host2uint64_t_le(cfg->volume_start);
+	mbs->volume_count = host2uint64_t_le(cfg->volume_count);
+	mbs->fat_sector_start = host2uint32_t_le(FAT_SECTOR_START);
+	mbs->fat_sector_count = host2uint32_t_le(cfg->fat_sector_count);
+	mbs->data_start_sector = host2uint32_t_le(cfg->data_start_sector);
+
+	mbs->data_clusters = host2uint32_t_le(cfg->total_clusters);
+
+	mbs->rootdir_cluster = host2uint32_t_le(cfg->rootdir_cluster);
+	mbs->volume_serial = host2uint32_t_le(0xe1028172);
+	mbs->version.major = 1;
+	mbs->version.minor = 0;
+	mbs->volume_flags = host2uint16_t_le(0);
+	mbs->bytes_per_sector = log2(cfg->sector_size);
+	mbs->sec_per_cluster = log2(cfg->cluster_size / cfg->sector_size);
+
+	/* Maximum cluster size is 32 Mb */
+	assert((mbs->bytes_per_sector + mbs->sec_per_cluster) <= 25);
+
+	mbs->fat_count = 1;
+	mbs->drive_no = 0x80;
+	mbs->allocated_percent = 0;
+	mbs->signature = host2uint16_t_le(0xAA55);
+
+	return vbr_checksum_start(mbs, sizeof(exfat_bs_t));
+}
+
+static int
+bootsec_write(service_id_t service_id, exfat_cfg_t *cfg)
+{
+	exfat_bs_t mbs;
+	uint32_t vbr_checksum;
+	uint32_t *chksum_sector;
+	int rc;
+	unsigned idx;
+
+	chksum_sector = calloc(cfg->sector_size, sizeof(uint8_t));
+	if (!chksum_sector)
+		return ENOMEM;
+
+	vbr_checksum = vbr_initialize(&mbs, cfg);
+
+	/* Write the Main Boot Sector to disk */
+	rc = block_write_direct(service_id, MBS_SECTOR, 1, &mbs);
+	if (rc != EOK)
+		goto exit;
+
+	/* Write the Main extended boot sectors to disk */
+	rc = ebs_write(service_id, cfg, EBS_SECTOR_START, &vbr_checksum);
+	if (rc != EOK)
+		goto exit;
+
+	/* Write the Main Boot Sector backup to disk */
+	rc = block_write_direct(service_id, MBS_BACKUP_SECTOR, 1, &mbs);
+	if (rc != EOK)
+		goto exit;
+
+	/* Initialize the checksum sectors */
+	for (idx = 0; idx < cfg->sector_size / sizeof(uint32_t); ++idx)
+		chksum_sector[idx] = host2uint32_t_le(vbr_checksum);
+
+	/* Write the main checksum sector to disk */
+	rc = block_write_direct(service_id,
+	    VBR_CHECKSUM_SECTOR, 1, chksum_sector);
+	if (rc != EOK)
+		goto exit;
+
+	/* Write the backup checksum sector to disk */
+	rc = block_write_direct(service_id,
+	    VBR_BACKUP_CHECKSUM_SECTOR, 1, chksum_sector);
+	if (rc != EOK)
+		goto exit;
+
+	/* Write the Main extended boot sectors backup to disk */ 
+	rc = ebs_write(service_id, cfg,
+	    EBS_BACKUP_SECTOR_START, &vbr_checksum);
+
+exit:
+	free(chksum_sector);
+	return rc;
+}
+
+/** Write the Main Extended Boot Sector to disk
+ *
+ * @param service_id  The service id.
+ * @param cfg  Pointer to the exFAT configuration structure.
+ * @param base Base sector of the EBS.
+ * @return  EOK on success or a negative error code.
+ */
+static int
+ebs_write(service_id_t service_id, exfat_cfg_t *cfg, int base,
+    uint32_t *chksum)
+{
+	uint32_t *ebs = calloc(cfg->sector_size, sizeof(uint8_t));
+	int i, rc;
+
+	if (!ebs)
+		return ENOMEM;
+
+	ebs[cfg->sector_size / 4 - 1] = host2uint32_t_le(0xAA550000);
+
+	for (i = 0; i < EBS_SIZE; ++i) {
+		vbr_checksum_update(ebs, cfg->sector_size, chksum);
+
+		rc = block_write_direct(service_id,
+		    i + base, 1, ebs);
+
+		if (rc != EOK)
+			goto exit;
+	}
+
+	/* The OEM record is not yet used
+	 * by the official exFAT implementation, we'll fill
+	 * it with zeroes.
+	 */
+
+	memset(ebs, 0, cfg->sector_size);
+	vbr_checksum_update(ebs, cfg->sector_size, chksum);
+
+	rc = block_write_direct(service_id, i++ + base, 1, ebs);
+	if (rc != EOK)
+		goto exit;
+
+	/* The next sector is reserved, fill it with zeroes too */
+	vbr_checksum_update(ebs, cfg->sector_size, chksum);
+
+	rc = block_write_direct(service_id, i + base, 1, ebs);
+	if (rc != EOK)
+		goto exit;
+
+exit:
+	free(ebs);
+	return rc;
+}
+
+/** Initialize the FAT table.
+ *
+ * @param service_id  The service id.
+ * @param cfg Pointer to the exfat_cfg structure.
+ * @return EOK on success or a negative error code.
+ */
+static int
+fat_initialize(service_id_t service_id, exfat_cfg_t *cfg)
+{
+	unsigned long i;
+	uint32_t *pfat;
+	int rc;
+
+	pfat = calloc(cfg->sector_size, 1);
+	if (!pfat)
+		return ENOMEM;
+
+	pfat[0] = host2uint32_t_le(0xFFFFFFF8);
+	pfat[1] = host2uint32_t_le(0xFFFFFFFF);
+
+	rc = block_write_direct(service_id, FAT_SECTOR_START, 1, pfat);
+	if (rc != EOK)
+		goto error;
+
+	pfat[0] = pfat[1] = 0;
+
+	for (i = 1; i < cfg->fat_sector_count; ++i) {
+		rc = block_write_direct(service_id,
+		    FAT_SECTOR_START + i, 1, pfat);
+		if (rc != EOK)
+			goto error;
+	}
+
+error:
+	free(pfat);
+	return rc;
+}
+
+/** Allocate a given number of clusters and create a cluster chain.
+ *
+ * @param service_id  The service id.
+ * @param cfg  Pointer to the exfat configuration structure.
+ * @param cur_cls  Cluster index from where to start the allocation.
+ * @param ncls  Number of clusters to allocate.
+ * @return EOK on success or a negative error code.
+ */
+static int
+fat_allocate_clusters(service_id_t service_id, exfat_cfg_t *cfg,
+    uint32_t cur_cls, unsigned long ncls)
+{
+	int rc;
+	unsigned const fat_entries = cfg->sector_size / sizeof(uint32_t);
+	aoff64_t fat_sec = cur_cls / fat_entries + FAT_SECTOR_START;
+	uint32_t *fat;
+	uint32_t next_cls = cur_cls;
+
+	cur_cls %= fat_entries;
+
+	fat = malloc(cfg->sector_size);
+	if (!fat)
+		return ENOMEM;
+
+loop:
+	rc = block_read_direct(service_id, fat_sec, 1, fat);
+	if (rc != EOK)
+		goto exit;
+
+	assert(fat[cur_cls] == 0);
+	assert(ncls > 0);
+
+	for (; cur_cls < fat_entries && ncls > 1; ++cur_cls, --ncls)
+		fat[cur_cls] = host2uint32_t_le(++next_cls);
+
+	if (cur_cls == fat_entries) {
+		/* This sector is full, there are no more free entries,
+		 * commit the changes to disk and restart from the next
+		 * sector.
+		 */
+		rc = block_write_direct(service_id, fat_sec++, 1, fat);
+		if (rc != EOK)
+			goto exit;
+		cur_cls = 0;
+		goto loop;
+	} else if (ncls == 1) {
+		/* This is the last cluster of this chain, mark it
+		 * with EOF.
+		 */
+		fat[cur_cls] = host2uint32_t_le(0xFFFFFFFF);
+	}
+
+	rc = block_write_direct(service_id, fat_sec, 1, fat);
+
+exit:
+	free(fat);
+	return rc;
+}
+
+/** Initialize the allocation bitmap.
+ *
+ * @param service_id   The service id.
+ * @param cfg  Pointer to the exfat configuration structure.
+ * @return  EOK on success or a negative error code.
+ */
+static int
+bitmap_write(service_id_t service_id, exfat_cfg_t *cfg)
+{
+	unsigned long i, sec;
+	unsigned long allocated_cls;
+	int rc = EOK;
+	bool need_reset = true;
+
+	/* Bitmap size in sectors */
+	size_t const bss = div_round_up(cfg->bitmap_size, cfg->sector_size);
+
+	uint8_t *bitmap = malloc(cfg->sector_size);
+	if (!bitmap)
+		return ENOMEM;
+
+	allocated_cls = cfg->allocated_clusters;
+
+	for (sec = 0; sec < bss; ++sec) {
+		if (need_reset) {
+			need_reset = false;
+			memset(bitmap, 0, cfg->sector_size);
+		}
+		if (allocated_cls > 0) {
+			for (i = 0; i < allocated_cls; ++i) {
+				unsigned byte_idx = i / 8;
+				unsigned bit_idx = i % 8;
+
+				if (byte_idx == cfg->sector_size)
+					break;
+				bitmap[byte_idx] |= 1 << bit_idx;
+			}
+
+			allocated_cls -= i;
+			need_reset = true;
+		}
+
+		rc = block_write_direct(service_id,
+		    cfg->data_start_sector + sec, 1, bitmap);
+		if (rc != EOK)
+			goto exit;
+	}
+
+exit:
+	free(bitmap);
+	return rc;
+}
+
+/** Write the upcase table to disk. */
+static int
+upcase_table_write(service_id_t service_id, exfat_cfg_t *cfg)
+{
+	int rc = EOK;
+	aoff64_t start_sec, nsecs, i;
+	uint8_t *table_ptr;
+	uint8_t *buf;
+	size_t table_size = sizeof(upcase_table);
+
+	buf = malloc(cfg->sector_size);
+	if (!buf)
+		return ENOENT;
+
+	/* Compute the start sector of the upcase table */
+	start_sec = cfg->data_start_sector;
+	start_sec += ((cfg->upcase_table_cluster - 2) * cfg->cluster_size) /
+	    cfg->sector_size;
+
+	/* Compute the number of sectors needed to store the table on disk */
+	nsecs = div_round_up(sizeof(upcase_table), cfg->sector_size);
+	table_ptr = (uint8_t *) upcase_table;
+
+	for (i = 0; i < nsecs; ++i,
+	    table_ptr += min(table_size, cfg->sector_size),
+	    table_size -= cfg->sector_size) {
+
+		if (table_size < cfg->sector_size) {
+			/* Reset the content of the unused part
+			 * of the last sector.
+			 */
+			memset(buf, 0, cfg->sector_size);
+		}
+		memcpy(buf, table_ptr, min(table_size, cfg->sector_size));
+
+		rc = block_write_direct(service_id,
+		    start_sec + i, 1, buf);
+		if (rc != EOK)
+			goto exit;
+	}
+
+exit:
+	free(buf);
+	return rc;
+}
+
+/** Initialize and write the root directory entries to disk.
+ *
+ * @param service_id   The service id.
+ * @param cfg   Pointer to the exFAT configuration structure.
+ * @return   EOK on success or a negative error code.
+ */
+static int
+root_dentries_write(service_id_t service_id, exfat_cfg_t *cfg)
+{
+	exfat_dentry_t *d;
+	aoff64_t rootdir_sec;
+	int rc;
+	uint8_t *data;
+	unsigned long i;
+
+	data = calloc(cfg->sector_size, 1);
+	if (!data)
+		return ENOMEM;
+
+	d = (exfat_dentry_t *) data;
+
+	/* Initialize the volume label dentry */
+	d->type = EXFAT_TYPE_VOLLABEL;
+	str_to_utf16(d->vollabel.label, 8, "HELENOS ");
+	d->vollabel.size = 8;
+
+	d++;
+
+	/* Initialize the allocation bitmap dentry */
+	d->type = EXFAT_TYPE_BITMAP;
+	d->bitmap.flags = 0; /* First FAT */
+	d->bitmap.firstc = host2uint32_t_le(cfg->bitmap_cluster);
+	d->bitmap.size = host2uint64_t_le(cfg->bitmap_size);
+
+	d++;
+
+	/* Initialize the upcase table dentry */
+	d->type = EXFAT_TYPE_UCTABLE;
+	d->uctable.checksum = host2uint32_t_le(upcase_table_checksum(
+	    upcase_table, sizeof(upcase_table)));
+	d->uctable.firstc = host2uint32_t_le(cfg->upcase_table_cluster);
+	d->uctable.size = host2uint64_t_le(sizeof(upcase_table));
+
+	/* Compute the number of the sector where the rootdir resides */
+
+	rootdir_sec = cfg->data_start_sector;
+	rootdir_sec += ((cfg->rootdir_cluster - 2) * cfg->cluster_size) /
+	    cfg->sector_size;
+
+	rc = block_write_direct(service_id, rootdir_sec, 1, data);
+	if (rc != EOK)
+		goto exit;
+
+	/* Fill the content of the sectors not used by the
+	 * root directory with zeroes.
+	 */
+	memset(data, 0, cfg->sector_size);
+	for (i = 1; i < cfg->cluster_size / cfg->sector_size; ++i) {
+		rc = block_write_direct(service_id, rootdir_sec + i, 1, data);
+		if (rc != EOK)
+			goto exit;
+	}
+
+exit:
+	free(data);
+	return rc;
+}
+
+/** Given a number (n), returns the result of log2(n).
+ *
+ * It works only if n is a power of two.
+ */
+static unsigned
+log2(unsigned n)
+{
+	unsigned r;
+
+	for (r = 0;n >> r != 1; ++r);
+
+	return r;
+}
+
+/** Initialize the VBR checksum calculation */
+static uint32_t
+vbr_checksum_start(void const *data, size_t nbytes)
+{
+	uint32_t checksum = 0;
+	size_t index;
+	uint8_t const *octets = (uint8_t *) data;
+
+	for (index = 0; index < nbytes; ++index) {
+		if (index == 106 || index == 107 || index == 112) {
+			/* Skip volume_flags and allocated_percent fields */
+			continue;
+		}
+
+		checksum = ((checksum << 31) | (checksum >> 1)) +
+		    octets[index];
+	}
+
+	return checksum;
+}
+
+/** Update the VBR checksum */
+static void
+vbr_checksum_update(void const *data, size_t nbytes, uint32_t *checksum)
+{
+	size_t index;
+	uint8_t const *octets = (uint8_t *) data;
+
+	for (index = 0; index < nbytes; ++index) {
+		*checksum = ((*checksum << 31) | (*checksum >> 1)) +
+		    octets[index];
+	}
+}
+
+/** Compute the checksum of the upcase table.
+ *
+ * @param data   Pointer to the upcase table.
+ * @param nbytes size of the upcase table in bytes.
+ * @return   Checksum value.
+ */
+static uint32_t
+upcase_table_checksum(void const *data, size_t nbytes)
+{
+	size_t index;
+	uint32_t chksum = 0;
+	uint8_t const *octets = (uint8_t *) data;
+
+	for (index = 0; index < nbytes; ++index)
+		chksum = ((chksum << 31) | (chksum >> 1)) + octets[index];
+
+	return chksum;
+}
+
+/** Check if a given number is a power of two.
+ *
+ * @param n   The number to check.
+ * @return    true if n is a power of two, false otherwise.
+ */
+static bool
+is_power_of_two(unsigned long n)
+{
+	if (n == 0)
+		return false;
+
+	return (n & (n - 1)) == 0;
+}
+
+int main (int argc, char **argv)
+{
+	exfat_cfg_t cfg;
+	uint32_t next_cls;
+	char *dev_path;
+	service_id_t service_id;
+	int rc, c, opt_ind;
+	aoff64_t user_fs_size = 0;
+
+	if (argc < 2) {
+		printf(NAME ": Error, argument missing\n");
+		usage();
+		return 1;
+	}
+
+	cfg.cluster_size = 0;
+
+	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
+		c = getopt_long(argc, argv, "hs:c:",
+		    long_options, &opt_ind);
+		switch (c) {
+		case 'h':
+			usage();
+			return 0;
+		case 's':
+			user_fs_size = (aoff64_t) strtol(optarg, NULL, 10);
+			break;
+
+		case 'c':
+			cfg.cluster_size = strtol(optarg, NULL, 10) * 1024;
+			if (cfg.cluster_size < 4096) {
+				printf(NAME ": Error, cluster size can't"
+				    " be less than 4096 byte.\n");
+				return 1;
+			} else if (cfg.cluster_size > 32 * 1024 * 1024) {
+				printf(NAME ": Error, cluster size can't"
+				    " be greater than 32 Mb");
+				return 1;
+			}
+
+			if (!is_power_of_two(cfg.cluster_size)) {
+				printf(NAME ": Error, the size of the cluster"
+				    " must be a power of two.\n");
+				return 1;
+			}
+			break;
+		}
+	}
+
+	argv += optind;
+	dev_path = *argv;
+
+	if (!dev_path) {
+		printf(NAME ": Error, you must specify a valid block"
+		    " device.\n");
+		usage();
+		return 1;
+	}
+
+	printf("Device = %s\n", dev_path);
+
+	rc = loc_service_get_id(dev_path, &service_id, 0);
+	if (rc != EOK) {
+		printf(NAME ": Error resolving device `%s'.\n", dev_path);
+		return 2;
+	}
+
+	rc = block_init(EXCHANGE_SERIALIZE, service_id, 2048);
+	if (rc != EOK) {
+		printf(NAME ": Error initializing libblock.\n");
+		return 2;
+	}
+
+	rc = block_get_bsize(service_id, &cfg.sector_size);
+	if (rc != EOK) {
+		printf(NAME ": Error determining device sector size.\n");
+		return 2;
+	}
+
+	user_fs_size *= cfg.sector_size;
+	if (user_fs_size > 0 && user_fs_size < 1024 * 1024) {
+		printf(NAME ": Error, fs size can't be less"
+		    " than 1 Mb.\n");
+		return 1;
+	}
+
+
+	if (cfg.sector_size > 4096) {
+		printf(NAME ": Error, sector size can't be greater" \
+		    " than 4096 bytes.\n");
+		return 2;
+	}
+
+	rc = block_get_nblocks(service_id, &cfg.volume_count);
+	if (rc != EOK) {
+		printf(NAME ": Warning, failed to obtain" \
+		    " block device size.\n");
+
+		if (user_fs_size == 0) {
+			printf(NAME ": You must specify the" \
+			    " filesystem size.\n");
+			return 1;
+		}
+	} else {
+		printf("Block device has %" PRIuOFF64 " blocks.\n",
+		    cfg.volume_count);
+	}
+
+	if (user_fs_size != 0) {
+		if (user_fs_size > cfg.volume_count * cfg.sector_size) {
+			printf(NAME ": Error, the device is not big enough"
+			    " to create a filesystem of"
+			    " the specified size.\n");
+			return 1;
+		}
+
+		cfg.volume_count = user_fs_size / cfg.sector_size;
+	}
+
+	cfg_params_initialize(&cfg);
+	cfg_print_info(&cfg);
+
+	if (cfg.total_clusters <= cfg.allocated_clusters + 2) {
+		printf(NAME ": Error, insufficient disk space on device.\n");
+		return 2;
+	}
+
+	printf("Writing the allocation table.\n");
+
+	/* Initialize the FAT table */
+	rc = fat_initialize(service_id, &cfg);
+	if (rc != EOK) {
+		printf(NAME ": Error, failed to write the FAT to disk\n");
+		return 2;
+	}
+
+	/* Allocate clusters for the bitmap */
+	rc = fat_allocate_clusters(service_id, &cfg, cfg.bitmap_cluster,
+	    div_round_up(cfg.bitmap_size, cfg.cluster_size));
+	if (rc != EOK) {
+		printf(NAME ": Error, failed to allocate" \
+		    " clusters for bitmap.\n");
+		return 2;
+	}
+
+	next_cls = cfg.bitmap_cluster +
+	    div_round_up(cfg.bitmap_size, cfg.cluster_size);
+	cfg.upcase_table_cluster = next_cls;
+
+	/* Allocate clusters for the upcase table */
+	rc = fat_allocate_clusters(service_id, &cfg, next_cls,
+	    div_round_up(sizeof(upcase_table), cfg.cluster_size));
+	if (rc != EOK) {
+		printf(NAME ":Error, failed to allocate clusters" \
+		    " for the upcase table.\n");
+		return 2;
+	}
+
+	next_cls += div_round_up(sizeof(upcase_table), cfg.cluster_size);
+	cfg.rootdir_cluster = next_cls;
+
+	/* Allocate a cluster for the root directory entry */
+	rc = fat_allocate_clusters(service_id, &cfg, next_cls, 1);
+	if (rc != EOK) {
+		printf(NAME ": Error, failed to allocate cluster" \
+		    " for the root dentry.\n");
+		return 2;
+	}
+
+	printf("Writing the allocation bitmap.\n");
+
+	/* Write the allocation bitmap to disk */
+	rc = bitmap_write(service_id, &cfg);
+	if (rc != EOK) {
+		printf(NAME ": Error, failed to write the allocation" \
+		    " bitmap to disk.\n");
+		return 2;
+	}
+
+	printf("Writing the upcase table.\n");
+
+	/* Write the upcase table to disk */
+	rc = upcase_table_write(service_id, &cfg);
+	if (rc != EOK) {
+		printf(NAME ": Error, failed to write the" \
+		    " upcase table to disk.\n");
+		return 2;
+	}
+
+	printf("Writing the root directory.\n");
+
+	rc = root_dentries_write(service_id, &cfg);
+	if (rc != EOK) {
+		printf(NAME ": Error, failed to write the root directory" \
+		    " entries to disk.\n");
+		return 2;
+	}
+
+	printf("Writing the boot sectors.\n");
+
+	rc = bootsec_write(service_id, &cfg);
+	if (rc != EOK) {
+		printf(NAME ": Error, failed to write the VBR to disk\n");
+		return 2;
+	}
+
+	printf("Success.\n");
+
+	return 0;
+}
+
+/**
+ * @}
+ */
+
Index: uspace/app/mkexfat/upcase.h
===================================================================
--- uspace/app/mkexfat/upcase.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
+++ uspace/app/mkexfat/upcase.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -0,0 +1,2964 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ * 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 _UPCASE_H_
+#define _UPCASE_H_
+
+/** Up-case unicode table */
+static uint8_t const upcase_table[] = {
+    0x00, 0x00,
+    0x01, 0x00,
+    0x02, 0x00,
+    0x03, 0x00,
+    0x04, 0x00,
+    0x05, 0x00,
+    0x06, 0x00,
+    0x07, 0x00,
+    0x08, 0x00,
+    0x09, 0x00,
+    0x0a, 0x00,
+    0x0b, 0x00,
+    0x0c, 0x00,
+    0x0d, 0x00,
+    0x0e, 0x00,
+    0x0f, 0x00,
+    0x10, 0x00,
+    0x11, 0x00,
+    0x12, 0x00,
+    0x13, 0x00,
+    0x14, 0x00,
+    0x15, 0x00,
+    0x16, 0x00,
+    0x17, 0x00,
+    0x18, 0x00,
+    0x19, 0x00,
+    0x1a, 0x00,
+    0x1b, 0x00,
+    0x1c, 0x00,
+    0x1d, 0x00,
+    0x1e, 0x00,
+    0x1f, 0x00,
+    0x20, 0x00,
+    0x21, 0x00,
+    0x22, 0x00,
+    0x23, 0x00,
+    0x24, 0x00,
+    0x25, 0x00,
+    0x26, 0x00,
+    0x27, 0x00,
+    0x28, 0x00,
+    0x29, 0x00,
+    0x2a, 0x00,
+    0x2b, 0x00,
+    0x2c, 0x00,
+    0x2d, 0x00,
+    0x2e, 0x00,
+    0x2f, 0x00,
+    0x30, 0x00,
+    0x31, 0x00,
+    0x32, 0x00,
+    0x33, 0x00,
+    0x34, 0x00,
+    0x35, 0x00,
+    0x36, 0x00,
+    0x37, 0x00,
+    0x38, 0x00,
+    0x39, 0x00,
+    0x3a, 0x00,
+    0x3b, 0x00,
+    0x3c, 0x00,
+    0x3d, 0x00,
+    0x3e, 0x00,
+    0x3f, 0x00,
+    0x40, 0x00,
+    0x41, 0x00,
+    0x42, 0x00,
+    0x43, 0x00,
+    0x44, 0x00,
+    0x45, 0x00,
+    0x46, 0x00,
+    0x47, 0x00,
+    0x48, 0x00,
+    0x49, 0x00,
+    0x4a, 0x00,
+    0x4b, 0x00,
+    0x4c, 0x00,
+    0x4d, 0x00,
+    0x4e, 0x00,
+    0x4f, 0x00,
+    0x50, 0x00,
+    0x51, 0x00,
+    0x52, 0x00,
+    0x53, 0x00,
+    0x54, 0x00,
+    0x55, 0x00,
+    0x56, 0x00,
+    0x57, 0x00,
+    0x58, 0x00,
+    0x59, 0x00,
+    0x5a, 0x00,
+    0x5b, 0x00,
+    0x5c, 0x00,
+    0x5d, 0x00,
+    0x5e, 0x00,
+    0x5f, 0x00,
+    0x60, 0x00,
+    0x41, 0x00,
+    0x42, 0x00,
+    0x43, 0x00,
+    0x44, 0x00,
+    0x45, 0x00,
+    0x46, 0x00,
+    0x47, 0x00,
+    0x48, 0x00,
+    0x49, 0x00,
+    0x4a, 0x00,
+    0x4b, 0x00,
+    0x4c, 0x00,
+    0x4d, 0x00,
+    0x4e, 0x00,
+    0x4f, 0x00,
+    0x50, 0x00,
+    0x51, 0x00,
+    0x52, 0x00,
+    0x53, 0x00,
+    0x54, 0x00,
+    0x55, 0x00,
+    0x56, 0x00,
+    0x57, 0x00,
+    0x58, 0x00,
+    0x59, 0x00,
+    0x5a, 0x00,
+    0x7b, 0x00,
+    0x7c, 0x00,
+    0x7d, 0x00,
+    0x7e, 0x00,
+    0x7f, 0x00,
+    0x80, 0x00,
+    0x81, 0x00,
+    0x82, 0x00,
+    0x83, 0x00,
+    0x84, 0x00,
+    0x85, 0x00,
+    0x86, 0x00,
+    0x87, 0x00,
+    0x88, 0x00,
+    0x89, 0x00,
+    0x8a, 0x00,
+    0x8b, 0x00,
+    0x8c, 0x00,
+    0x8d, 0x00,
+    0x8e, 0x00,
+    0x8f, 0x00,
+    0x90, 0x00,
+    0x91, 0x00,
+    0x92, 0x00,
+    0x93, 0x00,
+    0x94, 0x00,
+    0x95, 0x00,
+    0x96, 0x00,
+    0x97, 0x00,
+    0x98, 0x00,
+    0x99, 0x00,
+    0x9a, 0x00,
+    0x9b, 0x00,
+    0x9c, 0x00,
+    0x9d, 0x00,
+    0x9e, 0x00,
+    0x9f, 0x00,
+    0xa0, 0x00,
+    0xa1, 0x00,
+    0xa2, 0x00,
+    0xa3, 0x00,
+    0xa4, 0x00,
+    0xa5, 0x00,
+    0xa6, 0x00,
+    0xa7, 0x00,
+    0xa8, 0x00,
+    0xa9, 0x00,
+    0xaa, 0x00,
+    0xab, 0x00,
+    0xac, 0x00,
+    0xad, 0x00,
+    0xae, 0x00,
+    0xaf, 0x00,
+    0xb0, 0x00,
+    0xb1, 0x00,
+    0xb2, 0x00,
+    0xb3, 0x00,
+    0xb4, 0x00,
+    0xb5, 0x00,
+    0xb6, 0x00,
+    0xb7, 0x00,
+    0xb8, 0x00,
+    0xb9, 0x00,
+    0xba, 0x00,
+    0xbb, 0x00,
+    0xbc, 0x00,
+    0xbd, 0x00,
+    0xbe, 0x00,
+    0xbf, 0x00,
+    0xc0, 0x00,
+    0xc1, 0x00,
+    0xc2, 0x00,
+    0xc3, 0x00,
+    0xc4, 0x00,
+    0xc5, 0x00,
+    0xc6, 0x00,
+    0xc7, 0x00,
+    0xc8, 0x00,
+    0xc9, 0x00,
+    0xca, 0x00,
+    0xcb, 0x00,
+    0xcc, 0x00,
+    0xcd, 0x00,
+    0xce, 0x00,
+    0xcf, 0x00,
+    0xd0, 0x00,
+    0xd1, 0x00,
+    0xd2, 0x00,
+    0xd3, 0x00,
+    0xd4, 0x00,
+    0xd5, 0x00,
+    0xd6, 0x00,
+    0xd7, 0x00,
+    0xd8, 0x00,
+    0xd9, 0x00,
+    0xda, 0x00,
+    0xdb, 0x00,
+    0xdc, 0x00,
+    0xdd, 0x00,
+    0xde, 0x00,
+    0xdf, 0x00,
+    0xc0, 0x00,
+    0xc1, 0x00,
+    0xc2, 0x00,
+    0xc3, 0x00,
+    0xc4, 0x00,
+    0xc5, 0x00,
+    0xc6, 0x00,
+    0xc7, 0x00,
+    0xc8, 0x00,
+    0xc9, 0x00,
+    0xca, 0x00,
+    0xcb, 0x00,
+    0xcc, 0x00,
+    0xcd, 0x00,
+    0xce, 0x00,
+    0xcf, 0x00,
+    0xd0, 0x00,
+    0xd1, 0x00,
+    0xd2, 0x00,
+    0xd3, 0x00,
+    0xd4, 0x00,
+    0xd5, 0x00,
+    0xd6, 0x00,
+    0xf7, 0x00,
+    0xd8, 0x00,
+    0xd9, 0x00,
+    0xda, 0x00,
+    0xdb, 0x00,
+    0xdc, 0x00,
+    0xdd, 0x00,
+    0xde, 0x00,
+    0x78, 0x01,
+    0x00, 0x01,
+    0x00, 0x01,
+    0x02, 0x01,
+    0x02, 0x01,
+    0x04, 0x01,
+    0x04, 0x01,
+    0x06, 0x01,
+    0x06, 0x01,
+    0x08, 0x01,
+    0x08, 0x01,
+    0x0a, 0x01,
+    0x0a, 0x01,
+    0x0c, 0x01,
+    0x0c, 0x01,
+    0x0e, 0x01,
+    0x0e, 0x01,
+    0x10, 0x01,
+    0x10, 0x01,
+    0x12, 0x01,
+    0x12, 0x01,
+    0x14, 0x01,
+    0x14, 0x01,
+    0x16, 0x01,
+    0x16, 0x01,
+    0x18, 0x01,
+    0x18, 0x01,
+    0x1a, 0x01,
+    0x1a, 0x01,
+    0x1c, 0x01,
+    0x1c, 0x01,
+    0x1e, 0x01,
+    0x1e, 0x01,
+    0x20, 0x01,
+    0x20, 0x01,
+    0x22, 0x01,
+    0x22, 0x01,
+    0x24, 0x01,
+    0x24, 0x01,
+    0x26, 0x01,
+    0x26, 0x01,
+    0x28, 0x01,
+    0x28, 0x01,
+    0x2a, 0x01,
+    0x2a, 0x01,
+    0x2c, 0x01,
+    0x2c, 0x01,
+    0x2e, 0x01,
+    0x2e, 0x01,
+    0x30, 0x01,
+    0x31, 0x01,
+    0x32, 0x01,
+    0x32, 0x01,
+    0x34, 0x01,
+    0x34, 0x01,
+    0x36, 0x01,
+    0x36, 0x01,
+    0x38, 0x01,
+    0x39, 0x01,
+    0x39, 0x01,
+    0x3b, 0x01,
+    0x3b, 0x01,
+    0x3d, 0x01,
+    0x3d, 0x01,
+    0x3f, 0x01,
+    0x3f, 0x01,
+    0x41, 0x01,
+    0x41, 0x01,
+    0x43, 0x01,
+    0x43, 0x01,
+    0x45, 0x01,
+    0x45, 0x01,
+    0x47, 0x01,
+    0x47, 0x01,
+    0x49, 0x01,
+    0x4a, 0x01,
+    0x4a, 0x01,
+    0x4c, 0x01,
+    0x4c, 0x01,
+    0x4e, 0x01,
+    0x4e, 0x01,
+    0x50, 0x01,
+    0x50, 0x01,
+    0x52, 0x01,
+    0x52, 0x01,
+    0x54, 0x01,
+    0x54, 0x01,
+    0x56, 0x01,
+    0x56, 0x01,
+    0x58, 0x01,
+    0x58, 0x01,
+    0x5a, 0x01,
+    0x5a, 0x01,
+    0x5c, 0x01,
+    0x5c, 0x01,
+    0x5e, 0x01,
+    0x5e, 0x01,
+    0x60, 0x01,
+    0x60, 0x01,
+    0x62, 0x01,
+    0x62, 0x01,
+    0x64, 0x01,
+    0x64, 0x01,
+    0x66, 0x01,
+    0x66, 0x01,
+    0x68, 0x01,
+    0x68, 0x01,
+    0x6a, 0x01,
+    0x6a, 0x01,
+    0x6c, 0x01,
+    0x6c, 0x01,
+    0x6e, 0x01,
+    0x6e, 0x01,
+    0x70, 0x01,
+    0x70, 0x01,
+    0x72, 0x01,
+    0x72, 0x01,
+    0x74, 0x01,
+    0x74, 0x01,
+    0x76, 0x01,
+    0x76, 0x01,
+    0x78, 0x01,
+    0x79, 0x01,
+    0x79, 0x01,
+    0x7b, 0x01,
+    0x7b, 0x01,
+    0x7d, 0x01,
+    0x7d, 0x01,
+    0x7f, 0x01,
+    0x43, 0x02,
+    0x81, 0x01,
+    0x82, 0x01,
+    0x82, 0x01,
+    0x84, 0x01,
+    0x84, 0x01,
+    0x86, 0x01,
+    0x87, 0x01,
+    0x87, 0x01,
+    0x89, 0x01,
+    0x8a, 0x01,
+    0x8b, 0x01,
+    0x8b, 0x01,
+    0x8d, 0x01,
+    0x8e, 0x01,
+    0x8f, 0x01,
+    0x90, 0x01,
+    0x91, 0x01,
+    0x91, 0x01,
+    0x93, 0x01,
+    0x94, 0x01,
+    0xf6, 0x01,
+    0x96, 0x01,
+    0x97, 0x01,
+    0x98, 0x01,
+    0x98, 0x01,
+    0x3d, 0x02,
+    0x9b, 0x01,
+    0x9c, 0x01,
+    0x9d, 0x01,
+    0x20, 0x02,
+    0x9f, 0x01,
+    0xa0, 0x01,
+    0xa0, 0x01,
+    0xa2, 0x01,
+    0xa2, 0x01,
+    0xa4, 0x01,
+    0xa4, 0x01,
+    0xa6, 0x01,
+    0xa7, 0x01,
+    0xa7, 0x01,
+    0xa9, 0x01,
+    0xaa, 0x01,
+    0xab, 0x01,
+    0xac, 0x01,
+    0xac, 0x01,
+    0xae, 0x01,
+    0xaf, 0x01,
+    0xaf, 0x01,
+    0xb1, 0x01,
+    0xb2, 0x01,
+    0xb3, 0x01,
+    0xb3, 0x01,
+    0xb5, 0x01,
+    0xb5, 0x01,
+    0xb7, 0x01,
+    0xb8, 0x01,
+    0xb8, 0x01,
+    0xba, 0x01,
+    0xbb, 0x01,
+    0xbc, 0x01,
+    0xbc, 0x01,
+    0xbe, 0x01,
+    0xf7, 0x01,
+    0xc0, 0x01,
+    0xc1, 0x01,
+    0xc2, 0x01,
+    0xc3, 0x01,
+    0xc4, 0x01,
+    0xc5, 0x01,
+    0xc4, 0x01,
+    0xc7, 0x01,
+    0xc8, 0x01,
+    0xc7, 0x01,
+    0xca, 0x01,
+    0xcb, 0x01,
+    0xca, 0x01,
+    0xcd, 0x01,
+    0xcd, 0x01,
+    0xcf, 0x01,
+    0xcf, 0x01,
+    0xd1, 0x01,
+    0xd1, 0x01,
+    0xd3, 0x01,
+    0xd3, 0x01,
+    0xd5, 0x01,
+    0xd5, 0x01,
+    0xd7, 0x01,
+    0xd7, 0x01,
+    0xd9, 0x01,
+    0xd9, 0x01,
+    0xdb, 0x01,
+    0xdb, 0x01,
+    0x8e, 0x01,
+    0xde, 0x01,
+    0xde, 0x01,
+    0xe0, 0x01,
+    0xe0, 0x01,
+    0xe2, 0x01,
+    0xe2, 0x01,
+    0xe4, 0x01,
+    0xe4, 0x01,
+    0xe6, 0x01,
+    0xe6, 0x01,
+    0xe8, 0x01,
+    0xe8, 0x01,
+    0xea, 0x01,
+    0xea, 0x01,
+    0xec, 0x01,
+    0xec, 0x01,
+    0xee, 0x01,
+    0xee, 0x01,
+    0xf0, 0x01,
+    0xf1, 0x01,
+    0xf2, 0x01,
+    0xf1, 0x01,
+    0xf4, 0x01,
+    0xf4, 0x01,
+    0xf6, 0x01,
+    0xf7, 0x01,
+    0xf8, 0x01,
+    0xf8, 0x01,
+    0xfa, 0x01,
+    0xfa, 0x01,
+    0xfc, 0x01,
+    0xfc, 0x01,
+    0xfe, 0x01,
+    0xfe, 0x01,
+    0x00, 0x02,
+    0x00, 0x02,
+    0x02, 0x02,
+    0x02, 0x02,
+    0x04, 0x02,
+    0x04, 0x02,
+    0x06, 0x02,
+    0x06, 0x02,
+    0x08, 0x02,
+    0x08, 0x02,
+    0x0a, 0x02,
+    0x0a, 0x02,
+    0x0c, 0x02,
+    0x0c, 0x02,
+    0x0e, 0x02,
+    0x0e, 0x02,
+    0x10, 0x02,
+    0x10, 0x02,
+    0x12, 0x02,
+    0x12, 0x02,
+    0x14, 0x02,
+    0x14, 0x02,
+    0x16, 0x02,
+    0x16, 0x02,
+    0x18, 0x02,
+    0x18, 0x02,
+    0x1a, 0x02,
+    0x1a, 0x02,
+    0x1c, 0x02,
+    0x1c, 0x02,
+    0x1e, 0x02,
+    0x1e, 0x02,
+    0x20, 0x02,
+    0x21, 0x02,
+    0x22, 0x02,
+    0x22, 0x02,
+    0x24, 0x02,
+    0x24, 0x02,
+    0x26, 0x02,
+    0x26, 0x02,
+    0x28, 0x02,
+    0x28, 0x02,
+    0x2a, 0x02,
+    0x2a, 0x02,
+    0x2c, 0x02,
+    0x2c, 0x02,
+    0x2e, 0x02,
+    0x2e, 0x02,
+    0x30, 0x02,
+    0x30, 0x02,
+    0x32, 0x02,
+    0x32, 0x02,
+    0x34, 0x02,
+    0x35, 0x02,
+    0x36, 0x02,
+    0x37, 0x02,
+    0x38, 0x02,
+    0x39, 0x02,
+    0x65, 0x2c,
+    0x3b, 0x02,
+    0x3b, 0x02,
+    0x3d, 0x02,
+    0x66, 0x2c,
+    0x3f, 0x02,
+    0x40, 0x02,
+    0x41, 0x02,
+    0x41, 0x02,
+    0x43, 0x02,
+    0x44, 0x02,
+    0x45, 0x02,
+    0x46, 0x02,
+    0x46, 0x02,
+    0x48, 0x02,
+    0x48, 0x02,
+    0x4a, 0x02,
+    0x4a, 0x02,
+    0x4c, 0x02,
+    0x4c, 0x02,
+    0x4e, 0x02,
+    0x4e, 0x02,
+    0x50, 0x02,
+    0x51, 0x02,
+    0x52, 0x02,
+    0x81, 0x01,
+    0x86, 0x01,
+    0x55, 0x02,
+    0x89, 0x01,
+    0x8a, 0x01,
+    0x58, 0x02,
+    0x8f, 0x01,
+    0x5a, 0x02,
+    0x90, 0x01,
+    0x5c, 0x02,
+    0x5d, 0x02,
+    0x5e, 0x02,
+    0x5f, 0x02,
+    0x93, 0x01,
+    0x61, 0x02,
+    0x62, 0x02,
+    0x94, 0x01,
+    0x64, 0x02,
+    0x65, 0x02,
+    0x66, 0x02,
+    0x67, 0x02,
+    0x97, 0x01,
+    0x96, 0x01,
+    0x6a, 0x02,
+    0x62, 0x2c,
+    0x6c, 0x02,
+    0x6d, 0x02,
+    0x6e, 0x02,
+    0x9c, 0x01,
+    0x70, 0x02,
+    0x71, 0x02,
+    0x9d, 0x01,
+    0x73, 0x02,
+    0x74, 0x02,
+    0x9f, 0x01,
+    0x76, 0x02,
+    0x77, 0x02,
+    0x78, 0x02,
+    0x79, 0x02,
+    0x7a, 0x02,
+    0x7b, 0x02,
+    0x7c, 0x02,
+    0x64, 0x2c,
+    0x7e, 0x02,
+    0x7f, 0x02,
+    0xa6, 0x01,
+    0x81, 0x02,
+    0x82, 0x02,
+    0xa9, 0x01,
+    0x84, 0x02,
+    0x85, 0x02,
+    0x86, 0x02,
+    0x87, 0x02,
+    0xae, 0x01,
+    0x44, 0x02,
+    0xb1, 0x01,
+    0xb2, 0x01,
+    0x45, 0x02,
+    0x8d, 0x02,
+    0x8e, 0x02,
+    0x8f, 0x02,
+    0x90, 0x02,
+    0x91, 0x02,
+    0xb7, 0x01,
+    0x93, 0x02,
+    0x94, 0x02,
+    0x95, 0x02,
+    0x96, 0x02,
+    0x97, 0x02,
+    0x98, 0x02,
+    0x99, 0x02,
+    0x9a, 0x02,
+    0x9b, 0x02,
+    0x9c, 0x02,
+    0x9d, 0x02,
+    0x9e, 0x02,
+    0x9f, 0x02,
+    0xa0, 0x02,
+    0xa1, 0x02,
+    0xa2, 0x02,
+    0xa3, 0x02,
+    0xa4, 0x02,
+    0xa5, 0x02,
+    0xa6, 0x02,
+    0xa7, 0x02,
+    0xa8, 0x02,
+    0xa9, 0x02,
+    0xaa, 0x02,
+    0xab, 0x02,
+    0xac, 0x02,
+    0xad, 0x02,
+    0xae, 0x02,
+    0xaf, 0x02,
+    0xb0, 0x02,
+    0xb1, 0x02,
+    0xb2, 0x02,
+    0xb3, 0x02,
+    0xb4, 0x02,
+    0xb5, 0x02,
+    0xb6, 0x02,
+    0xb7, 0x02,
+    0xb8, 0x02,
+    0xb9, 0x02,
+    0xba, 0x02,
+    0xbb, 0x02,
+    0xbc, 0x02,
+    0xbd, 0x02,
+    0xbe, 0x02,
+    0xbf, 0x02,
+    0xc0, 0x02,
+    0xc1, 0x02,
+    0xc2, 0x02,
+    0xc3, 0x02,
+    0xc4, 0x02,
+    0xc5, 0x02,
+    0xc6, 0x02,
+    0xc7, 0x02,
+    0xc8, 0x02,
+    0xc9, 0x02,
+    0xca, 0x02,
+    0xcb, 0x02,
+    0xcc, 0x02,
+    0xcd, 0x02,
+    0xce, 0x02,
+    0xcf, 0x02,
+    0xd0, 0x02,
+    0xd1, 0x02,
+    0xd2, 0x02,
+    0xd3, 0x02,
+    0xd4, 0x02,
+    0xd5, 0x02,
+    0xd6, 0x02,
+    0xd7, 0x02,
+    0xd8, 0x02,
+    0xd9, 0x02,
+    0xda, 0x02,
+    0xdb, 0x02,
+    0xdc, 0x02,
+    0xdd, 0x02,
+    0xde, 0x02,
+    0xdf, 0x02,
+    0xe0, 0x02,
+    0xe1, 0x02,
+    0xe2, 0x02,
+    0xe3, 0x02,
+    0xe4, 0x02,
+    0xe5, 0x02,
+    0xe6, 0x02,
+    0xe7, 0x02,
+    0xe8, 0x02,
+    0xe9, 0x02,
+    0xea, 0x02,
+    0xeb, 0x02,
+    0xec, 0x02,
+    0xed, 0x02,
+    0xee, 0x02,
+    0xef, 0x02,
+    0xf0, 0x02,
+    0xf1, 0x02,
+    0xf2, 0x02,
+    0xf3, 0x02,
+    0xf4, 0x02,
+    0xf5, 0x02,
+    0xf6, 0x02,
+    0xf7, 0x02,
+    0xf8, 0x02,
+    0xf9, 0x02,
+    0xfa, 0x02,
+    0xfb, 0x02,
+    0xfc, 0x02,
+    0xfd, 0x02,
+    0xfe, 0x02,
+    0xff, 0x02,
+    0x00, 0x03,
+    0x01, 0x03,
+    0x02, 0x03,
+    0x03, 0x03,
+    0x04, 0x03,
+    0x05, 0x03,
+    0x06, 0x03,
+    0x07, 0x03,
+    0x08, 0x03,
+    0x09, 0x03,
+    0x0a, 0x03,
+    0x0b, 0x03,
+    0x0c, 0x03,
+    0x0d, 0x03,
+    0x0e, 0x03,
+    0x0f, 0x03,
+    0x10, 0x03,
+    0x11, 0x03,
+    0x12, 0x03,
+    0x13, 0x03,
+    0x14, 0x03,
+    0x15, 0x03,
+    0x16, 0x03,
+    0x17, 0x03,
+    0x18, 0x03,
+    0x19, 0x03,
+    0x1a, 0x03,
+    0x1b, 0x03,
+    0x1c, 0x03,
+    0x1d, 0x03,
+    0x1e, 0x03,
+    0x1f, 0x03,
+    0x20, 0x03,
+    0x21, 0x03,
+    0x22, 0x03,
+    0x23, 0x03,
+    0x24, 0x03,
+    0x25, 0x03,
+    0x26, 0x03,
+    0x27, 0x03,
+    0x28, 0x03,
+    0x29, 0x03,
+    0x2a, 0x03,
+    0x2b, 0x03,
+    0x2c, 0x03,
+    0x2d, 0x03,
+    0x2e, 0x03,
+    0x2f, 0x03,
+    0x30, 0x03,
+    0x31, 0x03,
+    0x32, 0x03,
+    0x33, 0x03,
+    0x34, 0x03,
+    0x35, 0x03,
+    0x36, 0x03,
+    0x37, 0x03,
+    0x38, 0x03,
+    0x39, 0x03,
+    0x3a, 0x03,
+    0x3b, 0x03,
+    0x3c, 0x03,
+    0x3d, 0x03,
+    0x3e, 0x03,
+    0x3f, 0x03,
+    0x40, 0x03,
+    0x41, 0x03,
+    0x42, 0x03,
+    0x43, 0x03,
+    0x44, 0x03,
+    0x45, 0x03,
+    0x46, 0x03,
+    0x47, 0x03,
+    0x48, 0x03,
+    0x49, 0x03,
+    0x4a, 0x03,
+    0x4b, 0x03,
+    0x4c, 0x03,
+    0x4d, 0x03,
+    0x4e, 0x03,
+    0x4f, 0x03,
+    0x50, 0x03,
+    0x51, 0x03,
+    0x52, 0x03,
+    0x53, 0x03,
+    0x54, 0x03,
+    0x55, 0x03,
+    0x56, 0x03,
+    0x57, 0x03,
+    0x58, 0x03,
+    0x59, 0x03,
+    0x5a, 0x03,
+    0x5b, 0x03,
+    0x5c, 0x03,
+    0x5d, 0x03,
+    0x5e, 0x03,
+    0x5f, 0x03,
+    0x60, 0x03,
+    0x61, 0x03,
+    0x62, 0x03,
+    0x63, 0x03,
+    0x64, 0x03,
+    0x65, 0x03,
+    0x66, 0x03,
+    0x67, 0x03,
+    0x68, 0x03,
+    0x69, 0x03,
+    0x6a, 0x03,
+    0x6b, 0x03,
+    0x6c, 0x03,
+    0x6d, 0x03,
+    0x6e, 0x03,
+    0x6f, 0x03,
+    0x70, 0x03,
+    0x71, 0x03,
+    0x72, 0x03,
+    0x73, 0x03,
+    0x74, 0x03,
+    0x75, 0x03,
+    0x76, 0x03,
+    0x77, 0x03,
+    0x78, 0x03,
+    0x79, 0x03,
+    0x7a, 0x03,
+    0xfd, 0x03,
+    0xfe, 0x03,
+    0xff, 0x03,
+    0x7e, 0x03,
+    0x7f, 0x03,
+    0x80, 0x03,
+    0x81, 0x03,
+    0x82, 0x03,
+    0x83, 0x03,
+    0x84, 0x03,
+    0x85, 0x03,
+    0x86, 0x03,
+    0x87, 0x03,
+    0x88, 0x03,
+    0x89, 0x03,
+    0x8a, 0x03,
+    0x8b, 0x03,
+    0x8c, 0x03,
+    0x8d, 0x03,
+    0x8e, 0x03,
+    0x8f, 0x03,
+    0x90, 0x03,
+    0x91, 0x03,
+    0x92, 0x03,
+    0x93, 0x03,
+    0x94, 0x03,
+    0x95, 0x03,
+    0x96, 0x03,
+    0x97, 0x03,
+    0x98, 0x03,
+    0x99, 0x03,
+    0x9a, 0x03,
+    0x9b, 0x03,
+    0x9c, 0x03,
+    0x9d, 0x03,
+    0x9e, 0x03,
+    0x9f, 0x03,
+    0xa0, 0x03,
+    0xa1, 0x03,
+    0xa2, 0x03,
+    0xa3, 0x03,
+    0xa4, 0x03,
+    0xa5, 0x03,
+    0xa6, 0x03,
+    0xa7, 0x03,
+    0xa8, 0x03,
+    0xa9, 0x03,
+    0xaa, 0x03,
+    0xab, 0x03,
+    0x86, 0x03,
+    0x88, 0x03,
+    0x89, 0x03,
+    0x8a, 0x03,
+    0xb0, 0x03,
+    0x91, 0x03,
+    0x92, 0x03,
+    0x93, 0x03,
+    0x94, 0x03,
+    0x95, 0x03,
+    0x96, 0x03,
+    0x97, 0x03,
+    0x98, 0x03,
+    0x99, 0x03,
+    0x9a, 0x03,
+    0x9b, 0x03,
+    0x9c, 0x03,
+    0x9d, 0x03,
+    0x9e, 0x03,
+    0x9f, 0x03,
+    0xa0, 0x03,
+    0xa1, 0x03,
+    0xa3, 0x03,
+    0xa3, 0x03,
+    0xa4, 0x03,
+    0xa5, 0x03,
+    0xa6, 0x03,
+    0xa7, 0x03,
+    0xa8, 0x03,
+    0xa9, 0x03,
+    0xaa, 0x03,
+    0xab, 0x03,
+    0x8c, 0x03,
+    0x8e, 0x03,
+    0x8f, 0x03,
+    0xcf, 0x03,
+    0xd0, 0x03,
+    0xd1, 0x03,
+    0xd2, 0x03,
+    0xd3, 0x03,
+    0xd4, 0x03,
+    0xd5, 0x03,
+    0xd6, 0x03,
+    0xd7, 0x03,
+    0xd8, 0x03,
+    0xd8, 0x03,
+    0xda, 0x03,
+    0xda, 0x03,
+    0xdc, 0x03,
+    0xdc, 0x03,
+    0xde, 0x03,
+    0xde, 0x03,
+    0xe0, 0x03,
+    0xe0, 0x03,
+    0xe2, 0x03,
+    0xe2, 0x03,
+    0xe4, 0x03,
+    0xe4, 0x03,
+    0xe6, 0x03,
+    0xe6, 0x03,
+    0xe8, 0x03,
+    0xe8, 0x03,
+    0xea, 0x03,
+    0xea, 0x03,
+    0xec, 0x03,
+    0xec, 0x03,
+    0xee, 0x03,
+    0xee, 0x03,
+    0xf0, 0x03,
+    0xf1, 0x03,
+    0xf9, 0x03,
+    0xf3, 0x03,
+    0xf4, 0x03,
+    0xf5, 0x03,
+    0xf6, 0x03,
+    0xf7, 0x03,
+    0xf7, 0x03,
+    0xf9, 0x03,
+    0xfa, 0x03,
+    0xfa, 0x03,
+    0xfc, 0x03,
+    0xfd, 0x03,
+    0xfe, 0x03,
+    0xff, 0x03,
+    0x00, 0x04,
+    0x01, 0x04,
+    0x02, 0x04,
+    0x03, 0x04,
+    0x04, 0x04,
+    0x05, 0x04,
+    0x06, 0x04,
+    0x07, 0x04,
+    0x08, 0x04,
+    0x09, 0x04,
+    0x0a, 0x04,
+    0x0b, 0x04,
+    0x0c, 0x04,
+    0x0d, 0x04,
+    0x0e, 0x04,
+    0x0f, 0x04,
+    0x10, 0x04,
+    0x11, 0x04,
+    0x12, 0x04,
+    0x13, 0x04,
+    0x14, 0x04,
+    0x15, 0x04,
+    0x16, 0x04,
+    0x17, 0x04,
+    0x18, 0x04,
+    0x19, 0x04,
+    0x1a, 0x04,
+    0x1b, 0x04,
+    0x1c, 0x04,
+    0x1d, 0x04,
+    0x1e, 0x04,
+    0x1f, 0x04,
+    0x20, 0x04,
+    0x21, 0x04,
+    0x22, 0x04,
+    0x23, 0x04,
+    0x24, 0x04,
+    0x25, 0x04,
+    0x26, 0x04,
+    0x27, 0x04,
+    0x28, 0x04,
+    0x29, 0x04,
+    0x2a, 0x04,
+    0x2b, 0x04,
+    0x2c, 0x04,
+    0x2d, 0x04,
+    0x2e, 0x04,
+    0x2f, 0x04,
+    0x10, 0x04,
+    0x11, 0x04,
+    0x12, 0x04,
+    0x13, 0x04,
+    0x14, 0x04,
+    0x15, 0x04,
+    0x16, 0x04,
+    0x17, 0x04,
+    0x18, 0x04,
+    0x19, 0x04,
+    0x1a, 0x04,
+    0x1b, 0x04,
+    0x1c, 0x04,
+    0x1d, 0x04,
+    0x1e, 0x04,
+    0x1f, 0x04,
+    0x20, 0x04,
+    0x21, 0x04,
+    0x22, 0x04,
+    0x23, 0x04,
+    0x24, 0x04,
+    0x25, 0x04,
+    0x26, 0x04,
+    0x27, 0x04,
+    0x28, 0x04,
+    0x29, 0x04,
+    0x2a, 0x04,
+    0x2b, 0x04,
+    0x2c, 0x04,
+    0x2d, 0x04,
+    0x2e, 0x04,
+    0x2f, 0x04,
+    0x00, 0x04,
+    0x01, 0x04,
+    0x02, 0x04,
+    0x03, 0x04,
+    0x04, 0x04,
+    0x05, 0x04,
+    0x06, 0x04,
+    0x07, 0x04,
+    0x08, 0x04,
+    0x09, 0x04,
+    0x0a, 0x04,
+    0x0b, 0x04,
+    0x0c, 0x04,
+    0x0d, 0x04,
+    0x0e, 0x04,
+    0x0f, 0x04,
+    0x60, 0x04,
+    0x60, 0x04,
+    0x62, 0x04,
+    0x62, 0x04,
+    0x64, 0x04,
+    0x64, 0x04,
+    0x66, 0x04,
+    0x66, 0x04,
+    0x68, 0x04,
+    0x68, 0x04,
+    0x6a, 0x04,
+    0x6a, 0x04,
+    0x6c, 0x04,
+    0x6c, 0x04,
+    0x6e, 0x04,
+    0x6e, 0x04,
+    0x70, 0x04,
+    0x70, 0x04,
+    0x72, 0x04,
+    0x72, 0x04,
+    0x74, 0x04,
+    0x74, 0x04,
+    0x76, 0x04,
+    0x76, 0x04,
+    0x78, 0x04,
+    0x78, 0x04,
+    0x7a, 0x04,
+    0x7a, 0x04,
+    0x7c, 0x04,
+    0x7c, 0x04,
+    0x7e, 0x04,
+    0x7e, 0x04,
+    0x80, 0x04,
+    0x80, 0x04,
+    0x82, 0x04,
+    0x83, 0x04,
+    0x84, 0x04,
+    0x85, 0x04,
+    0x86, 0x04,
+    0x87, 0x04,
+    0x88, 0x04,
+    0x89, 0x04,
+    0x8a, 0x04,
+    0x8a, 0x04,
+    0x8c, 0x04,
+    0x8c, 0x04,
+    0x8e, 0x04,
+    0x8e, 0x04,
+    0x90, 0x04,
+    0x90, 0x04,
+    0x92, 0x04,
+    0x92, 0x04,
+    0x94, 0x04,
+    0x94, 0x04,
+    0x96, 0x04,
+    0x96, 0x04,
+    0x98, 0x04,
+    0x98, 0x04,
+    0x9a, 0x04,
+    0x9a, 0x04,
+    0x9c, 0x04,
+    0x9c, 0x04,
+    0x9e, 0x04,
+    0x9e, 0x04,
+    0xa0, 0x04,
+    0xa0, 0x04,
+    0xa2, 0x04,
+    0xa2, 0x04,
+    0xa4, 0x04,
+    0xa4, 0x04,
+    0xa6, 0x04,
+    0xa6, 0x04,
+    0xa8, 0x04,
+    0xa8, 0x04,
+    0xaa, 0x04,
+    0xaa, 0x04,
+    0xac, 0x04,
+    0xac, 0x04,
+    0xae, 0x04,
+    0xae, 0x04,
+    0xb0, 0x04,
+    0xb0, 0x04,
+    0xb2, 0x04,
+    0xb2, 0x04,
+    0xb4, 0x04,
+    0xb4, 0x04,
+    0xb6, 0x04,
+    0xb6, 0x04,
+    0xb8, 0x04,
+    0xb8, 0x04,
+    0xba, 0x04,
+    0xba, 0x04,
+    0xbc, 0x04,
+    0xbc, 0x04,
+    0xbe, 0x04,
+    0xbe, 0x04,
+    0xc0, 0x04,
+    0xc1, 0x04,
+    0xc1, 0x04,
+    0xc3, 0x04,
+    0xc3, 0x04,
+    0xc5, 0x04,
+    0xc5, 0x04,
+    0xc7, 0x04,
+    0xc7, 0x04,
+    0xc9, 0x04,
+    0xc9, 0x04,
+    0xcb, 0x04,
+    0xcb, 0x04,
+    0xcd, 0x04,
+    0xcd, 0x04,
+    0xc0, 0x04,
+    0xd0, 0x04,
+    0xd0, 0x04,
+    0xd2, 0x04,
+    0xd2, 0x04,
+    0xd4, 0x04,
+    0xd4, 0x04,
+    0xd6, 0x04,
+    0xd6, 0x04,
+    0xd8, 0x04,
+    0xd8, 0x04,
+    0xda, 0x04,
+    0xda, 0x04,
+    0xdc, 0x04,
+    0xdc, 0x04,
+    0xde, 0x04,
+    0xde, 0x04,
+    0xe0, 0x04,
+    0xe0, 0x04,
+    0xe2, 0x04,
+    0xe2, 0x04,
+    0xe4, 0x04,
+    0xe4, 0x04,
+    0xe6, 0x04,
+    0xe6, 0x04,
+    0xe8, 0x04,
+    0xe8, 0x04,
+    0xea, 0x04,
+    0xea, 0x04,
+    0xec, 0x04,
+    0xec, 0x04,
+    0xee, 0x04,
+    0xee, 0x04,
+    0xf0, 0x04,
+    0xf0, 0x04,
+    0xf2, 0x04,
+    0xf2, 0x04,
+    0xf4, 0x04,
+    0xf4, 0x04,
+    0xf6, 0x04,
+    0xf6, 0x04,
+    0xf8, 0x04,
+    0xf8, 0x04,
+    0xfa, 0x04,
+    0xfa, 0x04,
+    0xfc, 0x04,
+    0xfc, 0x04,
+    0xfe, 0x04,
+    0xfe, 0x04,
+    0x00, 0x05,
+    0x00, 0x05,
+    0x02, 0x05,
+    0x02, 0x05,
+    0x04, 0x05,
+    0x04, 0x05,
+    0x06, 0x05,
+    0x06, 0x05,
+    0x08, 0x05,
+    0x08, 0x05,
+    0x0a, 0x05,
+    0x0a, 0x05,
+    0x0c, 0x05,
+    0x0c, 0x05,
+    0x0e, 0x05,
+    0x0e, 0x05,
+    0x10, 0x05,
+    0x10, 0x05,
+    0x12, 0x05,
+    0x12, 0x05,
+    0x14, 0x05,
+    0x15, 0x05,
+    0x16, 0x05,
+    0x17, 0x05,
+    0x18, 0x05,
+    0x19, 0x05,
+    0x1a, 0x05,
+    0x1b, 0x05,
+    0x1c, 0x05,
+    0x1d, 0x05,
+    0x1e, 0x05,
+    0x1f, 0x05,
+    0x20, 0x05,
+    0x21, 0x05,
+    0x22, 0x05,
+    0x23, 0x05,
+    0x24, 0x05,
+    0x25, 0x05,
+    0x26, 0x05,
+    0x27, 0x05,
+    0x28, 0x05,
+    0x29, 0x05,
+    0x2a, 0x05,
+    0x2b, 0x05,
+    0x2c, 0x05,
+    0x2d, 0x05,
+    0x2e, 0x05,
+    0x2f, 0x05,
+    0x30, 0x05,
+    0x31, 0x05,
+    0x32, 0x05,
+    0x33, 0x05,
+    0x34, 0x05,
+    0x35, 0x05,
+    0x36, 0x05,
+    0x37, 0x05,
+    0x38, 0x05,
+    0x39, 0x05,
+    0x3a, 0x05,
+    0x3b, 0x05,
+    0x3c, 0x05,
+    0x3d, 0x05,
+    0x3e, 0x05,
+    0x3f, 0x05,
+    0x40, 0x05,
+    0x41, 0x05,
+    0x42, 0x05,
+    0x43, 0x05,
+    0x44, 0x05,
+    0x45, 0x05,
+    0x46, 0x05,
+    0x47, 0x05,
+    0x48, 0x05,
+    0x49, 0x05,
+    0x4a, 0x05,
+    0x4b, 0x05,
+    0x4c, 0x05,
+    0x4d, 0x05,
+    0x4e, 0x05,
+    0x4f, 0x05,
+    0x50, 0x05,
+    0x51, 0x05,
+    0x52, 0x05,
+    0x53, 0x05,
+    0x54, 0x05,
+    0x55, 0x05,
+    0x56, 0x05,
+    0x57, 0x05,
+    0x58, 0x05,
+    0x59, 0x05,
+    0x5a, 0x05,
+    0x5b, 0x05,
+    0x5c, 0x05,
+    0x5d, 0x05,
+    0x5e, 0x05,
+    0x5f, 0x05,
+    0x60, 0x05,
+    0x31, 0x05,
+    0x32, 0x05,
+    0x33, 0x05,
+    0x34, 0x05,
+    0x35, 0x05,
+    0x36, 0x05,
+    0x37, 0x05,
+    0x38, 0x05,
+    0x39, 0x05,
+    0x3a, 0x05,
+    0x3b, 0x05,
+    0x3c, 0x05,
+    0x3d, 0x05,
+    0x3e, 0x05,
+    0x3f, 0x05,
+    0x40, 0x05,
+    0x41, 0x05,
+    0x42, 0x05,
+    0x43, 0x05,
+    0x44, 0x05,
+    0x45, 0x05,
+    0x46, 0x05,
+    0x47, 0x05,
+    0x48, 0x05,
+    0x49, 0x05,
+    0x4a, 0x05,
+    0x4b, 0x05,
+    0x4c, 0x05,
+    0x4d, 0x05,
+    0x4e, 0x05,
+    0x4f, 0x05,
+    0x50, 0x05,
+    0x51, 0x05,
+    0x52, 0x05,
+    0x53, 0x05,
+    0x54, 0x05,
+    0x55, 0x05,
+    0x56, 0x05,
+    0xff, 0xff,
+    0xf6, 0x17,
+    0x63, 0x2c,
+    0x7e, 0x1d,
+    0x7f, 0x1d,
+    0x80, 0x1d,
+    0x81, 0x1d,
+    0x82, 0x1d,
+    0x83, 0x1d,
+    0x84, 0x1d,
+    0x85, 0x1d,
+    0x86, 0x1d,
+    0x87, 0x1d,
+    0x88, 0x1d,
+    0x89, 0x1d,
+    0x8a, 0x1d,
+    0x8b, 0x1d,
+    0x8c, 0x1d,
+    0x8d, 0x1d,
+    0x8e, 0x1d,
+    0x8f, 0x1d,
+    0x90, 0x1d,
+    0x91, 0x1d,
+    0x92, 0x1d,
+    0x93, 0x1d,
+    0x94, 0x1d,
+    0x95, 0x1d,
+    0x96, 0x1d,
+    0x97, 0x1d,
+    0x98, 0x1d,
+    0x99, 0x1d,
+    0x9a, 0x1d,
+    0x9b, 0x1d,
+    0x9c, 0x1d,
+    0x9d, 0x1d,
+    0x9e, 0x1d,
+    0x9f, 0x1d,
+    0xa0, 0x1d,
+    0xa1, 0x1d,
+    0xa2, 0x1d,
+    0xa3, 0x1d,
+    0xa4, 0x1d,
+    0xa5, 0x1d,
+    0xa6, 0x1d,
+    0xa7, 0x1d,
+    0xa8, 0x1d,
+    0xa9, 0x1d,
+    0xaa, 0x1d,
+    0xab, 0x1d,
+    0xac, 0x1d,
+    0xad, 0x1d,
+    0xae, 0x1d,
+    0xaf, 0x1d,
+    0xb0, 0x1d,
+    0xb1, 0x1d,
+    0xb2, 0x1d,
+    0xb3, 0x1d,
+    0xb4, 0x1d,
+    0xb5, 0x1d,
+    0xb6, 0x1d,
+    0xb7, 0x1d,
+    0xb8, 0x1d,
+    0xb9, 0x1d,
+    0xba, 0x1d,
+    0xbb, 0x1d,
+    0xbc, 0x1d,
+    0xbd, 0x1d,
+    0xbe, 0x1d,
+    0xbf, 0x1d,
+    0xc0, 0x1d,
+    0xc1, 0x1d,
+    0xc2, 0x1d,
+    0xc3, 0x1d,
+    0xc4, 0x1d,
+    0xc5, 0x1d,
+    0xc6, 0x1d,
+    0xc7, 0x1d,
+    0xc8, 0x1d,
+    0xc9, 0x1d,
+    0xca, 0x1d,
+    0xcb, 0x1d,
+    0xcc, 0x1d,
+    0xcd, 0x1d,
+    0xce, 0x1d,
+    0xcf, 0x1d,
+    0xd0, 0x1d,
+    0xd1, 0x1d,
+    0xd2, 0x1d,
+    0xd3, 0x1d,
+    0xd4, 0x1d,
+    0xd5, 0x1d,
+    0xd6, 0x1d,
+    0xd7, 0x1d,
+    0xd8, 0x1d,
+    0xd9, 0x1d,
+    0xda, 0x1d,
+    0xdb, 0x1d,
+    0xdc, 0x1d,
+    0xdd, 0x1d,
+    0xde, 0x1d,
+    0xdf, 0x1d,
+    0xe0, 0x1d,
+    0xe1, 0x1d,
+    0xe2, 0x1d,
+    0xe3, 0x1d,
+    0xe4, 0x1d,
+    0xe5, 0x1d,
+    0xe6, 0x1d,
+    0xe7, 0x1d,
+    0xe8, 0x1d,
+    0xe9, 0x1d,
+    0xea, 0x1d,
+    0xeb, 0x1d,
+    0xec, 0x1d,
+    0xed, 0x1d,
+    0xee, 0x1d,
+    0xef, 0x1d,
+    0xf0, 0x1d,
+    0xf1, 0x1d,
+    0xf2, 0x1d,
+    0xf3, 0x1d,
+    0xf4, 0x1d,
+    0xf5, 0x1d,
+    0xf6, 0x1d,
+    0xf7, 0x1d,
+    0xf8, 0x1d,
+    0xf9, 0x1d,
+    0xfa, 0x1d,
+    0xfb, 0x1d,
+    0xfc, 0x1d,
+    0xfd, 0x1d,
+    0xfe, 0x1d,
+    0xff, 0x1d,
+    0x00, 0x1e,
+    0x00, 0x1e,
+    0x02, 0x1e,
+    0x02, 0x1e,
+    0x04, 0x1e,
+    0x04, 0x1e,
+    0x06, 0x1e,
+    0x06, 0x1e,
+    0x08, 0x1e,
+    0x08, 0x1e,
+    0x0a, 0x1e,
+    0x0a, 0x1e,
+    0x0c, 0x1e,
+    0x0c, 0x1e,
+    0x0e, 0x1e,
+    0x0e, 0x1e,
+    0x10, 0x1e,
+    0x10, 0x1e,
+    0x12, 0x1e,
+    0x12, 0x1e,
+    0x14, 0x1e,
+    0x14, 0x1e,
+    0x16, 0x1e,
+    0x16, 0x1e,
+    0x18, 0x1e,
+    0x18, 0x1e,
+    0x1a, 0x1e,
+    0x1a, 0x1e,
+    0x1c, 0x1e,
+    0x1c, 0x1e,
+    0x1e, 0x1e,
+    0x1e, 0x1e,
+    0x20, 0x1e,
+    0x20, 0x1e,
+    0x22, 0x1e,
+    0x22, 0x1e,
+    0x24, 0x1e,
+    0x24, 0x1e,
+    0x26, 0x1e,
+    0x26, 0x1e,
+    0x28, 0x1e,
+    0x28, 0x1e,
+    0x2a, 0x1e,
+    0x2a, 0x1e,
+    0x2c, 0x1e,
+    0x2c, 0x1e,
+    0x2e, 0x1e,
+    0x2e, 0x1e,
+    0x30, 0x1e,
+    0x30, 0x1e,
+    0x32, 0x1e,
+    0x32, 0x1e,
+    0x34, 0x1e,
+    0x34, 0x1e,
+    0x36, 0x1e,
+    0x36, 0x1e,
+    0x38, 0x1e,
+    0x38, 0x1e,
+    0x3a, 0x1e,
+    0x3a, 0x1e,
+    0x3c, 0x1e,
+    0x3c, 0x1e,
+    0x3e, 0x1e,
+    0x3e, 0x1e,
+    0x40, 0x1e,
+    0x40, 0x1e,
+    0x42, 0x1e,
+    0x42, 0x1e,
+    0x44, 0x1e,
+    0x44, 0x1e,
+    0x46, 0x1e,
+    0x46, 0x1e,
+    0x48, 0x1e,
+    0x48, 0x1e,
+    0x4a, 0x1e,
+    0x4a, 0x1e,
+    0x4c, 0x1e,
+    0x4c, 0x1e,
+    0x4e, 0x1e,
+    0x4e, 0x1e,
+    0x50, 0x1e,
+    0x50, 0x1e,
+    0x52, 0x1e,
+    0x52, 0x1e,
+    0x54, 0x1e,
+    0x54, 0x1e,
+    0x56, 0x1e,
+    0x56, 0x1e,
+    0x58, 0x1e,
+    0x58, 0x1e,
+    0x5a, 0x1e,
+    0x5a, 0x1e,
+    0x5c, 0x1e,
+    0x5c, 0x1e,
+    0x5e, 0x1e,
+    0x5e, 0x1e,
+    0x60, 0x1e,
+    0x60, 0x1e,
+    0x62, 0x1e,
+    0x62, 0x1e,
+    0x64, 0x1e,
+    0x64, 0x1e,
+    0x66, 0x1e,
+    0x66, 0x1e,
+    0x68, 0x1e,
+    0x68, 0x1e,
+    0x6a, 0x1e,
+    0x6a, 0x1e,
+    0x6c, 0x1e,
+    0x6c, 0x1e,
+    0x6e, 0x1e,
+    0x6e, 0x1e,
+    0x70, 0x1e,
+    0x70, 0x1e,
+    0x72, 0x1e,
+    0x72, 0x1e,
+    0x74, 0x1e,
+    0x74, 0x1e,
+    0x76, 0x1e,
+    0x76, 0x1e,
+    0x78, 0x1e,
+    0x78, 0x1e,
+    0x7a, 0x1e,
+    0x7a, 0x1e,
+    0x7c, 0x1e,
+    0x7c, 0x1e,
+    0x7e, 0x1e,
+    0x7e, 0x1e,
+    0x80, 0x1e,
+    0x80, 0x1e,
+    0x82, 0x1e,
+    0x82, 0x1e,
+    0x84, 0x1e,
+    0x84, 0x1e,
+    0x86, 0x1e,
+    0x86, 0x1e,
+    0x88, 0x1e,
+    0x88, 0x1e,
+    0x8a, 0x1e,
+    0x8a, 0x1e,
+    0x8c, 0x1e,
+    0x8c, 0x1e,
+    0x8e, 0x1e,
+    0x8e, 0x1e,
+    0x90, 0x1e,
+    0x90, 0x1e,
+    0x92, 0x1e,
+    0x92, 0x1e,
+    0x94, 0x1e,
+    0x94, 0x1e,
+    0x96, 0x1e,
+    0x97, 0x1e,
+    0x98, 0x1e,
+    0x99, 0x1e,
+    0x9a, 0x1e,
+    0x9b, 0x1e,
+    0x9c, 0x1e,
+    0x9d, 0x1e,
+    0x9e, 0x1e,
+    0x9f, 0x1e,
+    0xa0, 0x1e,
+    0xa0, 0x1e,
+    0xa2, 0x1e,
+    0xa2, 0x1e,
+    0xa4, 0x1e,
+    0xa4, 0x1e,
+    0xa6, 0x1e,
+    0xa6, 0x1e,
+    0xa8, 0x1e,
+    0xa8, 0x1e,
+    0xaa, 0x1e,
+    0xaa, 0x1e,
+    0xac, 0x1e,
+    0xac, 0x1e,
+    0xae, 0x1e,
+    0xae, 0x1e,
+    0xb0, 0x1e,
+    0xb0, 0x1e,
+    0xb2, 0x1e,
+    0xb2, 0x1e,
+    0xb4, 0x1e,
+    0xb4, 0x1e,
+    0xb6, 0x1e,
+    0xb6, 0x1e,
+    0xb8, 0x1e,
+    0xb8, 0x1e,
+    0xba, 0x1e,
+    0xba, 0x1e,
+    0xbc, 0x1e,
+    0xbc, 0x1e,
+    0xbe, 0x1e,
+    0xbe, 0x1e,
+    0xc0, 0x1e,
+    0xc0, 0x1e,
+    0xc2, 0x1e,
+    0xc2, 0x1e,
+    0xc4, 0x1e,
+    0xc4, 0x1e,
+    0xc6, 0x1e,
+    0xc6, 0x1e,
+    0xc8, 0x1e,
+    0xc8, 0x1e,
+    0xca, 0x1e,
+    0xca, 0x1e,
+    0xcc, 0x1e,
+    0xcc, 0x1e,
+    0xce, 0x1e,
+    0xce, 0x1e,
+    0xd0, 0x1e,
+    0xd0, 0x1e,
+    0xd2, 0x1e,
+    0xd2, 0x1e,
+    0xd4, 0x1e,
+    0xd4, 0x1e,
+    0xd6, 0x1e,
+    0xd6, 0x1e,
+    0xd8, 0x1e,
+    0xd8, 0x1e,
+    0xda, 0x1e,
+    0xda, 0x1e,
+    0xdc, 0x1e,
+    0xdc, 0x1e,
+    0xde, 0x1e,
+    0xde, 0x1e,
+    0xe0, 0x1e,
+    0xe0, 0x1e,
+    0xe2, 0x1e,
+    0xe2, 0x1e,
+    0xe4, 0x1e,
+    0xe4, 0x1e,
+    0xe6, 0x1e,
+    0xe6, 0x1e,
+    0xe8, 0x1e,
+    0xe8, 0x1e,
+    0xea, 0x1e,
+    0xea, 0x1e,
+    0xec, 0x1e,
+    0xec, 0x1e,
+    0xee, 0x1e,
+    0xee, 0x1e,
+    0xf0, 0x1e,
+    0xf0, 0x1e,
+    0xf2, 0x1e,
+    0xf2, 0x1e,
+    0xf4, 0x1e,
+    0xf4, 0x1e,
+    0xf6, 0x1e,
+    0xf6, 0x1e,
+    0xf8, 0x1e,
+    0xf8, 0x1e,
+    0xfa, 0x1e,
+    0xfb, 0x1e,
+    0xfc, 0x1e,
+    0xfd, 0x1e,
+    0xfe, 0x1e,
+    0xff, 0x1e,
+    0x08, 0x1f,
+    0x09, 0x1f,
+    0x0a, 0x1f,
+    0x0b, 0x1f,
+    0x0c, 0x1f,
+    0x0d, 0x1f,
+    0x0e, 0x1f,
+    0x0f, 0x1f,
+    0x08, 0x1f,
+    0x09, 0x1f,
+    0x0a, 0x1f,
+    0x0b, 0x1f,
+    0x0c, 0x1f,
+    0x0d, 0x1f,
+    0x0e, 0x1f,
+    0x0f, 0x1f,
+    0x18, 0x1f,
+    0x19, 0x1f,
+    0x1a, 0x1f,
+    0x1b, 0x1f,
+    0x1c, 0x1f,
+    0x1d, 0x1f,
+    0x16, 0x1f,
+    0x17, 0x1f,
+    0x18, 0x1f,
+    0x19, 0x1f,
+    0x1a, 0x1f,
+    0x1b, 0x1f,
+    0x1c, 0x1f,
+    0x1d, 0x1f,
+    0x1e, 0x1f,
+    0x1f, 0x1f,
+    0x28, 0x1f,
+    0x29, 0x1f,
+    0x2a, 0x1f,
+    0x2b, 0x1f,
+    0x2c, 0x1f,
+    0x2d, 0x1f,
+    0x2e, 0x1f,
+    0x2f, 0x1f,
+    0x28, 0x1f,
+    0x29, 0x1f,
+    0x2a, 0x1f,
+    0x2b, 0x1f,
+    0x2c, 0x1f,
+    0x2d, 0x1f,
+    0x2e, 0x1f,
+    0x2f, 0x1f,
+    0x38, 0x1f,
+    0x39, 0x1f,
+    0x3a, 0x1f,
+    0x3b, 0x1f,
+    0x3c, 0x1f,
+    0x3d, 0x1f,
+    0x3e, 0x1f,
+    0x3f, 0x1f,
+    0x38, 0x1f,
+    0x39, 0x1f,
+    0x3a, 0x1f,
+    0x3b, 0x1f,
+    0x3c, 0x1f,
+    0x3d, 0x1f,
+    0x3e, 0x1f,
+    0x3f, 0x1f,
+    0x48, 0x1f,
+    0x49, 0x1f,
+    0x4a, 0x1f,
+    0x4b, 0x1f,
+    0x4c, 0x1f,
+    0x4d, 0x1f,
+    0x46, 0x1f,
+    0x47, 0x1f,
+    0x48, 0x1f,
+    0x49, 0x1f,
+    0x4a, 0x1f,
+    0x4b, 0x1f,
+    0x4c, 0x1f,
+    0x4d, 0x1f,
+    0x4e, 0x1f,
+    0x4f, 0x1f,
+    0x50, 0x1f,
+    0x59, 0x1f,
+    0x52, 0x1f,
+    0x5b, 0x1f,
+    0x54, 0x1f,
+    0x5d, 0x1f,
+    0x56, 0x1f,
+    0x5f, 0x1f,
+    0x58, 0x1f,
+    0x59, 0x1f,
+    0x5a, 0x1f,
+    0x5b, 0x1f,
+    0x5c, 0x1f,
+    0x5d, 0x1f,
+    0x5e, 0x1f,
+    0x5f, 0x1f,
+    0x68, 0x1f,
+    0x69, 0x1f,
+    0x6a, 0x1f,
+    0x6b, 0x1f,
+    0x6c, 0x1f,
+    0x6d, 0x1f,
+    0x6e, 0x1f,
+    0x6f, 0x1f,
+    0x68, 0x1f,
+    0x69, 0x1f,
+    0x6a, 0x1f,
+    0x6b, 0x1f,
+    0x6c, 0x1f,
+    0x6d, 0x1f,
+    0x6e, 0x1f,
+    0x6f, 0x1f,
+    0xba, 0x1f,
+    0xbb, 0x1f,
+    0xc8, 0x1f,
+    0xc9, 0x1f,
+    0xca, 0x1f,
+    0xcb, 0x1f,
+    0xda, 0x1f,
+    0xdb, 0x1f,
+    0xf8, 0x1f,
+    0xf9, 0x1f,
+    0xea, 0x1f,
+    0xeb, 0x1f,
+    0xfa, 0x1f,
+    0xfb, 0x1f,
+    0x7e, 0x1f,
+    0x7f, 0x1f,
+    0x88, 0x1f,
+    0x89, 0x1f,
+    0x8a, 0x1f,
+    0x8b, 0x1f,
+    0x8c, 0x1f,
+    0x8d, 0x1f,
+    0x8e, 0x1f,
+    0x8f, 0x1f,
+    0x88, 0x1f,
+    0x89, 0x1f,
+    0x8a, 0x1f,
+    0x8b, 0x1f,
+    0x8c, 0x1f,
+    0x8d, 0x1f,
+    0x8e, 0x1f,
+    0x8f, 0x1f,
+    0x98, 0x1f,
+    0x99, 0x1f,
+    0x9a, 0x1f,
+    0x9b, 0x1f,
+    0x9c, 0x1f,
+    0x9d, 0x1f,
+    0x9e, 0x1f,
+    0x9f, 0x1f,
+    0x98, 0x1f,
+    0x99, 0x1f,
+    0x9a, 0x1f,
+    0x9b, 0x1f,
+    0x9c, 0x1f,
+    0x9d, 0x1f,
+    0x9e, 0x1f,
+    0x9f, 0x1f,
+    0xa8, 0x1f,
+    0xa9, 0x1f,
+    0xaa, 0x1f,
+    0xab, 0x1f,
+    0xac, 0x1f,
+    0xad, 0x1f,
+    0xae, 0x1f,
+    0xaf, 0x1f,
+    0xa8, 0x1f,
+    0xa9, 0x1f,
+    0xaa, 0x1f,
+    0xab, 0x1f,
+    0xac, 0x1f,
+    0xad, 0x1f,
+    0xae, 0x1f,
+    0xaf, 0x1f,
+    0xb8, 0x1f,
+    0xb9, 0x1f,
+    0xb2, 0x1f,
+    0xbc, 0x1f,
+    0xb4, 0x1f,
+    0xb5, 0x1f,
+    0xb6, 0x1f,
+    0xb7, 0x1f,
+    0xb8, 0x1f,
+    0xb9, 0x1f,
+    0xba, 0x1f,
+    0xbb, 0x1f,
+    0xbc, 0x1f,
+    0xbd, 0x1f,
+    0xbe, 0x1f,
+    0xbf, 0x1f,
+    0xc0, 0x1f,
+    0xc1, 0x1f,
+    0xc2, 0x1f,
+    0xc3, 0x1f,
+    0xc4, 0x1f,
+    0xc5, 0x1f,
+    0xc6, 0x1f,
+    0xc7, 0x1f,
+    0xc8, 0x1f,
+    0xc9, 0x1f,
+    0xca, 0x1f,
+    0xcb, 0x1f,
+    0xc3, 0x1f,
+    0xcd, 0x1f,
+    0xce, 0x1f,
+    0xcf, 0x1f,
+    0xd8, 0x1f,
+    0xd9, 0x1f,
+    0xd2, 0x1f,
+    0xd3, 0x1f,
+    0xd4, 0x1f,
+    0xd5, 0x1f,
+    0xd6, 0x1f,
+    0xd7, 0x1f,
+    0xd8, 0x1f,
+    0xd9, 0x1f,
+    0xda, 0x1f,
+    0xdb, 0x1f,
+    0xdc, 0x1f,
+    0xdd, 0x1f,
+    0xde, 0x1f,
+    0xdf, 0x1f,
+    0xe8, 0x1f,
+    0xe9, 0x1f,
+    0xe2, 0x1f,
+    0xe3, 0x1f,
+    0xe4, 0x1f,
+    0xec, 0x1f,
+    0xe6, 0x1f,
+    0xe7, 0x1f,
+    0xe8, 0x1f,
+    0xe9, 0x1f,
+    0xea, 0x1f,
+    0xeb, 0x1f,
+    0xec, 0x1f,
+    0xed, 0x1f,
+    0xee, 0x1f,
+    0xef, 0x1f,
+    0xf0, 0x1f,
+    0xf1, 0x1f,
+    0xf2, 0x1f,
+    0xf3, 0x1f,
+    0xf4, 0x1f,
+    0xf5, 0x1f,
+    0xf6, 0x1f,
+    0xf7, 0x1f,
+    0xf8, 0x1f,
+    0xf9, 0x1f,
+    0xfa, 0x1f,
+    0xfb, 0x1f,
+    0xf3, 0x1f,
+    0xfd, 0x1f,
+    0xfe, 0x1f,
+    0xff, 0x1f,
+    0x00, 0x20,
+    0x01, 0x20,
+    0x02, 0x20,
+    0x03, 0x20,
+    0x04, 0x20,
+    0x05, 0x20,
+    0x06, 0x20,
+    0x07, 0x20,
+    0x08, 0x20,
+    0x09, 0x20,
+    0x0a, 0x20,
+    0x0b, 0x20,
+    0x0c, 0x20,
+    0x0d, 0x20,
+    0x0e, 0x20,
+    0x0f, 0x20,
+    0x10, 0x20,
+    0x11, 0x20,
+    0x12, 0x20,
+    0x13, 0x20,
+    0x14, 0x20,
+    0x15, 0x20,
+    0x16, 0x20,
+    0x17, 0x20,
+    0x18, 0x20,
+    0x19, 0x20,
+    0x1a, 0x20,
+    0x1b, 0x20,
+    0x1c, 0x20,
+    0x1d, 0x20,
+    0x1e, 0x20,
+    0x1f, 0x20,
+    0x20, 0x20,
+    0x21, 0x20,
+    0x22, 0x20,
+    0x23, 0x20,
+    0x24, 0x20,
+    0x25, 0x20,
+    0x26, 0x20,
+    0x27, 0x20,
+    0x28, 0x20,
+    0x29, 0x20,
+    0x2a, 0x20,
+    0x2b, 0x20,
+    0x2c, 0x20,
+    0x2d, 0x20,
+    0x2e, 0x20,
+    0x2f, 0x20,
+    0x30, 0x20,
+    0x31, 0x20,
+    0x32, 0x20,
+    0x33, 0x20,
+    0x34, 0x20,
+    0x35, 0x20,
+    0x36, 0x20,
+    0x37, 0x20,
+    0x38, 0x20,
+    0x39, 0x20,
+    0x3a, 0x20,
+    0x3b, 0x20,
+    0x3c, 0x20,
+    0x3d, 0x20,
+    0x3e, 0x20,
+    0x3f, 0x20,
+    0x40, 0x20,
+    0x41, 0x20,
+    0x42, 0x20,
+    0x43, 0x20,
+    0x44, 0x20,
+    0x45, 0x20,
+    0x46, 0x20,
+    0x47, 0x20,
+    0x48, 0x20,
+    0x49, 0x20,
+    0x4a, 0x20,
+    0x4b, 0x20,
+    0x4c, 0x20,
+    0x4d, 0x20,
+    0x4e, 0x20,
+    0x4f, 0x20,
+    0x50, 0x20,
+    0x51, 0x20,
+    0x52, 0x20,
+    0x53, 0x20,
+    0x54, 0x20,
+    0x55, 0x20,
+    0x56, 0x20,
+    0x57, 0x20,
+    0x58, 0x20,
+    0x59, 0x20,
+    0x5a, 0x20,
+    0x5b, 0x20,
+    0x5c, 0x20,
+    0x5d, 0x20,
+    0x5e, 0x20,
+    0x5f, 0x20,
+    0x60, 0x20,
+    0x61, 0x20,
+    0x62, 0x20,
+    0x63, 0x20,
+    0x64, 0x20,
+    0x65, 0x20,
+    0x66, 0x20,
+    0x67, 0x20,
+    0x68, 0x20,
+    0x69, 0x20,
+    0x6a, 0x20,
+    0x6b, 0x20,
+    0x6c, 0x20,
+    0x6d, 0x20,
+    0x6e, 0x20,
+    0x6f, 0x20,
+    0x70, 0x20,
+    0x71, 0x20,
+    0x72, 0x20,
+    0x73, 0x20,
+    0x74, 0x20,
+    0x75, 0x20,
+    0x76, 0x20,
+    0x77, 0x20,
+    0x78, 0x20,
+    0x79, 0x20,
+    0x7a, 0x20,
+    0x7b, 0x20,
+    0x7c, 0x20,
+    0x7d, 0x20,
+    0x7e, 0x20,
+    0x7f, 0x20,
+    0x80, 0x20,
+    0x81, 0x20,
+    0x82, 0x20,
+    0x83, 0x20,
+    0x84, 0x20,
+    0x85, 0x20,
+    0x86, 0x20,
+    0x87, 0x20,
+    0x88, 0x20,
+    0x89, 0x20,
+    0x8a, 0x20,
+    0x8b, 0x20,
+    0x8c, 0x20,
+    0x8d, 0x20,
+    0x8e, 0x20,
+    0x8f, 0x20,
+    0x90, 0x20,
+    0x91, 0x20,
+    0x92, 0x20,
+    0x93, 0x20,
+    0x94, 0x20,
+    0x95, 0x20,
+    0x96, 0x20,
+    0x97, 0x20,
+    0x98, 0x20,
+    0x99, 0x20,
+    0x9a, 0x20,
+    0x9b, 0x20,
+    0x9c, 0x20,
+    0x9d, 0x20,
+    0x9e, 0x20,
+    0x9f, 0x20,
+    0xa0, 0x20,
+    0xa1, 0x20,
+    0xa2, 0x20,
+    0xa3, 0x20,
+    0xa4, 0x20,
+    0xa5, 0x20,
+    0xa6, 0x20,
+    0xa7, 0x20,
+    0xa8, 0x20,
+    0xa9, 0x20,
+    0xaa, 0x20,
+    0xab, 0x20,
+    0xac, 0x20,
+    0xad, 0x20,
+    0xae, 0x20,
+    0xaf, 0x20,
+    0xb0, 0x20,
+    0xb1, 0x20,
+    0xb2, 0x20,
+    0xb3, 0x20,
+    0xb4, 0x20,
+    0xb5, 0x20,
+    0xb6, 0x20,
+    0xb7, 0x20,
+    0xb8, 0x20,
+    0xb9, 0x20,
+    0xba, 0x20,
+    0xbb, 0x20,
+    0xbc, 0x20,
+    0xbd, 0x20,
+    0xbe, 0x20,
+    0xbf, 0x20,
+    0xc0, 0x20,
+    0xc1, 0x20,
+    0xc2, 0x20,
+    0xc3, 0x20,
+    0xc4, 0x20,
+    0xc5, 0x20,
+    0xc6, 0x20,
+    0xc7, 0x20,
+    0xc8, 0x20,
+    0xc9, 0x20,
+    0xca, 0x20,
+    0xcb, 0x20,
+    0xcc, 0x20,
+    0xcd, 0x20,
+    0xce, 0x20,
+    0xcf, 0x20,
+    0xd0, 0x20,
+    0xd1, 0x20,
+    0xd2, 0x20,
+    0xd3, 0x20,
+    0xd4, 0x20,
+    0xd5, 0x20,
+    0xd6, 0x20,
+    0xd7, 0x20,
+    0xd8, 0x20,
+    0xd9, 0x20,
+    0xda, 0x20,
+    0xdb, 0x20,
+    0xdc, 0x20,
+    0xdd, 0x20,
+    0xde, 0x20,
+    0xdf, 0x20,
+    0xe0, 0x20,
+    0xe1, 0x20,
+    0xe2, 0x20,
+    0xe3, 0x20,
+    0xe4, 0x20,
+    0xe5, 0x20,
+    0xe6, 0x20,
+    0xe7, 0x20,
+    0xe8, 0x20,
+    0xe9, 0x20,
+    0xea, 0x20,
+    0xeb, 0x20,
+    0xec, 0x20,
+    0xed, 0x20,
+    0xee, 0x20,
+    0xef, 0x20,
+    0xf0, 0x20,
+    0xf1, 0x20,
+    0xf2, 0x20,
+    0xf3, 0x20,
+    0xf4, 0x20,
+    0xf5, 0x20,
+    0xf6, 0x20,
+    0xf7, 0x20,
+    0xf8, 0x20,
+    0xf9, 0x20,
+    0xfa, 0x20,
+    0xfb, 0x20,
+    0xfc, 0x20,
+    0xfd, 0x20,
+    0xfe, 0x20,
+    0xff, 0x20,
+    0x00, 0x21,
+    0x01, 0x21,
+    0x02, 0x21,
+    0x03, 0x21,
+    0x04, 0x21,
+    0x05, 0x21,
+    0x06, 0x21,
+    0x07, 0x21,
+    0x08, 0x21,
+    0x09, 0x21,
+    0x0a, 0x21,
+    0x0b, 0x21,
+    0x0c, 0x21,
+    0x0d, 0x21,
+    0x0e, 0x21,
+    0x0f, 0x21,
+    0x10, 0x21,
+    0x11, 0x21,
+    0x12, 0x21,
+    0x13, 0x21,
+    0x14, 0x21,
+    0x15, 0x21,
+    0x16, 0x21,
+    0x17, 0x21,
+    0x18, 0x21,
+    0x19, 0x21,
+    0x1a, 0x21,
+    0x1b, 0x21,
+    0x1c, 0x21,
+    0x1d, 0x21,
+    0x1e, 0x21,
+    0x1f, 0x21,
+    0x20, 0x21,
+    0x21, 0x21,
+    0x22, 0x21,
+    0x23, 0x21,
+    0x24, 0x21,
+    0x25, 0x21,
+    0x26, 0x21,
+    0x27, 0x21,
+    0x28, 0x21,
+    0x29, 0x21,
+    0x2a, 0x21,
+    0x2b, 0x21,
+    0x2c, 0x21,
+    0x2d, 0x21,
+    0x2e, 0x21,
+    0x2f, 0x21,
+    0x30, 0x21,
+    0x31, 0x21,
+    0x32, 0x21,
+    0x33, 0x21,
+    0x34, 0x21,
+    0x35, 0x21,
+    0x36, 0x21,
+    0x37, 0x21,
+    0x38, 0x21,
+    0x39, 0x21,
+    0x3a, 0x21,
+    0x3b, 0x21,
+    0x3c, 0x21,
+    0x3d, 0x21,
+    0x3e, 0x21,
+    0x3f, 0x21,
+    0x40, 0x21,
+    0x41, 0x21,
+    0x42, 0x21,
+    0x43, 0x21,
+    0x44, 0x21,
+    0x45, 0x21,
+    0x46, 0x21,
+    0x47, 0x21,
+    0x48, 0x21,
+    0x49, 0x21,
+    0x4a, 0x21,
+    0x4b, 0x21,
+    0x4c, 0x21,
+    0x4d, 0x21,
+    0x32, 0x21,
+    0x4f, 0x21,
+    0x50, 0x21,
+    0x51, 0x21,
+    0x52, 0x21,
+    0x53, 0x21,
+    0x54, 0x21,
+    0x55, 0x21,
+    0x56, 0x21,
+    0x57, 0x21,
+    0x58, 0x21,
+    0x59, 0x21,
+    0x5a, 0x21,
+    0x5b, 0x21,
+    0x5c, 0x21,
+    0x5d, 0x21,
+    0x5e, 0x21,
+    0x5f, 0x21,
+    0x60, 0x21,
+    0x61, 0x21,
+    0x62, 0x21,
+    0x63, 0x21,
+    0x64, 0x21,
+    0x65, 0x21,
+    0x66, 0x21,
+    0x67, 0x21,
+    0x68, 0x21,
+    0x69, 0x21,
+    0x6a, 0x21,
+    0x6b, 0x21,
+    0x6c, 0x21,
+    0x6d, 0x21,
+    0x6e, 0x21,
+    0x6f, 0x21,
+    0x60, 0x21,
+    0x61, 0x21,
+    0x62, 0x21,
+    0x63, 0x21,
+    0x64, 0x21,
+    0x65, 0x21,
+    0x66, 0x21,
+    0x67, 0x21,
+    0x68, 0x21,
+    0x69, 0x21,
+    0x6a, 0x21,
+    0x6b, 0x21,
+    0x6c, 0x21,
+    0x6d, 0x21,
+    0x6e, 0x21,
+    0x6f, 0x21,
+    0x80, 0x21,
+    0x81, 0x21,
+    0x82, 0x21,
+    0x83, 0x21,
+    0x83, 0x21,
+    0xff, 0xff,
+    0x4b, 0x03,
+    0xb6, 0x24,
+    0xb7, 0x24,
+    0xb8, 0x24,
+    0xb9, 0x24,
+    0xba, 0x24,
+    0xbb, 0x24,
+    0xbc, 0x24,
+    0xbd, 0x24,
+    0xbe, 0x24,
+    0xbf, 0x24,
+    0xc0, 0x24,
+    0xc1, 0x24,
+    0xc2, 0x24,
+    0xc3, 0x24,
+    0xc4, 0x24,
+    0xc5, 0x24,
+    0xc6, 0x24,
+    0xc7, 0x24,
+    0xc8, 0x24,
+    0xc9, 0x24,
+    0xca, 0x24,
+    0xcb, 0x24,
+    0xcc, 0x24,
+    0xcd, 0x24,
+    0xce, 0x24,
+    0xcf, 0x24,
+    0xff, 0xff,
+    0x46, 0x07,
+    0x00, 0x2c,
+    0x01, 0x2c,
+    0x02, 0x2c,
+    0x03, 0x2c,
+    0x04, 0x2c,
+    0x05, 0x2c,
+    0x06, 0x2c,
+    0x07, 0x2c,
+    0x08, 0x2c,
+    0x09, 0x2c,
+    0x0a, 0x2c,
+    0x0b, 0x2c,
+    0x0c, 0x2c,
+    0x0d, 0x2c,
+    0x0e, 0x2c,
+    0x0f, 0x2c,
+    0x10, 0x2c,
+    0x11, 0x2c,
+    0x12, 0x2c,
+    0x13, 0x2c,
+    0x14, 0x2c,
+    0x15, 0x2c,
+    0x16, 0x2c,
+    0x17, 0x2c,
+    0x18, 0x2c,
+    0x19, 0x2c,
+    0x1a, 0x2c,
+    0x1b, 0x2c,
+    0x1c, 0x2c,
+    0x1d, 0x2c,
+    0x1e, 0x2c,
+    0x1f, 0x2c,
+    0x20, 0x2c,
+    0x21, 0x2c,
+    0x22, 0x2c,
+    0x23, 0x2c,
+    0x24, 0x2c,
+    0x25, 0x2c,
+    0x26, 0x2c,
+    0x27, 0x2c,
+    0x28, 0x2c,
+    0x29, 0x2c,
+    0x2a, 0x2c,
+    0x2b, 0x2c,
+    0x2c, 0x2c,
+    0x2d, 0x2c,
+    0x2e, 0x2c,
+    0x5f, 0x2c,
+    0x60, 0x2c,
+    0x60, 0x2c,
+    0x62, 0x2c,
+    0x63, 0x2c,
+    0x64, 0x2c,
+    0x65, 0x2c,
+    0x66, 0x2c,
+    0x67, 0x2c,
+    0x67, 0x2c,
+    0x69, 0x2c,
+    0x69, 0x2c,
+    0x6b, 0x2c,
+    0x6b, 0x2c,
+    0x6d, 0x2c,
+    0x6e, 0x2c,
+    0x6f, 0x2c,
+    0x70, 0x2c,
+    0x71, 0x2c,
+    0x72, 0x2c,
+    0x73, 0x2c,
+    0x74, 0x2c,
+    0x75, 0x2c,
+    0x75, 0x2c,
+    0x77, 0x2c,
+    0x78, 0x2c,
+    0x79, 0x2c,
+    0x7a, 0x2c,
+    0x7b, 0x2c,
+    0x7c, 0x2c,
+    0x7d, 0x2c,
+    0x7e, 0x2c,
+    0x7f, 0x2c,
+    0x80, 0x2c,
+    0x80, 0x2c,
+    0x82, 0x2c,
+    0x82, 0x2c,
+    0x84, 0x2c,
+    0x84, 0x2c,
+    0x86, 0x2c,
+    0x86, 0x2c,
+    0x88, 0x2c,
+    0x88, 0x2c,
+    0x8a, 0x2c,
+    0x8a, 0x2c,
+    0x8c, 0x2c,
+    0x8c, 0x2c,
+    0x8e, 0x2c,
+    0x8e, 0x2c,
+    0x90, 0x2c,
+    0x90, 0x2c,
+    0x92, 0x2c,
+    0x92, 0x2c,
+    0x94, 0x2c,
+    0x94, 0x2c,
+    0x96, 0x2c,
+    0x96, 0x2c,
+    0x98, 0x2c,
+    0x98, 0x2c,
+    0x9a, 0x2c,
+    0x9a, 0x2c,
+    0x9c, 0x2c,
+    0x9c, 0x2c,
+    0x9e, 0x2c,
+    0x9e, 0x2c,
+    0xa0, 0x2c,
+    0xa0, 0x2c,
+    0xa2, 0x2c,
+    0xa2, 0x2c,
+    0xa4, 0x2c,
+    0xa4, 0x2c,
+    0xa6, 0x2c,
+    0xa6, 0x2c,
+    0xa8, 0x2c,
+    0xa8, 0x2c,
+    0xaa, 0x2c,
+    0xaa, 0x2c,
+    0xac, 0x2c,
+    0xac, 0x2c,
+    0xae, 0x2c,
+    0xae, 0x2c,
+    0xb0, 0x2c,
+    0xb0, 0x2c,
+    0xb2, 0x2c,
+    0xb2, 0x2c,
+    0xb4, 0x2c,
+    0xb4, 0x2c,
+    0xb6, 0x2c,
+    0xb6, 0x2c,
+    0xb8, 0x2c,
+    0xb8, 0x2c,
+    0xba, 0x2c,
+    0xba, 0x2c,
+    0xbc, 0x2c,
+    0xbc, 0x2c,
+    0xbe, 0x2c,
+    0xbe, 0x2c,
+    0xc0, 0x2c,
+    0xc0, 0x2c,
+    0xc2, 0x2c,
+    0xc2, 0x2c,
+    0xc4, 0x2c,
+    0xc4, 0x2c,
+    0xc6, 0x2c,
+    0xc6, 0x2c,
+    0xc8, 0x2c,
+    0xc8, 0x2c,
+    0xca, 0x2c,
+    0xca, 0x2c,
+    0xcc, 0x2c,
+    0xcc, 0x2c,
+    0xce, 0x2c,
+    0xce, 0x2c,
+    0xd0, 0x2c,
+    0xd0, 0x2c,
+    0xd2, 0x2c,
+    0xd2, 0x2c,
+    0xd4, 0x2c,
+    0xd4, 0x2c,
+    0xd6, 0x2c,
+    0xd6, 0x2c,
+    0xd8, 0x2c,
+    0xd8, 0x2c,
+    0xda, 0x2c,
+    0xda, 0x2c,
+    0xdc, 0x2c,
+    0xdc, 0x2c,
+    0xde, 0x2c,
+    0xde, 0x2c,
+    0xe0, 0x2c,
+    0xe0, 0x2c,
+    0xe2, 0x2c,
+    0xe2, 0x2c,
+    0xe4, 0x2c,
+    0xe5, 0x2c,
+    0xe6, 0x2c,
+    0xe7, 0x2c,
+    0xe8, 0x2c,
+    0xe9, 0x2c,
+    0xea, 0x2c,
+    0xeb, 0x2c,
+    0xec, 0x2c,
+    0xed, 0x2c,
+    0xee, 0x2c,
+    0xef, 0x2c,
+    0xf0, 0x2c,
+    0xf1, 0x2c,
+    0xf2, 0x2c,
+    0xf3, 0x2c,
+    0xf4, 0x2c,
+    0xf5, 0x2c,
+    0xf6, 0x2c,
+    0xf7, 0x2c,
+    0xf8, 0x2c,
+    0xf9, 0x2c,
+    0xfa, 0x2c,
+    0xfb, 0x2c,
+    0xfc, 0x2c,
+    0xfd, 0x2c,
+    0xfe, 0x2c,
+    0xff, 0x2c,
+    0xa0, 0x10,
+    0xa1, 0x10,
+    0xa2, 0x10,
+    0xa3, 0x10,
+    0xa4, 0x10,
+    0xa5, 0x10,
+    0xa6, 0x10,
+    0xa7, 0x10,
+    0xa8, 0x10,
+    0xa9, 0x10,
+    0xaa, 0x10,
+    0xab, 0x10,
+    0xac, 0x10,
+    0xad, 0x10,
+    0xae, 0x10,
+    0xaf, 0x10,
+    0xb0, 0x10,
+    0xb1, 0x10,
+    0xb2, 0x10,
+    0xb3, 0x10,
+    0xb4, 0x10,
+    0xb5, 0x10,
+    0xb6, 0x10,
+    0xb7, 0x10,
+    0xb8, 0x10,
+    0xb9, 0x10,
+    0xba, 0x10,
+    0xbb, 0x10,
+    0xbc, 0x10,
+    0xbd, 0x10,
+    0xbe, 0x10,
+    0xbf, 0x10,
+    0xc0, 0x10,
+    0xc1, 0x10,
+    0xc2, 0x10,
+    0xc3, 0x10,
+    0xc4, 0x10,
+    0xc5, 0x10,
+    0xff, 0xff,
+    0x1b, 0xd2,
+    0x21, 0xff,
+    0x22, 0xff,
+    0x23, 0xff,
+    0x24, 0xff,
+    0x25, 0xff,
+    0x26, 0xff,
+    0x27, 0xff,
+    0x28, 0xff,
+    0x29, 0xff,
+    0x2a, 0xff,
+    0x2b, 0xff,
+    0x2c, 0xff,
+    0x2d, 0xff,
+    0x2e, 0xff,
+    0x2f, 0xff,
+    0x30, 0xff,
+    0x31, 0xff,
+    0x32, 0xff,
+    0x33, 0xff,
+    0x34, 0xff,
+    0x35, 0xff,
+    0x36, 0xff,
+    0x37, 0xff,
+    0x38, 0xff,
+    0x39, 0xff,
+    0x3a, 0xff,
+    0x5b, 0xff,
+    0x5c, 0xff,
+    0x5d, 0xff,
+    0x5e, 0xff,
+    0x5f, 0xff,
+    0x60, 0xff,
+    0x61, 0xff,
+    0x62, 0xff,
+    0x63, 0xff,
+    0x64, 0xff,
+    0x65, 0xff,
+    0x66, 0xff,
+    0x67, 0xff,
+    0x68, 0xff,
+    0x69, 0xff,
+    0x6a, 0xff,
+    0x6b, 0xff,
+    0x6c, 0xff,
+    0x6d, 0xff,
+    0x6e, 0xff,
+    0x6f, 0xff,
+    0x70, 0xff,
+    0x71, 0xff,
+    0x72, 0xff,
+    0x73, 0xff,
+    0x74, 0xff,
+    0x75, 0xff,
+    0x76, 0xff,
+    0x77, 0xff,
+    0x78, 0xff,
+    0x79, 0xff,
+    0x7a, 0xff,
+    0x7b, 0xff,
+    0x7c, 0xff,
+    0x7d, 0xff,
+    0x7e, 0xff,
+    0x7f, 0xff,
+    0x80, 0xff,
+    0x81, 0xff,
+    0x82, 0xff,
+    0x83, 0xff,
+    0x84, 0xff,
+    0x85, 0xff,
+    0x86, 0xff,
+    0x87, 0xff,
+    0x88, 0xff,
+    0x89, 0xff,
+    0x8a, 0xff,
+    0x8b, 0xff,
+    0x8c, 0xff,
+    0x8d, 0xff,
+    0x8e, 0xff,
+    0x8f, 0xff,
+    0x90, 0xff,
+    0x91, 0xff,
+    0x92, 0xff,
+    0x93, 0xff,
+    0x94, 0xff,
+    0x95, 0xff,
+    0x96, 0xff,
+    0x97, 0xff,
+    0x98, 0xff,
+    0x99, 0xff,
+    0x9a, 0xff,
+    0x9b, 0xff,
+    0x9c, 0xff,
+    0x9d, 0xff,
+    0x9e, 0xff,
+    0x9f, 0xff,
+    0xa0, 0xff,
+    0xa1, 0xff,
+    0xa2, 0xff,
+    0xa3, 0xff,
+    0xa4, 0xff,
+    0xa5, 0xff,
+    0xa6, 0xff,
+    0xa7, 0xff,
+    0xa8, 0xff,
+    0xa9, 0xff,
+    0xaa, 0xff,
+    0xab, 0xff,
+    0xac, 0xff,
+    0xad, 0xff,
+    0xae, 0xff,
+    0xaf, 0xff,
+    0xb0, 0xff,
+    0xb1, 0xff,
+    0xb2, 0xff,
+    0xb3, 0xff,
+    0xb4, 0xff,
+    0xb5, 0xff,
+    0xb6, 0xff,
+    0xb7, 0xff,
+    0xb8, 0xff,
+    0xb9, 0xff,
+    0xba, 0xff,
+    0xbb, 0xff,
+    0xbc, 0xff,
+    0xbd, 0xff,
+    0xbe, 0xff,
+    0xbf, 0xff,
+    0xc0, 0xff,
+    0xc1, 0xff,
+    0xc2, 0xff,
+    0xc3, 0xff,
+    0xc4, 0xff,
+    0xc5, 0xff,
+    0xc6, 0xff,
+    0xc7, 0xff,
+    0xc8, 0xff,
+    0xc9, 0xff,
+    0xca, 0xff,
+    0xcb, 0xff,
+    0xcc, 0xff,
+    0xcd, 0xff,
+    0xce, 0xff,
+    0xcf, 0xff,
+    0xd0, 0xff,
+    0xd1, 0xff,
+    0xd2, 0xff,
+    0xd3, 0xff,
+    0xd4, 0xff,
+    0xd5, 0xff,
+    0xd6, 0xff,
+    0xd7, 0xff,
+    0xd8, 0xff,
+    0xd9, 0xff,
+    0xda, 0xff,
+    0xdb, 0xff,
+    0xdc, 0xff,
+    0xdd, 0xff,
+    0xde, 0xff,
+    0xdf, 0xff,
+    0xe0, 0xff,
+    0xe1, 0xff,
+    0xe2, 0xff,
+    0xe3, 0xff,
+    0xe4, 0xff,
+    0xe5, 0xff,
+    0xe6, 0xff,
+    0xe7, 0xff,
+    0xe8, 0xff,
+    0xe9, 0xff,
+    0xea, 0xff,
+    0xeb, 0xff,
+    0xec, 0xff,
+    0xed, 0xff,
+    0xee, 0xff,
+    0xef, 0xff,
+    0xf0, 0xff,
+    0xf1, 0xff,
+    0xf2, 0xff,
+    0xf3, 0xff,
+    0xf4, 0xff,
+    0xf5, 0xff,
+    0xf6, 0xff,
+    0xf7, 0xff,
+    0xf8, 0xff,
+    0xf9, 0xff,
+    0xfa, 0xff,
+    0xfb, 0xff,
+    0xfc, 0xff,
+    0xfd, 0xff,
+    0xfe, 0xff,
+    0xff, 0xff
+};
+
+#endif
+
+/**
+ * @}
+ */
+
+
Index: uspace/app/sbi/src/run_texpr.c
===================================================================
--- uspace/app/sbi/src/run_texpr.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/sbi/src/run_texpr.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -98,6 +98,6 @@
 {
 	stree_symbol_t *sym;
-	tdata_item_t *targ_i;
-	tdata_item_t *titem;
+	tdata_item_t *targ_i = NULL;
+	tdata_item_t *titem = NULL;;
 	tdata_object_t *tobject;
 	tdata_deleg_t *tdeleg;
@@ -139,7 +139,4 @@
 		return;
 	}
-
-	/* Make compiler happy. */
-	titem = NULL;
 
 	switch (sym->sc) {
@@ -222,5 +219,5 @@
     stree_tindex_t *tindex, tdata_item_t **res)
 {
-	tdata_item_t *base_ti;
+	tdata_item_t *base_ti = NULL;
 	tdata_item_t *titem;
 	tdata_array_t *tarray;
Index: uspace/app/sportdmp/sportdmp.c
===================================================================
--- uspace/app/sportdmp/sportdmp.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/sportdmp/sportdmp.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -27,20 +27,20 @@
  */
 
+#include <device/char_dev.h>
 #include <errno.h>
+#include <ipc/serial_ctl.h>
+#include <loc.h>
 #include <stdio.h>
-#include <devman.h>
-#include <ipc/devman.h>
-#include <device/char_dev.h>
-#include <ipc/serial_ctl.h>
 
 #define BUF_SIZE 1
 
-static void syntax_print() {
-	fprintf(stderr, "Usage: sportdmp <baud> <device_path>\n");
+static void syntax_print(void)
+{
+	fprintf(stderr, "Usage: sportdmp <baud> <device_service>\n");
 }
 
 int main(int argc, char **argv)
 {
-	const char* devpath = "/hw/pci0/00:01.0/com1/a";
+	const char* svc_path = "devices/\\hw\\pci0\\00:01.0\\com1\\a";
 	sysarg_t baud = 9600;
 	
@@ -56,5 +56,5 @@
 	
 	if (argc > 2) {
-		devpath = argv[2];
+		svc_path = argv[2];
 	}
 	
@@ -64,15 +64,15 @@
 	}
 	
-	devman_handle_t device;
-	int rc = devman_fun_get_handle(devpath, &device, IPC_FLAG_BLOCKING);
+	service_id_t svc_id;
+	int rc = loc_service_get_id(svc_path, &svc_id, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
-		fprintf(stderr, "Cannot open device %s\n", devpath);
+		fprintf(stderr, "Cannot find device service %s\n", svc_path);
 		return 1;
 	}
 	
-	async_sess_t *sess = devman_device_connect(EXCHANGE_SERIALIZE, device,
+	async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE, svc_id,
 	    IPC_FLAG_BLOCKING);
 	if (!sess) {
-		fprintf(stderr, "Cannot connect device\n");
+		fprintf(stderr, "Failed connecting to service %s\n", svc_path);
 	}
 	
@@ -83,5 +83,5 @@
 	
 	if (rc != EOK) {
-		fprintf(stderr, "Cannot set serial properties\n");
+		fprintf(stderr, "Failed setting serial properties\n");
 		return 2;
 	}
@@ -89,5 +89,5 @@
 	uint8_t *buf = (uint8_t *) malloc(BUF_SIZE);
 	if (buf == NULL) {
-		fprintf(stderr, "Cannot allocate buffer\n");
+		fprintf(stderr, "Failed allocating buffer\n");
 		return 3;
 	}
Index: uspace/app/sysinfo/sysinfo.c
===================================================================
--- uspace/app/sysinfo/sysinfo.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/sysinfo/sysinfo.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -37,51 +37,24 @@
 #include <stdio.h>
 #include <sysinfo.h>
+#include <malloc.h>
 #include <sys/types.h>
 
-static int print_item_val(char *ipath);
-static int print_item_data(char *ipath);
-
-static void dump_bytes_hex(char *data, size_t size);
-static void dump_bytes_text(char *data, size_t size);
-
-static void print_syntax(void);
-
-int main(int argc, char *argv[])
-{
-	int rc;
-	char *ipath;
-	sysinfo_item_val_type_t tag;
-
-	if (argc != 2) {
-		print_syntax();
-		return 1;
-	}
-
-	ipath = argv[1];
-
-	tag = sysinfo_get_val_type(ipath);
-
-	/* Silence warning */
-	rc = EOK;
-
-	switch (tag) {
-	case SYSINFO_VAL_UNDEFINED:
-		printf("Error: Sysinfo item '%s' not defined.\n", ipath);
-		rc = 2;
-		break;
-	case SYSINFO_VAL_VAL:
-		rc = print_item_val(ipath);
-		break;
-	case SYSINFO_VAL_DATA:
-		rc = print_item_data(ipath);
-		break;
-	default:
-		printf("Error: Sysinfo item '%s' with unknown value type.\n",
-		    ipath);
-		rc = 2;
-		break;
-	}
-
-	return rc;
+static void dump_bytes_hex(char *data, size_t size)
+{
+	for (size_t i = 0; i < size; i++) {
+		if (i > 0)
+			putchar(' ');
+		printf("0x%02x", (uint8_t) data[i]);
+	}
+}
+
+static void dump_bytes_text(char *data, size_t size)
+{
+	size_t offset = 0;
+	
+	while (offset < size) {
+		wchar_t c = str_decode(data, &offset, size);
+		printf("%lc", (wint_t) c);
+	}
 }
 
@@ -89,15 +62,13 @@
 {
 	sysarg_t value;
-	int rc;
-
-	rc = sysinfo_get_value(ipath, &value);
+	int rc = sysinfo_get_value(ipath, &value);
 	if (rc != EOK) {
 		printf("Error reading item '%s'.\n", ipath);
 		return rc;
 	}
-
+	
 	printf("%s -> %" PRIu64 " (0x%" PRIx64 ")\n", ipath,
 	    (uint64_t) value, (uint64_t) value);
-
+	
 	return EOK;
 }
@@ -105,13 +76,11 @@
 static int print_item_data(char *ipath)
 {
-	void *data;
 	size_t size;
-
-	data = sysinfo_get_data(ipath, &size);
+	void *data = sysinfo_get_data(ipath, &size);
 	if (data == NULL) {
 		printf("Error reading item '%s'.\n", ipath);
 		return -1;
 	}
-
+	
 	printf("%s -> ", ipath);
 	dump_bytes_hex(data, size);
@@ -119,35 +88,115 @@
 	dump_bytes_text(data, size);
 	fputs("')\n", stdout);
-
+	
 	return EOK;
 }
 
-static void dump_bytes_hex(char *data, size_t size)
-{
-	size_t i;
-
-	for (i = 0; i < size; ++i) {
-		if (i > 0) putchar(' ');
-		printf("0x%02x", (uint8_t) data[i]);
-	}
-}
-
-static void dump_bytes_text(char *data, size_t size)
-{
-	wchar_t c;
-	size_t offset;
-
-	offset = 0;
-
-	while (offset < size) {
-		c = str_decode(data, &offset, size);
-		printf("%lc", (wint_t) c);
-	}
-}
-
-
-static void print_syntax(void)
-{
-	printf("Syntax: sysinfo <item_path>\n");
+static int print_item_property(char *ipath, char *iprop)
+{
+	size_t size;
+	void *data = sysinfo_get_property(ipath, iprop, &size);
+	if (data == NULL) {
+		printf("Error reading property '%s' of item '%s'.\n", iprop,
+		    ipath);
+		return -1;
+	}
+	
+	printf("%s property %s -> ", ipath, iprop);
+	dump_bytes_hex(data, size);
+	fputs(" ('", stdout);
+	dump_bytes_text(data, size);
+	fputs("')\n", stdout);
+	
+	return EOK;
+}
+
+static void print_spaces(size_t spaces)
+{
+	for (size_t i = 0; i < spaces; i++)
+		printf(" ");
+}
+
+static void print_keys(const char *path, size_t spaces)
+{
+	size_t size;
+	char *keys = sysinfo_get_keys(path, &size);
+	if ((keys == NULL) || (size == 0))
+		return;
+	
+	size_t pos = 0;
+	while (pos < size) {
+		/* Process each key with sanity checks */
+		size_t cur_size = str_nsize(keys + pos, size - pos);
+		if (keys[pos + cur_size] != 0)
+			break;
+		
+		size_t path_size = str_size(path) + cur_size + 2;
+		char *cur_path = (char *) malloc(path_size);
+		if (cur_path == NULL)
+			break;
+		
+		size_t length;
+		
+		if (path[0] != 0) {
+			print_spaces(spaces);
+			printf(".%s\n", keys + pos);
+			length = str_length(keys + pos) + 1;
+			
+			snprintf(cur_path, path_size, "%s.%s", path, keys + pos);
+		} else {
+			printf("%s\n", keys + pos);
+			length = str_length(keys + pos);
+			
+			snprintf(cur_path, path_size, "%s", keys + pos);
+		}
+		
+		print_keys(cur_path, spaces + length);
+		
+		free(cur_path);
+		pos += cur_size + 1;
+	}
+	
+	free(keys);
+}
+
+int main(int argc, char *argv[])
+{
+	int rc = 0;
+	
+	if (argc < 2) {
+		/* Print keys */
+		print_keys("", 0);
+		return rc;
+	}
+	
+	char *ipath = argv[1];
+	
+	if (argc < 3) {
+		sysinfo_item_val_type_t tag = sysinfo_get_val_type(ipath);
+		
+		switch (tag) {
+		case SYSINFO_VAL_UNDEFINED:
+			printf("Error: Sysinfo item '%s' not defined.\n", ipath);
+			rc = 2;
+			break;
+		case SYSINFO_VAL_VAL:
+			rc = print_item_val(ipath);
+			break;
+		case SYSINFO_VAL_DATA:
+			rc = print_item_data(ipath);
+			break;
+		default:
+			printf("Error: Sysinfo item '%s' with unknown value type.\n",
+			    ipath);
+			rc = 2;
+			break;
+		}
+		
+		return rc;
+	}
+	
+	char *iprop = argv[2];
+	rc = print_item_property(ipath, iprop);
+	return rc;
 }
 
Index: uspace/app/tester/Makefile
===================================================================
--- uspace/app/tester/Makefile	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/tester/Makefile	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -50,4 +50,5 @@
 	vfs/vfs1.c \
 	ipc/ping_pong.c \
+	ipc/starve.c \
 	loop/loop1.c \
 	mm/common.c \
Index: uspace/app/tester/fault/fault2.c
===================================================================
--- uspace/app/tester/fault/fault2.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/tester/fault/fault2.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -35,8 +35,6 @@
 const char *test_fault2(void)
 {
-	volatile long long var;
-	volatile int var1;
-	
-	var1 = *((aliasing_int *) (((char *) (&var)) + 1));
+	volatile long long var = 0;
+	volatile int var1 = *((aliasing_int *) (((char *) (&var)) + 1));
 	printf("Read %d\n", var1);
 	
Index: uspace/app/tester/hw/serial/serial1.c
===================================================================
--- uspace/app/tester/hw/serial/serial1.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/tester/hw/serial/serial1.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -42,6 +42,5 @@
 #include <async.h>
 #include <ipc/services.h>
-#include <ipc/devman.h>
-#include <devman.h>
+#include <loc.h>
 #include <device/char_dev.h>
 #include <str.h>
@@ -71,19 +70,19 @@
 		}
 	
-	devman_handle_t handle;
-	int res = devman_fun_get_handle("/hw/pci0/00:01.0/com1/a", &handle,
-	    IPC_FLAG_BLOCKING);
+	service_id_t svc_id;
+	int res = loc_service_get_id("devices/\\hw\\pci0\\00:01.0\\com1\\a",
+	    &svc_id, IPC_FLAG_BLOCKING);
 	if (res != EOK)
-		return "Could not get serial device handle";
-	
-	async_sess_t *sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
+		return "Failed getting serial port service ID";
+	
+	async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE, svc_id,
 	    IPC_FLAG_BLOCKING);
 	if (!sess)
-		return "Unable to connect to serial device";
+		return "Failed connecting to serial device";
 	
 	char *buf = (char *) malloc(cnt + 1);
 	if (buf == NULL) {
 		async_hangup(sess);
-		return "Failed to allocate input buffer";
+		return "Failed allocating input buffer";
 	}
 	
@@ -112,9 +111,9 @@
 		free(buf);
 		async_hangup(sess);
-		return "Failed to set serial communication parameters";
-	}
-	
-	TPRINTF("Trying to read %zu characters from serial device "
-	    "(handle=%" PRIun ")\n", cnt, handle);
+		return "Failed setting serial communication parameters";
+	}
+	
+	TPRINTF("Trying reading %zu characters from serial device "
+	    "(svc_id=%" PRIun ")\n", cnt, svc_id);
 	
 	size_t total = 0;
@@ -130,5 +129,5 @@
 			free(buf);
 			async_hangup(sess);
-			return "Failed read from serial device";
+			return "Failed reading from serial device";
 		}
 		
@@ -165,5 +164,5 @@
 				free(buf);
 				async_hangup(sess);
-				return "Failed write to serial device";
+				return "Failed writing to serial device";
 			}
 			
Index: uspace/app/tester/ipc/starve.c
===================================================================
--- uspace/app/tester/ipc/starve.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
+++ uspace/app/tester/ipc/starve.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <io/console.h>
+#include <async.h>
+#include "../tester.h"
+
+#define DURATION_SECS      30
+
+const char *test_starve_ipc(void)
+{
+	const char *err = NULL;
+	console_ctrl_t *console = console_init(stdin, stdout);
+	if (console == NULL) {
+		return "Failed to init connection with console.";
+	}
+	
+	struct timeval start;
+	if (gettimeofday(&start, NULL) != 0) {
+		err = "Failed getting the time";
+		goto leave;
+	}
+	
+	TPRINTF("Intensive computation shall be imagined (for %ds)...\n", DURATION_SECS);
+	TPRINTF("Press a key to terminate prematurely...\n");
+	while (true) {
+		struct timeval now;
+		if (gettimeofday(&now, NULL) != 0) {
+			err = "Failed getting the time";
+			goto leave;
+		}
+		
+		if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L)
+			break;
+		
+		kbd_event_t ev;
+		suseconds_t timeout = 0;
+		bool has_event = console_get_kbd_event_timeout(console, &ev, &timeout);
+		if (has_event && (ev.type == KEY_PRESS)) {
+			TPRINTF("Key %d pressed, terminating.\n", ev.key);
+			break;
+		}
+	}
+
+	// FIXME - unless a key was pressed, the answer leaked as no one
+	// will wait for it.
+	// We cannot use async_forget() directly, though. Something like
+	// console_forget_pending_kbd_event() shall come here.
+
+	TPRINTF("Terminating...\n");
+
+leave:
+	console_done(console);
+
+	return err;
+}
Index: uspace/app/tester/ipc/starve.def
===================================================================
--- uspace/app/tester/ipc/starve.def	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
+++ uspace/app/tester/ipc/starve.def	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -0,0 +1,6 @@
+{
+	"starve",
+	"Demonstrate starving IPC",
+	&test_starve_ipc,
+	true
+},
Index: uspace/app/tester/print/print1.c
===================================================================
--- uspace/app/tester/print/print1.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/tester/print/print1.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -42,5 +42,5 @@
 	
 	TPRINTF("Testing printf(\"%%8.10s\", \"text\"):\n");
-	TPRINTF("Expected output: \"text\"\n");
+	TPRINTF("Expected output: \"    text\"\n");
 	TPRINTF("Real output:     \"%8.10s\"\n\n", "text");
 	
@@ -49,4 +49,8 @@
 	TPRINTF("Real output:     \"%8.10s\"\n\n", "very long text");
 	
+	TPRINTF("Testing printf(\"%%-*.*s\", 7, 7, \"text\"):\n");
+	TPRINTF("Expected output: \"text   \"\n");
+	TPRINTF("Real output:     \"%-*.*s\"\n\n", 7, 7, "text");
+	
 	return NULL;
 }
Index: uspace/app/tester/tester.c
===================================================================
--- uspace/app/tester/tester.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/tester/tester.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -60,4 +60,5 @@
 #include "vfs/vfs1.def"
 #include "ipc/ping_pong.def"
+#include "ipc/starve.def"
 #include "loop/loop1.def"
 #include "mm/malloc1.def"
Index: uspace/app/tester/tester.h
===================================================================
--- uspace/app/tester/tester.h	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/tester/tester.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -93,4 +93,5 @@
 extern const char *test_vfs1(void);
 extern const char *test_ping_pong(void);
+extern const char *test_starve_ipc(void);
 extern const char *test_loop1(void);
 extern const char *test_malloc1(void);
Index: uspace/app/top/screen.c
===================================================================
--- uspace/app/top/screen.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/top/screen.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -37,4 +37,5 @@
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <io/console.h>
 #include <io/style.h>
@@ -43,4 +44,5 @@
 #include <stats.h>
 #include <inttypes.h>
+#include <macros.h>
 #include "screen.h"
 #include "top.h"
@@ -48,10 +50,13 @@
 #define USEC_COUNT  1000000
 
-static sysarg_t warn_col = 0;
-static sysarg_t warn_row = 0;
 static suseconds_t timeleft = 0;
 
 console_ctrl_t *console;
 
+static sysarg_t warning_col = 0;
+static sysarg_t warning_row = 0;
+static suseconds_t warning_timeleft = 0;
+static char *warning_text = NULL;
+
 static void screen_style_normal(void)
 {
@@ -64,4 +69,10 @@
 	console_flush(console);
 	console_set_style(console, STYLE_INVERTED);
+}
+
+static void screen_style_emphasis(void)
+{
+	console_flush(console);
+	console_set_style(console, STYLE_EMPHASIS);
 }
 
@@ -126,4 +137,7 @@
 void screen_done(void)
 {
+	free(warning_text);
+	warning_text = NULL;
+
 	screen_restart(true);
 	
@@ -277,18 +291,51 @@
 }
 
-static inline void print_tasks_head(void)
+static inline void print_help_head(void)
 {
 	screen_style_inverted();
-	printf("[taskid] [thrds] [resident] [%%resi] [virtual] [%%virt]"
-	    " [%%user] [%%kern] [name");
+	printf("Help");
 	screen_newline();
 	screen_style_normal();
 }
 
-static inline void print_tasks(data_t *data)
-{
-	sysarg_t cols;
-	sysarg_t rows;
-	screen_get_size(&cols, &rows);
+static inline void print_help(void)
+{
+	sysarg_t cols;
+	sysarg_t rows;
+	screen_get_size(&cols, &rows);
+	
+	screen_newline();
+	
+	printf("Operation modes:");
+	screen_newline();
+	
+	printf(" t .. tasks statistics");
+	screen_newline();
+	
+	printf(" i .. IPC statistics");
+	screen_newline();
+	
+	printf(" e .. exceptions statistics");
+	screen_newline();
+	
+	printf("      a .. toggle display of all/hot exceptions");
+	screen_newline();
+
+	printf(" h .. toggle this help screen");
+	screen_newline();
+
+	screen_newline();
+
+	printf("Other keys:");
+	screen_newline();
+	
+	printf(" s .. choose column to sort by");
+	screen_newline();
+	
+	printf(" r .. toggle reversed sorting");
+	screen_newline();
+	
+	printf(" q .. quit");
+	screen_newline();
 	
 	sysarg_t col;
@@ -296,32 +343,4 @@
 	screen_get_pos(&col, &row);
 	
-	size_t i;
-	for (i = 0; (i < data->tasks_count) && (row < rows); i++, row++) {
-		stats_task_t *task = data->tasks + data->tasks_map[i];
-		perc_task_t *perc = data->tasks_perc + data->tasks_map[i];
-		
-		uint64_t resmem;
-		const char *resmem_suffix;
-		bin_order_suffix(task->resmem, &resmem, &resmem_suffix, true);
-		
-		uint64_t virtmem;
-		const char *virtmem_suffix;
-		bin_order_suffix(task->virtmem, &virtmem, &virtmem_suffix, true);
-		
-		printf("%-8" PRIu64 " %7zu %7" PRIu64 "%s ",
-		    task->task_id, task->threads, resmem, resmem_suffix);
-		print_percent(perc->resmem, 2);
-		printf(" %6" PRIu64 "%s ", virtmem, virtmem_suffix);
-		print_percent(perc->virtmem, 2);
-		puts(" ");
-		print_percent(perc->ucycles, 2);
-		puts(" ");
-		print_percent(perc->kcycles, 2);
-		puts(" ");
-		print_string(task->name);
-		
-		screen_newline();
-	}
-	
 	while (row < rows) {
 		screen_newline();
@@ -330,14 +349,30 @@
 }
 
-static inline void print_ipc_head(void)
-{
+static inline void print_table_head(const table_t *table)
+{
+	sysarg_t cols;
+	sysarg_t rows;
+	screen_get_size(&cols, &rows);
+
 	screen_style_inverted();
-	printf("[taskid] [cls snt] [cls rcv] [ans snt]"
-	    " [ans rcv] [irq rcv] [forward] [name");
+	for (size_t i = 0; i < table->num_columns; i++) {
+		const char *name = table->columns[i].name;
+		int width = table->columns[i].width;
+		if (i != 0) {
+			puts(" ");
+		}
+		if (width == 0) {
+			sysarg_t col;
+			sysarg_t row;
+			screen_get_pos(&col, &row);
+			width = cols - col - 1;
+		}
+		printf("[%-*.*s]", width - 2, width - 2, name);
+	}
 	screen_newline();
 	screen_style_normal();
 }
 
-static inline void print_ipc(data_t *data)
+static inline void print_table(const table_t *table)
 {
 	sysarg_t cols;
@@ -350,44 +385,58 @@
 	
 	size_t i;
-	for (i = 0; (i < data->tasks_count) && (row < rows); i++, row++) {
-		uint64_t call_sent;
-		uint64_t call_received;
-		uint64_t answer_sent;
-		uint64_t answer_received;
-		uint64_t irq_notif_received;
-		uint64_t forwarded;
-		
-		char call_sent_suffix;
-		char call_received_suffix;
-		char answer_sent_suffix;
-		char answer_received_suffix;
-		char irq_notif_received_suffix;
-		char forwarded_suffix;
-		
-		order_suffix(data->tasks[i].ipc_info.call_sent, &call_sent,
-		    &call_sent_suffix);
-		order_suffix(data->tasks[i].ipc_info.call_received,
-		    &call_received, &call_received_suffix);
-		order_suffix(data->tasks[i].ipc_info.answer_sent,
-		    &answer_sent, &answer_sent_suffix);
-		order_suffix(data->tasks[i].ipc_info.answer_received,
-		    &answer_received, &answer_received_suffix);
-		order_suffix(data->tasks[i].ipc_info.irq_notif_received,
-		    &irq_notif_received, &irq_notif_received_suffix);
-		order_suffix(data->tasks[i].ipc_info.forwarded, &forwarded,
-		    &forwarded_suffix);
-		
-		printf("%-8" PRIu64 " %8" PRIu64 "%c %8" PRIu64 "%c"
-		     " %8" PRIu64 "%c %8" PRIu64 "%c %8" PRIu64 "%c"
-		     " %8" PRIu64 "%c ", data->tasks[i].task_id,
-		     call_sent, call_sent_suffix,
-		     call_received, call_received_suffix,
-		     answer_sent, answer_sent_suffix,
-		     answer_received, answer_received_suffix,
-		     irq_notif_received, irq_notif_received_suffix,
-		     forwarded, forwarded_suffix);
-		print_string(data->tasks[i].name);
-		
-		screen_newline();
+	for (i = 0; (i < table->num_fields) && (row < rows); i++) {
+		size_t column_index = i % table->num_columns;
+		int width = table->columns[column_index].width;
+		field_t *field = &table->fields[i];
+
+		if (column_index != 0) {
+			puts(" ");
+		}
+
+		if (width == 0) {
+			screen_get_pos(&col, &row);
+			width = cols - col - 1;
+		}
+
+		switch (field->type) {
+		case FIELD_EMPTY:
+			printf("%*s", width, "");
+			break;
+		case FIELD_UINT:
+			printf("%*" PRIu64, width, field->uint);
+			break;
+		case FIELD_UINT_SUFFIX_BIN: {
+			uint64_t val = field->uint;
+			const char *suffix;
+			width -= 3;
+			bin_order_suffix(val, &val, &suffix, true);
+			printf("%*" PRIu64 "%s", width, val, suffix);
+			break;
+		}
+		case FIELD_UINT_SUFFIX_DEC: {
+			uint64_t val = field->uint;
+			char suffix;
+			width -= 1;
+			order_suffix(val, &val, &suffix);
+			printf("%*" PRIu64 "%c", width, val, suffix);
+			break;
+		}
+		case FIELD_PERCENT:
+			width -= 5; /* nnn.% */
+			if (width > 2) {
+				printf("%*s", width - 2, "");
+				width = 2;
+			}
+			print_percent(field->fixed, width);
+			break;
+		case FIELD_STRING:
+			printf("%-*.*s", width, width, field->string);
+			break;
+		}
+
+		if (column_index == table->num_columns - 1) {
+			screen_newline();
+			row++;
+		}
 	}
 	
@@ -398,13 +447,5 @@
 }
 
-static inline void print_excs_head(void)
-{
-	screen_style_inverted();
-	printf("[exc   ] [count   ] [%%count] [cycles  ] [%%cycles] [description");
-	screen_newline();
-	screen_style_normal();
-}
-
-static inline void print_excs(data_t *data)
+static inline void print_sort(table_t *table)
 {
 	sysarg_t cols;
@@ -415,28 +456,8 @@
 	sysarg_t row;
 	screen_get_pos(&col, &row);
-	
-	size_t i;
-	for (i = 0; (i < data->exceptions_count) && (row < rows); i++) {
-		/* Filter-out cold exceptions if not instructed otherwise */
-		if ((!excs_all) && (!data->exceptions[i].hot))
-			continue;
-		
-		uint64_t count;
-		uint64_t cycles;
-		
-		char count_suffix;
-		char cycles_suffix;
-		
-		order_suffix(data->exceptions[i].count, &count, &count_suffix);
-		order_suffix(data->exceptions[i].cycles, &cycles, &cycles_suffix);
-		
-		printf("%-8u %9" PRIu64 "%c  ",
-		     data->exceptions[i].id, count, count_suffix);
-		print_percent(data->exceptions_perc[i].count, 2);
-		printf(" %9" PRIu64 "%c   ", cycles, cycles_suffix);
-		print_percent(data->exceptions_perc[i].cycles, 2);
-		puts(" ");
-		print_string(data->exceptions[i].desc);
-		
+
+	size_t num = min(table->num_columns, rows - row);
+	for (size_t i = 0; i < num; i++) {
+		printf("%c - %s", table->columns[i].key, table->columns[i].name);
 		screen_newline();
 		row++;
@@ -449,37 +470,16 @@
 }
 
-static void print_help(void)
-{
-	sysarg_t cols;
-	sysarg_t rows;
-	screen_get_size(&cols, &rows);
-	
-	sysarg_t col;
-	sysarg_t row;
-	screen_get_pos(&col, &row);
-	
-	screen_newline();
-	
-	printf("Operation modes:");
-	screen_newline();
-	
-	printf(" t .. tasks statistics");
-	screen_newline();
-	
-	printf(" i .. IPC statistics");
-	screen_newline();
-	
-	printf(" e .. exceptions statistics");
-	screen_newline();
-	
-	printf("      a .. toggle display of all/hot exceptions");
-	screen_newline();
-	
-	row += 6;
-	
-	while (row < rows) {
-		screen_newline();
-		row++;
-	}
+static inline void print_warning(void)
+{
+	screen_get_pos(&warning_col, &warning_row);
+	if (warning_timeleft > 0) {
+		screen_style_emphasis();
+		print_string(warning_text);
+		screen_style_normal();
+	} else {
+		free(warning_text);
+		warning_text = NULL;
+	}
+	screen_newline();
 }
 
@@ -492,24 +492,16 @@
 	print_cpu_info(data);
 	print_physmem_info(data);
-	
-	/* Empty row for warnings */
-	screen_get_pos(&warn_col, &warn_row);
-	screen_newline();
-	
-	switch (op_mode) {
-	case OP_TASKS:
-		print_tasks_head();
-		print_tasks(data);
+	print_warning();
+	
+	switch (screen_mode) {
+	case SCREEN_TABLE:
+		print_table_head(&data->table);
+		print_table(&data->table);
 		break;
-	case OP_IPC:
-		print_ipc_head();
-		print_ipc(data);
+	case SCREEN_SORT:
+		print_sort(&data->table);
 		break;
-	case OP_EXCS:
-		print_excs_head();
-		print_excs(data);
-		break;
-	case OP_HELP:
-		print_tasks_head();
+	case SCREEN_HELP:
+		print_help_head();
 		print_help();
 	}
@@ -518,14 +510,25 @@
 }
 
-void print_warning(const char *fmt, ...)
-{
-	screen_moveto(warn_col, warn_row);
-	
+void show_warning(const char *fmt, ...)
+{
+	sysarg_t cols;
+	sysarg_t rows;
+	screen_get_size(&cols, &rows);
+
+	size_t warning_text_size = 1 + cols * sizeof(*warning_text);
+	free(warning_text);
+	warning_text = malloc(warning_text_size);
+	if (!warning_text)
+		return;
+
 	va_list args;
 	va_start(args, fmt);
-	vprintf(fmt, args);
+	vsnprintf(warning_text, warning_text_size, fmt, args);
 	va_end(args);
 	
-	screen_newline();
+	warning_timeleft = 2 * USEC_COUNT;
+
+	screen_moveto(warning_col, warning_row);
+	print_warning();
 	console_flush(console);
 }
@@ -555,8 +558,10 @@
 		kbd_event_t event;
 		
+		warning_timeleft -= timeleft;
 		if (!console_get_kbd_event_timeout(console, &event, &timeleft)) {
 			timeleft = 0;
 			return -1;
 		}
+		warning_timeleft += timeleft;
 		
 		if (event.type == KEY_PRESS)
Index: uspace/app/top/screen.h
===================================================================
--- uspace/app/top/screen.h	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/top/screen.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -43,5 +43,5 @@
 extern void screen_done(void);
 extern void print_data(data_t *);
-extern void print_warning(const char *, ...);
+extern void show_warning(const char *, ...);
 
 extern int tgetchar(unsigned int);
Index: uspace/app/top/top.c
===================================================================
--- uspace/app/top/top.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/top/top.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -55,7 +55,80 @@
 #define MINUTE  60
 
-op_mode_t op_mode = OP_TASKS;
-sort_mode_t sort_mode = SORT_TASK_CYCLES;
-bool excs_all = false;
+typedef enum {
+	OP_TASKS,
+	OP_IPC,
+	OP_EXCS,
+} op_mode_t;
+
+static const column_t task_columns[] = {
+	{"taskid",   't',  8},
+	{"thrds",    'h',  7},
+	{"resident", 'r', 10},
+	{"%resi",    'R',  7},
+	{"virtual",  'v',  9},
+	{"%virt",    'V',  7},
+	{"%user",    'U',  7},
+	{"%kern",    'K',  7},
+	{"name",     'd',  0},
+};
+
+enum {
+	TASK_COL_ID = 0,
+	TASK_COL_NUM_THREADS,
+	TASK_COL_RESIDENT,
+	TASK_COL_PERCENT_RESIDENT,
+	TASK_COL_VIRTUAL,
+	TASK_COL_PERCENT_VIRTUAL,
+	TASK_COL_PERCENT_USER,
+	TASK_COL_PERCENT_KERNEL,
+	TASK_COL_NAME,
+	TASK_NUM_COLUMNS,
+};
+
+static const column_t ipc_columns[] = {
+	{"taskid",  't', 8},
+	{"cls snt", 'c', 9},
+	{"cls rcv", 'C', 9},
+	{"ans snt", 'a', 9},
+	{"ans rcv", 'A', 9},
+	{"forward", 'f', 9},
+	{"name",    'd', 0},
+};
+
+enum {
+	IPC_COL_TASKID = 0,
+	IPC_COL_CLS_SNT,
+	IPC_COL_CLS_RCV,
+	IPC_COL_ANS_SNT,
+	IPC_COL_ANS_RCV,
+	IPC_COL_FORWARD,
+	IPC_COL_NAME,
+	IPC_NUM_COLUMNS,
+};
+
+static const column_t exception_columns[] = {
+	{"exc",         'e',  8},
+	{"count",       'n', 10},
+	{"%count",      'N',  8},
+	{"cycles",      'c', 10},
+	{"%cycles",     'C',  9},
+	{"description", 'd',  0},
+};
+
+enum {
+	EXCEPTION_COL_ID = 0,
+	EXCEPTION_COL_COUNT,
+	EXCEPTION_COL_PERCENT_COUNT,
+	EXCEPTION_COL_CYCLES,
+	EXCEPTION_COL_PERCENT_CYCLES,
+	EXCEPTION_COL_DESCRIPTION,
+	EXCEPTION_NUM_COLUMNS,
+};
+
+screen_mode_t screen_mode = SCREEN_TABLE;
+static op_mode_t op_mode = OP_TASKS;
+static size_t sort_column = TASK_COL_PERCENT_USER;
+static int sort_reverse = -1;
+static bool excs_all = false;
 
 static const char *read_data(data_t *target)
@@ -67,5 +140,4 @@
 	target->tasks = NULL;
 	target->tasks_perc = NULL;
-	target->tasks_map = NULL;
 	target->threads = NULL;
 	target->exceptions = NULL;
@@ -76,4 +148,9 @@
 	target->ecycles_diff = NULL;
 	target->ecount_diff = NULL;
+	target->table.name = NULL;
+	target->table.num_columns = 0;
+	target->table.columns = NULL;
+	target->table.num_fields = 0;
+	target->table.fields = NULL;
 	
 	/* Get current time */
@@ -117,9 +194,4 @@
 	if (target->tasks_perc == NULL)
 		return "Not enough memory for task utilization";
-	
-	target->tasks_map =
-	    (size_t *) calloc(target->tasks_count, sizeof(size_t));
-	if (target->tasks_map == NULL)
-		return "Not enough memory for task map";
 	
 	/* Get threads */
@@ -289,29 +361,172 @@
 static int cmp_data(void *a, void *b, void *arg)
 {
-	size_t ia = *((size_t *) a);
-	size_t ib = *((size_t *) b);
-	data_t *data = (data_t *) arg;
-	
-	uint64_t acycles = data->ucycles_diff[ia] + data->kcycles_diff[ia];
-	uint64_t bcycles = data->ucycles_diff[ib] + data->kcycles_diff[ib];
-	
-	if (acycles > bcycles)
-		return -1;
-	
-	if (acycles < bcycles)
-		return 1;
-	
+	field_t *fa = (field_t *)a + sort_column;
+	field_t *fb = (field_t *)b + sort_column;
+	
+	if (fa->type > fb->type)
+		return 1 * sort_reverse;
+
+	if (fa->type < fb->type)
+		return -1 * sort_reverse;
+
+	switch (fa->type) {
+	case FIELD_EMPTY:
+		return 0;
+	case FIELD_UINT_SUFFIX_BIN: /* fallthrough */
+	case FIELD_UINT_SUFFIX_DEC: /* fallthrough */
+	case FIELD_UINT:
+		if (fa->uint > fb->uint)
+			return 1 * sort_reverse;
+		if (fa->uint < fb->uint)
+			return -1 * sort_reverse;
+		return 0;
+	case FIELD_PERCENT:
+		if (fa->fixed.upper * fb->fixed.lower
+		    > fb->fixed.upper * fa->fixed.lower)
+			return 1 * sort_reverse;
+		if (fa->fixed.upper * fb->fixed.lower
+		    < fb->fixed.upper * fa->fixed.lower)
+			return -1 * sort_reverse;
+		return 0;
+	case FIELD_STRING:
+		return str_cmp(fa->string, fb->string) * sort_reverse;
+	}
+
 	return 0;
 }
 
-static void sort_data(data_t *data)
-{
-	size_t i;
-	
-	for (i = 0; i < data->tasks_count; i++)
-		data->tasks_map[i] = i;
-	
-	qsort((void *) data->tasks_map, data->tasks_count,
-	    sizeof(size_t), cmp_data, (void *) data);
+static void sort_table(table_t *table)
+{
+	if (sort_column >= table->num_columns)
+		sort_column = 0;
+	/* stable sort is probably best, so we use gsort */
+	gsort((void *) table->fields, table->num_fields / table->num_columns,
+	    sizeof(field_t) * table->num_columns, cmp_data, NULL);
+}
+
+static const char *fill_task_table(data_t *data)
+{
+	data->table.name = "Tasks";
+	data->table.num_columns = TASK_NUM_COLUMNS;
+	data->table.columns = task_columns;
+	data->table.num_fields = data->tasks_count * TASK_NUM_COLUMNS;
+	data->table.fields = calloc(data->table.num_fields,
+	    sizeof(field_t));
+	if (data->table.fields == NULL)
+		return "Not enough memory for table fields";
+
+	field_t *field = data->table.fields;
+	for (size_t i = 0; i < data->tasks_count; i++) {
+		stats_task_t *task = &data->tasks[i];
+		perc_task_t *perc = &data->tasks_perc[i];
+		field[TASK_COL_ID].type = FIELD_UINT;
+		field[TASK_COL_ID].uint = task->task_id;
+		field[TASK_COL_NUM_THREADS].type = FIELD_UINT;
+		field[TASK_COL_NUM_THREADS].uint = task->threads;
+		field[TASK_COL_RESIDENT].type = FIELD_UINT_SUFFIX_BIN;
+		field[TASK_COL_RESIDENT].uint = task->resmem;
+		field[TASK_COL_PERCENT_RESIDENT].type = FIELD_PERCENT;
+		field[TASK_COL_PERCENT_RESIDENT].fixed = perc->resmem;
+		field[TASK_COL_VIRTUAL].type = FIELD_UINT_SUFFIX_BIN;
+		field[TASK_COL_VIRTUAL].uint = task->virtmem;
+		field[TASK_COL_PERCENT_VIRTUAL].type = FIELD_PERCENT;
+		field[TASK_COL_PERCENT_VIRTUAL].fixed = perc->virtmem;
+		field[TASK_COL_PERCENT_USER].type = FIELD_PERCENT;
+		field[TASK_COL_PERCENT_USER].fixed = perc->ucycles;
+		field[TASK_COL_PERCENT_KERNEL].type = FIELD_PERCENT;
+		field[TASK_COL_PERCENT_KERNEL].fixed = perc->kcycles;
+		field[TASK_COL_NAME].type = FIELD_STRING;
+		field[TASK_COL_NAME].string = task->name;
+		field += TASK_NUM_COLUMNS;
+	}
+
+	return NULL;
+}
+
+static const char *fill_ipc_table(data_t *data)
+{
+	data->table.name = "IPC";
+	data->table.num_columns = IPC_NUM_COLUMNS;
+	data->table.columns = ipc_columns;
+	data->table.num_fields = data->tasks_count * IPC_NUM_COLUMNS;
+	data->table.fields = calloc(data->table.num_fields,
+	    sizeof(field_t));
+	if (data->table.fields == NULL)
+		return "Not enough memory for table fields";
+
+	field_t *field = data->table.fields;
+	for (size_t i = 0; i < data->tasks_count; i++) {
+		field[IPC_COL_TASKID].type = FIELD_UINT;
+		field[IPC_COL_TASKID].uint = data->tasks[i].task_id;
+		field[IPC_COL_CLS_SNT].type = FIELD_UINT_SUFFIX_DEC;
+		field[IPC_COL_CLS_SNT].uint = data->tasks[i].ipc_info.call_sent;
+		field[IPC_COL_CLS_RCV].type = FIELD_UINT_SUFFIX_DEC;
+		field[IPC_COL_CLS_RCV].uint = data->tasks[i].ipc_info.call_received;
+		field[IPC_COL_ANS_SNT].type = FIELD_UINT_SUFFIX_DEC;
+		field[IPC_COL_ANS_SNT].uint = data->tasks[i].ipc_info.answer_sent;
+		field[IPC_COL_ANS_RCV].type = FIELD_UINT_SUFFIX_DEC;
+		field[IPC_COL_ANS_RCV].uint = data->tasks[i].ipc_info.answer_received;
+		field[IPC_COL_FORWARD].type = FIELD_UINT_SUFFIX_DEC;
+		field[IPC_COL_FORWARD].uint = data->tasks[i].ipc_info.forwarded;
+		field[IPC_COL_NAME].type = FIELD_STRING;
+		field[IPC_COL_NAME].string = data->tasks[i].name;
+		field += IPC_NUM_COLUMNS;
+	}
+
+	return NULL;
+}
+
+static const char *fill_exception_table(data_t *data)
+{
+	data->table.name = "Exceptions";
+	data->table.num_columns = EXCEPTION_NUM_COLUMNS;
+	data->table.columns = exception_columns;
+	data->table.num_fields = data->exceptions_count *
+	    EXCEPTION_NUM_COLUMNS;
+	data->table.fields = calloc(data->table.num_fields, sizeof(field_t));
+	if (data->table.fields == NULL)
+		return "Not enough memory for table fields";
+
+	field_t *field = data->table.fields;
+	for (size_t i = 0; i < data->exceptions_count; i++) {
+		if (!excs_all && !data->exceptions[i].hot)
+			continue;
+		field[EXCEPTION_COL_ID].type = FIELD_UINT;
+		field[EXCEPTION_COL_ID].uint = data->exceptions[i].id;
+		field[EXCEPTION_COL_COUNT].type = FIELD_UINT_SUFFIX_DEC;
+		field[EXCEPTION_COL_COUNT].uint = data->exceptions[i].count;
+		field[EXCEPTION_COL_PERCENT_COUNT].type = FIELD_PERCENT;
+		field[EXCEPTION_COL_PERCENT_COUNT].fixed = data->exceptions_perc[i].count;
+		field[EXCEPTION_COL_CYCLES].type = FIELD_UINT_SUFFIX_DEC;
+		field[EXCEPTION_COL_CYCLES].uint = data->exceptions[i].cycles;
+		field[EXCEPTION_COL_PERCENT_CYCLES].type = FIELD_PERCENT;
+		field[EXCEPTION_COL_PERCENT_CYCLES].fixed = data->exceptions_perc[i].cycles;
+		field[EXCEPTION_COL_DESCRIPTION].type = FIELD_STRING;
+		field[EXCEPTION_COL_DESCRIPTION].string = data->exceptions[i].desc;
+		field += EXCEPTION_NUM_COLUMNS;
+	}
+
+	/* in case any cold exceptions were ignored */
+	data->table.num_fields = field - data->table.fields;
+
+	return NULL;
+}
+
+static const char *fill_table(data_t *data)
+{
+	if (data->table.fields != NULL) {
+		free(data->table.fields);
+		data->table.fields = NULL;
+	}
+
+	switch (op_mode) {
+	case OP_TASKS:
+		return fill_task_table(data);
+	case OP_IPC:
+		return fill_ipc_table(data);
+	case OP_EXCS:
+		return fill_exception_table(data);
+	}
+	return NULL;
 }
 
@@ -356,4 +571,7 @@
 	if (target->ecount_diff != NULL)
 		free(target->ecount_diff);
+
+	if (target->table.fields != NULL)
+		free(target->table.fields);
 }
 
@@ -367,65 +585,94 @@
 	printf("Reading initial data...\n");
 	
-	if ((ret = read_data(&data_prev)) != NULL)
+	if ((ret = read_data(&data)) != NULL)
 		goto out;
 	
 	/* Compute some rubbish to have initialised values */
-	compute_percentages(&data_prev, &data_prev);
+	compute_percentages(&data, &data);
 	
 	/* And paint screen until death */
 	while (true) {
 		int c = tgetchar(UPDATE_INTERVAL);
-		if (c < 0) {
+
+		if (c < 0) { /* timeout */
+			data_prev = data;
 			if ((ret = read_data(&data)) != NULL) {
-				free_data(&data);
+				free_data(&data_prev);
 				goto out;
 			}
 			
 			compute_percentages(&data_prev, &data);
-			sort_data(&data);
-			print_data(&data);
 			free_data(&data_prev);
-			data_prev = data;
-			
-			continue;
-		}
-		
+
+			c = -1;
+		}
+
+		if (screen_mode == SCREEN_HELP && c >= 0) {
+			if (c == 'h' || c == '?')
+				c = -1;
+			/* go back to table and handle the key */
+			screen_mode = SCREEN_TABLE;
+		}
+
+		if (screen_mode == SCREEN_SORT && c >= 0) {
+			for (size_t i = 0; i < data.table.num_columns; i++) {
+				if (data.table.columns[i].key == c) {
+					sort_column = i;
+					screen_mode = SCREEN_TABLE;
+				}
+			}
+
+			c = -1;
+		}
+
 		switch (c) {
-			case 't':
-				print_warning("Showing task statistics");
-				op_mode = OP_TASKS;
+		case -1: /* do nothing */
+			break;
+		case 't':
+			op_mode = OP_TASKS;
+			break;
+		case 'i':
+			op_mode = OP_IPC;
+			break;
+		case 'e':
+			op_mode = OP_EXCS;
+			break;
+		case 's':
+			screen_mode = SCREEN_SORT;
+			break;
+		case 'r':
+			sort_reverse = -sort_reverse;
+			break;
+		case 'h':
+		case '?':
+			screen_mode = SCREEN_HELP;
+			break;
+		case 'q':
+			goto out;
+		case 'a':
+			if (op_mode == OP_EXCS) {
+				excs_all = !excs_all;
+				if (excs_all)
+					show_warning("Showing all exceptions");
+				else
+					show_warning("Showing only hot exceptions");
 				break;
-			case 'i':
-				print_warning("Showing IPC statistics");
-				op_mode = OP_IPC;
-				break;
-			case 'e':
-				print_warning("Showing exception statistics");
-				op_mode = OP_EXCS;
-				break;
-			case 'h':
-				print_warning("Showing help");
-				op_mode = OP_HELP;
-				break;
-			case 'q':
-				goto out;
-			case 'a':
-				if (op_mode == OP_EXCS) {
-					excs_all = !excs_all;
-					if (excs_all)
-						print_warning("Showing all exceptions");
-					else
-						print_warning("Showing only hot exceptions");
-					break;
-				}
-			default:
-				print_warning("Unknown command \"%c\", use \"h\" for help", c);
-				break;
-		}
+			}
+			/* fallthrough */
+		default:
+			show_warning("Unknown command \"%c\", use \"h\" for help", c);
+			continue; /* don't redraw */
+		}
+
+		if ((ret = fill_table(&data)) != NULL) {
+			goto out;
+		}
+		sort_table(&data.table);
+		print_data(&data);
 	}
 	
 out:
 	screen_done();
-	free_data(&data_prev);
+	free_data(&data);
 	
 	if (ret != NULL) {
Index: uspace/app/top/top.h
===================================================================
--- uspace/app/top/top.h	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/top/top.h	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -51,17 +51,10 @@
 
 typedef enum {
-	OP_TASKS,
-	OP_IPC,
-	OP_EXCS,
-	OP_HELP
-} op_mode_t;
+	SCREEN_TABLE,
+	SCREEN_SORT,
+	SCREEN_HELP,
+} screen_mode_t;
 
-typedef enum {
-	SORT_TASK_CYCLES
-} sort_mode_t;
-
-extern op_mode_t op_mode;
-extern sort_mode_t sort_mode;
-extern bool excs_all;
+extern screen_mode_t screen_mode;
 
 typedef struct {
@@ -87,4 +80,32 @@
 } perc_exc_t;
 
+typedef enum {
+	FIELD_EMPTY, FIELD_UINT, FIELD_UINT_SUFFIX_BIN, FIELD_UINT_SUFFIX_DEC,
+	FIELD_PERCENT, FIELD_STRING
+} field_type_t;
+
+typedef struct {
+	field_type_t type;
+	union {
+		fixed_float fixed;
+		uint64_t uint;
+		const char *string;
+	};
+} field_t;
+
+typedef struct {
+	const char *name;
+	char key;
+	int width;
+} column_t;
+
+typedef struct {
+	const char *name;
+	size_t num_columns;
+	const column_t *columns;
+	size_t num_fields;
+	field_t *fields;
+} table_t;
+
 typedef struct {
 	time_t hours;
@@ -107,5 +128,4 @@
 	stats_task_t *tasks;
 	perc_task_t *tasks_perc;
-	size_t *tasks_map;
 	
 	size_t threads_count;
@@ -122,4 +142,6 @@
 	uint64_t *ecycles_diff;
 	uint64_t *ecount_diff;
+
+	table_t table;
 } data_t;
 
Index: uspace/app/websrv/websrv.c
===================================================================
--- uspace/app/websrv/websrv.c	(revision 06a1d07797fc4e18922cbd44b9d0ee795f27b1ad)
+++ uspace/app/websrv/websrv.c	(revision b1213b0d019ee5b8bf4ee139ae99b9a3fdf827a0)
@@ -200,5 +200,5 @@
 {
 	if (str_cmp(uri, "/") == 0)
-		uri = "/index.htm";
+		uri = "/index.html";
 	
 	char *fname;
