diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index e557cac..f330302 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -1,6 +1,7 @@
 subdir-$(arm32) += arm32
 subdir-$(arm64) += arm64
 subdir-y += platforms
+subdir-$(arm64) += efi
 
 obj-$(EARLY_PRINTK) += early_printk.o
 obj-y += cpu.o
diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
index d22af1c..7650abe 100644
--- a/xen/arch/arm/arm64/head.S
+++ b/xen/arch/arm/arm64/head.S
@@ -24,6 +24,8 @@
 #include <asm/page.h>
 #include <asm/asm_defns.h>
 #include <asm/early_printk.h>
+#include <efi/efierr.h>
+#include <asm/arm64/efibind.h>
 
 #define PT_PT     0xf7f /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=1 P=1 */
 #define PT_MEM    0xf7d /* nG=1 AF=1 SH=11 AP=01 NS=1 ATTR=111 T=0 P=1 */
@@ -104,8 +106,14 @@ GLOBAL(start)
         /*
          * DO NOT MODIFY. Image header expected by Linux boot-loaders.
          */
-        b       real_start           /* branch to kernel start, magic */
-        .long   0                    /* reserved */
+efi_head:
+        /*
+         * This add instruction has no meaningful effect except that
+         * its opcode forms the magic "MZ" signature of a PE/COFF file
+         * that is required for UEFI applications.
+         */
+        add     x13, x18, #0x16
+        b       real_start           /* branch to kernel start */
         .quad   0                    /* Image load offset from start of RAM */
         .quad   0                    /* reserved */
         .quad   0                    /* reserved */
@@ -116,8 +124,113 @@ GLOBAL(start)
         .byte   0x52
         .byte   0x4d
         .byte   0x64
-        .word   0                    /* reserved */
+        .long   pe_header - efi_head        /* Offset to the PE header. */
+
+        /*
+         * Add the PE/COFF header to the file.  The address of this header
+         * is at offset 0x3c in the file, and is part of Linux "Image"
+         * header.  The arm64 Linux Image format is designed to support
+         * being both an 'Image' format binary and a PE/COFF binary.
+         * The PE/COFF format is defined by Microsoft, and is available
+         * from: http://msdn.microsoft.com/en-us/gg463119.aspx
+         * Version 8.3 adds support for arm64 and UEFI usage.
+         */
+
+        .align  3
+pe_header:
+        .ascii  "PE"
+        .short  0
+coff_header:
+        .short  0xaa64                          /* AArch64 */
+        .short  2                               /* nr_sections */
+        .long   0                               /* TimeDateStamp */
+        .long   0                               /* PointerToSymbolTable */
+        .long   1                               /* NumberOfSymbols */
+        .short  section_table - optional_header /* SizeOfOptionalHeader */
+        .short  0x206                           /* Characteristics. */
+                                                /* IMAGE_FILE_DEBUG_STRIPPED | */
+                                                /* IMAGE_FILE_EXECUTABLE_IMAGE | */
+                                                /* IMAGE_FILE_LINE_NUMS_STRIPPED */
+optional_header:
+        .short  0x20b                           /* PE32+ format */
+        .byte   0x02                            /* MajorLinkerVersion */
+        .byte   0x14                            /* MinorLinkerVersion */
+        .long   _end - real_start               /* SizeOfCode */
+        .long   0                               /* SizeOfInitializedData */
+        .long   0                               /* SizeOfUninitializedData */
+        .long   efi_start - efi_head            /* AddressOfEntryPoint */
+        .long   real_start - efi_head           /* BaseOfCode */
+
+extra_header_fields:
+        .quad   0                               /* ImageBase */
+        .long   0x1000                          /* SectionAlignment (4 KByte) */
+        .long   0x8                             /* FileAlignment */
+        .short  0                               /* MajorOperatingSystemVersion */
+        .short  0                               /* MinorOperatingSystemVersion */
+        .short  0                               /* MajorImageVersion */
+        .short  0                               /* MinorImageVersion */
+        .short  0                               /* MajorSubsystemVersion */
+        .short  0                               /* MinorSubsystemVersion */
+        .long   0                               /* Win32VersionValue */
+
+        .long   _end - efi_head                 /* SizeOfImage */
+
+        /* Everything before the kernel image is considered part of the header */
+        .long   real_start - efi_head           /* SizeOfHeaders */
+        .long   0                               /* CheckSum */
+        .short  0xa                             /* Subsystem (EFI application) */
+        .short  0                               /* DllCharacteristics */
+        .quad   0                               /* SizeOfStackReserve */
+        .quad   0                               /* SizeOfStackCommit */
+        .quad   0                               /* SizeOfHeapReserve */
+        .quad   0                               /* SizeOfHeapCommit */
+        .long   0                               /* LoaderFlags */
+        .long   0x6                             /* NumberOfRvaAndSizes */
+
+        .quad   0                               /* ExportTable */
+        .quad   0                               /* ImportTable */
+        .quad   0                               /* ResourceTable */
+        .quad   0                               /* ExceptionTable */
+        .quad   0                               /* CertificationTable */
+        .quad   0                               /* BaseRelocationTable */
+
+        /* Section table */
+section_table:
 
