Index: uspace/lib/gpt/global.c
===================================================================
--- uspace/lib/gpt/global.c	(revision 256cbfe514223bde4eeeb03138267ab8192ed09b)
+++ uspace/lib/gpt/global.c	(revision 256cbfe514223bde4eeeb03138267ab8192ed09b)
@@ -0,0 +1,106 @@
+/*
+ * 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 libgpt
+ * @{
+ */
+/** @file
+ */
+
+#include "libgpt.h"
+
+/** GPT header signature ("EFI PART" in ASCII) */
+const uint8_t efi_signature[8] = {
+	0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54
+};
+
+const struct partition_type gpt_ptypes[] = {
+	{ "Unused entry",					"00000000-0000-0000-0000-000000000000" },
+	{ "MBR partition scheme",			"024DEE41-33E7-11D3-9D69-0008C781F39F" },
+	{ "EFI System",						"C12A7328-F81F-11D2-BA4B-00A0C93EC93B" },
+	{ "BIOS Boot",						"21686148-6449-6E6F-744E-656564454649" },
+	{ "Windows Reserved",				"E3C9E316-0B5C-4DB8-817D-F92DF00215AE" },
+	{ "Windows Basic data",				"EBD0A0A2-B9E5-4433-87C0-68B6B72699C7" },
+	{ "Windows LDM metadata", 			"5808C8AA-7E8F-42E0-85D2-E1E90434CFB3" },
+	{ "Windows LDM data", 				"AF9B60A0-1431-4F62-BC68-3311714A69AD" },
+	{ "Windows Recovery Environment",	"DE94BBA4-06D1-4D40-A16A-BFD50179D6AC" },
+	{ "Windows IBM GPFS",				"37AFFC90-EF7D-4E96-91C3-2D7AE055B174" },
+	{ "Windows Cluster metadata",		"DB97DBA9-0840-4BAE-97F0-FFB9A327C7E1" },
+	{ "HP-UX Data",						"75894C1E-3AEB-11D3-B7C1-7B03A0000000" },
+	{ "HP-UX Service",					"E2A1E728-32E3-11D6-A682-7B03A0000000" },
+	{ "Linux filesystem data",			"EBD0A0A2-B9E5-4433-87C0-68B6B72699C7" },
+	{ "Linux filesystem data",			"0FC63DAF-8483-4772-8E79-3D69D8477DE4" },
+	{ "Linux RAID",						"A19D880F-05FC-4D3B-A006-743F0F84911E" },
+	{ "Linux Swap",						"0657FD6D-A4AB-43C4-84E5-0933C84B4F4F" },
+	{ "Linux LVM",						"E6D6D379-F507-44C2-A23C-238F2A3DF928" },
+	{ "Linux Reserved",					"8DA63339-0007-60C0-C436-083AC8230908" },
+	{ "FreeBSD Boot",					"83BD6B9D-7F41-11DC-BE0B-001560B84F0F" },
+	{ "FreeBSD Data",					"516E7CB4-6ECF-11D6-8FF8-00022D09712B" },
+	{ "FreeBSD Swap",					"516E7CB5-6ECF-11D6-8FF8-00022D09712B" },
+	{ "FreeBSD UFS", 					"516E7CB6-6ECF-11D6-8FF8-00022D09712B" },
+	{ "FreeBSD Vinum VM",				"516E7CB8-6ECF-11D6-8FF8-00022D09712B" },
+	{ "FreeBSD ZFS",					"516E7CBA-6ECF-11D6-8FF8-00022D09712B" },
+	{ "Mac OS X HFS+",					"48465300-0000-11AA-AA11-00306543ECAC" },
+	{ "Mac OS X UFS",					"55465300-0000-11AA-AA11-00306543ECAC" },
+	{ "Mac OS X ZFS",					"6A898CC3-1DD2-11B2-99A6-080020736631" },
+	{ "Mac OS X RAID",					"52414944-0000-11AA-AA11-00306543ECAC" },
+	{ "Mac OS X RAID, offline",			"52414944-5F4F-11AA-AA11-00306543ECAC" },
+	{ "Mac OS X Boot",					"426F6F74-0000-11AA-AA11-00306543ECAC" },
+	{ "Mac OS X Label",					"4C616265-6C00-11AA-AA11-00306543ECAC" },
+	{ "Mac OS X TV Recovery",			"5265636F-7665-11AA-AA11-00306543ECAC" },
+	{ "Mac OS X Core Storage",			"53746F72-6167-11AA-AA11-00306543ECAC" },
+	{ "Solaris Boot",					"6A82CB45-1DD2-11B2-99A6-080020736631" },
+	{ "Solaris Root",					"6A85CF4D-1DD2-11B2-99A6-080020736631" },
+	{ "Solaris Swap",					"6A87C46F-1DD2-11B2-99A6-080020736631" },
+	{ "Solaris Backup",					"6A8B642B-1DD2-11B2-99A6-080020736631" },
+	{ "Solaris /usr",					"6A898CC3-1DD2-11B2-99A6-080020736631" },
+	{ "Solaris /var",					"6A8EF2E9-1DD2-11B2-99A6-080020736631" },
+	{ "Solaris /home",					"6A90BA39-1DD2-11B2-99A6-080020736631" },
+	{ "Solaris Alternate sector",		"6A9283A5-1DD2-11B2-99A6-080020736631" },
+	{ "Solaris Reserved",				"6A945A3B-1DD2-11B2-99A6-080020736631" },
+	{ "Solaris Reserved",				"6A9630D1-1DD2-11B2-99A6-080020736631" },
+	{ "Solaris Reserved",				"6A980767-1DD2-11B2-99A6-080020736631" },
+	{ "Solaris Reserved",				"6A96237F-1DD2-11B2-99A6-080020736631" },
+	{ "Solaris Reserved",				"6A8D2AC7-1DD2-11B2-99A6-080020736631" },
+	{ "NetBSD Swap",					"49F48D32-B10E-11DC-B99B-0019D1879648" },
+	{ "NetBSD FFS",						"49F48D5A-B10E-11DC-B99B-0019D1879648" },
+	{ "NetBSD LFS",						"49F48D82-B10E-11DC-B99B-0019D1879648" },
+	{ "NetBSD RAID",					"49F48DAA-B10E-11DC-B99B-0019D1879648" },
+	{ "NetBSD Concatenated",			"2DB519C4-B10F-11DC-B99B-0019D1879648" },
+	{ "NetBSD Encrypted",				"2DB519EC-B10F-11DC-B99B-0019D1879648" },
+	{ "ChromeOS ChromeOS kernel",		"FE3A2A5D-4F32-41A7-B725-ACCC3285A309" },
+	{ "ChromeOS rootfs",				"3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC" },
+	{ "ChromeOS future use",			"2E0A753D-9E48-43B0-8337-B15192CB1B5E" },
+	{ "MidnightBSD Boot",				"85D5E45E-237C-11E1-B4B3-E89A8F7FC3A7" },
+	{ "MidnightBSD Data",				"85D5E45A-237C-11E1-B4B3-E89A8F7FC3A7" },
+	{ "MidnightBSD Swap",				"85D5E45B-237C-11E1-B4B3-E89A8F7FC3A7" },
+	{ "MidnightBSD UFS",				"0394Ef8B-237E-11E1-B4B3-E89A8F7FC3A7" },
+	{ "MidnightBSD Vinum VM",			"85D5E45C-237C-11E1-B4B3-E89A8F7FC3A7" },
+	{ "MidnightBSD ZFS",				"85D5E45D-237C-11E1-B4B3-E89A8F7FC3A7" },
+	{ "Uknown", NULL}	// keep this as the last one! gpt_get_part_type depends on it!
+};
Index: uspace/lib/gpt/libgpt.c
===================================================================
--- uspace/lib/gpt/libgpt.c	(revision 271e24a4aca586ebdc97458d9836e0a3a3e1038c)
+++ uspace/lib/gpt/libgpt.c	(revision 256cbfe514223bde4eeeb03138267ab8192ed09b)
@@ -117,4 +117,6 @@
  * 
  * @return				0 on success, libblock error code otherwise
