Index: uspace/lib/label/include/types/liblabel.h
===================================================================
--- uspace/lib/label/include/types/liblabel.h	(revision 70815a24cf429286a07e08f8ad1f2a835d6be638)
+++ uspace/lib/label/include/types/liblabel.h	(revision b7a4d06b6d03da11c24ad8eee4f374f7b8a7dc13)
@@ -68,4 +68,6 @@
 	/** Label type */
 	label_type_t ltype;
+	/** Label flags */
+	label_flags_t flags;
 	/** First block that can be allocated */
 	aoff64_t ablock0;
@@ -77,4 +79,6 @@
 	/** Partition index */
 	int index;
+	/** Partition kind */
+	label_pkind_t pkind;
 	/** Address of first block */
 	aoff64_t block0;
@@ -88,5 +92,9 @@
 	struct label *label;
 	/** Link to label_t.parts */
-	link_t llabel;
+	link_t lparts;
+	/** Link to label_t.pri_parts */
+	link_t lpri;
+	/** Link to label_t.log_parts */
+	link_t llog;
 	/** Index */
 	int index;
@@ -109,4 +117,6 @@
 	/** Number of blocks */
 	aoff64_t nblocks;
+	/** Partition kind */
+	label_pkind_t pkind;
 	/** Partition type */
 	uint64_t ptype;
@@ -135,4 +145,8 @@
 	/** Partitions */
 	list_t parts; /* of label_part_t */
+	/** Primary partitions */
+	list_t pri_parts; /* of label_part_t */
+	/** Logical partitions */
+	list_t log_parts; /* of label_part_t */
 	/** First block that can be allocated */
 	aoff64_t ablock0;
@@ -141,4 +155,6 @@
 	/** Number of primary partition entries */
 	int pri_entries;
+	/** Index of extended partition or -1 if there is none */
+	int ext_part_idx;
 	/** Block size */
 	size_t block_size;
Index: uspace/lib/label/src/gpt.c
===================================================================
--- uspace/lib/label/src/gpt.c	(revision 70815a24cf429286a07e08f8ad1f2a835d6be638)
+++ uspace/lib/label/src/gpt.c	(revision b7a4d06b6d03da11c24ad8eee4f374f7b8a7dc13)
@@ -150,4 +150,6 @@
 
 	list_initialize(&label->parts);
+	list_initialize(&label->pri_parts);
+	list_initialize(&label->log_parts);
 
 	for (j = 0; j < 2; j++) {
@@ -300,4 +302,5 @@
 	label->pri_entries = num_entries;
 	label->block_size = bsize;
+	label->ext_part_idx = -1;
 
 	label->lt.gpt.hdr_ba[0] = gpt_hdr_ba;
@@ -436,4 +439,6 @@
 
 	list_initialize(&label->parts);
+	list_initialize(&label->pri_parts);
+	list_initialize(&label->log_parts);
 
 	label->ops = &gpt_label_ops;
@@ -444,4 +449,5 @@
 	label->pri_entries = num_entries;
 	label->block_size = bsize;
+	label->ext_part_idx = -1;
 
 	label->lt.gpt.hdr_ba[0] = hdr_ba[0];
@@ -468,5 +474,6 @@
 	part = gpt_part_first(label);
 	while (part != NULL) {
-		list_remove(&part->llabel);
+		list_remove(&part->lparts);
+		list_remove(&part->lpri);
 		free(part);
 		part = gpt_part_first(label);
@@ -532,4 +539,9 @@
 }
 
+static bool gpt_can_create_pri(label_t *label)
+{
+	return list_count(&label->parts) < (size_t)label->pri_entries;
+}
+
 static int gpt_get_info(label_t *label, label_info_t *linfo)
 {
@@ -537,4 +549,7 @@
 	linfo->dcnt = dc_label;
 	linfo->ltype = lt_gpt;
+	linfo->flags = 0;
+	if (gpt_can_create_pri(label))
+		linfo->flags = linfo->flags | lf_can_create_pri;
 	linfo->ablock0 = label->ablock0;
 	linfo->anblocks = label->anblocks;
@@ -550,5 +565,5 @@
 		return NULL;
 
-	return list_get_instance(link, label_part_t, llabel);
+	return list_get_instance(link, label_part_t, lparts);
 }
 
@@ -557,9 +572,9 @@
 	link_t *link;
 
-	link = list_next(&part->llabel, &part->label->parts);
+	link = list_next(&part->lparts, &part->label->parts);
 	if (link == NULL)
 		return NULL;
 
-	return list_get_instance(link, label_part_t, llabel);
+	return list_get_instance(link, label_part_t, lparts);
 }
 
