diff --git a/diskimage_builder/block_device/level0/localloop.py b/diskimage_builder/block_device/level0/localloop.py
index d5bd2c2e6..aaf8b5560 100644
--- a/diskimage_builder/block_device/level0/localloop.py
+++ b/diskimage_builder/block_device/level0/localloop.py
@@ -38,10 +38,16 @@ def image_delete(filename):
     os.remove(filename)
 
 
-def loopdev_attach(filename):
+def loopdev_attach(filename, block_size):
+    if str(block_size) not in ['512', '4096']:
+        logger.warning("Block device size is set to %s, only 512 and "
+                       "4096 has been tested.", block_size)
     logger.info("loopdev attach")
-    logger.debug("Calling [sudo losetup --show -f %s]", filename)
-    block_device = exec_sudo(["losetup", "--show", "-f", filename])
+    log_msg = ("Calling [sudo losetup --sector-size %s --show -f %s]"
+               % (str(block_size), filename))
+    logger.debug(log_msg)
+    block_device = exec_sudo(["losetup", "--sector-size", str(block_size),
+                              "--show", "-f", filename])
     # [:-1]: Cut of the newline
     block_device = block_device[:-1]
     logger.info("New block device [%s]", block_device)
@@ -85,6 +91,12 @@ class LocalLoopNode(NodeBase):
             self.image_dir = config['directory']
         else:
             self.image_dir = default_config['image-dir']
+        if 'DIB_BLOCK_SIZE' in os.environ:
+            self.block_size = os.environ['DIB_BLOCK_SIZE']
+        elif 'block_size' in config:
+            self.block_size = config['block_size']
+        else:
+            self.block_size = 512
         self.filename = os.path.join(self.image_dir, self.name + ".raw")
 
     def get_edges(self):
@@ -98,7 +110,7 @@ class LocalLoopNode(NodeBase):
         self.add_rollback(image_delete, self.filename)
         image_create(self.filename, self.size)
 
-        block_device = loopdev_attach(self.filename)
+        block_device = loopdev_attach(self.filename, self.block_size)
         self.add_rollback(loopdev_detach, block_device)
 
         if 'blockdev' not in self.state:
diff --git a/diskimage_builder/block_device/level1/partitioning.py b/diskimage_builder/block_device/level1/partitioning.py
index 31ef8e54c..d3ea2a637 100644
--- a/diskimage_builder/block_device/level1/partitioning.py
+++ b/diskimage_builder/block_device/level1/partitioning.py
@@ -95,6 +95,8 @@ class Partitioning(PluginBase):
 
     def _create_mbr(self):
         """Create partitions with MBR"""
+        # NOTE(TheJulia): This is funcitonally incompatible with block/sector
+        # sizing other than 512 bytes.
         with MBR(self.image_path, self.disk_size, self.align) as part_impl:
             for part_cfg in self.partitions:
                 part_name = part_cfg.get_name()
@@ -127,7 +129,10 @@ class Partitioning(PluginBase):
     def _create_gpt(self):
         """Create partitions with GPT"""
 
-        cmd = ['sgdisk', self.image_path]
+        # Use the loopback via device_path, as using the file means the
+        # partitioning is exposed to sector sizing of the OS, not of the
+        # underlying "device" provided by the loopback.
+        cmd = ['sgdisk', self.device_path]
 
         # This padding gives us a little room for rounding so we don't
         # go over the end of the disk
diff --git a/diskimage_builder/block_device/tests/test_gpt.py b/diskimage_builder/block_device/tests/test_gpt.py
index 5c4c80bee..cba3fe87b 100644
--- a/diskimage_builder/block_device/tests/test_gpt.py
+++ b/diskimage_builder/block_device/tests/test_gpt.py
@@ -63,7 +63,7 @@ class TestGPT(tc.TestGraphGeneration):
                 node.create()
 
         # check the parted call looks right
