diff --git a/core/init.c b/core/init.c
index 6b8137c..bf42f3e 100644
--- a/core/init.c
+++ b/core/init.c
@@ -47,6 +47,8 @@
 #include <nvram.h>
 #include <libstb/stb.h>
 #include <libstb/container.h>
+#include <timebase.h>
+#include "libxz/xz.h"
 
 enum proc_gen proc_gen;
 unsigned int pcie_max_link_speed;
@@ -302,34 +304,50 @@ extern char __builtin_kernel_start[];
 extern char __builtin_kernel_end[];
 extern uint64_t boot_offset;
 
-static size_t initramfs_size;
+static struct boot_resources boot_res = {
+	.kernel_base      = KERNEL_LOAD_BASE,
+	.kernel_size      = KERNEL_LOAD_SIZE,
+	.kernel_loaded    = false,
+	.initramfs_base   = INITRAMFS_LOAD_BASE,
+	.initramfs_size   = INITRAMFS_LOAD_SIZE,
+	.initramfs_loaded = false,
+	.success          = false,
+};
+static struct cpu_job *load_boot_resource_job = NULL;
 
 bool start_preload_kernel(void)
 {
 	int loaded;
-
+	
 	/* Try to load an external kernel payload through the platform hooks */
-	kernel_size = KERNEL_LOAD_SIZE;
 	loaded = start_preload_resource(RESOURCE_ID_KERNEL,
 					RESOURCE_SUBID_NONE,
 					KERNEL_LOAD_BASE,
-					&kernel_size);
+					&boot_res.kernel_size);
 	if (loaded != OPAL_SUCCESS) {
 		printf("INIT: platform start load kernel failed\n");
 		kernel_size = 0;
 		return false;
 	}
 
-	initramfs_size = INITRAMFS_LOAD_SIZE;
 	loaded = start_preload_resource(RESOURCE_ID_INITRAMFS,
 					RESOURCE_SUBID_NONE,
-					INITRAMFS_LOAD_BASE, &initramfs_size);
+					INITRAMFS_LOAD_BASE,
+					&boot_res.initramfs_size);
 	if (loaded != OPAL_SUCCESS) {
 		printf("INIT: platform start load initramfs failed\n");
-		initramfs_size = 0;
 		return false;
 	}
 
+
+	/*
+	 * Async job to load, configure and decode kernel and initramfs
+	 * This is platform specific. FSPs only have to decode the initramfs.
+	 * BMCs have to parse the FIT, configure the resource locations, then
+	 * decode the initramfs.
+	 */
+	load_boot_resource_job = start_async_load(&boot_res);
+
 	return true;
 }
 
@@ -342,12 +360,16 @@ static bool load_kernel(void)
 
 	prlog(PR_NOTICE, "INIT: Waiting for kernel...\n");
 
-	loaded = wait_for_resource_loaded(RESOURCE_ID_KERNEL,
-					  RESOURCE_SUBID_NONE);
+	/* If on FSP machine, initramfs is decoded but need to load the kernel*/
+	if (!boot_res.kernel_loaded) {
 
-	if (loaded != OPAL_SUCCESS) {
-		printf("INIT: platform wait for kernel load failed\n");
-		kernel_size = 0;
+		loaded = wait_for_resource_loaded(RESOURCE_ID_KERNEL,
+						  RESOURCE_SUBID_NONE);
+
+		if (loaded != OPAL_SUCCESS) {
+			printf("INIT: platform wait for kernel load failed\n");
+			kernel_size = 0;
+		}
 	}
 
 	/* Try embedded kernel payload */
@@ -395,6 +417,9 @@ static bool load_kernel(void)
 		}
 	}
 
+	if (boot_res.success)
+		kh = (struct elf_hdr *)boot_res.kernel_base;
+
 	printf("INIT: Kernel loaded, size: %zu bytes (0 = unknown preload)\n",
 	       kernel_size);
 