@@ -567,4 +582,5 @@
 {
 	pinfo->index = part->index;
+	pinfo->pkind = lpk_primary;
 	pinfo->block0 = part->block0;
 	pinfo->nblocks = part->nblocks;
@@ -587,4 +603,10 @@
 
 	if (pspec->index < 1 || pspec->index > label->pri_entries) {
+		rc = EINVAL;
+		goto error;
+	}
+
+	/* GPT only has primary partitions */
+	if (pspec->pkind != lpk_primary) {
 		rc = EINVAL;
 		goto error;
@@ -614,5 +636,6 @@
 	}
 
-	list_append(&part->llabel, &label->parts);
+	list_append(&part->lparts, &label->parts);
+	list_append(&part->lpri, &label->pri_parts);
 
 	*rpart = part;
@@ -636,5 +659,6 @@
 		return EIO;
 
-	list_remove(&part->llabel);
+	list_remove(&part->lparts);
+	list_remove(&part->lpri);
 	free(part);
 	return EOK;
@@ -694,5 +718,6 @@
 
 	part->label = label;
-	list_append(&part->llabel, &label->parts);
+	list_append(&part->lparts, &label->parts);
+	list_append(&part->lpri, &label->pri_parts);
 	return EOK;
 }
Index: uspace/lib/label/src/mbr.c
===================================================================
--- uspace/lib/label/src/mbr.c	(revision 70815a24cf429286a07e08f8ad1f2a835d6be638)
+++ uspace/lib/label/src/mbr.c	(revision b7a4d06b6d03da11c24ad8eee4f374f7b8a7dc13)
@@ -122,4 +122,6 @@
 
 	list_initialize(&label->parts);
+	list_initialize(&label->pri_parts);
+	list_initialize(&label->log_parts);
 
 	/* Verify boot record signature */
@@ -130,4 +132,5 @@
 	}
 
+	label->ext_part_idx = -1;
 	for (entry = 0; entry < mbr_nprimary; entry++) {
 		eptr = &mbr->pte[entry];
@@ -187,4 +190,6 @@
 
 	list_initialize(&label->parts);
+	list_initialize(&label->pri_parts);
+	list_initialize(&label->log_parts);
 
 	mbr->media_id = 0;
@@ -210,4 +215,5 @@
 	label->anblocks = nblocks - mbr_ablock0;
 	label->pri_entries = mbr_nprimary;
+	label->ext_part_idx = -1;
 
 	*rlabel = label;
@@ -225,5 +231,9 @@
 	part = mbr_part_first(label);
 	while (part != NULL) {
-		list_remove(&part->llabel);
+		list_remove(&part->lparts);
+		if (link_used(&part->lpri))
+			list_remove(&part->lpri);
+		if (link_used(&part->llog))
+			list_remove(&part->llog);
 		free(part);
 
@@ -273,6 +283,21 @@
 	linfo->dcnt = dc_label;
 	linfo->ltype = lt_mbr;
+
+	/* We support extended partitions */
+	linfo->flags = lf_ext_supp;
+
+	/** Can create primary if there is a free slot */
+	if (list_count(&label->pri_parts) < mbr_nprimary)
+		linfo->flags |= lf_can_create_pri;
+	/* Can create extended if there is a free slot and no extended */
+	if ((linfo->flags & lf_can_create_pri) != 0 && label->ext_part_idx < 0)
+		linfo->flags |= lf_can_create_ext;
+	/* Can create logical if there is an extended partition */
+	if (label->ext_part_idx >= 0)
+		linfo->flags |= lf_can_create_log;
+
 	linfo->ablock0 = label->ablock0;
 	linfo->anblocks = label->anblocks;
+
 	return EOK;
 }
@@ -286,5 +311,5 @@
 		return NULL;
 
-	return list_get_instance(link, label_part_t, llabel);
+	return list_get_instance(link, label_part_t, lparts);
 }
 
@@ -293,11 +318,12 @@
 	link_t *link;
 
-	link = list_next(&part->llabel, &part->label->parts);
+	link = list_next(&part->lparts, &part->label->parts);
 	if (link == NULL)
 		return NULL;
 
-	return list_get_instance(link, label_part_t, llabel);
-}
-
+	return list_get_instance(link, label_part_t, lparts);
+}
+
+#include <io/log.h>
 static void mbr_part_get_info(label_part_t *part, label_part_info_t *pinfo)
 {
@@ -305,4 +331,13 @@
 	pinfo->block0 = part->block0;
 	pinfo->nblocks = part->nblocks;
+
+	log_msg(LOG_DEFAULT, LVL_NOTE, "mbr_part_get_info: index=%d ptype=%d",
+	    (int)part->index, (int)part->ptype);
+	if (link_used(&part->llog))
+		pinfo->pkind = lpk_logical;
+	else if (part->ptype == mbr_pt_extended)
+		pinfo->pkind = lpk_extended;
+	else
+		pinfo->pkind = lpk_primary;
 }
 