-        parted_cmd = ['sgdisk', self.image_path,
+        parted_cmd = ['sgdisk', '/dev/loopX',
                       '-n', '1:0:+8M', '-t', '1:EF00', '-c', '1:ESP',
                       '-n', '2:0:+8M', '-t', '2:EF02', '-c', '2:BSP',
                       '-n', '3:0:+1006M', '-t', '3:8300', '-c', '3:Root Part']
diff --git a/diskimage_builder/elements/block-device-efi-4k/README.rst b/diskimage_builder/elements/block-device-efi-4k/README.rst
new file mode 100644
index 000000000..215d30735
--- /dev/null
+++ b/diskimage_builder/elements/block-device-efi-4k/README.rst
@@ -0,0 +1,19 @@
+================
+Block Device EFI
+================
+
+This provides a block-device configuration for the ``vm`` element to
+get a single-partition disk suitable for EFI booting on a block device
+which uses a native 4KiB sector size. This is important because GPT
+partitioning relies on sector boundry placement and the GPT disk partition
+table always starts on the second sector of the disk.
+
+Note on x86 this provides the extra `BIOS boot partition
+<https://en.wikipedia.org/wiki/BIOS_boot_partition>`__ and a EFI boot
+partition for maximum compatability.
+
+This element requires ``mkfs.vfat`` command to be available on the build
+system, usually included in the dosfstools OS package.
+
+Furthermore, the sector size created by this element will not be compatible
+with devices using 512 byte sectors.
diff --git a/diskimage_builder/elements/block-device-efi-4k/block-device-default.yaml b/diskimage_builder/elements/block-device-efi-4k/block-device-default.yaml
new file mode 100644
index 000000000..61fa67cfe
--- /dev/null
+++ b/diskimage_builder/elements/block-device-efi-4k/block-device-default.yaml
@@ -0,0 +1,30 @@
+- local_loop:
+    name: image0
+    block_size: 4096
+- partitioning:
+    base: image0
+    label: gpt
+    partitions:
+      - name: ESP
+        type: 'EF00'
+        size: 500MiB
+        mkfs:
+          type: vfat
+          mount:
+            mount_point: /boot/efi
+            fstab:
+              options: "defaults"
+              fsck-passno: 2
+      - name: BSP
+        type: 'EF02'
+        size: 8MiB
+      - name: root
+        type: '8300'
+        size: 100%
+        mkfs:
+          type: ext4
+          mount:
+            mount_point: /
+            fstab:
+              options: "defaults"
+              fsck-passno: 1
diff --git a/diskimage_builder/elements/block-device-efi-4k/element-provides b/diskimage_builder/elements/block-device-efi-4k/element-provides
new file mode 100644
index 000000000..c0180a2cb
--- /dev/null
+++ b/diskimage_builder/elements/block-device-efi-4k/element-provides
@@ -0,0 +1 @@
+block-device
\ No newline at end of file
diff --git a/diskimage_builder/elements/block-device-efi-4k/environment.d/15-block-device.bash b/diskimage_builder/elements/block-device-efi-4k/environment.d/15-block-device.bash
new file mode 100644
index 000000000..ad8a26745
--- /dev/null
+++ b/diskimage_builder/elements/block-device-efi-4k/environment.d/15-block-device.bash
@@ -0,0 +1,10 @@
+#
+# Arch gate
+#
+
+if [[ "ppc64 ppc64le ppc64el" =~ "$ARCH" ]]; then
+    echo "block-device-efi is not supported on Power; use block-device-gpt or block-device-mbr"
+    exit 1
+fi
+
+export DIB_BLOCK_DEVICE=efi
diff --git a/doc/source/user_guide/building_an_image.rst b/doc/source/user_guide/building_an_image.rst
index ac629e779..c7c3e8780 100644
--- a/doc/source/user_guide/building_an_image.rst
+++ b/doc/source/user_guide/building_an_image.rst
@@ -216,6 +216,22 @@ size
 directory
   (optional) The directory where the image is created.
 
+block_size
+  (optional) Defaults to 512 bytes. Usable to set a different logical block
+  size, or in loopback context sector size, which will govern how partitioning
+  and filesystem utilities will interact with the device and ultimately the
+  block layout on disk.
+  Examples: 512, 4096.
+  This option is critical if you have block devices which natively operate
+  with 4KiB block sizes and need to craft an image to use boot from those
+  devices using a GPT partition table. This setting can also be asserted
+  using a DIB_BLOCK_SIZE environment variable which may be useful for
+  users who need to craft similar, but different block size images without
+  the need to separately maintain different block device YAML documents.
+  Please keep in mind, with larger block sizes, total disk image sizes
+  *and* partition sizes on the disk image will need to be perfectly
+  divisible by the block size being asserted.
+
 Example:
 
 .. code-block:: yaml
diff --git a/releasenotes/notes/add-4k-block-device-support-8397c2b6122d864c.yaml b/releasenotes/notes/add-4k-block-device-support-8397c2b6122d864c.yaml
new file mode 100644
index 000000000..5c218a8d4
--- /dev/null
+++ b/releasenotes/notes/add-4k-block-device-support-8397c2b6122d864c.yaml
@@ -0,0 +1,10 @@
+---
+features:
+  - |
+    Adds the ability for diskimage-builder to create images with different
+    block sizes. By default, this remains at the default of 512 bytes,
+    but some newer devices require 4096 bytes to be used, which impacts
+    the overall layout rendering 512 byte images incompatible. This setting
+    can also be asserted and overridden using the ``DIB_BLOCK_SIZE``
+    environment variable, but alternatively exists as a new ``block_size``
+    parameter for ``local_loop`` section in block device YAML documents.