+        /*
+         * The EFI application loader requires a relocation section
+         * because EFI applications must be relocatable.  This is a
+         * dummy section as far as we are concerned.
+         */
+        .ascii  ".reloc"
+        .byte   0
+        .byte   0                               /* end of 0 padding of section name */
+        .long   0
+        .long   0
+        .long   0                               /* SizeOfRawData */
+        .long   0                               /* PointerToRawData */
+        .long   0                               /* PointerToRelocations */
+        .long   0                               /* PointerToLineNumbers */
+        .short  0                               /* NumberOfRelocations */
+        .short  0                               /* NumberOfLineNumbers */
+        .long   0x42100040                      /* Characteristics (section flags) */
+
+
+        .ascii  ".text"
+        .byte   0
+        .byte   0
+        .byte   0                               /* end of 0 padding of section name */
+        .long   _end - real_start               /* VirtualSize */
+        .long   real_start - efi_head           /* VirtualAddress */
+        .long   __init_end_efi - real_start     /* SizeOfRawData */
+        .long   real_start - efi_head           /* PointerToRawData */
+
+        .long   0                /* PointerToRelocations (0 for executables) */
+        .long   0                /* PointerToLineNumbers (0 for executables) */
+        .short  0                /* NumberOfRelocations  (0 for executables) */
+        .short  0                /* NumberOfLineNumbers  (0 for executables) */
+        .long   0xe0500020       /* Characteristics (section flags) */
+        .align  5
 real_start:
         msr   DAIFSet, 0xf           /* Disable all interrupts */
 
@@ -621,6 +734,37 @@ putn:   ret
 ENTRY(lookup_processor_type)
         mov  x0, #0
         ret
