diff --git a/src/os/uefi/disk.rs b/src/os/uefi/disk.rs
index 25b9aa01bb1fa1e0cb5e78d308f07f8ebc19167d..b8ca967ae04a134d1ec75e2f71af81cf107fb6d3 100644
--- a/src/os/uefi/disk.rs
+++ b/src/os/uefi/disk.rs
@@ -1,11 +1,12 @@
 use core::ops::{ControlFlow, Try};
+use core::slice;
 use redoxfs::{BLOCK_SIZE, Disk};
 use syscall::{EIO, Error, Result};
 use std::proto::Protocol;
 use uefi::guid::{Guid, BLOCK_IO_GUID};
 use uefi::block_io::BlockIo as UefiBlockIo;
 
-pub struct DiskEfi(pub &'static mut UefiBlockIo);
+pub struct DiskEfi(pub &'static mut UefiBlockIo, &'static mut [u8]);
 
 impl Protocol<UefiBlockIo> for DiskEfi {
     fn guid() -> Guid {
@@ -13,7 +14,16 @@ impl Protocol<UefiBlockIo> for DiskEfi {
     }
 
     fn new(inner: &'static mut UefiBlockIo) -> Self {
-        Self(inner)
+        // Hack to get aligned buffer
+        let block = unsafe {
+            let ptr = super::alloc_zeroed_page_aligned(BLOCK_SIZE as usize);
+            slice::from_raw_parts_mut(
+                ptr,
+                BLOCK_SIZE as usize,
+            )
+        };
+
+        Self(inner, block)
     }
 }
 
@@ -31,12 +41,27 @@ impl Disk for DiskEfi {
             }
         }
 
-        let block_size = self.0.Media.BlockSize as u64;
+        // Use aligned buffer if necessary
+        let mut ptr = buffer.as_mut_ptr();
+        if self.0.Media.IoAlign != 0 {
+            if (ptr as usize) % (self.0.Media.IoAlign as usize) != 0 {
+                if buffer.len() == self.1.len() {
+                    ptr = self.1.as_mut_ptr();
+                }
+            }
+        }
 
+        let block_size = self.0.Media.BlockSize as u64;
         let lba = block * BLOCK_SIZE / block_size;
 
-        match (self.0.ReadBlocks)(self.0, self.0.Media.MediaId, lba, buffer.len(), buffer.as_mut_ptr()).branch() {
-            ControlFlow::Continue(_) => Ok(buffer.len()),
+        match (self.0.ReadBlocks)(self.0, self.0.Media.MediaId, lba, buffer.len(), ptr).branch() {
+            ControlFlow::Continue(_) => {
+                // Copy to original buffer if using aligned buffer
+                if ptr != buffer.as_mut_ptr() {
+                    buffer.copy_from_slice(&self.1);
+                }
+                Ok(buffer.len())
+            },
             ControlFlow::Break(err) => {
                 println!("DiskEfi::read_at 0x{:X} failed: {:?}", block, err);
                 Err(Error::new(EIO))
diff --git a/src/os/uefi/mod.rs b/src/os/uefi/mod.rs
index 87c3a67fc3e407e01cbcd7db19ba53fa06c212c0..f9348e0220b4979c9354fa75b636d9153d1486bb 100644
--- a/src/os/uefi/mod.rs
+++ b/src/os/uefi/mod.rs
@@ -34,6 +34,36 @@ mod dtb;
 mod memory_map;
 mod video_mode;
 
+pub(crate) fn page_size() -> usize {
+    // EDK2 always uses 4096 as the page size
+    4096
+}
+
+pub(crate) fn alloc_zeroed_page_aligned(size: usize) -> *mut u8 {
+    assert!(size != 0);
+
+    let page_size = page_size();
+    let pages = (size + page_size - 1) / page_size;
+
+    let ptr = {
+        // Max address mapped by src/arch paging code (8 GiB)
+        let mut ptr = 0x2_0000_0000;
+        status_to_result(
+            (std::system_table().BootServices.AllocatePages)(
+                1, // AllocateMaxAddress
+                MemoryType::EfiRuntimeServicesData, // Keeps this memory out of free space list
+                pages,
+                &mut ptr
+            )
+        ).unwrap();
+        ptr as *mut u8
+    };
+
+    assert!(!ptr.is_null());
+    unsafe { ptr::write_bytes(ptr, 0, pages * page_size) };
+    ptr
+}
+
 pub struct OsEfi {
     st: &'static SystemTable,
 }
@@ -53,32 +83,11 @@ impl Os<
     }
 
     fn alloc_zeroed_page_aligned(&self, size: usize) -> *mut u8 {
-        assert!(size != 0);
-
-        let page_size = self.page_size();
-        let pages = (size + page_size - 1) / page_size;
-
-        let ptr = {
-            // Max address mapped by src/arch paging code (8 GiB)
-            let mut ptr = 0x2_0000_0000;
-            status_to_result(
-                (self.st.BootServices.AllocatePages)(
-                    1, // AllocateMaxAddress
-                    MemoryType::EfiRuntimeServicesData, // Keeps this memory out of free space list
-                    pages,
-                    &mut ptr
-                )
-            ).unwrap();
-            ptr as *mut u8
-        };
-
-        assert!(!ptr.is_null());
-        unsafe { ptr::write_bytes(ptr, 0, pages * page_size) };
-        ptr
+        alloc_zeroed_page_aligned(size)
     }
 
     fn page_size(&self) -> usize {
-        4096
+        page_size()
     }
 
     fn filesystem(&self, password_opt: Option<&[u8]>) -> syscall::Result<redoxfs::FileSystem<DiskEfi>> {