Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 7570e80086a542f15630c4997dbb37e9720c123f)
+++ uspace/Makefile	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
@@ -41,4 +41,5 @@
 	app/edit \
 	app/getterm \
+	app/hdisk \
 	app/init \
 	app/inet \
@@ -219,4 +220,5 @@
 	lib/bithenge \
 	lib/posix \
+	lib/mbr \
 	lib/gpt
 
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 7570e80086a542f15630c4997dbb37e9720c123f)
+++ uspace/Makefile.common	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
@@ -133,7 +133,8 @@
 LIBSCSI_PREFIX = $(LIB_PREFIX)/scsi
 
+LIBBITHENGE_PREFIX = $(LIB_PREFIX)/bithenge
+
+LIBMBR_PREFIX = $(LIB_PREFIX)/mbr
 LIBGPT_PREFIX = $(LIB_PREFIX)/gpt
-
-LIBBITHENGE_PREFIX = $(LIB_PREFIX)/bithenge
 
 ifeq ($(STATIC_NEEDED),y)
Index: uspace/lib/c/generic/checksum.c
===================================================================
--- uspace/lib/c/generic/checksum.c	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
+++ uspace/lib/c/generic/checksum.c	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2012 Dominik Taborsky
+ * 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 <checksum.h>
+
+/** This is 256-value table of precomputed polynomials for CRC32. Note
+ *  the values depend on the selected divisor polynomial (currently
+ *  0xedb88320) and whether the CRC computation is reflected or not.
+ *  See http://www.repairfaq.org/filipg/LINK/F_crc_v3.html for a perfect
+ *  source of info about this.
+ */
+uint32_t poly_table[256] =
+{
+	0,			0x77073096, 0xEE0E612C, 0x990951BA,
+	0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+	0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+	0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+	0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+	0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+	0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+	0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+	0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+	0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+	0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+	0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+	0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+	0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+	0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+	0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+	0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+	0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+	0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+	0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+	0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+	0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+	0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+	0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+	0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+	0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+	0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+	0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+	0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+	0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+	0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+	0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+	0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+	0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+	0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+	0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+	0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+	0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+	0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+	0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+	0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+	0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+	0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+	0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+	0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+	0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+	0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+	0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+	0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+	0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+	0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+	0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+	0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+	0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+	0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+	0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+	0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+	0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+	0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+	0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+	0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+	0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+	0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+	0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+/** Computes CRC32 value.
+ * @param[in] data		Pointer to the beginning of data to process.
+ * @param[in] length	Length of the data in bytes.
+ * 
+ * @return		The computed CRC32 of the data.
+ * 
+ * Note: see wiki.osdev.org/CRC32 for reference.
+ */
+uint32_t compute_crc32(uint8_t * data, size_t length)
+{
+	uint32_t seed = 0x0;
+	
+	return compute_crc32_seed(data, length, seed);
+}
+
+/** Computes CRC32 value with initial seed.
+ * Use this when checksumming not continous data (linked lists, trees,
+ * etc.). On the first data block call compute_crc32() and use the result
+ * as the seed for the following call of compute_crc32_seed() on the next
+ * block. Then use the result of that call as the seed of the following
+ * call, etc. 
+ * 
+ * @param[in] data		Pointer to the beginning of data to process.
+ * @param[in] length	Length of the data in bytes.
+ * @param[in] seed		The starting value of the CRC.
+ * 
+ * @return		The computed CRC32 of the data of all the previous
+ * 				blocks together.
+ * 
+ */
+uint32_t compute_crc32_seed(uint8_t * data, size_t length, uint32_t seed)
+{
+	uint32_t crc = ~seed;
+	for (;length !=0; --length)
+		crc = poly_table[((uint8_t) crc ^ *(data++))] ^ (crc >> 8);
+
+	return (~crc);
+}
+
+/** @}
+ */
Index: uspace/lib/c/include/checksum.h
===================================================================
--- uspace/lib/c/include/checksum.h	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
+++ uspace/lib/c/include/checksum.h	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012 Dominik Taborsky
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_CHECKSUM_H_
+#define LIBC_CHECKSUM_H_
+
+#include <sys/types.h>
+
+extern uint32_t compute_crc32(uint8_t *, size_t);
+extern uint32_t compute_crc32_seed(uint8_t *, size_t, uint32_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/gpt/libgpt.c
===================================================================
--- uspace/lib/gpt/libgpt.c	(revision 7570e80086a542f15630c4997dbb37e9720c123f)
+++ uspace/lib/gpt/libgpt.c	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Dominik Taborsky
+ * Copyright (c) 2011, 2012, 2013 Dominik Taborsky
  * All rights reserved.
  *
Index: uspace/lib/gpt/libgpt.h
===================================================================
--- uspace/lib/gpt/libgpt.h	(revision 7570e80086a542f15630c4997dbb37e9720c123f)
+++ uspace/lib/gpt/libgpt.h	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009 Jiri Svoboda, 2011 Dominik Taborsky
+ * Copyright (c) 2009 Jiri Svoboda, 2011, 2012, 2013 Dominik Taborsky
  * All rights reserved.
  *
Index: uspace/lib/mbr/Makefile
===================================================================
--- uspace/lib/mbr/Makefile	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
+++ uspace/lib/mbr/Makefile	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2011 Dominik Taborsky
+# 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 = ../..
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX)
+LIBRARY = libmbr
+
+SOURCES = \
+	libmbr.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/mbr/libmbr.c
===================================================================
--- uspace/lib/mbr/libmbr.c	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
+++ uspace/lib/mbr/libmbr.c	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 2011, 2012, 2013 Dominik Taborsky
+ * 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 libmbr
+ * @{
+ */
+/** @file MBR extraxtion library
+ */
+
+#include <ipc/bd.h>
+#include <async.h>
+#include <stdio.h>
+#include <block.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <byteorder.h>
+
+#include "libmbr.h"
+
+static br_block_t * alloc_br(void);
+static int decode_part(pt_entry_t * src, part_t * trgt, uint32_t base);
+static int decode_logical(mbr_t * mbr, mbr_parts_t * p, part_t * ext);
+static void encode_part(part_t * src, pt_entry_t * trgt, uint32_t base);
+
+/** Read MBR from specific device
+ * @param	dev_handle	device to read MBR from
+ *
+ * @return				mbr record on success, NULL on error
+ */
+mbr_t * mbr_read_mbr(service_id_t dev_handle)
+{
+	int rc;
+
+	mbr_t * mbr = malloc(sizeof(mbr_t));
+	if (mbr == NULL) {
+		return NULL;
+	}
+
+	rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
+	if (rc != EOK) {
+		return NULL;
+	}
+
+	rc = block_read_direct(dev_handle, 0, 1, &(mbr->raw_data));
+	if (rc != EOK) {
+		block_fini(dev_handle);
+		return NULL;
+	}
+
+	block_fini(dev_handle);
+
+	mbr->device = dev_handle;
+	//mbr->partitions = NULL;
+
+	return mbr;
+}
+
+/** Write mbr to disk
+ * @param mbr			MBR to be written
+ * @param dev_handle	device handle to write MBR to (may be different
+ * 							from the device in 'mbr')
+ *
+ * @return				0 on success, -1 on block_init error, -2 on write error
+ */
+int mbr_write_mbr(mbr_t * mbr, service_id_t dev_handle)
+{
+	int rc;
+
+	rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data));
+	block_fini(dev_handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	return 0;
+}
+
+/** Decide whether this is an actual MBR or a Protective MBR from GPT
+ *
+ * @param mbr		the actual MBR to decide upon
+ *
+ * @return			1 if MBR, 0 if GPT
+ */
+int mbr_is_mbr(mbr_t * mbr)
+{
+	return (mbr->raw_data.pte[0].ptype != PT_GPT) ? 1 : 0;
+}
+
+/** Parse partitions from MBR
+ * @param mbr	MBR to be parsed
+ *
+ * @return 		linked list of partitions or NULL on error
+ */
+mbr_parts_t * mbr_read_partitions(mbr_t * mbr)
+{
+	int rc, i;
+	part_t * p;
+	part_t * ext = NULL;
+	mbr_parts_t * parts;
+
+	if (mbr == NULL)
+		return NULL;
+
+	parts = mbr_alloc_partitions();
+	if (parts == NULL) {
+		return NULL;
+	}
+
+	// Generate the primary partitions
+	for (i = 0; i < N_PRIMARY; ++i) {
+		if (mbr->raw_data.pte[i].ptype == PT_UNUSED)
+			continue;
+		
+		p = malloc(sizeof(part_t));
+		if (p == NULL) {
+			printf(NAME ": Error on memory allocation.\n");
+			free(p);
+			mbr_free_partitions(parts);
+			return NULL;
+		}
+		list_append(&(p->link), &(parts->list));
+		p->ebr = NULL;
+		if (decode_part(&(mbr->raw_data.pte[i]), p, 0))
+			ext = p;
+	}
+
+	// Fill in the primary partitions and generate logical ones, if any
+	rc = decode_logical(mbr, parts, ext);
+	if (rc != EOK) {
+		printf(NAME ": Error occured during decoding the MBR.\n" \
+			   NAME ": Partition list may be incomplete.\n");
+	}
+
+	return parts;
+}
+
+/** Write MBR and partitions to device
+ * @param parts			partition list to be written
+ * @param mbr			MBR to be written with 'parts' partitions
+ * @param dev_handle	device to write the data to
+ *
+ * @return				returns EOK on succes, specific error code otherwise
+ */
+int mbr_write_partitions(mbr_parts_t * parts, mbr_t * mbr, service_id_t dev_handle)
+{
+	bool logical = false;
+	int i = 0;
+	int rc;
+	part_t * p;
+	part_t * ext = (parts->l_extended == NULL) ? NULL
+					: list_get_instance(parts->l_extended, part_t, link);
+	
+	br_block_t * last_ebr = NULL;
+
+
+	rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (ext == NULL)
+		goto no_extended;
+
+	aoff64_t addr = ext->start_addr;
+	part_t * prev_part = NULL;
+
+	list_foreach(parts->list, it) {
+		p = list_get_instance(it, part_t, link);
+		if (mbr_get_flag(p, ST_LOGIC)) {
+			// writing logical partition
+
+			if (p->ebr == NULL) {
+				p->ebr = alloc_br();
+				if (p->ebr == NULL)
+				{
+					rc = ENOMEM;
+					goto end;
+				}
+			}
+
+
+			encode_part(p, &(p->ebr->pte[0]), addr);
+			if (prev_part != NULL) {
+				encode_part(p, &(prev_part->ebr->pte[1]), ext->start_addr);
+				rc = block_write_direct(dev_handle, p->start_addr, 1, prev_part->ebr);
+				if (rc != EOK)
+					goto end;
+			}
+			
+			addr = p->start_addr;
+			prev_part = p;
+		} else {
+			// writing primary partition
+			if (i >= 4) {
+				rc = EINVAL;
+				goto end;
+			}
+
+			encode_part(p, &(mbr->raw_data.pte[i]), 0);
+
+			++i;
+		}
+	}
+
+	/* If there was an extended but no logical, we should overwrite
+	 * the space where the first logical's EBR would have been. There
+	 * might be some garbage from the past.
+	 */
+	
+	last_ebr = prev_part->ebr;
+	
+	if (!logical)
+	{
+		last_ebr = alloc_br();
+		if (last_ebr == NULL) {
+			rc = ENOMEM;
+			goto end;
+		}
+		
+		last_ebr->pte[0].ptype = PT_UNUSED;
+	}
+	
+	
+	encode_part(NULL, &(last_ebr->pte[1]), 0);
+	rc = block_write_direct(dev_handle, addr, 1, last_ebr);
+	
+	if (!logical)
+	{
+		free(last_ebr);
+	}
+	
+	if (rc != EOK)
+		goto end;
+
+	goto skip;
+
+no_extended:
+
+	list_foreach(parts->list, it) {
+		p = list_get_instance(it, part_t, link);
+		if (mbr_get_flag(p, ST_LOGIC)) {
+			// extended does not exist, fail
+			return EINVAL;
+		} else {
+			// writing primary partition
+			if (i >= 4)
+				return EINVAL;
+
+			encode_part(p, &(mbr->raw_data.pte[i]), 0);
+
+			++i;
+		}
+	}
+
+skip:
+	rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data));
+	if (rc != EOK)
+		goto end;
+
+	/*
+	for (i = 0; i < N_PRIMARY; ++i) {
+		encode_part(&(p->partition), &(mbr->raw_data.pte[i]), 0);
+		if (p->type == PT_EXTENDED)
+			ext = p;
+
+		//p = list_get_instance(p->link.next, mbr_parts_t, link);
+		p = p->next;
+	}
+
+	rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data));
+	if (rc != EOK) {
+		block_fini(dev_handle);
+		return rc;
+	}
+
+	//writing logical partitions
+
+	if (p == NULL && ext != NULL) {
+		//we need an empty EBR to rewrite the old EBR on disk, if we need to delete it
+		br_block_t * temp_ebr = alloc_br();
+		if (temp_ebr == NULL) {
+			block_fini(dev_handle);
+			return ENOMEM;
+		}
+
+		temp_ebr->pte[0].ptype = PT_UNUSED;
+		encode_part(NULL, &(temp_ebr->pte[1]), 0);
+		rc = block_write_direct(dev_handle, ext->start_addr, 1, temp_ebr);
+		free(temp_ebr);
+		block_fini(dev_handle);
+		return rc;
+	}
+
+	if (p != NULL && ext == NULL) {
+		block_fini(dev_handle);
+		//no extended but one or more logical? EINVAL to the rescue!
+		return EINVAL;
+	}
+
+	aoff64_t addr = ext->start_addr;
+
+	while (p != NULL) {
+		if (p->type == PT_UNUSED) {
+			p = p->next;
+			continue;
+		}
+		//encode_part(p, &(p->ebr->pte[0]), p->start_addr - 63 * 512);
+		encode_part(p, &(p->ebr->pte[0]), addr);
+		encode_part(p->next, &(p->ebr->pte[1]), ext->start_addr);
+
+		rc = block_write_direct(dev_handle, p->start_addr, 1, p->ebr);
+		if (rc != EOK) {
+			block_fini(dev_handle);
+			return rc;
+		}
+		addr = p->start_addr;
+		p = p->next;
+	}*/
+
+	rc = EOK;
+	
+end:
+	block_fini(dev_handle);
+
+	return rc;
+}
+
+/** part_t constructor */
+part_t * mbr_alloc_partition(void)
+{
+	part_t * p = malloc(sizeof(part_t));
+	if (p == NULL) {
+		return NULL;
+	}
+	link_initialize(&(p->link));
+	p->ebr = NULL;
+	p->type = 0;
+	p->status = 0;
+	p->start_addr = 0;
+	p->length = 0;
+
+	return p;
+}
+
+mbr_parts_t * mbr_alloc_partitions(void)
+{
+	mbr_parts_t * parts = malloc(sizeof(mbr_parts_t));
+	if (parts == NULL) {
+		return NULL;
+	}
+
+	list_initialize(&(parts->list));
+
+	return parts;
+}
+
+/** Add partition */
+void mbr_add_partition(mbr_parts_t * parts, part_t * partition)
+{
+	list_append(&(partition->link), &(parts->list));
+}
+
+/** Remove partition */
+void mbr_remove_partition(mbr_parts_t * parts, int idx)
+{
+	link_t * l = list_nth(&(parts->list), idx);
+	list_remove(l);
+	part_t * p = list_get_instance(l, part_t, link);
+	mbr_free_partition(p);
+}
+
+/** part_t destructor */
+void mbr_free_partition(part_t * p)
+{
+	if (p->ebr != NULL)
+		free(p->ebr);
+	free(p);
+}
+
+/** Get flag bool value */
+int mbr_get_flag(part_t * p, MBR_FLAGS flag)
+{
+	return (p->status & (1 << flag)) ? 1 : 0;
+}
+
+/** Set a specifig status flag to a value */
+void mbr_set_flag(part_t * p, MBR_FLAGS flag, bool value)
+{
+	uint8_t status = p->status;
+
+	if (value)
+		status = status | (1 << flag);
+	else
+		status = status ^ (status & (1 << flag));
+
+	p->status = status;
+}
+
+/** Just a wrapper for free() */
+void mbr_free_mbr(mbr_t * mbr)
+{
+	free(mbr);
+}
+
+/** Free partition list
+ *
+ * @param parts		partition list to be freed
+ */
+void mbr_free_partitions(mbr_parts_t * parts)
+{
+	list_foreach_safe(parts->list, cur_link, next) {
+		part_t * p = list_get_instance(cur_link, part_t, link);
+		list_remove(cur_link);
+		mbr_free_partition(p);
+	}
+}
+
+// Internal functions follow //
+
+static br_block_t * alloc_br()
+{
+	br_block_t * br = malloc(sizeof(br_block_t));
+	if (br == NULL)
+		return NULL;
+
+	br->media_id = 0;
+	br->pad0 = 0;
+	br->signature = host2uint16_t_le(BR_SIGNATURE);
+
+	return br;
+}
+
+/** Parse partition entry to part_t */
+static int decode_part(pt_entry_t * src, part_t * trgt, uint32_t base)
+{
+	trgt->type = src->ptype;
+
+	/* Checking only 0x80; otherwise writing will fix to 0x00 */
+	//trgt->bootable = (src->status == B_ACTIVE) ? true : false;
+	mbr_set_flag(trgt, ST_BOOT, (src->status == B_ACTIVE) ? true : false);
+
+	trgt->start_addr = uint32_t_le2host(src->first_lba) + base;
+	trgt->length = uint32_t_le2host(src->length);
+
+	return (src->ptype == PT_EXTENDED) ? 1 : 0;
+}
+
+/** Parse MBR contents to part_t list
+ * parameter 'p' is allocated for only used primary partitions
+ */
+static int decode_logical(mbr_t * mbr, mbr_parts_t * parts, part_t * ext)
+{
+	int rc;
+	part_t * p;
+
+	if (mbr == NULL || parts == NULL)
+		return EINVAL;
+
+
+	if (ext == NULL)
+		return EOK;
+
+
+	uint32_t addr = ext->start_addr;
+	//uint32_t base = ext->start_addr;
+	br_block_t * ebr;
+
+	rc = block_init(EXCHANGE_ATOMIC, mbr->device, 512);
+	if (rc != EOK)
+		return rc;
+
+	do {
+		ebr = alloc_br();
+		if (ebr == NULL) {
+			return ENOMEM;
+		}
+
+		rc = block_read_direct(mbr->device, addr, 1, ebr);
+		if (rc != EOK) {
+			return rc;
+		}
+
+		//FIXME: is this the right way?
+		if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) {
+			return EINVAL;
+		}
+
+		p = mbr_alloc_partition();
+
+		decode_part(&(ebr->pte[0]), p, addr);
+		mbr_set_flag(p, ST_LOGIC, true);
+		p->ebr = ebr;
+		mbr_add_partition(parts, p);
+
+		//TODO: Check this code
+		addr = ebr->pte[1].first_lba + ext->start_addr;
+	} while (ebr->pte[1].ptype != PT_UNUSED);
+
+
+	block_fini(mbr->device);
+
+	return EOK;
+}
+
+/** Convert part_t to pt_entry_t */
+static void encode_part(part_t * src, pt_entry_t * trgt, uint32_t base)
+{
+	if (src != NULL) {
+		trgt->status = mbr_get_flag(src, ST_BOOT) ? B_ACTIVE : B_INACTIVE;
+		trgt->ptype = src->type;
+		trgt->first_lba = host2uint32_t_le(src->start_addr - base + 63); //63 sectors skipped
+		trgt->length = host2uint32_t_le(src->length - 64);	//63 + 1 (EBR)
+	} else {
+		trgt->status = 0;
+		trgt->first_chs[0] = 0;
+		trgt->first_chs[1] = 0;
+		trgt->first_chs[2] = 0;
+		trgt->ptype = 0;
+		trgt->last_chs[0] = 0;
+		trgt->last_chs[1] = 0;
+		trgt->last_chs[2] = 0;
+		trgt->first_lba = 0;
+		trgt->length = 0;
+	}
+}
+
Index: uspace/lib/mbr/libmbr.h
===================================================================
--- uspace/lib/mbr/libmbr.h	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
+++ uspace/lib/mbr/libmbr.h	(revision 5beb1ff28ca0095f6ff9e09ade3782654e79f764)
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2011, 2012, 2013 Dominik Taborsky
+ * 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 libmbr
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBMBR_LIBMBR_H_
+#define LIBMBR_LIBMBR_H_
+
+#define NAME	"libmbr"
+
+/** Number of primary partition records */
+#define N_PRIMARY		4
+
+/** Boot record signature */
+#define BR_SIGNATURE	0xAA55
+
+enum {
+	/** Non-bootable */
+	B_INACTIVE = 0x00,
+	/** Bootable */
+	B_ACTIVE = 0x80,
+	/** Anything else means invalid */
+};
+
+typedef enum {
+	/** Bootability */
+	ST_BOOT = 0,
+	/** Logical partition, 0 = primary, 1 = logical*/
+	ST_LOGIC = 1
+} MBR_FLAGS;
+
+enum {
+	/** Unused partition entry */
+	PT_UNUSED	= 0x00,
+	/** Extended partition */
+	PT_EXTENDED	= 0x05,
+	/** GPT Protective partition */
+	PT_GPT	= 0xEE,
+};
+
+/** Structure of a partition table entry */
+typedef struct {
+	uint8_t status;
+	/** CHS of fist block in partition */
+	uint8_t first_chs[3];
+	/** Partition type */
+	uint8_t ptype;
+	/** CHS of last block in partition */
+	uint8_t last_chs[3];
+	/** LBA of first block in partition */
+	uint32_t first_lba;
+	/** Number of blocks in partition */
+	uint32_t length;
+} __attribute__((packed)) pt_entry_t;
+
+/** Structure of a boot-record block */
+typedef struct {
+	/** Area for boot code */
+	uint8_t code_area[440];
+	/** Optional media ID */
+	uint32_t media_id;
+	/** Padding */
+	uint16_t pad0;
+	/** Partition table entries */
+	pt_entry_t pte[N_PRIMARY];
+	/** Boot record block signature (@c BR_SIGNATURE) */
+	uint16_t signature;
+} __attribute__((packed)) br_block_t;
+
+/** MBR header */
+typedef struct {
+	/** Raw access to data */
+	br_block_t raw_data;
+	/** Device where the data are from */
+	service_id_t device;
+	/** Pointer to partition list */
+	//list of partitions;	//if we keep this in here, we should free() it in mbr_free_mbr()
+} mbr_t;
+
+
+//FIXME: make mbr_parts_t as the linked list for keeping the same interface as with GPT
+/** Partition */
+typedef struct part {
+	/** The link in the doubly-linked list */
+	link_t link;
+	/** Partition type */
+	uint8_t type;
+	/** Flags */
+	uint8_t status;
+	/** Address of first block */
+	aoff64_t start_addr;
+	/** Number of blocks */
+	aoff64_t length;
+	/** Points to Extended Boot Record of logical partition */
+	br_block_t * ebr;
+} part_t;
+
+typedef struct mbr_parts {
+	/** Number of primary partitions */
+	unsigned char n_primary;
+	/** Link to the extended partition in the list */
+	link_t * l_extended;
+	/** Number of logical partitions */
+	unsigned int n_logical;
+	/** Partition linked list */
+	list_t list;
+} mbr_parts_t;
+
+
+/** Read/Write MBR header.
+ * WARNING: when changing both header and partitions, write first header,
+ * then partitions. The MBR headers' raw_data is NOT updated to follow
+ * partition changes. */
+extern mbr_t * mbr_read_mbr(service_id_t dev_handle);
+extern int mbr_write_mbr(mbr_t * mbr, service_id_t dev_handle);
+extern int mbr_is_mbr(mbr_t * mbr);
+
+/** Read/Write/Set MBR partitions. */
+extern mbr_parts_t * mbr_read_partitions(mbr_t * mbr);
+extern int 			 mbr_write_partitions(mbr_parts_t * parts, mbr_t * mbr, service_id_t dev_handle);
+extern part_t *		 mbr_alloc_partition(void);
+extern mbr_parts_t * mbr_alloc_partitions(void);
+extern void			 mbr_add_partition(mbr_parts_t * parts, part_t * partition);
+extern void			 mbr_remove_partition(mbr_parts_t * parts, int idx);
+extern int			 mbr_get_flag(part_t * p, MBR_FLAGS flag);
+extern void			 mbr_set_flag(part_t * p, MBR_FLAGS flag, bool value);
+
+#define mbr_part_foreach(parts, iterator)	\
+			list_foreach(parts->list, iterator)
+
+/** free() wrapper functions. */
+extern void mbr_free_mbr(mbr_t * mbr);
+extern void mbr_free_partition(part_t * p);
+extern void mbr_free_partitions(mbr_parts_t * parts);
+
+#endif
+