+ * 
+ * Note: Firstly write partitions (if changed), then gpt header.
  */
 int gpt_write_gpt_header(gpt_t * gpt, service_id_t dev_handle)
@@ -167,9 +169,9 @@
 	unsigned int i;
 	gpt_partitions_t * res;
-	uint32_t num_ent = uint32_t_le2host(gpt->raw_data->num_entries);
+	uint32_t fill = uint32_t_le2host(gpt->raw_data->fillries);
 	uint32_t ent_size = uint32_t_le2host(gpt->raw_data->entry_size);
 	uint64_t ent_lba = uint64_t_le2host(gpt->raw_data->entry_lba);
 	
-	res = alloc_part_array(num_ent);
+	res = alloc_part_array(fill);
 	if (res == NULL) {
 		//errno = ENOMEM; // already set in alloc_part_array()
@@ -204,5 +206,5 @@
 	 * will always read just sizeof(gpt_entry_t) bytes - hopefully they
 	 * don't break backward compatibility) */
-	for (i = 0; i < num_ent; ++i) {
+	for (i = 0; i < fill; ++i) {
 		//FIXME: this does bypass cache...
 		rc = block_read_bytes_direct(gpt->device, pos, sizeof(gpt_entry_t), res->part_array + i);
@@ -223,5 +225,5 @@
 	 * on all of the partition entry array.
 	 */
-	uint32_t crc = compute_crc32((uint8_t *) res->part_array, res->num_ent * sizeof(gpt_entry_t));
+	uint32_t crc = compute_crc32((uint8_t *) res->part_array, res->fill * sizeof(gpt_entry_t));
 	
 	if(uint32_t_le2host(gpt->raw_data->pe_array_crc32) != crc)
@@ -247,5 +249,5 @@
 	size_t b_size;
 	
-	gpt->raw_data->pe_array_crc32 = compute_crc32((uint8_t *) parts->part_array, parts->num_ent * gpt->raw_data->entry_size);
+	gpt->raw_data->pe_array_crc32 = compute_crc32((uint8_t *) parts->part_array, parts->fill * gpt->raw_data->entry_size);
 	
 	rc = block_get_bsize(dev_handle, &b_size);
@@ -259,5 +261,5 @@
 	/* Write to main GPT partition array location */
 	rc = block_write_direct(dev_handle, uint64_t_le2host(gpt->raw_data->entry_lba), 
-			nearest_larger_int((uint64_t_le2host(gpt->raw_data->entry_size) * parts->num_ent) / b_size), 
+			nearest_larger_int((uint64_t_le2host(gpt->raw_data->entry_size) * parts->fill) / b_size), 
 			parts->part_array);
 	if (rc != EOK)
@@ -277,21 +279,70 @@
 	
 	
-	gpt_write_gpt_header(gpt, dev_handle);
-	
-	return 0;
-	
-}
-
-gpt_partitions_t * gpt_add_partition(gpt_partitions_t * parts, gpt_part_t * partition)
-{
-	
+	return gpt_write_gpt_header(gpt, dev_handle);
+}
+
+/** Alloc new partition
+ * 
+ * @param parts		partition table to carry new partition
+ * 
+ * @return			returns pointer to the new partition or NULL on ENOMEM
+ * 
+ * Note: use either gpt_alloc_partition or gpt_add_partition. The first
+ * returns a pointer to write your data to, the second copies the data 
+ * (and does not free the memory).
+ */
+gpt_part_t * gpt_alloc_partition(gpt_partitions_t * parts)
+{
+	if (parts->fill == parts->arr_size) {
+		if (extend_part_array(parts) == -1)
+			return NULL;
+	}
+	
+	return parts->part_array + parts->fill++;
+}
+
+/** Copy partition into partition array
+ * 
+ * @param parts			target partition array
+ * @param partition		source partition to copy
+ * 
+ * @return 				-1 on error, 0 otherwise
+ * 
+ * Note: use either gpt_alloc_partition or gpt_add_partition. The first
+ * returns a pointer to write your data to, the second copies the data 
+ * (and does not free the memory).
+ */
+int gpt_add_partition(gpt_partitions_t * parts, gpt_part_t * partition)
+{
+	if (parts->fill == parts->arr_size) {
+		if (extend_part_array(parts) == -1)
+			return -1;
+	}
 	extend_part_array(parts);
 	return parts;
 }
 
-gpt_partitions_t * gpt_remove_partition(gpt_partitions_t * parts, size_t idx)
-{
-	reduce_part_array(parts);
-	return parts;
+/** Remove partition from array
+ * 
+ * @param idx		index of the partition to remove
+ * 
+ * @return			-1 on error, 0 otherwise
+ * 
+ * Note: even if it fails, the partition still gets removed. Only
+ * reducing the array failed.
+ */
+int gpt_remove_partition(gpt_partitions_t * parts, size_t idx)
+{
+	if (idx != parts->fill - 1) {
+		memcpy(parts->part_array + idx, parts->part_array + fill - 1, sizeof(gpt_entry_t));
+		parts->fill -= 1;
+	}
+	
+	if (parts->fill < (parts->arr_size / 2) - GPT_IGNORE_FILL_NUM) {
+		if (reduce_part_array(parts) == -1)
+			return -1;
+	}
+	
+	return 0;
 }
 
@@ -311,4 +362,18 @@
 	free(parts->part_array);
 	free(parts);
+}
+
+/** Get partition type by linear search
+ * (hopefully this doesn't get slow)
+ */
+size_t gpt_get_part_type(gpt_part_t * p)
+{
+	size_t i;
+	for (i = 0; gpt_ptypes[i].guid != NULL; i++) {
+		if (memcmp(p->raw_data.part_type, gpt_ptypes[i].guid, 16) == 0) {
+			break;
+		}
+	}
+	return i;
 }
 
@@ -343,8 +408,36 @@
 }
 
+char * gpt_get_part_name(gpt_entry_t * p)
+{
+	return p->raw_data.part_name;
+}
+
 /** Copy partition name */
 void gpt_set_part_name(gpt_entry_t * p, char * name[], size_t length)
 {
+	if (length >= 72)
+		length = 71;
+	
 	memcpy(p->part_name, name, length);
+	p->part_name[length] = '\0';
+}
+
+/** Get partition attribute */
+extern bool gpt_get_flag(gpt_part_t * p, GPT_ATTR flag)
+{
+	return (p->raw_data.attributes & (((uint64_t) 1) << flag)) ? 1 : 0;
+}
+
+/** Set partition attribute */
+extern void gpt_set_flag(gpt_part_t * p, GPT_ATTR flag, bool value)
+{
+	uint64_t attr = p->raw_data.attributes;
+
+	if (value)
+		attr = attr | (((uint64_t) 1) << flag);
+	else
+		attr = attr ^ (attr & (((uint64_t) 1) << flag));
+
+	p->raw_data.attributes = attr;
 }
 
@@ -405,5 +498,5 @@
 	}
 	