+/*
+ *  Function to transition from EFI loader in C, to Xen entry point.
+ *  void noreturn efi_xen_start(void *fdt_ptr);
+ */
+ENTRY(efi_xen_start)
+        /*
+         * Turn off cache and MMU as Xen expects. EFI enables them, but also
+         * mandates a 1:1 (unity) VA->PA mapping, so we can turn off the
+         * MMU while executing EFI code before entering Xen.
+         * The EFI loader calls this to start Xen.
+         * Preserve x0 (fdf pointer) across call to __flush_dcache_all,
+         * restore for entry into Xen.
+         */
+        mov   x20, x0
+        bl    __flush_dcache_all
+        ic    ialluis
+
+        /* Turn off Dcache and MMU */
+        mrs   x0, sctlr_el2
+        bic   x0, x0, #1 << 0        /* clear SCTLR.M */
+        bic   x0, x0, #1 << 2        /* clear SCTLR.C */
+        msr   sctlr_el2, x0
+        isb
+
+        /* Jump to Xen entry point */
+        mov   x0, x20
+        mov   x1, xzr
+        mov   x2, xzr
+        mov   x3, xzr
+        b     real_start
+ENDPROC(efi_xen_start)
 
 /*
  * Local variables:
diff --git a/xen/arch/arm/efi/Makefile b/xen/arch/arm/efi/Makefile
new file mode 100644
index 0000000..e8a93e3
--- /dev/null
+++ b/xen/arch/arm/efi/Makefile
@@ -0,0 +1,4 @@
+CFLAGS += -fshort-wchar
+
+obj-y +=  boot.init.o runtime.o
+
diff --git a/xen/arch/arm/efi/efi-boot.h b/xen/arch/arm/efi/efi-boot.h
new file mode 100644
index 0000000..61cb13a
--- /dev/null
+++ b/xen/arch/arm/efi/efi-boot.h
@@ -0,0 +1,575 @@
+/*
+ * Architecture specific implementation for EFI boot code.  This file
+ * is intended to be included by common/efi/boot.c _only_, and
+ * therefore can define arch specific global variables.
+ */
+#include <xen/device_tree.h>
+#include <xen/libfdt/libfdt.h>
+#include <asm/setup.h>
+
+void noreturn efi_xen_start(void *fdt_ptr);
+
+#define DEVICE_TREE_GUID \
+{0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0}}
+
+static struct file __initdata dtbfile;
+static void __initdata *fdt;
+static void __initdata *memmap;
+
+static int __init setup_chosen_node(void *fdt, int *addr_cells, int *size_cells)
+{
+    int node;
+    const struct fdt_property *prop;
+    int len;
+    uint32_t val;
+
+    if ( !fdt || !addr_cells || !size_cells )
+        return -1;
+
+    /* locate chosen node, which is where we add Xen module info. */
+    node = fdt_subnode_offset(fdt, 0, "chosen");
+    if ( node < 0 )
+    {
+        node = fdt_add_subnode(fdt, 0, "chosen");
+        if ( node < 0 )
+            return node;
+    }
+
+    /* Get or set #address-cells and #size-cells */
+    prop = fdt_get_property(fdt, node, "#address-cells", &len);
+    if ( !prop )
+    {
+        val = cpu_to_fdt32(2);
+        if ( fdt_setprop(fdt, node, "#address-cells", &val, sizeof(val)) )
+            return -1;
+        *addr_cells = 2;
+    }
+    else
+        *addr_cells = fdt32_to_cpu(*((uint32_t *)prop->data));
+
+    prop = fdt_get_property(fdt, node, "#size-cells", &len);
+    if ( !prop )
+    {
+        val = cpu_to_fdt32(2);
+        if ( fdt_setprop(fdt, node, "#size-cells", &val, sizeof(val)) )
+            return -1;
+        *size_cells = 2;
+    }
+    else
+        *size_cells = fdt32_to_cpu(*((uint32_t *)prop->data));
+
+    /*
+     * Make sure ranges is empty if it exists, otherwise create empty ranges
+     * property.
+     */
+    prop = fdt_get_property(fdt, node, "ranges", &len);
+    if ( !prop )
+    {
+        val = cpu_to_fdt32(0);
+        if ( fdt_setprop(fdt, node, "ranges", &val, 0) )
+            return -1;
+    }
+    else if ( fdt32_to_cpu(prop->len) )
+            return -1;  /* Non-empty ranges property */
+    return node;
+}
+
+/*
+ * Set a single 'reg' property taking into account the
+ * configured addr and size cell sizes.
+ */
+static int __init fdt_set_reg(void *fdt, int node, int addr_cells,
+                              int size_cells, uint64_t addr, uint64_t len)
+{
+    __be32 val[4]; /* At most 2 64 bit values to be stored */
+    __be32 *cellp;
+
+    /*
+     * Make sure that the values provided can be represented in
+     * the reg property, and sizes are valid.
+     */
+    if ( addr_cells < 1 || addr_cells > 2 || size_cells < 1 || size_cells > 2 )
+        return -1;
+    if ( addr_cells == 1 && (addr >> 32) )
+        return -1;
+    if ( size_cells == 1 && (len >> 32) )
+        return -1;
+
+    cellp = (__be32 *)val;
+    dt_set_cell(&cellp, addr_cells, addr);
+    dt_set_cell(&cellp, size_cells, len);
+
+    return(fdt_setprop(fdt, node, "reg", val, sizeof(*cellp) * (cellp - val)));
+}
+
+static void __init *lookup_fdt_config_table(EFI_SYSTEM_TABLE *sys_table)
+{
+    const EFI_GUID fdt_guid = DEVICE_TREE_GUID;
+    EFI_CONFIGURATION_TABLE *tables;
+    void *fdt = NULL;
+    int i;
+
+    tables = sys_table->ConfigurationTable;
+    for ( i = 0; i < sys_table->NumberOfTableEntries; i++ )
+    {
+        if ( match_guid(&tables[i].VendorGuid, &fdt_guid) )
+        {
+            fdt = tables[i].VendorTable;
+            break;
+        }
+    }
+    return fdt;
+}
+
+static EFI_STATUS __init efi_process_memory_map_bootinfo(EFI_MEMORY_DESCRIPTOR *map,
+                                                UINTN mmap_size,
+                                                UINTN desc_size)
+{
+    int Index;
+    int i = 0;
+    EFI_MEMORY_DESCRIPTOR *desc_ptr = map;
+
+    for ( Index = 0; Index < (mmap_size / desc_size); Index++ )
+    {
+        if ( desc_ptr->Type == EfiConventionalMemory
+             || desc_ptr->Type == EfiBootServicesCode
+             || desc_ptr->Type == EfiBootServicesData )
+        {
+            bootinfo.mem.bank[i].start = desc_ptr->PhysicalStart;
+            bootinfo.mem.bank[i].size = desc_ptr->NumberOfPages * EFI_PAGE_SIZE;
+            if ( ++i >= NR_MEM_BANKS )
+            {
+                PrintStr(L"Warning: All ");
+                DisplayUint(NR_MEM_BANKS, -1);
+                PrintStr(L" bootinfo mem banks exhausted.\r\n");
+                break;
+            }
+        }
+        desc_ptr = NextMemoryDescriptor(desc_ptr, desc_size);
+    }
+
+    bootinfo.mem.nr_banks = i;
+    return EFI_SUCCESS;
+}
+
+/*
+ * Add the FDT nodes for the standard EFI information, which consist
+ * of the System table address, the address of the final EFI memory map,
+ * and memory map information.
+ */
+EFI_STATUS __init fdt_add_uefi_nodes(EFI_SYSTEM_TABLE *sys_table,
+                                            void *fdt,
+                                            EFI_MEMORY_DESCRIPTOR *memory_map,
+                                            UINTN map_size,
+                                            UINTN desc_size,
+                                            UINT32 desc_ver)
+{
+    int node;
+    int status;
+    u32 fdt_val32;
+    u64 fdt_val64;
+    int prev;
+    int num_rsv;
+
+    /*
+     * Delete any memory nodes present.  The EFI memory map is the only
+     * memory description provided to Xen.
+     */
+    prev = 0;
+    for (;;)
+    {
+        const char *type;
+        int len;
+
+        node = fdt_next_node(fdt, prev, NULL);
+        if ( node < 0 )
+            break;
+
+        type = fdt_getprop(fdt, node, "device_type", &len);
+        if ( type && strncmp(type, "memory", len) == 0 )
+        {
+            fdt_del_node(fdt, node);
+            continue;
+        }
+
+        prev = node;
+    }
+
+   /*
+    * Delete all memory reserve map entries. When booting via UEFI,
+    * kernel will use the UEFI memory map to find reserved regions.
+    */
+   num_rsv = fdt_num_mem_rsv(fdt);
+   while ( num_rsv-- > 0 )
+       fdt_del_mem_rsv(fdt, num_rsv);
+
+    /* Add FDT entries for EFI runtime services in chosen node. */
+    node = fdt_subnode_offset(fdt, 0, "chosen");
+    if ( node < 0 )
+    {
+        node = fdt_add_subnode(fdt, 0, "chosen");
+        if ( node < 0 )
+        {
+            status = node; /* node is error code when negative */
+            goto fdt_set_fail;
+        }
+    }
+
+    fdt_val64 = cpu_to_fdt64((u64)(uintptr_t)sys_table);
+    status = fdt_setprop(fdt, node, "linux,uefi-system-table",
+                         &fdt_val64, sizeof(fdt_val64));
+    if ( status )
+        goto fdt_set_fail;
+
+    fdt_val64 = cpu_to_fdt64((u64)(uintptr_t)memory_map);
+    status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
+                         &fdt_val64,  sizeof(fdt_val64));
+    if ( status )
+        goto fdt_set_fail;
+
+    fdt_val32 = cpu_to_fdt32(map_size);
+    status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
+                         &fdt_val32,  sizeof(fdt_val32));
+    if ( status )
+        goto fdt_set_fail;
+
+    fdt_val32 = cpu_to_fdt32(desc_size);
+    status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
+                         &fdt_val32, sizeof(fdt_val32));
+    if ( status )
+        goto fdt_set_fail;
+
+    fdt_val32 = cpu_to_fdt32(desc_ver);
+    status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
+                         &fdt_val32, sizeof(fdt_val32));
+    if ( status )
+        goto fdt_set_fail;
+
+    return EFI_SUCCESS;
+
+fdt_set_fail:
+    if ( status == -FDT_ERR_NOSPACE )
+        return EFI_BUFFER_TOO_SMALL;
+
+    return EFI_LOAD_ERROR;
+}
+
+/*
+ * Allocates new memory for a larger FDT, and frees existing memory if
+ * struct file size is non-zero.  Updates file struct with new memory
+ * address/size for later freeing.  If fdtfile.ptr is NULL, an empty FDT
+ * is created.
+ */
+static void __init *fdt_increase_size(struct file *fdtfile, int add_size)
+{
+    EFI_STATUS status;
+    EFI_PHYSICAL_ADDRESS fdt_addr;
+    int fdt_size;
+    int pages;
+    void *new_fdt;
+
+    if ( fdtfile->ptr )
+        fdt_size = fdt_totalsize(fdtfile->ptr);
+    else
+        fdt_size = 0;
+
+    pages = PFN_UP(fdt_size + add_size);
+    status = efi_bs->AllocatePages(AllocateAnyPages, EfiLoaderData,
+                                   pages, &fdt_addr);
+
+    if ( status != EFI_SUCCESS )
+        return NULL;
+
+    new_fdt = (void *)fdt_addr;
+
+    if ( fdt_size )
+    {
+        if ( fdt_open_into(dtbfile.ptr, new_fdt, pages * EFI_PAGE_SIZE) )
+            return NULL;
+    }
+    else
+    {
+        /*
+         * Create an empty FDT if not provided one, which is the expected case
+         * when booted from the UEFI shell on an ACPI only system.  We will use
+         * the FDT to pass the EFI information to Xen, as well as nodes for
+         * any modules the stub loads.  The ACPI tables are part of the UEFI
+         * system table that is passed in the FDT.
+         */
+        if ( fdt_create_empty_tree(new_fdt, pages * EFI_PAGE_SIZE) )
+            return NULL;
+    }
+
+    /*
+     * Now that we have the new FDT allocated and copied, free the
+     * original and update the struct file so that the error handling
+     * code will free it.  If the original FDT came from a configuration
+     * table, we don't own that memory and can't free it.
+     */
+    if ( dtbfile.size )
+        efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size));
+
+    /* Update 'file' info for new memory so we clean it up on error exits */
+    dtbfile.addr = fdt_addr;
+    dtbfile.size = pages * EFI_PAGE_SIZE;
+    return new_fdt;
+}
+
+static void __init efi_arch_relocate_image(unsigned long delta)
+{
+}
+
+static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
+                                               void *map,
+                                               UINTN map_size,
+                                               UINTN desc_size,
+                                               UINT32 desc_ver)
+{
+    EFI_STATUS status;
+
+    status = efi_process_memory_map_bootinfo(map, map_size, desc_size);
+    if ( EFI_ERROR(status) )
+        blexit(L"EFI memory map processing failed");
+
+    status = fdt_add_uefi_nodes(SystemTable, fdt, map, map_size, desc_size,
+                                desc_ver);
+    if ( EFI_ERROR(status) )
+        PrintErrMesg(L"Updating FDT failed\r\n", status);
+}
+
+static void __init efi_arch_pre_exit_boot(void)
+{
+}
+
+static void __init efi_arch_post_exit_boot(void)
+{
+    efi_xen_start(fdt);
+}
+
+static void __init efi_arch_cfg_file_early(EFI_FILE_HANDLE dir_handle, char *section)
+{
+    union string name;
+
+    /*
+     * The DTB must be processed before any other entries in the configuration
+     * file, as the DTB is updated as modules are loaded.
+     */
+    name.s = get_value(&cfg, section, "dtb");
+    if ( name.s )
+    {
+        split_string(name.s);
+        read_file(dir_handle, s2w(&name), &dtbfile, NULL);
+            blexit(NULL);
+        efi_bs->FreePool(name.w);
+    }
+    fdt = fdt_increase_size(&dtbfile, cfg.size + EFI_PAGE_SIZE);
+    if ( !fdt )
+        blexit(L"Unable to create new FDT");
+}
+
+static void __init efi_arch_cfg_file_late(EFI_FILE_HANDLE dir_handle, char *section)
+{
+}
+
+static void *__init efi_arch_allocate_mmap_buffer(UINTN map_size)
+{
+    void *ptr;
+    EFI_STATUS status;
+
+    status = efi_bs->AllocatePool(EfiLoaderData, map_size + EFI_PAGE_SIZE, &ptr);
+    if ( status != EFI_SUCCESS )
+        return NULL;
+    return ptr;
+}
+
+static void __init efi_arch_edd(void)
+{
+}
+
+static void __init efi_arch_memory_setup(void)
+{
+}
+
+static void __init efi_arch_handle_cmdline(CHAR16 *image_name,
+                                           CHAR16 *cmdline_options,
+                                           char *cfgfile_options)
+{
+    union string name;
+    char *buf;
+    EFI_STATUS status;
+    int prop_len;
+    int chosen;
+
+    /* locate chosen node, which is where we add Xen module info. */
+    chosen = fdt_subnode_offset(fdt, 0, "chosen");
+    if ( chosen < 0 )
+        blexit(L"Unable to find chosen node");
+
+    status = efi_bs->AllocatePool(EfiBootServicesData, EFI_PAGE_SIZE, (void **)&buf);
+    if ( EFI_ERROR(status) )
+        PrintErrMesg(L"Unable to allocate string buffer\r\n", status);
+
+    if ( image_name )
+    {
+        name.w = image_name;
+        w2s(&name);
+    }
+    else
+        name.s = "xen";
+
+    prop_len = 0;
+    prop_len += snprintf(buf + prop_len,
+                           EFI_PAGE_SIZE - prop_len, "%s", name.s);
+    if ( prop_len >= EFI_PAGE_SIZE )
+        blexit(L"FDT string overflow");
+
+    if ( cfgfile_options )
+    {
+        prop_len += snprintf(buf + prop_len,
+                               EFI_PAGE_SIZE - prop_len, " %s", cfgfile_options);
+        if ( prop_len >= EFI_PAGE_SIZE )
+            blexit(L"FDT string overflow");
+    }
+
+    if ( cmdline_options )
+    {
+        name.w = cmdline_options;
+        w2s(&name);
+    }
+    else
+        name.s = NULL;
+
+    if ( name.s )
+    {
+        prop_len += snprintf(buf + prop_len,
+                               EFI_PAGE_SIZE - prop_len, " %s", name.s);
+        if ( prop_len >= EFI_PAGE_SIZE )
+            blexit(L"FDT string overflow");
+    }
+
+    if ( fdt_setprop_string(fdt, chosen, "xen,xen-bootargs", buf) < 0 )
+        blexit(L"Unable to set xen,xen-bootargs property.");
+
+    efi_bs->FreePool(buf);
+}
+
+static void __init efi_arch_handle_module(struct file *file, const CHAR16 *name,
+                                          char *options)
+{
+    int node;
+    int chosen;
+    int addr_len, size_len;
+
+    if ( file == &dtbfile )
+        return;
+    chosen = setup_chosen_node(fdt, &addr_len, &size_len);
+    if ( chosen < 0 )
+        blexit(L"Unable to setup chosen node");
+
+    if ( file == &ramdisk )
+    {
+        char ramdisk_compat[] = "multiboot,ramdisk\0multiboot,module";
+        node = fdt_add_subnode(fdt, chosen, "ramdisk");
+        if ( node < 0 )
+            blexit(L"Unable to add ramdisk FDT node.");
+        if ( fdt_setprop(fdt, node, "compatible", ramdisk_compat,
+                         sizeof(ramdisk_compat)) < 0 )
+            blexit(L"Unable to set compatible property.");
+        if ( fdt_set_reg(fdt, node, addr_len, size_len, ramdisk.addr,
+                    ramdisk.size) < 0 )
+            blexit(L"Unable to set reg property.");
+    }
+    else if ( file == &xsm )
+    {
+        char xsm_compat[] = "xen,xsm-policy\0multiboot,module";
+        node = fdt_add_subnode(fdt, chosen, "xsm");
+        if ( node < 0 )
+            blexit(L"Unable to add xsm FDT node.");
+        if ( fdt_setprop(fdt, node, "compatible", xsm_compat,
+                         sizeof(xsm_compat)) < 0 )
+            blexit(L"Unable to set compatible property.");
+        if ( fdt_set_reg(fdt, node, addr_len, size_len, xsm.addr,
+                    xsm.size) < 0 )
+            blexit(L"Unable to set reg property.");
+    }
+    else if ( file == &kernel )
+    {
+        char kernel_compat[] = "multiboot,kernel\0multiboot,module";
+        node = fdt_add_subnode(fdt, chosen, "kernel");
+        if ( node < 0 )
+            blexit(L"Unable to add dom0 FDT node.");
+        if ( fdt_setprop(fdt, node, "compatible", kernel_compat,
+                         sizeof(kernel_compat)) < 0 )
+            blexit(L"Unable to set compatible property.");
+        if ( options && fdt_setprop_string(fdt, node, "bootargs", options) < 0 )
+            blexit(L"Unable to set bootargs property.");
+        if ( fdt_set_reg(fdt, node, addr_len, size_len, kernel.addr,
+                         kernel.size) < 0 )
+            blexit(L"Unable to set reg property.");
+    }
+    else
+        blexit(L"Unknown module type");
+}
+
+static void __init efi_arch_cpu(void)
+{
+}
+
+static void __init efi_arch_blexit(void)
+{
+    if ( dtbfile.addr && dtbfile.size )
+        efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size));
+    if ( memmap )
+        efi_bs->FreePool(memmap);
+}
+
+static void __init efi_arch_load_addr_check(EFI_LOADED_IMAGE *loaded_image)
+{
+    if ( (unsigned long)loaded_image->ImageBase & ((1 << 12) - 1) )
+        blexit(L"Xen must be loaded at a 4 KByte boundary.");
+}
+
+static bool_t __init efi_arch_use_config_file(EFI_SYSTEM_TABLE *SystemTable)
+{
+    /*
+     * For arm, we may get a device tree from GRUB (or other bootloader)
+     * that contains modules that have already been loaded into memory.  In
+     * this case, we do not use a configuration file, and rely on the
+     * bootloader to have loaded all required modules and appropriate
+     * options.
+     */
+
+    fdt = lookup_fdt_config_table(SystemTable);
+    dtbfile.ptr = fdt;
+    dtbfile.size = 0;  /* Config table memory can't be freed, so set size to 0 */
+    if ( !fdt || fdt_node_offset_by_compatible(fdt, 0, "multiboot,module") < 0 )
+    {
+        /*
+         * We either have no FDT, or one without modules, so we must have a
+         * Xen EFI configuration file to specify modules.  (dom0 required)
+         */
+        return 1;
+    }
+    PrintStr(L"Using modules provided by bootloader in FDT\r\n");
+    /* We have modules already defined in fdt, just add space. */
+    fdt = fdt_increase_size(&dtbfile, EFI_PAGE_SIZE);
+    return 0;
+}
+
+static void __init efi_arch_console_init(UINTN cols, UINTN rows)
+{
+}
+
+static void __init efi_arch_video_init(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
+                                       UINTN info_size,
+                                       EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info)
+{
+}
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index 079e085..d8b0cfe 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -135,6 +135,7 @@ SECTIONS
        *(.xsm_initcall.init)
        __xsm_initcall_end = .;
   } :text
