>From ad0359896826878f3394a3321418ab7f7ebd2adb Mon Sep 17 00:00:00 2001
From: Fu Wei <fu.wei@linaro.org>
Date: Wed, 12 Mar 2014 15:39:26 +0800
Subject: [PATCH] Add multiboot/module command support in multiboot module for
 aarch64.     -This implementation follow <Multiboot on ARM Specification>:   
   http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot  
    and xen/docs/misc/arm/device-tree/booting.txt in Xen source code.     -The
 example of this support is <How to boot Xen with GRUB on AArch64 FVP_base
 model>:     
 https://wiki.linaro.org/LEG/Engineering/Grub2/Xen_booting_on_FVP_Base_AEMv8A

---
 grub-core/Makefile.am                  |   4 +
 grub-core/Makefile.core.def            |   6 +
 grub-core/kern/arm64/cache_flush.S     |  40 +++
 grub-core/kern/arm64/misc.c            |  34 +++
 grub-core/kern/arm64/misc_irq.S        |  35 +++
 grub-core/loader/arm64/linux.c         |  39 +++
 grub-core/loader/arm64/multiboot.c     | 462 +++++++++++++++++++++++++++++++++
 grub-core/loader/arm64/multiboot_xen.c | 373 ++++++++++++++++++++++++++
 include/grub/arm64/linux.h             |  12 +
 include/grub/arm64/multiboot.h         |  86 ++++++
 include/grub/arm64/multiboot_xen.h     |  80 ++++++
 include/grub/arm64/system.h            |   7 +
 12 files changed, 1178 insertions(+)
 create mode 100644 grub-core/kern/arm64/misc.c
 create mode 100644 grub-core/kern/arm64/misc_irq.S
 create mode 100644 grub-core/loader/arm64/multiboot.c
 create mode 100644 grub-core/loader/arm64/multiboot_xen.c
 create mode 100644 include/grub/arm64/multiboot.h
 create mode 100644 include/grub/arm64/multiboot_xen.h
 create mode 100644 include/grub/arm64/system.h

diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 5c087c8..5a82b64 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -238,6 +238,10 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
 endif
 
