diff --git a/core/app_main.c b/core/app_main.c
index 447d78a..33699e3 100644
--- a/core/app_main.c
+++ b/core/app_main.c
@@ -135,6 +135,8 @@ static void IRAM default_putc(char c) {
 }
 
 void init_newlib_locks(void);
+extern uint8_t sdk_wDevCtrl[];
+void nano_malloc_insert_chunk(void *start, size_t size);
 
 // .text+0x258
 void IRAM sdk_user_start(void) {
@@ -203,6 +205,15 @@ void IRAM sdk_user_start(void) {
     Cache_Read_Enable(0, 0, 1);
     zero_bss();
     sdk_os_install_putc1(default_putc);
+
+    /* HACK Reclaim a region of unused bss from wdev.o. This would not be
+     * necessary if the source code to wdev were available, and then it would
+     * not be a fragmented area, but the extra memory is desparately needed and
+     * it is in very useful dram. */
+    nano_malloc_insert_chunk((void *)(sdk_wDevCtrl + 0x2190), 8000);
+
+    init_newlib_locks();
+
     if (cksum_magic == 0xffffffff) {
         // No checksum required
     } else if ((cksum_magic == 0x55aa55aa) &&
@@ -225,7 +236,6 @@ void IRAM sdk_user_start(void) {
             status = sysparam_init(sysparam_addr, 0);
         }
     }
-    init_newlib_locks();
     if (status != SYSPARAM_OK) {
         printf("WARNING: Could not initialize sysparams (%d)!\n", status);
     }
diff --git a/core/newlib_syscalls.c b/core/newlib_syscalls.c
index 8fcb49a..a09017f 100644
--- a/core/newlib_syscalls.c
+++ b/core/newlib_syscalls.c
@@ -61,6 +61,14 @@ IRAM void *_sbrk_r (struct _reent *r, ptrdiff_t incr)
     return (caddr_t) prev_heap_end;
 }
 
+
+/* Insert a disjoint region into the nano malloc pool. Create a malloc chunk,
+ * filling the size as newlib nano malloc expects, and then free it. */
+void nano_malloc_insert_chunk(void *start, size_t size) {
+    *(uint32_t *)start = size;
+    free(start + sizeof(size_t));
+}
+
 /* syscall implementation for stdio write to UART */
 __attribute__((weak)) ssize_t _write_stdout_r(struct _reent *r, int fd, const void *ptr, size_t len )
 {