>From eafa216fa21a0caf87e0f9ddcdcc5bc24d821390 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 linux module for
 aarch64 Xen boot.

But it also can easily expand these commands to support other images by
implementing "struct multiboot_function".

- the implementation for Xen is following  <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.

- Add multiboot command for loading multiboot kernel image.
  Usage:  multiboot <the path of kernel image file> [cmdline]

- Add module command for loading multiboot module.
  Usage:  module [option] <the path of module file> [cmdline]

  The [option]  for Xen is [--type <compatible stream in FDT>].
  For now, the <compatible stream in FDT> could be :
    "xen,linux-zimage", "xen,linux-initrd", "xen,linux-ramdisk",
    "xen,xsm-policy" or the custom compatible stream

- Add some common functions for non-stub kernel boot for arm64:
    void grub_arm64_prepare_platform (void); (#include <grub/arm64/system.h>)

    in kernel module of GRUB for arm64:
      void grub_arch_disable_interrupts (void);
      void grub_arm64_disable_caches_mmu (void);

- The reason of adding this functionality to the existing "linux" module
rather than "multiboot(2)"

  The multiboot specification is defined for x86. The multiboot2 does not
  describe an ARM port, but talks only about x86 and MIPS, and for several
  reasons this seems to be overkill.
  So we add multiboot commands into the "linux" module to avoid using the code
  of the "multiboot(2)" mudule.

- 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            |   4 +
 grub-core/kern/arm64/cache_flush.S     |  31 +++
 grub-core/kern/arm64/misc.c            |  34 +++
 grub-core/kern/arm64/misc_irq.S        |  35 +++
 grub-core/loader/arm64/linux.c         |  27 ++
 grub-core/loader/arm64/multiboot.c     | 458 +++++++++++++++++++++++++++++++++
 grub-core/loader/arm64/multiboot_xen.c | 381 +++++++++++++++++++++++++++
 include/grub/arm64/linux.h             |   8 +
 include/grub/arm64/multiboot.h         |  86 +++++++
 include/grub/arm64/multiboot_xen.h     |  80 ++++++
 include/grub/arm64/system.h            |   7 +
 12 files changed, 1155 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..add4b83 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,8 @@ 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;
   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..b5caa71 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,30 @@ FUNCTION(grub_arch_invalidate_icache_range)
 2:	dsb	ish
 	isb
 	ret
+
+FUNCTION(grub_arm64_disable_caches_mmu)
+    mrs    x1, CurrentEL
+    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       3f
+2:  mrs     x0, sctlr_el2        // Get control register EL2
+3:  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, #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       3f
+2:  msr     sctlr_el2, x0        // Write back control register EL2
+3:  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..73e6d57
--- /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_arm64_disable_caches_mmu (void);
+
+void
+grub_arm64_prepare_platform (void)
+{
+  grub_arch_disable_interrupts();
+  grub_arm64_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..3e9c6d8 100644
--- a/grub-core/loader/arm64/linux.c
+++ b/grub-core/loader/arm64/linux.c
@@ -26,6 +26,7 @@
 #include <grub/mm.h>
 #include <grub/types.h>
 #include <grub/cpu/linux.h>
+#include <grub/cpu/multiboot.h>
 #include <grub/efi/efi.h>
 #include <grub/efi/pe32.h>
 #include <grub/i18n.h>
@@ -54,6 +55,27 @@ 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;
+}
+
+void *grub_arm64_linux_get_fdt (void)
+{
+    get_fdt ();
+    return (fdt);
+}
+/************************************************************/
+
+
 static void *
 get_firmware_fdt (void)
 {
@@ -476,6 +498,9 @@ GRUB_MOD_INIT (linux)
   cmd_devicetree =
     grub_register_command ("devicetree", grub_cmd_devicetree, 0,
 			   N_("Load DTB file."));
+
+  grub_arm64_linux_register_multiboot_command(mod);
+
   my_mod = mod;
 }
 
@@ -484,4 +509,6 @@ GRUB_MOD_FINI (linux)
   grub_unregister_command (cmd_linux);
   grub_unregister_command (cmd_initrd);
   grub_unregister_command (cmd_devicetree);
+
+  grub_arm64_linux_unregister_multiboot_command();
 }
diff --git a/grub-core/loader/arm64/multiboot.c b/grub-core/loader/arm64/multiboot.c
new file mode 100644
index 0000000..6fe5633
--- /dev/null
+++ b/grub-core/loader/arm64/multiboot.c
@@ -0,0 +1,458 @@
+/*
+ *  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>
+
+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)
+{
+  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__);
+
+  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)
+    {
+      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(grub_dl_t mod)
+{
+  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."));
+  linux_mod = mod;
+}
+
+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..22087c9
--- /dev/null
+++ b/grub-core/loader/arm64/multiboot_xen.c
@@ -0,0 +1,381 @@
+/*
+ *  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 grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
+
+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;
+  int got_type = 0;
+
+  if ((*argc) >= 3 && grub_strcmp (*argv[0], "--type") == 0)
+    {
+      while ((*argc)>1)
+        {
+          (*argc)--;
+          (*argv)++;
+          if (got_type == 1)
+            continue;
+          if (grub_strcmp (*argv[0], "--type") == 0)
+            continue;
+          if (grub_strcmp (*argv[0], "xen,linux-zimage") == 0)
+            {
+              node_info->type = XEN_MODULE_IMAGE;
+              got_type = 1;
+              continue;
+            }
+          if ((grub_strcmp (*argv[0], "xen,linux-initrd") == 0)
+              || (grub_strcmp (*argv[0], "xen,linux-ramdisk") == 0))
+            {
+              node_info->type = XEN_MODULE_INITRD;
+              got_type = 1;
+              continue;
+            }
+          if (grub_strcmp (*argv[0], "xen,xsm-policy") == 0)
+            {
+              node_info->type = XEN_MODULE_XSM;
+              got_type = 1;
+              continue;
+            }
+
+          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 (&fdt_guid, 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..c54dfaf 100644
--- a/include/grub/arm64/linux.h
+++ b/include/grub/arm64/linux.h
@@ -38,4 +38,12 @@ 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****/
+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);
+/************************************/
+
 #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..3a49a7b
--- /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 (grub_dl_t mod);
+
+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