-	res->num_ent = num;
+	res->fill = num;
 	res->arr_size = size;
 	
@@ -420,5 +513,5 @@
 	}
 	
-	memcpy(tmp, p->part_array, p->num_ent);
+	memcpy(tmp, p->part_array, p->fill);
 	free(p->part_array);
 	p->part_array = tmp;
@@ -438,5 +531,5 @@
 		}
 		
-		memcpy(tmp, p->part_array, p->num_ent < nsize ? p->num_ent : nsize);
+		memcpy(tmp, p->part_array, p->fill < nsize ? p->fill  : nsize);
 		free(p->part_array);
 		p->part_array = tmp;
Index: uspace/lib/gpt/libgpt.h
===================================================================
--- uspace/lib/gpt/libgpt.h	(revision 271e24a4aca586ebdc97458d9836e0a3a3e1038c)
+++ uspace/lib/gpt/libgpt.h	(revision 256cbfe514223bde4eeeb03138267ab8192ed09b)
@@ -49,7 +49,17 @@
 /** Basic number of GPT partition entries */
 #define GPT_BASE_PART_NUM (GPT_MIN_PART_NUM)
+/** How much fill we ignore before resizing partition array */
+#define GPT_IGNORE_FILL_NUM 10
 
 /** GPT header signature ("EFI PART" in ASCII) */
 extern const uint8_t efi_signature[8];