+  __init_end_efi = .;
   . = ALIGN(STACK_SIZE);
   __init_end = .;
 
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 3d3d76b..c6c0658 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -18,9 +18,17 @@
 #include <xen/string.h>
 #include <xen/stringify.h>
 #include <xen/vga.h>
+#ifdef CONFIG_X86
+/*
+ * Keep this arch-specific modified include in the common file, as moving
+ * it to the arch specific include file would obscure that special care is
+ * taken to include it with __ASSEMBLY__ defined.
+ */
 #define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */
 #include <asm/fixmap.h>
 #undef __ASSEMBLY__
+#endif
+#include <xen/bitops.h>
 
 /* Using SetVirtualAddressMap() is incompatible with kexec: */
 #undef USE_SET_VIRTUAL_ADDRESS_MAP
@@ -66,6 +74,7 @@ static bool_t read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name,
                         struct file *file, char *options);
 static size_t wstrlen(const CHAR16 * s);
 static int set_color(u32 mask, int bpp, u8 *pos, u8 *sz);
+static bool_t match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2);
 
 static EFI_BOOT_SERVICES *__initdata efi_bs;
 static EFI_HANDLE __initdata efi_ih;
@@ -121,7 +130,7 @@ static void __init DisplayUint(UINT64 Val, INTN Width)
     PrintStr(PrintString);
 }
 