@@ -433,23 +458,27 @@ static bool load_kernel(void)
 
 static void load_initramfs(void)
 {
-	int loaded;
+	int loaded = 0;
 
-	loaded = wait_for_resource_loaded(RESOURCE_ID_INITRAMFS,
-					  RESOURCE_SUBID_NONE);
+	printf("INIT: called load_initramfs\n");
+	if (!boot_res.initramfs_loaded)
+		loaded = wait_for_resource_loaded(RESOURCE_ID_INITRAMFS,
+						  RESOURCE_SUBID_NONE);
 
-	if (loaded != OPAL_SUCCESS || !initramfs_size)
+	if (loaded != OPAL_SUCCESS || !boot_res.initramfs_size)
 		return;
 
 	dt_check_del_prop(dt_chosen, "linux,initrd-start");
 	dt_check_del_prop(dt_chosen, "linux,initrd-end");
 
-	printf("INIT: Initramfs loaded, size: %zu bytes\n", initramfs_size);
+	printf("INIT: Initramfs loaded, base: %p, size: %zu bytes\n",
+			boot_res.initramfs_base, boot_res.initramfs_size);
 
 	dt_add_property_u64(dt_chosen, "linux,initrd-start",
-			(uint64_t)INITRAMFS_LOAD_BASE);
+			    (uint64_t)boot_res.initramfs_base);
 	dt_add_property_u64(dt_chosen, "linux,initrd-end",
-			(uint64_t)INITRAMFS_LOAD_BASE + initramfs_size);
+			    (uint64_t)boot_res.initramfs_base +
+				  boot_res.initramfs_size);
 }
 
 int64_t mem_dump_free(void);
@@ -553,6 +582,23 @@ void __noreturn load_and_boot_kernel(bool is_reboot)
 	start_kernel(kernel_entry, fdt, mem_top);
 }
 
+static int wait_for_async_load(void)
+{
+	cpu_wait_job(load_boot_resource_job, true);
+	prlog(PR_PRINTF, "Completed async job. boot_res.success = %i, \
+			kernel_base %p, size %lu \n",
+			boot_res.success, boot_res.kernel_base,
+			boot_res.kernel_size);
+
+	/* Set new local values for kernel base and size */
+	if (boot_res.kernel_loaded) {
+		kernel_entry = (uint64_t)boot_res.kernel_base;
+		kernel_size  = boot_res.kernel_size;
+	}
+
+	return OPAL_SUCCESS;
+}
+
 static void dt_fixups(void)
 {
 	struct dt_node *n;
@@ -936,6 +982,10 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
 
 	phb3_preload_vpd();
 	phb3_preload_capp_ucode();
+
+	/* Initialise crc32 tables before trying to decode */
+	xz_crc32_init();
+
 	start_preload_kernel();
 
 	/* NX init */
@@ -978,6 +1028,10 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
 	/* Add the list of interrupts going to OPAL */
 	add_opal_interrupts();
 
+	/* Wait for async job to setup images*/
+	if (load_boot_resource_job)
+		wait_for_async_load();
+
 	/* Now release parts of memory nodes we haven't used ourselves... */
 	mem_region_release_unused();
 
diff --git a/core/platform.c b/core/platform.c
index 2a206c8..63b67c3 100644
--- a/core/platform.c
+++ b/core/platform.c
@@ -261,3 +261,14 @@ int wait_for_resource_loaded(enum resource_id id, uint32_t idx)
 	      id, idx, waited);
 	return r;
 }
+
+/* Start async job to load and setup the boot resources */
+struct cpu_job* start_async_load(struct boot_resources *r)
+{
+	if (!platform.load_done) {
+		printf("PLATFORM: start_async_load not supported on this arch");
+		return NULL;
+	}
+
+	return platform.load_done(r);
+}
diff --git a/hw/fsp/fsp.c b/hw/fsp/fsp.c
index a0c5a78..c564a3e 100644
--- a/hw/fsp/fsp.c
+++ b/hw/fsp/fsp.c
@@ -23,6 +23,7 @@
  * If we are going to support P8 PSI and FSP2, we probably want
  * to split the PSI support from the FSP support proper first.
  */
+#include <skiboot.h>
 #include <stdarg.h>
 #include <processor.h>
 #include <io.h>
@@ -38,6 +39,8 @@
 #include <opal.h>
 #include <opal-msg.h>
 #include <ccan/list/list.h>
+#include <libxz/xz.h>
+#include <string.h>
 
 DEFINE_LOG_ENTRY(OPAL_RC_FSP_POLL_TIMEOUT, OPAL_PLATFORM_ERR_EVT, OPAL_FSP,
 		 OPAL_PLATFORM_FIRMWARE, OPAL_ERROR_PANIC, OPAL_NA);