+
+typedef enum {
+	AT_REQ_PART = 0,
+	AT_NO_BLOCK_IO,
+	AT_LEGACY_BOOT,
+	AT_UNDEFINED,
+	AT_SPECIFIC = 48
+} GPT_ATTR;
 
 /** GPT header
@@ -68,5 +78,5 @@
 	uint8_t disk_guid[16];
 	uint64_t entry_lba;
-	uint32_t num_entries;
+	uint32_t fillries;
 	uint32_t entry_size;
 	uint32_t pe_array_crc32;
@@ -105,7 +115,7 @@
 typedef struct gpt_parts {
 	/** Number of entries */
-	unsigned int num_ent;
+	size_t fill;
 	/** Size of the array */
-	unsigned int arr_size;
+	size_t arr_size;
 	/** Resizable partition array */
 	gpt_entry_t * part_array;
@@ -132,8 +142,17 @@
 extern gpt_partitions_t * gpt_read_partitions(gpt_t * gpt);
 extern int 				  gpt_write_partitions(gpt_partitions_t * parts, gpt_t * header, service_id_t dev_handle);
-extern gpt_partitions_t * gpt_add_partition(gpt_partitions_t * parts, gpt_part_t * partition);
-extern gpt_partitions_t * gpt_remove_partition(gpt_partitions_t * parts, size_t idx);
-extern void 			  gpt_set_part_type(gpt_part_t * p, int type);
+extern gpt_part_t *		  gpt_alloc_partition(gpt_partitions_t * parts);
+extern int				  gpt_add_partition(gpt_partitions_t * parts, gpt_part_t * partition);
+extern int				  gpt_remove_partition(gpt_partitions_t * parts, size_t idx);
+extern size_t			  gpt_get_part_type(gpt_part_t * p);
+extern void 			  gpt_set_part_type(gpt_part_t * p, size_t type);
+extern char * 			  gpt_get_part_name(gpt_entry_t * p);
 extern void 			  gpt_set_part_name(gpt_entry_t * p, char * name[], size_t length);