@@ -318,10 +353,4 @@
 		return ENOMEM;
 
-	/* XXX Verify index, block0, nblocks */
-
-	if (pspec->index < 1 || pspec->index > label->pri_entries) {
-		rc = EINVAL;
-		goto error;
-	}
 
 	/* XXX Check if index is used */
@@ -331,19 +360,60 @@
 	part->block0 = pspec->block0;
 	part->nblocks = pspec->nblocks;
-	part->ptype = pspec->ptype;
-
-	rc = mbr_part_to_pte(part, &pte);
-	if (rc != EOK) {
-		rc = EINVAL;
-		goto error;
-	}
-
-	rc = mbr_pte_update(label, &pte, pspec->index - 1);
-	if (rc != EOK) {
-		rc = EIO;
-		goto error;
-	}
-
-	list_append(&part->llabel, &label->parts);
+
+	switch (pspec->pkind) {
+	case lpk_primary:
+		part->ptype = pspec->ptype;
+		break;
+	case lpk_extended:
+		part->ptype = mbr_pt_extended;
+		if (pspec->ptype != 0) {
+			rc = EINVAL;
+			goto error;
+		}
+		if (label->ext_part_idx >= 0) {
+			rc = EEXISTS;
+			goto error;
+		}
+		break;
+	case lpk_logical:
+		part->ptype = pspec->ptype;
+		if (pspec->index != 0) {
+			rc = EINVAL;
+			goto error;
+		}
+		break;
+	}
+
+	if (pspec->pkind != lpk_logical) {
+		/* Primary or extended partition */
+		/* XXX Verify index, block0, nblocks */
+
+		if (pspec->index < 1 || pspec->index > label->pri_entries) {
+			rc = EINVAL;
+			goto error;
+		}
+
+		rc = mbr_part_to_pte(part, &pte);
+		if (rc != EOK) {
+			rc = EINVAL;
+			goto error;
+		}
+
+		rc = mbr_pte_update(label, &pte, pspec->index - 1);
+		if (rc != EOK) {
+			rc = EIO;
+			goto error;
+		}
+
+		list_append(&part->lparts, &label->parts);
+		list_append(&part->lpri, &label->pri_parts);
+
+		if (pspec->pkind == lpk_extended)
+			label->ext_part_idx = pspec->index - 1;
+	} else {
+		/* Logical partition */
+		rc = ENOTSUP;
+		goto error;
+	}
 
 	*rpart = part;
@@ -367,5 +437,13 @@
 		return EIO;
 
-	list_remove(&part->llabel);
+	/* If it was the extended partition, clear ext. part. index */
+	if (part->index - 1 == part->label->ext_part_idx)
+		part->label->ext_part_idx = -1;
+
+	list_remove(&part->lparts);
+	if (link_used(&part->lpri))
+		list_remove(&part->lpri);
+	if (link_used(&part->llog))
+		list_remove(&part->llog);
 	free(part);
 	return EOK;
@@ -386,4 +464,7 @@
 		return EINVAL;
 
+	log_msg(LOG_DEFAULT, LVL_NOTE, "mbr_part_to_pte: a0=%" PRIu64
+	    " len=%" PRIu64 " ptype=%d", part->block0, part->nblocks,
+	    (int)part->ptype);
 	memset(pte, 0, sizeof(mbr_pte_t));
 	pte->ptype = part->ptype;
@@ -403,6 +484,5 @@
 
 	/* See UEFI specification 2.0 section 5.2.1 Legacy Master Boot Record */
-	if (pte->ptype == mbr_pt_unused || pte->ptype == mbr_pt_extended ||
-	    nblocks == 0)
+	if (pte->ptype == mbr_pt_unused || nblocks == 0)
 		return EOK;
 
@@ -411,4 +491,5 @@
 		return ENOMEM;
 
+	part->ptype = pte->ptype;
 	part->index = index;
 	part->block0 = block0;
@@ -422,5 +503,9 @@
 
 	part->label = label;
-	list_append(&part->llabel, &label->parts);
+	list_append(&part->lparts, &label->parts);
+	list_append(&part->lpri, &label->pri_parts);
+
+	if (pte->ptype == mbr_pt_extended)
+		label->ext_part_idx = index - 1;
 	return EOK;
 }