@@ -2635,3 +2638,59 @@ void fsp_used_by_console(void)
 	lock(&fsp_lock);
 	unlock(&fsp_lock);
 }
+
+struct boot_resources *boot_res;
+static struct cpu_job *fsp_load_res_job = NULL;
+
+static void fsp_setup_boot_resource(void *data __unused)
+{
+	int r, waited;
+	size_t len;
+	void *buf;
+
+	waited = 0;
+	/* Wait for initramfs to load */
+	do {
+		opal_run_pollers();
+		r = fsp_resource_loaded(RESOURCE_ID_INITRAMFS,
+					RESOURCE_SUBID_NONE);
+		if (r != OPAL_BUSY)
+			break;
+		time_wait_ms_nopoll(5);
+		waited += 5;
+	}
+	while (r == OPAL_BUSY);
+
+	boot_res->initramfs_loaded = true;
+	prlog(PR_PRINTF, "FSP: fsp_decode_resource loaded INITRAMFS %u ms\n",
+			waited);
+
+	/* Decode the initramfs*/
+	buf = boot_res->initramfs_base;
+	len = boot_res->initramfs_size;
+
+	r = decode_resource_xz(&buf, &len, NULL);
+	printf("FSP: deocde result r=%i\n", r);
+
+	if (r) {
+		boot_res->initramfs_base = buf;
+		boot_res->initramfs_size = len;
+	}
+
+	boot_res->success = true;
+	return;
+}
+
+struct cpu_job* fsp_load_boot_resource(struct boot_resources *r)
+{
+	boot_res = r;
+	if (fsp_load_res_job)
+		cpu_wait_job(fsp_load_res_job, true);
+
+	fsp_load_res_job = cpu_queue_job(NULL, "fsp_setup_boot_resource",
+					 fsp_setup_boot_resource, NULL);
+
+	cpu_process_local_jobs();
+
+	return fsp_load_res_job;
+}
diff --git a/include/fsp.h b/include/fsp.h
index f75b6ad..74582e6 100644
--- a/include/fsp.h
+++ b/include/fsp.h
@@ -756,6 +756,9 @@ extern int fsp_resource_loaded(enum resource_id id, uint32_t idx);
 extern int fsp_preload_lid(uint32_t lid_no, char *buf, size_t *size);
 extern int fsp_wait_lid_loaded(uint32_t lid_no);
 
+/* Setup boot resources */
+extern struct cpu_job* fsp_load_boot_resource(struct boot_resources *r);
+
 /* FSP console stuff */
 extern void fsp_console_preinit(void);
 extern void fsp_console_init(void);
diff --git a/include/platform.h b/include/platform.h
index 9133204..e8848ca 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -42,6 +42,18 @@ struct bmc_platform {
 	uint32_t ipmi_oem_pnor_access_status;
 };
 
+struct boot_resources {
+	void  *kernel_base;
+	size_t kernel_size;
+	bool   kernel_loaded;
+
+	void  *initramfs_base;
+	size_t initramfs_size;
+	bool   initramfs_loaded;
+	/* Success of loading boot resources */
+	bool    success;
+};
+
 /*
  * Each platform can provide a set of hooks
  * that can affect the generic code
@@ -168,6 +180,16 @@ struct platform {
 	int		(*resource_loaded)(enum resource_id id, uint32_t idx);
 
 	/*
+	 * Returns a pointer to the cpu_job struct.
+	 * load_done is platform specific. On FSP machines we wait for the
+	 * initramfs to load, then decode it.
+	 * On BMC machines we first have to parse and setup the FIT, then
+	 * decode the initramfs.
+	 * This is done asyncronously.
+	 */
+	struct cpu_job* (*load_done)(struct boot_resources *r);
+
+	/*
 	 * Executed just prior to handing control over to the payload.
 	 */
 	void		(*exit)(void);
@@ -210,4 +232,6 @@ extern int wait_for_resource_loaded(enum resource_id id, uint32_t idx);
 
 extern void set_bmc_platform(const struct bmc_platform *bmc);
 
+extern struct cpu_job* start_async_load(struct boot_resources *r);
+
 #endif /* __PLATFORM_H */