+extern bool				  gpt_get_flag(gpt_part_t * p, GPT_ATTR flag);
+extern void				  gpt_set_flag(gpt_part_t * p, GPT_ATTR flag, bool value);
+
+#define gpt_foreach(parts, i, iterator) \
+		for(size_t i = 0, gpt_part_t * iterator = parts->part_array;
+		    i < parts->fill; i++, iterator++)
 
 extern void gpt_free_gpt(gpt_t * gpt);
Index: uspace/lib/mbr/Makefile
===================================================================
--- uspace/lib/mbr/Makefile	(revision 271e24a4aca586ebdc97458d9836e0a3a3e1038c)
+++ uspace/lib/mbr/Makefile	(revision 256cbfe514223bde4eeeb03138267ab8192ed09b)
@@ -28,5 +28,5 @@
 
 USPACE_PREFIX = ../..
-EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX)
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -DDEBUG_CONFIG
 LIBRARY = libmbr
 
Index: uspace/lib/mbr/libmbr.c
===================================================================
--- uspace/lib/mbr/libmbr.c	(revision 271e24a4aca586ebdc97458d9836e0a3a3e1038c)
+++ uspace/lib/mbr/libmbr.c	(revision 256cbfe514223bde4eeeb03138267ab8192ed09b)
@@ -150,8 +150,12 @@
 			return NULL;
 		}