+if COND_arm64
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm64/system.h
+endif
+
 if COND_emu
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 42443bc..5670fd3 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -269,6 +269,8 @@ kernel = {
   arm64 = kern/arm64/cache_flush.S;
   arm64 = kern/arm64/dl.c;
   arm64 = kern/arm64/dl_helper.c;
+  arm64 = kern/arm64/misc.c;
+  arm64 = kern/arm64/misc_irq.S;
 
   emu = disk/host.c;
   emu = kern/emu/cache_s.S;
@@ -1673,6 +1675,10 @@ module = {
   ia64_efi = loader/ia64/efi/linux.c;
   arm = loader/arm/linux.c;
   arm64 = loader/arm64/linux.c;
+  arm64 = loader/arm64/multiboot.c;
+  arm64 = loader/arm64/multiboot_xen.c;
+  arm64_cppflags = "-DGRUB_LINUX_MULTIBOOT";
+
   fdt = lib/fdt.c;
   common = loader/linux.c;
   common = lib/cmdline.c;
diff --git a/grub-core/kern/arm64/cache_flush.S b/grub-core/kern/arm64/cache_flush.S
index e064f7e..e6e3576 100644
--- a/grub-core/kern/arm64/cache_flush.S
+++ b/grub-core/kern/arm64/cache_flush.S
@@ -21,6 +21,10 @@
 	.file	"cache_flush.S"
 	.text
 
+.set CTRL_M_BIT,      (1 << 0)
+.set CTRL_C_BIT,      (1 << 2)
+.set CTRL_I_BIT,      (1 << 12)
+
 /*
  * Simple cache maintenance functions
  */
@@ -53,3 +57,39 @@ FUNCTION(grub_arch_invalidate_icache_range)
 2:	dsb	ish
 	isb
 	ret
+
+FUNCTION(grub_arch_disable_caches_mmu)
+    mrs    x1, CurrentEL
+    cmp    x1, #0xC
+    b.eq   3f
+    cmp    x1, #0x8
+    b.eq   2f
+    cmp    x1, #0x4
+    b.ne   .                     // We should never get here
+
+1:  mrs     x0, sctlr_el1        // Get control register EL1
+    b       4f
+2:  mrs     x0, sctlr_el2        // Get control register EL2
+    b       4f
+3:  mrs     x0, sctlr_el3        // Get control register EL3
+
+4:  bic     x0, x0, #CTRL_M_BIT  // Disable MMU
+    bic     x0, x0, #CTRL_C_BIT  // Disable D Cache
+    bic     x0, x0, #CTRL_I_BIT  // Disable I Cache
+
+    mrs    x1, CurrentEL
+    cmp    x1, #0xC
+    b.eq   3f
+    cmp    x1, #0x8
+    b.eq   2f
+    cmp    x1, #0x4
+    b.ne   .                     // We should never get here
+
+1:  msr     sctlr_el1, x0        // Write back control register EL1
+    b       4f
+2:  msr     sctlr_el2, x0        // Write back control register EL2
+    b       4f
+3:  msr     sctlr_el3, x0        // Write back control register EL3
+4:  dsb     sy
+    isb
+    ret
diff --git a/grub-core/kern/arm64/misc.c b/grub-core/kern/arm64/misc.c
new file mode 100644
index 0000000..35ec9af
--- /dev/null
+++ b/grub-core/kern/arm64/misc.c
@@ -0,0 +1,34 @@
+/* misc.c - various system functions for an arm64-based system */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/misc.h>
+#include <grub/cpu/system.h>
+
+void grub_arch_disable_interrupts (void);
+void grub_arch_disable_caches_mmu (void);
+
+void
+grub_arm64_prepare_platform (void)
+{
+  grub_arch_disable_interrupts();
+  grub_arch_disable_caches_mmu();
+
+  grub_dprintf("linux", "Caches and MMU are disabled\n");
+}
+
diff --git a/grub-core/kern/arm64/misc_irq.S b/grub-core/kern/arm64/misc_irq.S
new file mode 100644
index 0000000..60465a5
--- /dev/null
+++ b/grub-core/kern/arm64/misc_irq.S
@@ -0,0 +1,35 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2014  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+
+	.file	"misc.S"
+	.text
+
+.set DAIF_FIQ_BIT,   (1 << 0)
+.set DAIF_IRQ_BIT,   (1 << 1)
+.set DAIF_INT_BITS,  (DAIF_FIQ_BIT | DAIF_IRQ_BIT)
+
+/*
+ * Simple misc maintenance functions
+ */
+
+FUNCTION(grub_arch_disable_interrupts)
+    msr   daifset, #DAIF_INT_BITS
+    isb
+    ret
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
index f1d10a1..53d0a3d 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -26,6 +26,9 @@
 #include <grub/mm.h>
 #include <grub/types.h>
 #include <grub/cpu/linux.h>
+#if defined(GRUB_LINUX_MULTIBOOT)
+  #include <grub/cpu/multiboot.h>
+#endif
 #include <grub/efi/efi.h>
 #include <grub/efi/pe32.h>
 #include <grub/i18n.h>
@@ -38,6 +41,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
 #define GRUB_EFI_PE_MAGIC	0x5A4D
 
 static grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
+grub_efi_guid_t *grub_arm64_linux_fdt_guid_p = &fdt_guid;
 
 static grub_dl_t my_mod;
 static int loaded;
@@ -54,6 +58,32 @@ static grub_addr_t initrd_end;
 static void *loaded_fdt;
 static void *fdt;
 
+/****The accessor functions for dtb and the "loaded" flag****/
+static void get_fdt (void);
+
+int grub_arm64_linux_get_loaded (void)
+{
+    return (loaded);
+}
+
+void grub_arm64_linux_set_loaded (int loaded_flag)
+{
+    loaded = loaded_flag;
+}
+
+grub_dl_t grub_arm64_linux_get_mod(void)
+{
+    return (my_mod);
+}
+
+void *grub_arm64_linux_get_fdt (void)
+{
+    get_fdt ();
+    return (fdt);
+}
+/************************************************************/
+
+
 static void *
 get_firmware_fdt (void)
 {
@@ -476,6 +506,11 @@ GRUB_MOD_INIT (linux)
   cmd_devicetree =
     grub_register_command ("devicetree", grub_cmd_devicetree, 0,
 			   N_("Load DTB file."));
+
+#if defined(GRUB_LINUX_MULTIBOOT)
+  grub_arm64_linux_register_multiboot_command();
+#endif
+
   my_mod = mod;
 }
 
@@ -484,4 +519,8 @@ GRUB_MOD_FINI (linux)
   grub_unregister_command (cmd_linux);
   grub_unregister_command (cmd_initrd);
   grub_unregister_command (cmd_devicetree);
+
+#if defined(GRUB_LINUX_MULTIBOOT)
+  grub_arm64_linux_unregister_multiboot_command();
+#endif
 }
diff --git a/grub-core/loader/arm64/multiboot.c b/grub-core/loader/arm64/multiboot.c
new file mode 100644
index 0000000..821d340
--- /dev/null
+++ b/grub-core/loader/arm64/multiboot.c
@@ -0,0 +1,462 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2014  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/cache.h>
+#include <grub/charset.h>
+#include <grub/command.h>
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/fdt.h>
+#include <grub/linux.h>
+#include <grub/list.h>
+#include <grub/loader.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/cpu/linux.h>
+#include <grub/cpu/multiboot.h>
+#include <grub/cpu/multiboot_xen.h>
+#include <grub/cpu/system.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/pe32.h>
+#include <grub/i18n.h>
+#include <grub/lib/cmdline.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_dl_t linux_mod;
+static multiboot_function_t *multiboot_function;
+static multiboot_module_t kernel = NULL;
+static multiboot_module_t module_head = NULL;
+
+static grub_multiboot_type_t
+identify_kernel_type(grub_file_t file __attribute__ ((unused)))
+{
+  grub_multiboot_type_t type = GRUB_MULTIBOOT_XEN;
+  grub_dprintf ("linux", "Assuming the kernel image launched is xen!\n");
+  /*identify the more supported kernel files here*/
+
+  return (type);
+}
+
+static grub_err_t init_multiboot_function(grub_multiboot_type_t type)
+{
+  switch (type)
+    {
+    case GRUB_MULTIBOOT_XEN:
+      {
+        multiboot_function = &multiboot_function_xen;
+        break;
+      }
+    /*add the more support here*/
+    default:
+      return (grub_error (GRUB_ERR_BAD_ARGUMENT,
+          N_("Unsupported multiboot kernle type!")));
+    }
+
+  return (GRUB_ERR_NONE);
+}
+
+
+static void sync_caches(void)
+{
+  static multiboot_module_t module;
+
+  if (multiboot_function->params_sync_caches)
+    multiboot_function->params_sync_caches();
+
+  FOR_LIST_ELEMENTS (module, module_head) {
+    if (module->start_unaligned && module->size > 0) {
+        grub_arch_sync_caches ((void *) module->start_unaligned,
+            module->size + module->align);
+    }
+    if (module->cmdline && module->cmdline_size > 0) {
+        grub_arch_sync_caches ((void *) module->cmdline, module->cmdline_size);
+    }
+  }
+}
+
+static void *
+finalize_params_multiboot (void)
+{
+  multiboot_module_t module;
+  grub_err_t retval;
+  void *params_blob = NULL;
+
+  /* Set Multiboot Kernel params info */
+  module = (multiboot_module_t) grub_named_list_find
+    (GRUB_AS_NAMED_LIST (module_head), GRUB_MULTIBOOT_KERNEL_NAME);
+  if (module)
+    {
+      kernel = module;
+      if (multiboot_function->prepare_kernel_params)
+        {
+          retval = multiboot_function->prepare_kernel_params (module);
+          if (retval != GRUB_ERR_NONE)
+            goto failure_kernel;
+        }
+
+      grub_list_remove(GRUB_AS_LIST (module));
+
+    } else {
+      grub_dprintf ("linux", "Please load Multiboot Kernel first!\n");
+      goto failure;
+    }
+
+  /* Set module params info */
+  FOR_LIST_ELEMENTS (module, module_head) {
+    if (module->start && module->size > 0){
+        grub_dprintf ("linux", "Module %s @ 0x%lx size:0x%lx\n",
+            module->name, module->start, module->size);
+        if (multiboot_function->prepare_module_params)
+          {
+            retval = multiboot_function->prepare_module_params (module);
+            if (retval != GRUB_ERR_NONE)
+              goto failure_module;
+          }
+    } else {
+      grub_dprintf ("linux", "Module info error: %s!\n", module->name);
+      goto failure_module;
+    }
+  }
+  grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (kernel));
+
+  if (multiboot_function->install_all_params)
+    params_blob = (void *)multiboot_function->install_all_params ();
+
+  if (!params_blob)
+    {
+      goto failure_kernel;
+    } else {
+        return (params_blob);
+    }
+
+failure_module:
+  grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (kernel));
+failure_kernel:
+  if (multiboot_function->clean_all_params)
+    multiboot_function->clean_all_params();
+failure:
+  return (params_blob);
+}
+
+static grub_err_t
+grub_multiboot_boot (void)
+{
+  void *params_blob;
+  kernel_entry_t linuxmain;
+
+  params_blob = finalize_params_multiboot();
+  if (!params_blob)
+    return (grub_error (GRUB_ERR_BAD_OS, "failed to finalize boot params"));
+
+  grub_dprintf ("linux", "Jumping to Multiboot Kernel @ 0x%lx\n",
+      kernel->start);
+
+  /* Boot the ARM64 system.
+   *   Arguments to Multiboot Kernel:
+   *     x0 - address of params blob (e.g. DTB)
+   *     x1 - 0 (reserved for future use)
+   *     x2 - 0 (reserved for future use)
+   *     x3 - 0 (reserved for future use)
+   */
+  linuxmain = (kernel_entry_t) kernel->start;
+
+  sync_caches();
+  grub_arm64_prepare_platform();
+
+  linuxmain (params_blob, 0, 0, 0);
+
+  return (grub_error (GRUB_ERR_BAD_OS, "Multiboot call returned"));
+}
+
+static void
+single_module_unload (multiboot_module_t module)
+{
+  if (module && module->start_unaligned && module->size > 0){
+      grub_efi_free_pages ((grub_efi_physical_address_t) module->start_unaligned,
+          BYTES_TO_PAGES (module->size + module->align));
+  }
+  if (module && module->cmdline && module->cmdline_size > 0)
+    {
+      grub_free (module->cmdline);
+      grub_dprintf ("linux", "Module %s cmdline memory free @ %p size: %d\n",
+          module->name, module->cmdline, module->cmdline_size);
+    }
+  if (module)
+    {
+      if (multiboot_function->clean_extra_info)
+        multiboot_function->clean_extra_info(module);
+      grub_list_remove(GRUB_AS_LIST (module));
+      grub_dprintf ("linux", "Module %s struct memory free @ %p size: 0x%lx\n",
+          module->name, module, sizeof(module));
+      grub_free (module);
+    }
+  return;
+}
+
+static grub_err_t
+grub_module_unload (char *name)
+{
+  multiboot_module_t module;
+
+  if (name) {
+      module = (multiboot_module_t) grub_named_list_find
+          (GRUB_AS_NAMED_LIST (module_head), name);
+      single_module_unload(module);
+  } else {
+      FOR_LIST_ELEMENTS (module, module_head) {
+        single_module_unload(module);
+      }
+  }
+  return (GRUB_ERR_NONE);
+}
+
+static grub_err_t
+grub_multiboot_unload (void)
+{
+  linux_mod = grub_arm64_linux_get_mod();
+  grub_dl_unref (linux_mod);
+
+  grub_arm64_linux_set_loaded(0);
+  grub_module_unload (NULL);
+  if (multiboot_function->clean_all_params)
+    multiboot_function->clean_all_params();
+
+  return (GRUB_ERR_NONE);
+}
+
+static grub_err_t
+grub_module_load (multiboot_module_t module, grub_file_t file,
+    int argc, char *argv[])
+{
+  grub_ssize_t temp = 0;
+
+  module->size = grub_file_size (file);
+  grub_dprintf ("linux", "Multiboot %s file size: 0x%lx\n",
+      module->name, module->size);
+
+  module->start_unaligned = (grub_addr_t) grub_efi_allocate_pages (0,
+      (BYTES_TO_PAGES (module->size + module->align)));
+  if (!module->start_unaligned)
+    {
+      return (grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")));
+    }
+  grub_dprintf ("linux", "Multiboot %s numpages: 0x%lx\n",
+      module->name, BYTES_TO_PAGES (module->size + module->align));
+
+  if (module->align) {
+      module->start = ALIGN_UP(module->start_unaligned, module->align);
+  } else {
+      module->start = module->start_unaligned;
+  }
+  grub_dprintf ("linux", "Multiboot %s address align(0x%lx) from 0x%lx to 0x%lx\n",
+      module->name, module->align, module->start_unaligned, module->start);
+
+  temp = grub_file_read (file, (void *)module->start, module->size);
+  if (temp != (grub_ssize_t) module->size)
+    {
+      grub_dprintf ("linux", "Multiboot %s(%p) load fail size: %ld,(expect  0x%lx)\n",
+        module->name, file, temp, module->size);
+      single_module_unload(module);
+      return (grub_error (GRUB_ERR_BAD_OS,
+          N_("premature end of file %s"), argv[0]));
+    }
+
+  grub_dprintf ("linux", "Multiboot %s loaded to 0x%lx size: 0x%lx\n",
+      module->name, module->start, temp);
+
+  /* Skip the multiboot module file name */
+  {
+    argc--;
+    argv++;
+  }
+  if (argc > 0 && (module->flags & GRUB_MULTIBOOT_FLAGS_CMDLINE)) {
+      module->cmdline_size = grub_loader_cmdline_size (argc, argv);
+      module->cmdline = grub_malloc (module->cmdline_size);
+      if (!module->cmdline)
+        {
+          single_module_unload(module);
+          return (grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")));
+        }
+      grub_create_loader_cmdline (argc, argv,
+          module->cmdline, module->cmdline_size);
+      grub_dprintf ("linux", "Multiboot %s cmdline @ %p %s, size: %d\n",
+          module->name, module->cmdline, module->cmdline, module->cmdline_size);
+  } else {
+      module->cmdline_size = 0;
+      module->cmdline = NULL;
+      grub_dprintf ("linux", "Multiboot %s has not cmdline\n", module->name);
+  }
+
+  return (GRUB_ERR_NONE);
+}
+
+static grub_err_t
+grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
+		 int argc, char *argv[])
+{
+
+  grub_file_t file = 0;
+  multiboot_module_t module = NULL, temp = NULL;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+      goto fail;
+    }
+
+  if (!grub_arm64_linux_get_loaded())
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT,
+          N_("you need to use multiboot command first"));
+      goto fail;
+    }
+
+  module = (multiboot_module_t) grub_malloc (sizeof(struct multiboot_module));
+  if (!module)
+    return (grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")));
+
+  /* for more specific   */
+  if (multiboot_function->init_module_info)
+    {
+      grub_errno = multiboot_function->init_module_info(module_head,
+          module, &argc, &argv);
+      if (grub_errno != GRUB_ERR_NONE)
+        goto fail;
+    }
+  if (module->flags & GRUB_MULTIBOOT_FLAGS_UNIQUE)
+    {
+      temp = grub_named_list_find(GRUB_AS_NAMED_LIST (module_head), module->name);
+      if (temp)
+        single_module_unload(temp);
+    }
+
+  file = grub_file_open (argv[0]);
+  if (!file)
+    goto fail;
+
+  grub_errno = grub_module_load (module, file, argc, argv);
+
+  if (grub_errno == GRUB_ERR_NONE)
+    {
+      grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
+    }
+
+ fail:
+    if (file)
+        grub_file_close (file);
+    if (grub_errno != GRUB_ERR_NONE)
+      {
+        single_module_unload(module);
+      }
+  return (grub_errno);
+}
+
+static grub_err_t
+grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
+		int argc, char *argv[])
+{
+  grub_file_t file = NULL;
+  multiboot_module_t module = NULL;
+  grub_multiboot_type_t multiboot_type = GRUB_MULTIBOOT_OTHER;
+  grub_err_t retval;
+
+  grub_dprintf ("linux", "Multiboot for ARM64 @ %s %s\n", __DATE__,__TIME__);
+
+  linux_mod = grub_arm64_linux_get_mod();
+  grub_dl_ref (linux_mod);
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+      goto fail;
+    }
+
+  file = grub_file_open (argv[0]);
+  if (!file)
+    goto fail;
+  grub_dprintf ("linux", "Multiboot kernel file: struct grub_file at %p\n",
+      file);
+
+  grub_loader_unset();
+
+  multiboot_type = identify_kernel_type(file);
+
+  retval = init_multiboot_function(multiboot_type);
+  if (retval != GRUB_ERR_NONE)
+    goto fail;
+
+  grub_module_unload (NULL);
+
+  module = (multiboot_module_t) grub_malloc (sizeof(struct multiboot_module));
+  if (!module)
+    return (grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")));
+  module->name = GRUB_MULTIBOOT_KERNEL_NAME;
+
+  /* for more specific   */
+  if (multiboot_function->init_kernel_info)
+    {
+      retval = multiboot_function->init_kernel_info(module_head, module,
+          &argc, &argv);
+      if (retval != GRUB_ERR_NONE)
+        grub_dprintf ("linux", "Multiboot init_kernel_info fail %d\n",
+            retval);
+    }
+
+  grub_errno = grub_module_load (module, file, argc, argv);
+
+  if (grub_errno == GRUB_ERR_NONE)
+    {
+      grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
+      grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
+      grub_arm64_linux_set_loaded(1);
+    }
+
+fail:
+  if (file)
+    grub_file_close (file);
+  if (grub_errno != GRUB_ERR_NONE)
+    {
+      linux_mod = grub_arm64_linux_get_mod();
+      grub_dl_unref (linux_mod);
+      grub_arm64_linux_set_loaded(0);
+      grub_module_unload (NULL);
+    }
+
+  return (grub_errno);
+}
+
+static grub_command_t cmd_multiboot, cmd_module;
+
+void grub_arm64_linux_register_multiboot_command(void)
+{
+  cmd_multiboot =
+    grub_register_command ("multiboot", grub_cmd_multiboot, 0,
+			   N_("Load a multiboot kernel."));
+  cmd_module =
+    grub_register_command ("module", grub_cmd_module, 0,
+			   N_("Load a multiboot module."));
+}
+
+void grub_arm64_linux_unregister_multiboot_command(void)
+{
+  grub_unregister_command (cmd_multiboot);
+  grub_unregister_command (cmd_module);
+}
+
diff --git a/grub-core/loader/arm64/multiboot_xen.c b/grub-core/loader/arm64/multiboot_xen.c
new file mode 100644
index 0000000..8e1c952
--- /dev/null
+++ b/grub-core/loader/arm64/multiboot_xen.c
@@ -0,0 +1,373 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2014  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/cache.h>
+#include <grub/err.h>
+#include <grub/fdt.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/cpu/linux.h>
+#include <grub/cpu/multiboot.h>
+#include <grub/cpu/multiboot_xen.h>
+
+static xen_module_type_t module_type = XEN_MODULE_IMAGE;
+static void *multiboot_fdt = NULL;
+static grub_size_t multiboot_fdt_size = 0;
+static int chosen_node = 0;
+static int module_index = 0;
+
+static grub_err_t
+clean_extra_info_xen(multiboot_module_t module)
+{
+  if (module && module->extra_info)
+    {
+      grub_free (module->extra_info);
+      module->extra_info = NULL;
+    }
+  return (GRUB_ERR_NONE);
+}
+
+static grub_err_t
+set_xen_module_type(multiboot_module_t module, int *argc, char **argv[])
+{
+  xen_node_info_t node_info =(xen_node_info_t) module->extra_info;
+  char *temp_string = node_info->compatible_custom;
+
+  if ((*argc) >= 3 && grub_strcmp (*argv[0], "--type") == 0)
+    {
+      while ((*argc)>1)
+        {
+          (*argc)--;
+          (*argv)++;
+          if (grub_strcmp (*argv[0], "--type") == 0)
+            continue;
+          if (grub_strcmp (*argv[0], "xen,linux-zimage") == 0)
+            {
+              node_info->type = XEN_MODULE_IMAGE;
+              break;
+            }
+          if ((grub_strcmp (*argv[0], "xen,linux-initrd") == 0)
+              || (grub_strcmp (*argv[0], "xen,linux-ramdisk") == 0))
+            {
+              node_info->type = XEN_MODULE_INITRD;
+              break;
+            }
+          if (grub_strcmp (*argv[0], "xen,xsm-policy") == 0)
+            {
+              node_info->type = XEN_MODULE_XSM;
+              break;
+            }
+
+          grub_strcpy(temp_string, *argv[0]);
+          node_info->compatible_size += grub_strlen(*argv[0]) + 1;
+          temp_string += grub_strlen(*argv[0]);
+          *temp_string = '\0';
+          temp_string++;
+          node_info->type = XEN_MODULE_CUSTOM;
+        }
+    } else {
+        node_info->type = module_type++;
+      if (module_type > XEN_MODULE_OTHER)
+        module_type = XEN_MODULE_OTHER;
+    }
+
+  return (GRUB_ERR_NONE);
+}
+
+static grub_err_t
+params_sync_caches_xen (void)
+{
+  if (multiboot_fdt && multiboot_fdt_size > 0) {
+  grub_arch_sync_caches ((void *) multiboot_fdt, multiboot_fdt_size);
+  }
+  return (GRUB_ERR_NONE);
+}
+
+
+static grub_err_t
+prepare_kernel_params_xen (multiboot_module_t module)
+{
+  int retval;
+  xen_node_info_t node_info = NULL;
+
+  if (module && module->extra_info)
+    {
+      node_info = (xen_node_info_t) module->extra_info;
+    } else {
+        return (grub_error (GRUB_ERR_BAD_ARGUMENT, N_("failed to get kernel")));
+    }
+
+  multiboot_fdt = grub_arm64_linux_get_fdt ();
+  multiboot_fdt_size = grub_fdt_get_totalsize (multiboot_fdt);
+  if (!multiboot_fdt)
+    return (grub_error(GRUB_ERR_BAD_OS, "failed to get FDT"));
+
+  chosen_node = grub_fdt_find_subnode (multiboot_fdt, 0, "chosen");
+  if (chosen_node < 0)
+      chosen_node = grub_fdt_add_subnode (multiboot_fdt, 0, "chosen");
+
+  if (chosen_node < 1)
+    return (grub_error(GRUB_ERR_BAD_OS, "failed to get chosen node"));
+
+  /* Set reg decode info to avoid succeeding these info from parent's node */
+  retval = grub_fdt_set_prop32 (multiboot_fdt, chosen_node,
+      "#address-cells", node_info->reg.cells_info[0]);
+  retval = grub_fdt_set_prop32 (multiboot_fdt, chosen_node,
+      "#size-cells",  node_info->reg.cells_info[1]);
+  if (retval)
+    return (grub_error(GRUB_ERR_BAD_OS,
+        "failed to add reg decode info to chosen node"));
+
+  grub_dprintf ("linux", "Multiboot Kernel cmdline : %s @ %p size:%d\n",
+      module->cmdline, module->cmdline, module->cmdline_size);
+
+  retval = grub_fdt_set_prop (multiboot_fdt, chosen_node,
+      node_info->cmdline_name,
+      module->cmdline, module->cmdline_size);
+
+  if (retval)
+    return (grub_error(GRUB_ERR_BAD_OS,
+        "failed to set kernel cmdline info to chosen node"));
+
+  return (GRUB_ERR_NONE);
+}
+
+static grub_err_t
+prepare_module_params_xen (multiboot_module_t module)
+{
+  int retval, module_node = 0, target_node = 0;
+  xen_node_info_t node_info = NULL;
+  char module_name[XEN_MODULE_NAME_MAX_SIZE];
+
+  if (module && module->extra_info)
+    {
+      node_info = (xen_node_info_t) module->extra_info;
+    } else {
+        return (grub_error (GRUB_ERR_BAD_ARGUMENT, N_("failed to get module")));
+    }
+
+  retval = grub_snprintf(module_name, XEN_MODULE_NAME_MAX_SIZE,
+      "module@%d", module_index++);
+  if (retval <(int) sizeof("module@"))
+    return (grub_error(GRUB_ERR_BAD_OS,
+        N_("failed to set node name for module")));
+
+  module_node = grub_fdt_find_subnode (multiboot_fdt, chosen_node, module_name);
+  if (module_node < 0)
+    module_node = grub_fdt_add_subnode (multiboot_fdt, chosen_node, module_name);
+
+  retval = grub_fdt_set_prop (multiboot_fdt, module_node, "compatible",
+      node_info->compatible,
+      node_info->compatible_size);
+  if (retval)
+    return (grub_error(GRUB_ERR_BAD_OS,
+        N_("failed to get module node in chosen node")));
+
+  grub_dprintf ("linux", "Module %s compatible = %s size = %x\n",
+      module->name,
+      node_info->compatible,
+      node_info->compatible_size);
+
+  node_info->reg.reg_64 = module->start;
+  node_info->reg.reg_32[0] = grub_cpu_to_be32((grub_uint32_t)node_info->reg.reg_64);
+  node_info->reg.reg_32[1] = grub_cpu_to_be32((grub_uint32_t)module->size);
+
+  retval = grub_fdt_set_prop (multiboot_fdt, module_node, "reg",
+      node_info->reg.reg_32, 8);
+  if (retval)
+    return (grub_error(GRUB_ERR_BAD_OS,
+        N_("failed to set reg info in module node")));
+
+  grub_dprintf ("linux", "Module %s reg = <0x%012x 0x%012x>\n",
+      module->name,
+      node_info->reg.reg_32[0],
+      node_info->reg.reg_32[1]);
+
+  if ((module->cmdline) && (module->cmdline_size > 0))
+    {
+      grub_dprintf ("linux", "Module %s cmdline : %s @ %p size:%d\n",
+          module->name, module->cmdline, module->cmdline, module->cmdline_size);
+      if (node_info->type == XEN_MODULE_IMAGE)
+        {
+          target_node = chosen_node;
+        } else {
+            target_node = module_node;
+        }
+      retval = grub_fdt_set_prop (multiboot_fdt, target_node,
+          node_info->cmdline_name,
+          module->cmdline, module->cmdline_size + 1);
+      if (retval)
+        return (grub_error(GRUB_ERR_BAD_OS,
+            "failed to set module cmdline info to chosen node"));
+    } else {
+      grub_dprintf ("linux", "Module %s has not bootargs!\n", module->name);
+    }
+
+  return (GRUB_ERR_NONE);
+}
+
+static void *
+install_all_params_xen (void)
+{
+  grub_efi_boot_services_t *b;
+  grub_efi_status_t status;
+
+  b = grub_efi_system_table->boot_services;
+  status = b->install_configuration_table (grub_arm64_linux_fdt_guid_p, multiboot_fdt);
+  if (status != GRUB_EFI_SUCCESS)
+    {
+      grub_dprintf ("linux", "Installed/updated FDT configuration table fail %p\n",
+          multiboot_fdt);
+      return NULL;
+    }
+
+  grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
+      multiboot_fdt);
+  return ((void *)multiboot_fdt);
+}
+
+static grub_err_t
+clean_all_params_xen (void)
+{
+  if (multiboot_fdt) {
+      grub_efi_free_pages ((grub_efi_physical_address_t) multiboot_fdt,
+          BYTES_TO_PAGES (multiboot_fdt_size));
+      multiboot_fdt = NULL;
+      multiboot_fdt_size = 0;
+  }
+  return (GRUB_ERR_NONE);
+}
+
+static grub_err_t
+init_module_info_xen(multiboot_module_t module_head __attribute__ ((unused)),
+    multiboot_module_t module, int *argc, char **argv[])
+{
+  xen_node_info_t node_info =
+      (xen_node_info_t) grub_malloc (sizeof(struct xen_node_info));
+  if (!node_info)
+    return (grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")));
+  module->extra_info =(void *) node_info;
+
+  /* get module type */
+  grub_errno = set_xen_module_type(module, argc, argv);
+  if (grub_errno != GRUB_ERR_NONE)
+    return (grub_errno);
+
+  switch (node_info->type)
+    {
+    case XEN_MODULE_IMAGE:
+      {
+        node_info->compatible = XEN_MODULE_IMAGE_COMPATIBLE;
+        node_info->compatible_size = sizeof(XEN_MODULE_IMAGE_COMPATIBLE);
+        node_info->cmdline_name = XEN_MODULE_DOM0_BOOTARGS;
+        module->name = XEN_MODULE_IMAGE_NAME;
+        module->flags = (GRUB_MULTIBOOT_FLAGS_UNIQUE |
+            GRUB_MULTIBOOT_FLAGS_CMDLINE);
+        module->align = XEN_MODULE_IMAGE_MIN_ALIGN;
+        break;
+      }
+    case XEN_MODULE_INITRD:
+      {
+        node_info->compatible = XEN_MODULE_INITRD_COMPATIBLE;
+        node_info->compatible_size = sizeof(XEN_MODULE_INITRD_COMPATIBLE);
+        node_info->cmdline_name = XEN_MODULE_BOOTARGS;
+        module->name = XEN_MODULE_INITRD_NAME;
+        module->flags = GRUB_MULTIBOOT_FLAGS_UNIQUE;
+        module->align = XEN_MODULE_INITRD_MIN_ALIGN;
+        break;
+      }
+    case XEN_MODULE_XSM:
+      {
+        node_info->compatible = XEN_MODULE_XSM_COMPATIBLE;
+        node_info->compatible_size = sizeof(XEN_MODULE_XSM_COMPATIBLE);
+        node_info->cmdline_name = XEN_MODULE_BOOTARGS;
+        module->name = XEN_MODULE_XSM_NAME;
+        module->flags = GRUB_MULTIBOOT_FLAGS_UNIQUE;
+        module->align = XEN_MODULE_XSM_MIN_ALIGN;
+        break;
+      }
+    case XEN_MODULE_OTHER:
+      {
+        node_info->compatible = XEN_MODULE_OTHER_COMPATIBLE;
+        node_info->compatible_size = sizeof(XEN_MODULE_OTHER_COMPATIBLE);
+        node_info->cmdline_name = XEN_MODULE_BOOTARGS;
+        module->name = XEN_MODULE_OTHER_NAME;
+        module->flags = GRUB_MULTIBOOT_FLAGS_CMDLINE;
+        module->align = XEN_MODULE_OTHER_MIN_ALIGN;
+        break;
+      }
+    case XEN_MODULE_CUSTOM:
+      {
+        node_info->compatible = node_info->compatible_custom;
+        /* node_info->compatible_size
+           has set in set_xen_module_type()*/
+        node_info->cmdline_name = XEN_MODULE_BOOTARGS;
+        module->name = XEN_MODULE_OTHER_NAME;
+        module->flags = GRUB_MULTIBOOT_FLAGS_CMDLINE;
+        module->align = XEN_MODULE_CUSTOM_MIN_ALIGN;
+        break;
+      }
+    default:
+      return (grub_error (GRUB_ERR_BAD_ARGUMENT, N_("error module type")));
+    }
+
+  grub_dprintf ("linux", "Init %s module and node info successfully\n",
+      module->name);
+
+  return (GRUB_ERR_NONE);
+}
+
+static grub_err_t
+init_kernel_info_xen(multiboot_module_t module_head __attribute__ ((unused)),
+    multiboot_module_t module,
+    int *argc __attribute__ ((unused)),
+    char **argv[] __attribute__ ((unused)))
+{
+  xen_node_info_t node_info =
+      (xen_node_info_t) grub_malloc (sizeof(struct xen_node_info));
+  if (!node_info)
+    return (grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")));
+
+  node_info->compatible = NULL;
+  node_info->compatible_size = 0;
+  node_info->reg.cells_info[0] = 0x1;
+  node_info->reg.cells_info[1] = 0x1;
+  node_info->cmdline_name = XEN_KERNEL_BOOTARGS;
+  module->extra_info =(void *) node_info;
+
+  module->align = XEN_KERNEL_MIN_ALIGN;
+  module->flags = (GRUB_MULTIBOOT_FLAGS_UNIQUE |
+      GRUB_MULTIBOOT_FLAGS_CMDLINE);
+
+  grub_dprintf ("linux", "Init %s info successfully\n",
+      module->name);
+
+  return (GRUB_ERR_NONE);
+}
+
+struct multiboot_function multiboot_function_xen =
+    {
+        .init_kernel_info = init_kernel_info_xen,
+        .init_module_info = init_module_info_xen,
+        .clean_extra_info = clean_extra_info_xen,
+        .prepare_kernel_params = prepare_kernel_params_xen,
+        .prepare_module_params = prepare_module_params_xen,
+        .install_all_params = install_all_params_xen,
+        .params_sync_caches = params_sync_caches_xen,
+        .clean_all_params = clean_all_params_xen
+    };
diff --git a/include/grub/arm64/linux.h b/include/grub/arm64/linux.h
index 864e5dc..cc11370 100644
--- a/include/grub/arm64/linux.h
+++ b/include/grub/arm64/linux.h
@@ -38,4 +38,16 @@ struct grub_arm64_linux_kernel_header
   grub_uint32_t hdr_offset;	/* Offset of PE/COFF header */
 };
 
+/****The accessor functions for dtb and the "loaded" flag****/
+grub_efi_guid_t EXPORT_VAR(*grub_arm64_linux_fdt_guid_p);
+
+void EXPORT_FUNC (*grub_arm64_linux_get_fdt) (void);
+
+int EXPORT_FUNC (grub_arm64_linux_get_loaded) (void);
+
+void EXPORT_FUNC (grub_arm64_linux_set_loaded) (int loaded_flag);
+
+grub_dl_t EXPORT_FUNC (grub_arm64_linux_get_mod) (void);
+/************************************/
+
 #endif /* ! GRUB_LINUX_CPU_HEADER */
diff --git a/include/grub/arm64/multiboot.h b/include/grub/arm64/multiboot.h
new file mode 100644
index 0000000..7b5ab5b
--- /dev/null
+++ b/include/grub/arm64/multiboot.h
@@ -0,0 +1,86 @@
+/*  multiboot.h - Multiboot header file.  */
+/*  Copyright (C) 2014  Free Software Foundation, Inc.
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to
+ *  deal in the Software without restriction, including without limitation the
+ *  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ *  sell copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in
+ *  all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL ANY
+ *  DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ *  IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef MULTIBOOT_HEADER
+#define MULTIBOOT_HEADER 1
+
+#include <grub/list.h>
+
+#define GRUB_EFI_PAGE_SHIFT	12
+#define BYTES_TO_PAGES(bytes)   (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT)
+
+#define GRUB_MULTIBOOT_FLAGS_UNIQUE (0x1)
+#define GRUB_MULTIBOOT_FLAGS_CMDLINE (0x2)
+
+#define GRUB_MULTIBOOT_KERNEL_NAME  "multiboot_kernel"
+
+enum grub_multiboot_type
+{
+  GRUB_MULTIBOOT_XEN,
+  /*we can add more types here to support more images those need multiboot*/
+  GRUB_MULTIBOOT_OTHER
+};
+typedef enum grub_multiboot_type grub_multiboot_type_t;
+
+struct multiboot_module
+{
+  struct multiboot_module *next;
+  struct multiboot_module **prev;
+  const char *name;
+
+  int flags;
+
+  grub_addr_t start_unaligned;
+  grub_addr_t start;
+  grub_size_t size;
+  grub_size_t align;
+
+  char *cmdline;
+  int cmdline_size;
+
+  /* for more info */
+  void *extra_info;
+};
+typedef struct multiboot_module *multiboot_module_t;
+
+struct multiboot_function
+{
+  grub_err_t (*init_kernel_info)  (multiboot_module_t module_head,
+      multiboot_module_t module, int *argc, char **argv[]);
+  grub_err_t (*init_module_info) (multiboot_module_t module_head,
+      multiboot_module_t module, int *argc, char **argv[]);
+  grub_err_t (*clean_extra_info) (multiboot_module_t module);
+  grub_err_t (*prepare_kernel_params) (multiboot_module_t module);
+  grub_err_t (*prepare_module_params) (multiboot_module_t module);
+  void *(*install_all_params) (void);
+  grub_err_t (*clean_all_params) (void);
+  grub_err_t (*params_sync_caches) (void);
+};
+
+typedef struct multiboot_function multiboot_function_t;
+
+typedef void (*kernel_entry_t) (void *, int, int, int);
+
+void grub_arm64_linux_register_multiboot_command (void);
+
+void grub_arm64_linux_unregister_multiboot_command(void);
+
+#endif /* ! MULTIBOOT_HEADER */
diff --git a/include/grub/arm64/multiboot_xen.h b/include/grub/arm64/multiboot_xen.h
new file mode 100644
index 0000000..98cee6d
--- /dev/null
+++ b/include/grub/arm64/multiboot_xen.h
@@ -0,0 +1,80 @@
+/*  multiboot.h - Multiboot header file.  */
+/*  Copyright (C) 2014  Free Software Foundation, Inc.
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to
+ *  deal in the Software without restriction, including without limitation the
+ *  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ *  sell copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in
+ *  all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL ANY
+ *  DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ *  IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef MULTIBOOT_XEN_HEADER
+#define MULTIBOOT_XEN_HEADER 1
+
+#include <grub/types.h>
+
+#define XEN_MODULE_DEFAULT_ALIGN  (0x0)
+
+#define XEN_KERNEL_MIN_ALIGN  (0x200000)
+#define XEN_MODULE_IMAGE_MIN_ALIGN  XEN_MODULE_DEFAULT_ALIGN
+#define XEN_MODULE_INITRD_MIN_ALIGN  XEN_MODULE_DEFAULT_ALIGN
+#define XEN_MODULE_XSM_MIN_ALIGN  XEN_MODULE_DEFAULT_ALIGN
+#define XEN_MODULE_OTHER_MIN_ALIGN  XEN_MODULE_DEFAULT_ALIGN
+#define XEN_MODULE_CUSTOM_MIN_ALIGN  XEN_MODULE_DEFAULT_ALIGN
+
+#define XEN_KERNEL_BOOTARGS  "xen,xen-bootargs"
+#define XEN_MODULE_IMAGE_NAME  "linux-zimage"
+#define XEN_MODULE_IMAGE_COMPATIBLE  "xen,linux-zimage\0xen,multiboot-module"
+#define XEN_MODULE_INITRD_NAME  "linux-initrd"
+#define XEN_MODULE_INITRD_COMPATIBLE  "xen,linux-initrd\0xen,multiboot-module"
+#define XEN_MODULE_XSM_NAME  "xsm-policy"
+#define XEN_MODULE_XSM_COMPATIBLE  "xen,xsm-policy\0xen,multiboot-module"
+#define XEN_MODULE_OTHER_NAME  "multiboot-module"
+#define XEN_MODULE_OTHER_COMPATIBLE  "xen,multiboot-module"
+#define XEN_MODULE_DOM0_BOOTARGS  "xen,dom0-bootargs"
+#define XEN_MODULE_BOOTARGS  "bootargs"
+#define XEN_COMPATIBLE_MAX_SIZE (128)
+#define XEN_MODULE_NAME_MAX_SIZE (16)
+
+enum xen_module_type
+  {
+    XEN_MODULE_IMAGE,
+    XEN_MODULE_INITRD,
+    XEN_MODULE_XSM,
+    XEN_MODULE_OTHER,
+    XEN_MODULE_CUSTOM
+  };
+typedef enum xen_module_type xen_module_type_t;
+
+struct xen_node_info
+{
+  xen_module_type_t type;
+
+  const char *compatible;
+  char compatible_custom[XEN_COMPATIBLE_MAX_SIZE];
+  int compatible_size;
+
+  union {
+    grub_uint32_t cells_info[2];
+    grub_uint32_t reg_32[2];
+    grub_uint64_t reg_64;
+  } reg;
+
+  const char *cmdline_name;
+};
+typedef struct xen_node_info *xen_node_info_t;
+
+multiboot_function_t EXPORT_VAR(multiboot_function_xen);
+
+#endif /* ! MULTIBOOT_XEN_HEADER */
diff --git a/include/grub/arm64/system.h b/include/grub/arm64/system.h
new file mode 100644
index 0000000..950f9b0
--- /dev/null
+++ b/include/grub/arm64/system.h
@@ -0,0 +1,7 @@
+#ifndef GRUB_SYSTEM_CPU_HEADER
+#define GRUB_SYSTEM_CPU_HEADER	1
+
+void EXPORT_FUNC (grub_arm64_prepare_platform) (void);
+
+#endif /* ! GRUB_SYSTEM_CPU_HEADER */
+
-- 
1.8.3.1

