diff --git a/elements/partitioning-sfdisk/README.rst b/elements/partitioning-sfdisk/README.rst
new file mode 100644
index 000000000..8528e04d1
--- /dev/null
+++ b/elements/partitioning-sfdisk/README.rst
@@ -0,0 +1,19 @@
+===================
+partitioning-sfdisk
+===================
+Sets up a partitioned disk using sfdisk, according to user needs.
+
+Environment Variables
+---------------------
+DIB_PARTITIONING_SFDISK_SCHEMA
+  : Required: Yes
+  : Default: 2048,,L *
+             0 0;
+             0 0;
+             0 0;
+  : Description: A multi-line string specifying a disk schema in sectors.
+  : Example: ``DIB_PARTITIONING_SFDISK_SCHEMA="
+    2048,10000,L *
+    10248,,L
+    0 0;
+    " will create two partitions on disk, first one will be bootable.
diff --git a/elements/partitioning-sfdisk/block-device.d/10-partitioning-sfdisk b/elements/partitioning-sfdisk/block-device.d/10-partitioning-sfdisk
new file mode 100755
index 000000000..447f23a0e
--- /dev/null
+++ b/elements/partitioning-sfdisk/block-device.d/10-partitioning-sfdisk
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+if [ ${DIB_DEBUG_TRACE:-0} -gt 0 ]; then
+    set -x
+fi
+set -eu
+set -o pipefail
+
+# sanity checks
+source $_LIB/die
+[ -n "$IMAGE_BLOCK_DEVICE" ] || die "Image block device not set"
+
+# execute sfdisk with the given partitioning schema
+sudo sfdisk -uS --force $IMAGE_BLOCK_DEVICE <<EOF
+$DIB_PARTITIONING_SFDISK_SCHEMA
+EOF
+sudo partprobe $IMAGE_BLOCK_DEVICE
+
+# To ensure no race conditions exist from calling partprobe
+sudo udevadm settle
+
+# If the partition isn't under /dev/loop*p1, create it with kpartx
+DM=
+if [ ! -e "${IMAGE_BLOCK_DEVICE}p1" ]; then
+    DM=${IMAGE_BLOCK_DEVICE/#\/dev/\/dev\/mapper}
+    # If running inside Docker, make our nodes manually, because udev will not be working.
+    if [ -f /.dockerenv ]; then
+        # kpartx cannot run in sync mode in docker.
+        sudo kpartx -av $TMP_IMAGE_PATH
+        sudo dmsetup --noudevsync mknodes
+    else
+        sudo kpartx -asv $TMP_IMAGE_PATH
+    fi
+elif [[ "$ARCH" =~ "ppc" ]]; then
+    sudo kpartx -asv $TMP_IMAGE_PATH
+fi
+
+if [ -n "$DM" ]; then
+    echo "IMAGE_BLOCK_DEVICE=${DM}p1"
+elif [[ "$ARCH" =~ "ppc" ]]; then
+    DM=${IMAGE_BLOCK_DEVICE/#\/dev/\/dev\/mapper}
+    echo "IMAGE_BLOCK_DEVICE=${DM}p2"
+else
+    echo "IMAGE_BLOCK_DEVICE=${IMAGE_BLOCK_DEVICE}p1"
+fi
diff --git a/elements/partitioning-sfdisk/environment.d/10-partitioning-sfdisk b/elements/partitioning-sfdisk/environment.d/10-partitioning-sfdisk
new file mode 100644
index 000000000..03d62bf7c
--- /dev/null
+++ b/elements/partitioning-sfdisk/environment.d/10-partitioning-sfdisk
@@ -0,0 +1,5 @@
+DEFAULT_SCHEMA="2048 + L *
+             0 0;
+             0 0;
+             0 0;"
+export DIB_PARTITIONING_SFDISK_SCHEMA=${DIB_PARTITIONING_SFDISK_SCHEMA:-$DEFAULT_SCHEMA}
diff --git a/elements/partitioning-sfdisk/finalise.d/50-partitioning-remove-bogus-udev-links b/elements/partitioning-sfdisk/finalise.d/50-partitioning-remove-bogus-udev-links
new file mode 100755
index 000000000..10bf1204d
--- /dev/null
+++ b/elements/partitioning-sfdisk/finalise.d/50-partitioning-remove-bogus-udev-links
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+if [ ${DIB_DEBUG_TRACE:-1} -gt 0 ]; then
+    set -x
+fi
+set -eu
+set -o pipefail
+
+if [ $DISTRO_NAME = 'opensuse' ] ; then
+    # workaround for https://bugzilla.novell.com/show_bug.cgi?id=859493
+    rm -f /dev/mapper/loop*_part1
+fi