-		list_append(&(p->link), &(parts->list));
+		//list_append(&(p->link), &(parts->list));
 		p->ebr = NULL;
-		if (decode_part(&(mbr->raw_data.pte[i]), p, 0))
+		if (decode_part(&(mbr->raw_data.pte[i]), p, 0)) {
 			ext = p;
+			parts->l_extended = list_last(&(parts->list));
+		}
+		mbr_set_flag(p, ST_LOGIC, false);
+		mbr_add_partition(parts, p);
 	}
 
@@ -183,8 +187,11 @@
 	
 	br_block_t * last_ebr = NULL;
-
-
+	link_t * it;
+	
+	DEBUG_PRINT_3(LIBMBR_NAME "Writing partitions: n_primary: %u, n_logical:%u, l_extended:%p", parts->n_primary, parts->n_logical, parts->l_extended);
+	
 	rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
 	if (rc != EOK) {
+		DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
 		return rc;
 	}
@@ -193,12 +200,20 @@
 		goto no_extended;
 
-	aoff64_t addr = ext->start_addr;
+	uint32_t base = ext->start_addr;
+	uint32_t addr = base;
+	uint32_t prev_addr;
 	mbr_part_t * prev_part = NULL;
 
-	list_foreach(parts->list, it) {
-		p = list_get_instance(it, mbr_part_t, link);
+	list_foreach(parts->list, iter) {
+		p = list_get_instance(iter, mbr_part_t, link);
 		if (mbr_get_flag(p, ST_LOGIC)) {
 			// writing logical partition
-
+			
+			if (p->start_addr < base || p->start_addr + p->length > base + ext->length) {
+				// out of bounds
+				return EINVAL;
+			}
+			
+			
 			if (p->ebr == NULL) {
 				p->ebr = alloc_br();
@@ -210,14 +225,27 @@
 			}
 
-
-			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)
+				// addr is the address of EBR
+				addr = p->start_addr - base;
+				// base-1 means start_lba+1
+				encode_part(p, &(p->ebr->pte[0]), addr - 1);
+				encode_part(p, &(prev_part->ebr->pte[1]), base);
+				rc = block_write_direct(dev_handle, prev_addr, 1, prev_part->ebr);
+				if (rc != EOK) {
+					DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
 					goto end;
+				}
+			} else {
+				// addr is the address of EBR
+				addr = base;
+				// base-1 means start_lba+1
+				encode_part(p, &(p->ebr->pte[0]), base - 1);
 			}
 			
-			addr = p->start_addr;
+			//addr = p->start_addr;
+			prev_addr = addr;
 			prev_part = p;
 		} else {
@@ -261,6 +289,8 @@
 	}
 	
-	if (rc != EOK)
+	if (rc != EOK) {
+		DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
 		goto end;
+	}
 
 	goto skip;
@@ -268,5 +298,5 @@
 no_extended:
 
-	list_foreach(parts->list, it) {
+	/*list_foreach(parts->list, it) {
 		p = list_get_instance(it, mbr_part_t, link);
 		if (mbr_get_flag(p, ST_LOGIC)) {
@@ -282,10 +312,35 @@
 			++i;
 		}
-	}
+	}*/
+	
+	it = parts->list.head.next;
+	for (i = 0; i < N_PRIMARY; i++) {
+		if (it != &parts->list.head) {
+			p = list_get_instance(it, mbr_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);
+
+			}
+			
+			it = it->next;
+		} else {
+			encode_part(NULL, &(mbr->raw_data.pte[i]), 0);
+		}
+	}
+	
 
 skip:
 	rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data));