-static size_t __init wstrlen(const CHAR16 *s)
+static size_t __init __maybe_unused wstrlen(const CHAR16 *s)
 {
     const CHAR16 *sc;
 
@@ -661,7 +670,7 @@ static void __init setup_efi_pci(void)
     efi_bs->FreePool(handles);
 }
 
-static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
+static int __init __maybe_unused set_color(u32 mask, int bpp, u8 *pos, u8 *sz)
 {
    if ( bpp < 0 )
        return bpp;
@@ -986,8 +995,10 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
 	       efi.smbios = (long)efi_ct[i].VendorTable;
     }
 
+#ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
     if (efi.smbios != EFI_INVALID_TABLE_ADDR)
         dmi_efi_get_table((void *)(long)efi.smbios);
+#endif
 
     /* Collect PCI ROM contents. */
     setup_efi_pci();
@@ -1058,6 +1069,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     for( ; ; ); /* not reached */
 }
 
+#ifndef CONFIG_ARM /* TODO - runtime service support */
 #ifndef USE_SET_VIRTUAL_ADDRESS_MAP
 static __init void copy_mapping(unsigned long mfn, unsigned long end,
                                 bool_t (*is_valid)(unsigned long smfn,
@@ -1283,3 +1295,4 @@ void __init efi_init_memory(void)
         efi_l4_pgtable[i] = idle_pg_table[i];
 #endif
 }
+#endif
diff --git a/xen/common/efi/efi.h b/xen/common/efi/efi.h
index a80d5f1..bee3b77 100644
--- a/xen/common/efi/efi.h
+++ b/xen/common/efi/efi.h
@@ -28,7 +28,9 @@ extern EFI_RUNTIME_SERVICES *efi_rs;
 extern UINTN efi_memmap_size, efi_mdesc_size;
 extern void *efi_memmap;
 
+#ifdef CONFIG_X86
 extern l4_pgentry_t *efi_l4_pgtable;
+#endif
 
 extern const struct efi_pci_rom *efi_pci_roms;
 
diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c
index 166852d..6acdcec 100644
--- a/xen/common/efi/runtime.c
+++ b/xen/common/efi/runtime.c
@@ -4,17 +4,23 @@
 #include <xen/guest_access.h>
 #include <xen/irq.h>
 #include <xen/time.h>
+#ifdef CONFIG_X86
 #include <asm/mc146818rtc.h>
+#endif
 
 DEFINE_XEN_GUEST_HANDLE(CHAR16);
 
 #ifndef COMPAT
 
+#ifdef CONFIG_ARM  /* Disabled until runtime services implemented */
+const bool_t efi_enabled = 0;
+#else
 # include <asm/i387.h>
 # include <asm/xstate.h>
 # include <public/platform.h>
 
 const bool_t efi_enabled = 1;
+#endif
 
 unsigned int __read_mostly efi_num_ct;
 EFI_CONFIGURATION_TABLE *__read_mostly efi_ct;
@@ -24,7 +30,6 @@ unsigned int __read_mostly efi_fw_revision;
 const CHAR16 *__read_mostly efi_fw_vendor;
 
 EFI_RUNTIME_SERVICES *__read_mostly efi_rs;
-static DEFINE_SPINLOCK(efi_rs_lock);
 
 UINTN __read_mostly efi_memmap_size;
 UINTN __read_mostly efi_mdesc_size;
@@ -41,10 +46,12 @@ struct efi __read_mostly efi = {
 	.smbios = EFI_INVALID_TABLE_ADDR,
 };
 
-l4_pgentry_t *__read_mostly efi_l4_pgtable;
-
 const struct efi_pci_rom *__read_mostly efi_pci_roms;
 
+#ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
+static DEFINE_SPINLOCK(efi_rs_lock);
+l4_pgentry_t *__read_mostly efi_l4_pgtable;
+
 unsigned long efi_rs_enter(void)
 {
     static const u16 fcw = FCW_DEFAULT;
@@ -134,8 +141,10 @@ void efi_reset_system(bool_t warm)
     printk(XENLOG_WARNING "EFI: could not reset system (%#lx)\n", status);
 }
 
+#endif /* CONFIG_ARM */
 #endif
 
+#ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
 int efi_get_info(uint32_t idx, union xenpf_efi_info *info)
 {
     unsigned int i, n;
@@ -545,3 +554,4 @@ int efi_runtime_call(struct xenpf_efi_runtime_call *op)
 
     return rc;
 }
+#endif
diff --git a/xen/include/asm-arm/arm64/efibind.h b/xen/include/asm-arm/arm64/efibind.h
new file mode 100644
index 0000000..2b0bf40
--- /dev/null
+++ b/xen/include/asm-arm/arm64/efibind.h
@@ -0,0 +1,216 @@
+/*++
+
+Copyright (c) 1998  Intel Corporation
+
+Module Name:
+
+    efefind.h
+
+Abstract:
+
+    EFI to compile bindings
+
+
+
+
+Revision History
+
+--*/
+
+#ifndef __GNUC__
+#pragma pack()
+#endif
+
+#define EFIERR(a)           (0x8000000000000000 | a)
+#define EFI_ERROR_MASK      0x8000000000000000
+#define EFIERR_OEM(a)       (0xc000000000000000 | a)
+
+#define BAD_POINTER         0xFBFBFBFBFBFBFBFB
+#define MAX_ADDRESS         0xFFFFFFFFFFFFFFFF
+
+#define EFI_STUB_ERROR      MAX_ADDRESS
+
+#ifndef __ASSEMBLY__
+//
+// Basic int types of various widths
+//
+
+#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L )
+
+    // No ANSI C 1999/2000 stdint.h integer width declarations
+
+    #if defined(__GNUC__)
+        typedef unsigned long long  uint64_t __attribute__((aligned (8)));
+        typedef long long           int64_t __attribute__((aligned (8)));
+        typedef unsigned int        uint32_t;
+        typedef int                 int32_t;
+        typedef unsigned short      uint16_t;
+        typedef short               int16_t;
+        typedef unsigned char       uint8_t;
+        typedef char                int8_t;
+    #elif defined(UNIX_LP64)
+
+        /*  Use LP64 programming model from C_FLAGS for integer width declarations */
+
+       typedef unsigned long       uint64_t;
+       typedef long                int64_t;
+       typedef unsigned int        uint32_t;
+       typedef int                 int32_t;
+       typedef unsigned short      uint16_t;
+       typedef short               int16_t;
+       typedef unsigned char       uint8_t;
+       typedef char                int8_t;
+    #else
+
+       /*  Assume P64 programming model from C_FLAGS for integer width declarations */
+
+       typedef unsigned long long  uint64_t __attribute__((aligned (8)));
+       typedef long long           int64_t __attribute__((aligned (8)));
+       typedef unsigned int        uint32_t;
+       typedef int                 int32_t;
+       typedef unsigned short      uint16_t;
+       typedef short               int16_t;
+       typedef unsigned char       uint8_t;
+       typedef char                int8_t;
+    #endif
+#endif
+
+//
+// Basic EFI types of various widths
+//
+
+#ifndef __WCHAR_TYPE__
+# define __WCHAR_TYPE__ short
+#endif
+
+typedef uint64_t   UINT64;
+typedef int64_t    INT64;
+
+#ifndef _BASETSD_H_
+    typedef uint32_t   UINT32;
+    typedef int32_t    INT32;
+#endif
+
+typedef uint16_t   UINT16;
+typedef int16_t    INT16;
+typedef uint8_t    UINT8;
+typedef int8_t     INT8;
+typedef __WCHAR_TYPE__ WCHAR;
+
+#undef VOID
+#define VOID    void
+
+
+typedef int64_t    INTN;
+typedef uint64_t   UINTN;
+
+#define POST_CODE(_Data)
+
+
+#define BREAKPOINT()        while (TRUE);    // Make it hang on Bios[Dbg]32
+
+//
+// Pointers must be aligned to these address to function
+//
+
+#define MIN_ALIGNMENT_SIZE  4
+
+#define ALIGN_VARIABLE(Value ,Adjustment) \
+            (UINTN)Adjustment = 0; \
+            if((UINTN)Value % MIN_ALIGNMENT_SIZE) \
+                (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \
+            Value = (UINTN)Value + (UINTN)Adjustment
+
+
+//
+// Define macros to build data structure signatures from characters.
+//
+
+#define EFI_SIGNATURE_16(A,B)             ((A) | (B<<8))
+#define EFI_SIGNATURE_32(A,B,C,D)         (EFI_SIGNATURE_16(A,B)     | (EFI_SIGNATURE_16(C,D)     << 16))
+#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
+
+#define EXPORTAPI
+
+
+//
+// EFIAPI - prototype calling convention for EFI function pointers
+// BOOTSERVICE - prototype for implementation of a boot service interface
+// RUNTIMESERVICE - prototype for implementation of a runtime service interface
+// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service
+// RUNTIME_CODE - pragma macro for declaring runtime code
+//
+
+#ifndef EFIAPI                  // Forces EFI calling conventions reguardless of compiler options
+        #define EFIAPI          // Substitute expresion to force C calling convention
+#endif
+
+#define BOOTSERVICE
+//#define RUNTIMESERVICE(proto,a)    alloc_text("rtcode",a); proto a
+//#define RUNTIMEFUNCTION(proto,a)   alloc_text("rtcode",a); proto a
+#define RUNTIMESERVICE
+#define RUNTIMEFUNCTION
+
+
+#define RUNTIME_CODE(a)         alloc_text("rtcode", a)
+#define BEGIN_RUNTIME_DATA()    data_seg("rtdata")
+#define END_RUNTIME_DATA()      data_seg("")
+
+#define VOLATILE    volatile
+
+#define MEMORY_FENCE()
+
+
+//
+// When build similiar to FW, then link everything together as
+// one big module.
+//
+
+#define EFI_DRIVER_ENTRY_POINT(InitFunction)    \
+    UINTN                                       \
+    InitializeDriver (                          \
+        VOID    *ImageHandle,                   \
+        VOID    *SystemTable                    \
+        )                                       \
+    {                                           \
+        return InitFunction(ImageHandle,        \
+                SystemTable);                   \
+    }                                           \
+                                                \
+    EFI_STATUS efi_main(                        \
+        EFI_HANDLE image,                       \
+        EFI_SYSTEM_TABLE *systab                \
+        ) __attribute__((weak,                  \
+                alias ("InitializeDriver")));
+
+#define LOAD_INTERNAL_DRIVER(_if, type, name, entry)    \
+        (_if)->LoadInternal(type, name, entry)
+
+
+//
+// Some compilers don't support the forward reference construct:
+//  typedef struct XXXXX
+//
+// The following macro provide a workaround for such cases.
+//
+#ifdef NO_INTERFACE_DECL
+#define INTERFACE_DECL(x)
+#else
+#ifdef __GNUC__
+#define INTERFACE_DECL(x) struct x
+#else
+#define INTERFACE_DECL(x) typedef struct x
+#endif
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/efibind.h b/xen/include/asm-arm/efibind.h
new file mode 100644
index 0000000..09dca7a
--- /dev/null
+++ b/xen/include/asm-arm/efibind.h
@@ -0,0 +1,2 @@
+#include <xen/types.h>
+#include <asm/arm64/efibind.h>
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index 36e5704..ba5a67d 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -3,7 +3,7 @@
 
 #include <public/version.h>
 
-#define NR_MEM_BANKS 8
+#define NR_MEM_BANKS 64
 
 #define MAX_MODULES 5 /* Current maximum useful modules */
 
