diff --git a/layout.ld b/layout.ld
index 5bc9d0cceb05d4094e8a24d9fe1a3161e782b6cf..fde1c400d956dc22415612c5321cb27f1565f0fe 100644
--- a/layout.ld
+++ b/layout.ld
@@ -71,18 +71,6 @@ SECTIONS {
         . = ALIGN(32);
     } > FLASH =0xFF
 
-    /* App state section. Used for persistent app data.
-     * We put this first because this is what libtock-c does. They provide the
-     * following explanation: if the app code changes but the persistent data
-     * doesn't, the app_state can be preserved.
-     */
-    .wfr.app_state :
-    {
-        . = ALIGN(4K);
-        KEEP (*(.app_state))
-        . = ALIGN(4K);
-    } > FLASH =0xFFFFFFFF
-
     /* Text section, Code! */
     .text :
     {
diff --git a/src/embedded_flash/syscall.rs b/src/embedded_flash/syscall.rs
index 7fca17afcb68c6e8d95aee8c33ea2bafd93d8c6b..b67a7c4aab74972e8eb10415c0403e5148b44e1c 100644
--- a/src/embedded_flash/syscall.rs
+++ b/src/embedded_flash/syscall.rs
@@ -55,7 +55,7 @@ impl SyscallStorage {
     ///
     /// # Safety
     ///
-    /// The `storage` must be in a writeable flash region.
+    /// The `storage` must be readable.
     ///
     /// # Errors
     ///
@@ -74,14 +74,15 @@ impl SyscallStorage {
     /// # extern crate ctap2;
     /// # use ctap2::embedded_flash::SyscallStorage;
     /// # use ctap2::embedded_flash::StorageResult;
-    /// # const NUM_PAGES: usize = 1;
-    /// # const PAGE_SIZE: usize = 1;
-    /// #[link_section = ".app_state"]
-    /// static mut STORAGE: [u8; NUM_PAGES * PAGE_SIZE] = [0xff; NUM_PAGES * PAGE_SIZE];
+    /// # const STORAGE_ADDR: usize = 0x1000;
+    /// # const STORAGE_SIZE: usize = 0x1000;
     /// # fn foo() -> StorageResult<SyscallStorage> {
-    /// // This is safe because this is the only use of `STORAGE` in the whole program and this is
-    /// // called only once.
-    /// unsafe { SyscallStorage::new(&mut STORAGE) }
+    /// // This is safe because we create and use `storage` only once in the whole program.
+    /// let storage = unsafe {
+    ///     core::slice::from_raw_parts_mut(STORAGE_ADDR as *mut u8, STORAGE_SIZE)
+    /// };
+    /// // This is safe because `storage` is readable.
+    /// unsafe { SyscallStorage::new(storage) }
     /// # }
     /// ```
     pub unsafe fn new(storage: &'static mut [u8]) -> StorageResult<SyscallStorage> {