-	if (rc != EOK)
+	if (rc != EOK) {
+		DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
 		goto end;
+	}
 
 	/*
@@ -382,4 +437,8 @@
 
 	list_initialize(&(parts->list));
+	
+	parts->n_primary = 0;
+	parts->n_logical = 0;
+	parts->l_extended = NULL;
 
 	return parts;
@@ -387,7 +446,21 @@
 
 /** Add partition */
-int mbr_add_partition(mbr_partitions_t * parts, mbr_part_t * partition)
-{
-	list_append(&(partition->link), &(parts->list));
+int mbr_add_partition(mbr_partitions_t * parts, mbr_part_t * p)
+{
+	list_append(&(p->link), &(parts->list));
+	if (mbr_get_flag(p, ST_LOGIC)) {
+		parts->n_logical += 1;
+	} else {
+		parts->n_primary += 1;
+	}
+	/* if we're adding new logical partition, we need 1 sector for the EBR 
+	 * for that partition (including the next one); we'd better make sure here
+	 * before writing */
+	if (mbr_get_flag(p, ST_LOGIC) && p->ebr == NULL) {
+		p->start_addr += 1;
+		p->length -= 1;
+	}
+	//FIXME: we can have multiple extended partitions! :-(
+	
 	return EOK;
 }
@@ -396,7 +469,19 @@
 int mbr_remove_partition(mbr_partitions_t * parts, size_t idx)
 {
+	DEBUG_PRINT_1(LIBMBR_NAME "Removing partition: %d\n", idx);
 	link_t * l = list_nth(&(parts->list), idx);
+	if (l == parts->l_extended) {
+		DEBUG_PRINT_0(LIBMBR_NAME "Removing extended partition.\n");
+		parts->l_extended = NULL;
+	}
 	list_remove(l);
 	mbr_part_t * p = list_get_instance(l, mbr_part_t, link);
+	if (mbr_get_flag(p, ST_LOGIC)) {
+		parts->n_logical -= 1;
+	} else {
+		parts->n_primary -= 1;
+	}
+	
+	
 	mbr_free_partition(p);
 	
@@ -448,4 +533,6 @@
 		mbr_free_partition(p);
 	}
+	
+	free(parts);
 }
 
@@ -465,5 +552,7 @@
 }
 
-/** Parse partition entry to mbr_part_t */
+/** Parse partition entry to mbr_part_t
+ * @return		returns 1, if extended partition, 0 otherwise
+ * */
 static int decode_part(pt_entry_t * src, mbr_part_t * trgt, uint32_t base)
 {
@@ -480,7 +569,5 @@
 }
 
-/** Parse MBR contents to mbr_part_t list
- * parameter 'p' is allocated for only used primary partitions
- */
+/** Parse MBR contents to mbr_part_t list */
 static int decode_logical(mbr_t * mbr, mbr_partitions_t * parts, mbr_part_t * ext)
 {
@@ -496,6 +583,6 @@
 
 
-	uint32_t addr = ext->start_addr;
-	//uint32_t base = ext->start_addr;
+	uint32_t base = ext->start_addr;
+	uint32_t addr = base;
 	br_block_t * ebr;
 
@@ -503,36 +590,80 @@
 	if (rc != EOK)
 		return rc;
-
-	do {
+	
+	ebr = alloc_br();
+	if (ebr == NULL) {
+		rc = ENOMEM;
+		goto end;
+	}
+
+	rc = block_read_direct(mbr->device, addr, 1, ebr);
+	if (rc != EOK) {
+		goto free_ebr_end;
+	}
+
+	if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) {
+		rc = EINVAL;
+		goto free_ebr_end;
+	}
+	
+	if (ebr->pte[0].ptype == PT_UNUSED) {
+		rc = EOK;
+		goto free_ebr_end;
+	}
+	
+	p = mbr_alloc_partition();
+	if (p == NULL) {
+		rc = ENOMEM;
+		goto free_ebr_end;
+	}
+	
+
+	decode_part(&(ebr->pte[0]), p, base);
+	mbr_set_flag(p, ST_LOGIC, true);
+	p->ebr = ebr;
+	mbr_add_partition(parts, p);
+
+	addr = uint32_t_le2host(ebr->pte[1].first_lba) + base;
+	
+	while (ebr->pte[1].ptype != PT_UNUSED) {
 		ebr = alloc_br();
 		if (ebr == NULL) {
-			return ENOMEM;
+			rc = ENOMEM;
+			goto end;
 		}
 
 		rc = block_read_direct(mbr->device, addr, 1, ebr);
 		if (rc != EOK) {
-			return rc;
-		}
-
-		//FIXME: is this the right way?
+			goto free_ebr_end;
+		}
+
 		if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) {
-			return EINVAL;
+			rc = EINVAL;
+			goto free_ebr_end;
 		}
 
 		p = mbr_alloc_partition();
-
-		decode_part(&(ebr->pte[0]), p, addr);
+		if (p == NULL) {
+			rc = ENOMEM;
+			goto free_ebr_end;
+		}
+
+		decode_part(&(ebr->pte[0]), p, base);
 		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);
-
-
+		addr = uint32_t_le2host(ebr->pte[1].first_lba) + base;
+	}
+	
+	rc = EOK;
+	
+free_ebr_end:
+	free(ebr);
+	
+end:
 	block_fini(mbr->device);
 
-	return EOK;
+	return rc;
 }
 
@@ -543,6 +674,6 @@
 		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)
+		trgt->first_lba = host2uint32_t_le(src->start_addr - base);
+		trgt->length = host2uint32_t_le(src->length);
 	} else {
 		trgt->status = 0;
Index: uspace/lib/mbr/libmbr.h
===================================================================
--- uspace/lib/mbr/libmbr.h	(revision 271e24a4aca586ebdc97458d9836e0a3a3e1038c)
+++ uspace/lib/mbr/libmbr.h	(revision 256cbfe514223bde4eeeb03138267ab8192ed09b)
@@ -39,4 +39,22 @@
 
 #define LIBMBR_NAME	"libmbr"
+
+#ifdef DEBUG_CONFIG
+#include <stdio.h>
+#include <str_error.h>
+#define DEBUG_PRINT_0(str) \
+	printf("%s:%d: " str, __FILE__, __LINE__)
+#define DEBUG_PRINT_1(str, arg1) \
+	printf("%s:%d: " str, __FILE__, __LINE__, arg1)
+#define DEBUG_PRINT_2(str, arg1, arg2) \
+	printf("%s:%d: " str, __FILE__, __LINE__, arg1, arg2)
+#define DEBUG_PRINT_3(str, arg1, arg2, arg3) \
+	printf("%s:%d: " str, __FILE__, __LINE__, arg1, arg2, arg3)
+#else
+#define DEBUG_PRINT_0(str) 
+#define DEBUG_PRINT_1(str, arg1)
+#define DEBUG_PRINT_2(str, arg1, arg2)
+#define DEBUG_PRINT_3(str, arg1, arg2, arg3)
+#endif
 
 /** Number of primary partition records */
@@ -105,10 +123,7 @@
 	/** 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_partitions_t as the linked list for keeping the same interface as with GPT
 /** Partition */
 typedef struct mbr_part {
@@ -127,4 +142,5 @@
 } mbr_part_t;
 
+/** Partition list structure */
 typedef struct mbr_parts {
 	/** Number of primary partitions */
@@ -138,4 +154,5 @@
 } mbr_partitions_t;
 
+/** Both header and partition list */
 typedef struct mbr_table {
 	mbr_t * mbr;
@@ -151,5 +168,6 @@
 extern int mbr_is_mbr(mbr_t * mbr);
 
-/** Read/Write/Set MBR partitions. */
+/** Read/Write/Set MBR partitions.
+ * NOTE: Writing partitions writes the complete header as well. */
 extern mbr_partitions_t * mbr_read_partitions(mbr_t * mbr);
 extern int 			mbr_write_partitions(mbr_partitions_t * parts, mbr_t * mbr, service_id_t dev_handle);
