From: Fu Wei fu.wei@linaro.org
- This adds support for the Xen boot on ARM specification for arm64.
- 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.
- The multiboot/module commands have existed, so we use xen_hypervisor/xen_module instead.
- This Xen boot support is built into linux module for aarch64, and can not be used alone.
- Adding this functionality to the existing "linux" module is for reusing the existing code of devicetree.
- Add the support of xen_hypervisor/xen_module commands in util/grub.d/20_linux_xen.in
- Add the introduction of xen_hypervisor/xen_module commands in docs/grub.texi
- The example of this support is <How to boot Xen with GRUB on AArch64 the Foundation FVP model> https://wiki.linaro.org/LEG/Engineering/Grub2/Xen_booting_on_Foundation_FVP_...
Changelog: v2: remove the patches which have been accepted. according to Vladimir's suggestion, change the command manes and relevant code: multiboot-->xen_hypervisor module-->xen_module improve the option parsing support for xen_hypervisor/xen_module commands. add a patch for adding xen_hypervisor/xen_module support in util/grub.d/20_linux_xen.in. update docs/grub.texi patch for the new command names.
v1: The first version upstream patchset to grub-devel mailing list
Fu Wei (3): arm64: Add Xen boot support file * util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64 arm64: Add the introduction of xen_hypervisor/xen_module command in docs/grub.texi
docs/grub.texi | 27 ++ grub-core/Makefile.core.def | 1 + grub-core/loader/arm64/linux.c | 6 + grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++ include/grub/arm64/xen_boot.h | 115 +++++++ util/grub.d/20_linux_xen.in | 14 +- 6 files changed, 775 insertions(+), 3 deletions(-) create mode 100644 grub-core/loader/arm64/xen_boot.c create mode 100644 include/grub/arm64/xen_boot.h
From: Fu Wei fu.wei@linaro.org
This patch adds Xen boot support file: grub-core/loader/arm64/xen_boot.c include/grub/arm64/xen_boot.h
This patch also adds commands register code and hearder file into grub-core/loader/arm64/linux.c
- This adds support for the Xen boot on ARM specification for arm64. - 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. - The multiboot/module commands have existed, so we use xen_hypervisor/xen_module instead. - This Xen boot support is built into linux module for aarch64. - Adding this functionality to the existing "linux" module is for reusing the existing code of devicetree.
Signed-off-by: Fu Wei fu.wei@linaro.org --- grub-core/Makefile.core.def | 1 + grub-core/loader/arm64/linux.c | 6 + grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++ include/grub/arm64/xen_boot.h | 115 +++++++ 4 files changed, 737 insertions(+) create mode 100644 grub-core/loader/arm64/xen_boot.c create mode 100644 include/grub/arm64/xen_boot.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index a6101de..01f8261 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1659,6 +1659,7 @@ module = { ia64_efi = loader/ia64/efi/linux.c; arm = loader/arm/linux.c; arm64 = loader/arm64/linux.c; + arm64 = loader/arm64/xen_boot.c; fdt = lib/fdt.c; common = loader/linux.c; common = lib/cmdline.c; diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c index 987f5b9..7ae9bde 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/xen_boot.h> #include <grub/efi/efi.h> #include <grub/efi/pe32.h> #include <grub/i18n.h> @@ -477,6 +478,9 @@ GRUB_MOD_INIT (linux) cmd_devicetree = grub_register_command ("devicetree", grub_cmd_devicetree, 0, N_("Load DTB file.")); + + grub_arm64_linux_register_xen_boot_command (mod, &loaded); + my_mod = mod; }
@@ -485,4 +489,6 @@ GRUB_MOD_FINI (linux) grub_unregister_command (cmd_linux); grub_unregister_command (cmd_initrd); grub_unregister_command (cmd_devicetree); + + grub_arm64_linux_unregister_xen_boot_command (); } diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c new file mode 100644 index 0000000..23bd00e --- /dev/null +++ b/grub-core/loader/arm64/xen_boot.c @@ -0,0 +1,615 @@ +/* + * 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/xen_boot.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 int *loaded; + +static struct xen_boot_binary *xen_hypervisor; +static struct xen_boot_binary *module_head; +static const grub_size_t module_default_align[] = { + MODULE_IMAGE_MIN_ALIGN, + MODULE_INITRD_MIN_ALIGN, + MODULE_OTHER_MIN_ALIGN, + MODULE_CUSTOM_MIN_ALIGN +}; + +static void *xen_boot_fdt; +static const compat_string_struct_t default_compat_string[] = { + FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE), + FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE), + FDT_COMPATIBLE (MODULE_OTHER_COMPATIBLE) +}; + + +/* Parse all the options of xen_module command. For now, we support + (1) --type <the compatible stream> + (2) --nounzip + We also set up the type of module in this function. + If there are some "--type" options in the command line, + we make a custom compatible stream in this function. */ +static grub_err_t +set_module_type (struct xen_boot_binary *module, int argc, char *argv[], + int *file_name_index) +{ + char **compat_string_temp_array = + (char **) grub_zalloc (sizeof (char *) * argc); + static module_type_t default_type = MODULE_IMAGE; + grub_size_t total_size = 0; + int num_types = 0, i; + char *temp = NULL; + + *file_name_index = 0; + + /* if there are some options we need to process. */ + while (argc > 1 && !grub_strncmp (argv[0], "--", 2)) + { + if (!grub_strcmp (argv[0], "--type")) + { + module->node_info.type = MODULE_CUSTOM; + ARG_SHIFT (argc, argv); + total_size += grub_strlen (argv[0]) + 1; + compat_string_temp_array[num_types++] = argv[0]; + ARG_SHIFT (argc, argv); + (*file_name_index) += 2; + } + else if (!grub_strcmp (argv[0], "--nounzip")) + { + grub_file_filter_disable_compression (); + ARG_SHIFT (argc, argv); + (*file_name_index) += 1; + } + else /* we can add more options process code here. */ + { + grub_dprintf ("xen_boot_loader", + "Unknown option %s, skip.\n", argv[0]); + ARG_SHIFT (argc, argv); + (*file_name_index) += 1; + } + } + + /* To prevent some wrong command lines using "--type" option */ + if (!argc) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + /* For the default module type : + The implementation is following <Multiboot on ARM Specification>: + Each module will be given a default compatibility property + based on the order in which the modules are added. + The 1st module: compatible = "multiboot,kernel", "multiboot,module" + The 2nd module: compatible = "multiboot,ramdisk", "multiboot,module" + All subsequent modules: compatible = "multiboot,module" + But this order will NOT be interfered with "--type"(MODULE_CUSTOM) + For more detail, please refer to: + http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot */ + if (module->node_info.type != MODULE_CUSTOM) + { + /* the module type is set by the load order */ + module->node_info.type = default_type; + switch (default_type) + { + case MODULE_IMAGE: + default_type = MODULE_INITRD; + break; + + case MODULE_INITRD: + default_type = MODULE_OTHER; + break; + + case MODULE_OTHER: + break; + + default: + default_type = MODULE_IMAGE; /* error, reset the type */ + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument")); + } + } + else + { + /* the module type is set by "--type"(MODULE_CUSTOM) */ + module->node_info.compat_string = temp = + (char *) grub_zalloc (total_size); + module->node_info.compat_string_size = total_size; + for (i = 0; num_types > 0; num_types--, i++, temp++) + { + grub_strcpy (temp, compat_string_temp_array[i]); + temp += grub_strlen (compat_string_temp_array[i]); + } + } + + grub_free (compat_string_temp_array); + + return GRUB_ERR_NONE; +} + +static grub_err_t +prepare_xen_hypervisor_params (void) +{ + int chosen_node = 0; + int retval; + + xen_boot_fdt = grub_linux_get_fdt (); + if (!xen_boot_fdt) + return grub_error (GRUB_ERR_BAD_OS, "failed to get FDT"); + + chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen"); + if (chosen_node < 0) + chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen"); + if (chosen_node < 1) + return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT"); + + grub_dprintf ("xen_boot_loader", + "Xen Hypervisor cmdline : %s @ %p size:%d\n", + xen_hypervisor->cmdline, xen_hypervisor->cmdline, + xen_hypervisor->cmdline_size); + + retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs", + xen_hypervisor->cmdline, + xen_hypervisor->cmdline_size); + if (retval) + return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT"); + + return GRUB_ERR_NONE; +} + +static grub_err_t +prepare_xen_module_params (struct xen_boot_binary *module) +{ + int retval, chosen_node = 0, module_node = 0; + char module_name[FDT_NODE_NAME_MAX_SIZE]; + + retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx", + xen_boot_address_align (module->start, + module->align)); + grub_dprintf ("xen_boot_loader", "Module node name %s \n", module_name); + + if (retval < (int) sizeof ("module@")) + return grub_error (GRUB_ERR_BAD_OS, N_("failed to get FDT")); + + chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen"); + if (chosen_node < 0) + chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen"); + if (chosen_node < 1) + return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT"); + + module_node = + grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name); + if (module_node < 0) + module_node = + grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name); + + retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible", + module->node_info.compat_string, + (grub_uint32_t) module->node_info. + compat_string_size); + if (retval) + return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT")); + + grub_dprintf ("xen_boot_loader", "Module %s compatible = %s size = 0x%lx\n", + module->name, module->node_info.compat_string, + module->node_info.compat_string_size); + + retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node, + xen_boot_address_align (module->start, + module->align), + module->size); + if (retval) + return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT")); + + if (module->cmdline && module->cmdline_size > 0) + { + grub_dprintf ("xen_boot_loader", + "Module %s cmdline : %s @ %p size:%d\n", module->name, + module->cmdline, module->cmdline, module->cmdline_size); + + retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs", + module->cmdline, module->cmdline_size + 1); + if (retval) + return grub_error (GRUB_ERR_BAD_OS, "failed to update FDT"); + } + else + { + grub_dprintf ("xen_boot_loader", "Module %s has not bootargs!\n", + module->name); + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +install_all_params (void) +{ + grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID; + 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, xen_boot_fdt); + if (status != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_BAD_OS, "failed to install FDT"); + + grub_dprintf ("xen_boot_loader", + "Installed/updated FDT configuration table @ %p\n", + xen_boot_fdt); + + return GRUB_ERR_NONE; +} + +static grub_err_t +clean_all_params (void) +{ + if (xen_boot_fdt) + { + grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt, + BYTES_TO_PAGES (grub_fdt_get_totalsize + (xen_boot_fdt))); + xen_boot_fdt = NULL; + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +finalize_params_xen_boot (void) +{ + struct xen_boot_binary *module; + + if (xen_hypervisor) + { + if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE) + goto fail; + } + else + { + grub_dprintf ("xen_boot_loader", + "Failed to get Xen Hypervisor info!\n"); + goto fail; + } + + /* Set module params info */ + FOR_LIST_ELEMENTS (module, module_head) + { + if (module->start && module->size > 0) + { + grub_dprintf ("xen_boot_loader", "Module %s @ 0x%lx size:0x%lx\n", + module->name, + xen_boot_address_align (module->start, module->align), + module->size); + if (prepare_xen_module_params (module) != GRUB_ERR_NONE) + goto fail; + } + else + { + grub_dprintf ("xen_boot_loader", "Module info error: %s!\n", + module->name); + goto fail; + } + } + + if (install_all_params () == GRUB_ERR_NONE) + return GRUB_ERR_NONE; + +fail: + clean_all_params (); + + return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT"); +} + + +static grub_err_t +xen_boot (void) +{ + if (finalize_params_xen_boot () != GRUB_ERR_NONE) + return grub_errno; + + return grub_arm64_uefi_boot_image (xen_hypervisor->start, + xen_hypervisor->size, + xen_hypervisor->cmdline); +} + +static void +single_binary_unload (struct xen_boot_binary *binary) +{ + if (binary && binary->start && binary->size > 0) + { + grub_efi_free_pages ((grub_efi_physical_address_t) binary->start, + BYTES_TO_PAGES (binary->size + binary->align)); + } + + if (binary && binary->cmdline && binary->cmdline_size > 0) + { + grub_free (binary->cmdline); + grub_dprintf ("xen_boot_loader", + "Module %s cmdline memory free @ %p size: %d\n", + binary->name, binary->cmdline, binary->cmdline_size); + } + + if (binary) + { + if (binary->node_info.type == MODULE_CUSTOM) + grub_free ((void *) binary->node_info.compat_string); + if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME)) + grub_list_remove (GRUB_AS_LIST (binary)); + grub_dprintf ("xen_boot_loader", + "Module %s struct memory free @ %p size: 0x%lx\n", + binary->name, binary, sizeof (binary)); + grub_free (binary); + } + + return; +} + +static void +all_binaries_unload (void) +{ + struct xen_boot_binary *binary; + + FOR_LIST_ELEMENTS (binary, module_head) + { + single_binary_unload (binary); + } + + if (xen_hypervisor) + single_binary_unload (xen_hypervisor); + + return; +} + +static grub_err_t +xen_unload (void) +{ + *loaded = 0; + all_binaries_unload (); + clean_all_params (); + grub_dl_unref (linux_mod); + + return GRUB_ERR_NONE; +} + +static grub_err_t +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file, + int argc, char *argv[]) +{ + binary->size = grub_file_size (file); + grub_dprintf ("xen_boot_loader", "Xen_boot %s file size: 0x%lx\n", + binary->name, binary->size); + + binary->start = (grub_addr_t) grub_efi_allocate_pages (0, + (BYTES_TO_PAGES + (binary->size + + binary->align))); + if (!binary->start) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + + grub_dprintf ("xen_boot_loader", "Xen_boot %s numpages: 0x%lx\n", + binary->name, BYTES_TO_PAGES (binary->size + binary->align)); + + if (grub_file_read (file, (void *) xen_boot_address_align (binary->start, + binary->align), + binary->size) < (grub_ssize_t) binary->size) + { + single_binary_unload (binary); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + argv[0]); + } + + /* Skip the xen_boot binary file name */ + ARG_SHIFT (argc, argv); + + if (argc > 0) + { + binary->cmdline_size = grub_loader_cmdline_size (argc, argv); + binary->cmdline = grub_zalloc (binary->cmdline_size); + if (!binary->cmdline) + { + single_binary_unload (binary); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + } + grub_create_loader_cmdline (argc, argv, binary->cmdline, + binary->cmdline_size); + grub_dprintf ("xen_boot_loader", + "Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name, + binary->cmdline, binary->cmdline, binary->cmdline_size); + } + else + { + binary->cmdline_size = 0; + binary->cmdline = NULL; + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_xen_module (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + + struct xen_boot_binary *module = NULL; + int file_name_index = 0; + grub_file_t file = 0; + + if (!argc) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + goto fail; + } + + if (!*loaded) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("you need to load the Xen Hypervisor first")); + goto fail; + } + + module = + (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary)); + if (!module) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + + /* process all the options and get module type */ + if (set_module_type (module, argc, argv, &file_name_index) != GRUB_ERR_NONE) + goto fail; + switch (module->node_info.type) + { + case MODULE_IMAGE: + case MODULE_INITRD: + case MODULE_OTHER: + module->node_info.compat_string = + default_compat_string[module->node_info.type].compat_string; + module->node_info.compat_string_size = + default_compat_string[module->node_info.type].size; + break; + + case MODULE_CUSTOM: + /* we have set the node_info in set_module_type */ + break; + + default: + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument")); + } + module->name = module->node_info.compat_string; + module->align = module_default_align[module->node_info.type]; + + grub_dprintf ("xen_boot_loader", "Init %s module and node info:\n" + "compatible %s\ncompat_string_size 0x%lx\n", + module->name, module->node_info.compat_string, + module->node_info.compat_string_size); + + file = grub_file_open (argv[file_name_index]); + if (!file) + goto fail; + + grub_errno = xen_boot_binary_load (module, file, argc - file_name_index, + argv + file_name_index); + + 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_binary_unload (module); + + return grub_errno; +} + +static grub_err_t +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + struct xen_hypervisor_header sh; + grub_file_t file = NULL; + + grub_dl_ref (linux_mod); + + if (!argc) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + goto fail; + } + + /* For now, we don't support any option in xen_hypervisor command. + If there are some options, we skip them. */ + while (argc > 1 && !grub_strncmp (argv[0], "--", 2)) + { + grub_dprintf ("xen_boot_loader", "Unknown option %s, skip.\n", argv[0]); + ARG_SHIFT (argc, argv); + } + + file = grub_file_open (argv[0]); + if (!file) + goto fail; + + if (grub_file_read (file, &sh, sizeof (sh)) < (long) sizeof (sh)) + goto fail; + if (grub_arm64_uefi_check_image + ((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE) + goto fail; + grub_file_seek (file, 0); + + grub_loader_unset (); + + xen_hypervisor = + (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary)); + if (!xen_hypervisor) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + + xen_hypervisor->name = XEN_HYPERVISOR_NAME; + xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment; + + grub_errno = xen_boot_binary_load (xen_hypervisor, file, argc, argv); + if (grub_errno == GRUB_ERR_NONE) + { + grub_loader_set (xen_boot, xen_unload, 0); + *loaded = 1; + } + +fail: + if (file) + grub_file_close (file); + if (grub_errno != GRUB_ERR_NONE) + { + *loaded = 0; + all_binaries_unload (); + grub_dl_unref (linux_mod); + } + + return grub_errno; +} + +static grub_command_t cmd_xen_hypervisor, cmd_xen_module; + +void +grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *linux_loaded) +{ + cmd_xen_hypervisor = + grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0, + N_("Load a xen hypervisor.")); + cmd_xen_module = + grub_register_command ("xen_module", grub_cmd_xen_module, 0, + N_("Load a xen module.")); + linux_mod = mod; + loaded = linux_loaded; +} + +void +grub_arm64_linux_unregister_xen_boot_command (void) +{ + grub_unregister_command (cmd_xen_hypervisor); + grub_unregister_command (cmd_xen_module); +} diff --git a/include/grub/arm64/xen_boot.h b/include/grub/arm64/xen_boot.h new file mode 100644 index 0000000..8e8f6cb --- /dev/null +++ b/include/grub/arm64/xen_boot.h @@ -0,0 +1,115 @@ +/* + * xen_boot.h - Xen boot header file for Xen boot via FDT + * on AArch64 architecture. + * 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/. + */ + +#ifndef XEN_BOOT_HEADER +#define XEN_BOOT_HEADER 1 + +#include <grub/list.h> +#include <grub/types.h> +#include <grub/efi/pe32.h> /* required by struct xen_hypervisor_header */ + +#define XEN_HYPERVISOR_NAME "xen_hypervisor" + +#define MODULE_DEFAULT_ALIGN (0x0) +#define MODULE_IMAGE_MIN_ALIGN MODULE_DEFAULT_ALIGN +#define MODULE_INITRD_MIN_ALIGN MODULE_DEFAULT_ALIGN +#define MODULE_OTHER_MIN_ALIGN MODULE_DEFAULT_ALIGN +#define MODULE_CUSTOM_MIN_ALIGN MODULE_DEFAULT_ALIGN + +#define MODULE_IMAGE_COMPATIBLE "multiboot,kernel\0multiboot,module" +#define MODULE_INITRD_COMPATIBLE "multiboot,ramdisk\0multiboot,module" +#define MODULE_OTHER_COMPATIBLE "multiboot,module" + +/* This maximum size is defined in Power.org ePAPR V1.1 + * https://www.power.org/documentation/epapr-version-1-1/ + * 2.2.1.1 Node Name Requirements + * node-name@unit-address + * 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49 + */ +#define FDT_NODE_NAME_MAX_SIZE (49) + +#define ARG_SHIFT(argc, argv) \ + do { \ + (argc)--; \ + (argv)++; \ + } while (0) + +struct compat_string_struct +{ + grub_size_t size; + const char *compat_string; +}; +typedef struct compat_string_struct compat_string_struct_t; +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)} + +enum module_type +{ + MODULE_IMAGE, + MODULE_INITRD, + MODULE_OTHER, + MODULE_CUSTOM +}; +typedef enum module_type module_type_t; + +struct fdt_node_info +{ + module_type_t type; + + const char *compat_string; + grub_size_t compat_string_size; +}; + +struct xen_hypervisor_header +{ + struct grub_arm64_linux_kernel_header efi_head; + + /* This is always PE\0\0. */ + grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE]; + /* The COFF file header. */ + struct grub_pe32_coff_header coff_header; + /* The Optional header. */ + struct grub_pe64_optional_header optional_header; +}; + +struct xen_boot_binary +{ + struct xen_boot_binary *next; + struct xen_boot_binary **prev; + const char *name; + + grub_addr_t start; + grub_size_t size; + grub_size_t align; + + char *cmdline; + int cmdline_size; + + struct fdt_node_info node_info; +}; + +void grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *loaded); +void grub_arm64_linux_unregister_xen_boot_command (void); + +static __inline grub_addr_t +xen_boot_address_align (grub_addr_t start, grub_size_t align) +{ + return (align ? (ALIGN_UP (start, align)) : start); +} + +#endif /* ! XEN_BOOT_HEADER */
On 13.07.2015 10:53, fu.wei@linaro.org wrote:
From: Fu Wei fu.wei@linaro.org
This patch adds Xen boot support file: grub-core/loader/arm64/xen_boot.c include/grub/arm64/xen_boot.h
This patch also adds commands register code and hearder file into grub-core/loader/arm64/linux.c
- This adds support for the Xen boot on ARM specification for arm64.
- The implementation for Xen is following <Multiboot on ARM Specification>: http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
Please don't refer to this protocol as multiboot anywhere in grub or around because it's NOT multiboot and we don't want to confuse those 2 protocols.
and xen/docs/misc/arm/device-tree/booting.txt in Xen source code.
- The multiboot/module commands have existed, so we use xen_hypervisor/xen_module instead.
- This Xen boot support is built into linux module for aarch64.
- Adding this functionality to the existing "linux" module is for reusing the existing code of devicetree.
Please create separate module. Modules are dynamically linked.
Signed-off-by: Fu Wei fu.wei@linaro.org
grub-core/Makefile.core.def | 1 + grub-core/loader/arm64/linux.c | 6 + grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++ include/grub/arm64/xen_boot.h | 115 +++++++ 4 files changed, 737 insertions(+) create mode 100644 grub-core/loader/arm64/xen_boot.c create mode 100644 include/grub/arm64/xen_boot.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index a6101de..01f8261 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1659,6 +1659,7 @@ module = { ia64_efi = loader/ia64/efi/linux.c; arm = loader/arm/linux.c; arm64 = loader/arm64/linux.c;
- arm64 = loader/arm64/xen_boot.c; fdt = lib/fdt.c; common = loader/linux.c; common = lib/cmdline.c;
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c index 987f5b9..7ae9bde 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/xen_boot.h> #include <grub/efi/efi.h> #include <grub/efi/pe32.h> #include <grub/i18n.h> @@ -477,6 +478,9 @@ GRUB_MOD_INIT (linux) cmd_devicetree = grub_register_command ("devicetree", grub_cmd_devicetree, 0, N_("Load DTB file."));
- grub_arm64_linux_register_xen_boot_command (mod, &loaded);
- my_mod = mod;
} @@ -485,4 +489,6 @@ GRUB_MOD_FINI (linux) grub_unregister_command (cmd_linux); grub_unregister_command (cmd_initrd); grub_unregister_command (cmd_devicetree);
- grub_arm64_linux_unregister_xen_boot_command ();
}
Not needed with separate module.
diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c new file mode 100644 index 0000000..23bd00e --- /dev/null +++ b/grub-core/loader/arm64/xen_boot.c @@ -0,0 +1,615 @@ +/*
- 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/xen_boot.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 int *loaded;
+static struct xen_boot_binary *xen_hypervisor; +static struct xen_boot_binary *module_head; +static const grub_size_t module_default_align[] = {
- MODULE_IMAGE_MIN_ALIGN,
- MODULE_INITRD_MIN_ALIGN,
- MODULE_OTHER_MIN_ALIGN,
- MODULE_CUSTOM_MIN_ALIGN
+};
+static void *xen_boot_fdt; +static const compat_string_struct_t default_compat_string[] = {
- FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
- FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
- FDT_COMPATIBLE (MODULE_OTHER_COMPATIBLE)
+};
+/* Parse all the options of xen_module command. For now, we support
- (1) --type <the compatible stream>
- (2) --nounzip
- We also set up the type of module in this function.
- If there are some "--type" options in the command line,
- we make a custom compatible stream in this function. */
+static grub_err_t +set_module_type (struct xen_boot_binary *module, int argc, char *argv[],
int *file_name_index)
+{
- char **compat_string_temp_array =
- (char **) grub_zalloc (sizeof (char *) * argc);
- static module_type_t default_type = MODULE_IMAGE;
- grub_size_t total_size = 0;
- int num_types = 0, i;
- char *temp = NULL;
- *file_name_index = 0;
- /* if there are some options we need to process. */
- while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
- {
if (!grub_strcmp (argv[0], "--type"))
- {
module->node_info.type = MODULE_CUSTOM;
ARG_SHIFT (argc, argv);
total_size += grub_strlen (argv[0]) + 1;
compat_string_temp_array[num_types++] = argv[0];
ARG_SHIFT (argc, argv);
(*file_name_index) += 2;
This (and subsequent) parsing is unecessarily complicated. Please create separate commands for different types
- }
else if (!grub_strcmp (argv[0], "--nounzip"))
- {
grub_file_filter_disable_compression ();
ARG_SHIFT (argc, argv);
(*file_name_index) += 1;
- }
else /* we can add more options process code here. */
- {
grub_dprintf ("xen_boot_loader",
"Unknown option %s, skip.\n", argv[0]);
ARG_SHIFT (argc, argv);
(*file_name_index) += 1;
- }
- }
- /* To prevent some wrong command lines using "--type" option */
- if (!argc)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- /* For the default module type :
The implementation is following <Multiboot on ARM Specification>:
Each module will be given a default compatibility property
based on the order in which the modules are added.
The 1st module: compatible = "multiboot,kernel", "multiboot,module"
The 2nd module: compatible = "multiboot,ramdisk", "multiboot,module"
All subsequent modules: compatible = "multiboot,module"
But this order will NOT be interfered with "--type"(MODULE_CUSTOM)
For more detail, please refer to:
http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot */
- if (module->node_info.type != MODULE_CUSTOM)
- {
/* the module type is set by the load order */
module->node_info.type = default_type;
Please don't make it order-dependent more than necessarry.
switch (default_type)
- {
- case MODULE_IMAGE:
default_type = MODULE_INITRD;
break;
- case MODULE_INITRD:
default_type = MODULE_OTHER;
break;
- case MODULE_OTHER:
break;
- default:
default_type = MODULE_IMAGE; /* error, reset the type */
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
- }
- }
- else
- {
/* the module type is set by "--type"(MODULE_CUSTOM) */
module->node_info.compat_string = temp =
- (char *) grub_zalloc (total_size);
module->node_info.compat_string_size = total_size;
for (i = 0; num_types > 0; num_types--, i++, temp++)
- {
grub_strcpy (temp, compat_string_temp_array[i]);
temp += grub_strlen (compat_string_temp_array[i]);
- }
- }
- grub_free (compat_string_temp_array);
- return GRUB_ERR_NONE;
+}
+static grub_err_t +prepare_xen_hypervisor_params (void) +{
- int chosen_node = 0;
- int retval;
- xen_boot_fdt = grub_linux_get_fdt ();
- if (!xen_boot_fdt)
- return grub_error (GRUB_ERR_BAD_OS, "failed to get FDT");
- chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
- if (chosen_node < 0)
- chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
- if (chosen_node < 1)
- return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
BAD_OS means that OS images are invalid. ERR_IO is a generic error for such cases.
- grub_dprintf ("xen_boot_loader",
"Xen Hypervisor cmdline : %s @ %p size:%d\n",
xen_hypervisor->cmdline, xen_hypervisor->cmdline,
xen_hypervisor->cmdline_size);
No need for "boot_". xen_loader is fine and mre consistent.
- retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
xen_hypervisor->cmdline,
xen_hypervisor->cmdline_size);
- if (retval)
- return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
ditto
- return GRUB_ERR_NONE;
+}
+static grub_err_t +prepare_xen_module_params (struct xen_boot_binary *module) +{
- int retval, chosen_node = 0, module_node = 0;
- char module_name[FDT_NODE_NAME_MAX_SIZE];
- retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
xen_boot_address_align (module->start,
module->align));
- grub_dprintf ("xen_boot_loader", "Module node name %s \n", module_name);
- if (retval < (int) sizeof ("module@"))
- return grub_error (GRUB_ERR_BAD_OS, N_("failed to get FDT"));
- chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
- if (chosen_node < 0)
- chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
- if (chosen_node < 1)
- return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
- module_node =
- grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
- if (module_node < 0)
- module_node =
grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
- retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
module->node_info.compat_string,
(grub_uint32_t) module->node_info.
compat_string_size);
- if (retval)
- return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
- grub_dprintf ("xen_boot_loader", "Module %s compatible = %s size = 0x%lx\n",
module->name, module->node_info.compat_string,
module->node_info.compat_string_size);
- retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
xen_boot_address_align (module->start,
module->align),
module->size);
- if (retval)
- return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
- if (module->cmdline && module->cmdline_size > 0)
- {
grub_dprintf ("xen_boot_loader",
"Module %s cmdline : %s @ %p size:%d\n", module->name,
module->cmdline, module->cmdline, module->cmdline_size);
retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
module->cmdline, module->cmdline_size + 1);
if (retval)
- return grub_error (GRUB_ERR_BAD_OS, "failed to update FDT");
- }
- else
- {
grub_dprintf ("xen_boot_loader", "Module %s has not bootargs!\n",
module->name);
- }
- return GRUB_ERR_NONE;
+}
+static grub_err_t +install_all_params (void) +{
- grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
- 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, xen_boot_fdt);
- if (status != GRUB_EFI_SUCCESS)
- return grub_error (GRUB_ERR_BAD_OS, "failed to install FDT");
- grub_dprintf ("xen_boot_loader",
"Installed/updated FDT configuration table @ %p\n",
xen_boot_fdt);
- return GRUB_ERR_NONE;
+}
+static grub_err_t +clean_all_params (void) +{
- if (xen_boot_fdt)
- {
grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
BYTES_TO_PAGES (grub_fdt_get_totalsize
(xen_boot_fdt)));
xen_boot_fdt = NULL;
- }
- return GRUB_ERR_NONE;
+}
+static grub_err_t +finalize_params_xen_boot (void) +{
- struct xen_boot_binary *module;
- if (xen_hypervisor)
- {
if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
- goto fail;
- }
- else
- {
grub_dprintf ("xen_boot_loader",
"Failed to get Xen Hypervisor info!\n");
goto fail;
- }
- /* Set module params info */
- FOR_LIST_ELEMENTS (module, module_head)
- {
- if (module->start && module->size > 0)
{
- grub_dprintf ("xen_boot_loader", "Module %s @ 0x%lx size:0x%lx\n",
module->name,
xen_boot_address_align (module->start, module->align),
module->size);
- if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
goto fail;
}
- else
{
- grub_dprintf ("xen_boot_loader", "Module info error: %s!\n",
module->name);
- goto fail;
}
- }
- if (install_all_params () == GRUB_ERR_NONE)
- return GRUB_ERR_NONE;
+fail:
- clean_all_params ();
- return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
+}
+static grub_err_t +xen_boot (void) +{
- if (finalize_params_xen_boot () != GRUB_ERR_NONE)
- return grub_errno;
Better use err = finalize_params_xen_boot (); if (err) return err;
- return grub_arm64_uefi_boot_image (xen_hypervisor->start,
xen_hypervisor->size,
xen_hypervisor->cmdline);
+}
+static void +single_binary_unload (struct xen_boot_binary *binary) +{
Just put if (!binary) return; It will save a lot of if's.
- if (binary && binary->start && binary->size > 0)
- {
grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
BYTES_TO_PAGES (binary->size + binary->align));
- }
- if (binary && binary->cmdline && binary->cmdline_size > 0)
- {
grub_free (binary->cmdline);
grub_dprintf ("xen_boot_loader",
"Module %s cmdline memory free @ %p size: %d\n",
binary->name, binary->cmdline, binary->cmdline_size);
- }
- if (binary)
- {
if (binary->node_info.type == MODULE_CUSTOM)
- grub_free ((void *) binary->node_info.compat_string);
if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
- grub_list_remove (GRUB_AS_LIST (binary));
grub_dprintf ("xen_boot_loader",
"Module %s struct memory free @ %p size: 0x%lx\n",
binary->name, binary, sizeof (binary));
grub_free (binary);
- }
- return;
+}
+static void +all_binaries_unload (void) +{
- struct xen_boot_binary *binary;
- FOR_LIST_ELEMENTS (binary, module_head)
- {
- single_binary_unload (binary);
- }
- if (xen_hypervisor)
- single_binary_unload (xen_hypervisor);
- return;
+}
+static grub_err_t +xen_unload (void) +{
- *loaded = 0;
- all_binaries_unload ();
- clean_all_params ();
- grub_dl_unref (linux_mod);
- return GRUB_ERR_NONE;
+}
+static grub_err_t +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
int argc, char *argv[])
+{
- binary->size = grub_file_size (file);
- grub_dprintf ("xen_boot_loader", "Xen_boot %s file size: 0x%lx\n",
binary->name, binary->size);
- binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
(BYTES_TO_PAGES
(binary->size +
binary->align)));
- if (!binary->start)
- return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
- grub_dprintf ("xen_boot_loader", "Xen_boot %s numpages: 0x%lx\n",
binary->name, BYTES_TO_PAGES (binary->size + binary->align));
- if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
binary->align),
binary->size) < (grub_ssize_t) binary->size)
- {
We use != throughout. It's safer.
single_binary_unload (binary);
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
argv[0]);
- }
- /* Skip the xen_boot binary file name */
- ARG_SHIFT (argc, argv);
There shouldn't be any need for shifting. Just use argc - 1 and argv + 1
- if (argc > 0)
- {
binary->cmdline_size = grub_loader_cmdline_size (argc, argv);
binary->cmdline = grub_zalloc (binary->cmdline_size);
if (!binary->cmdline)
- {
single_binary_unload (binary);
return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
- }
grub_create_loader_cmdline (argc, argv, binary->cmdline,
binary->cmdline_size);
grub_dprintf ("xen_boot_loader",
"Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
binary->cmdline, binary->cmdline, binary->cmdline_size);
- }
- else
- {
binary->cmdline_size = 0;
binary->cmdline = NULL;
- }
- return GRUB_ERR_NONE;
+}
+static grub_err_t +grub_cmd_xen_module (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
+{
- struct xen_boot_binary *module = NULL;
- int file_name_index = 0;
- grub_file_t file = 0;
- if (!argc)
- {
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
goto fail;
- }
- if (!*loaded)
- {
grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the Xen Hypervisor first"));
goto fail;
- }
- module =
- (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
- if (!module)
- return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
Just return grub_errno; zalloc already calls grub_error
- /* process all the options and get module type */
- if (set_module_type (module, argc, argv, &file_name_index) != GRUB_ERR_NONE)
- goto fail;
- switch (module->node_info.type)
- {
- case MODULE_IMAGE:
- case MODULE_INITRD:
- case MODULE_OTHER:
module->node_info.compat_string =
- default_compat_string[module->node_info.type].compat_string;
module->node_info.compat_string_size =
- default_compat_string[module->node_info.type].size;
break;
- case MODULE_CUSTOM:
/* we have set the node_info in set_module_type */
break;
- default:
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
- }
- module->name = module->node_info.compat_string;
- module->align = module_default_align[module->node_info.type];
- grub_dprintf ("xen_boot_loader", "Init %s module and node info:\n"
"compatible %s\ncompat_string_size 0x%lx\n",
module->name, module->node_info.compat_string,
module->node_info.compat_string_size);
- file = grub_file_open (argv[file_name_index]);
- if (!file)
- goto fail;
- grub_errno = xen_boot_binary_load (module, file, argc - file_name_index,
argv + file_name_index);
When you call grub_error. grub_errno is already set
- 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_binary_unload (module);
- return grub_errno;
+}
+static grub_err_t +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
+{
- struct xen_hypervisor_header sh;
- grub_file_t file = NULL;
- grub_dl_ref (linux_mod);
- if (!argc)
- {
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
goto fail;
- }
- /* For now, we don't support any option in xen_hypervisor command.
If there are some options, we skip them. */
- while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
- {
grub_dprintf ("xen_boot_loader", "Unknown option %s, skip.\n", argv[0]);
ARG_SHIFT (argc, argv);
- }
Why do you need this? Just delete it.
- file = grub_file_open (argv[0]);
- if (!file)
- goto fail;
- if (grub_file_read (file, &sh, sizeof (sh)) < (long) sizeof (sh))
- goto fail;
- if (grub_arm64_uefi_check_image
((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
- goto fail;
- grub_file_seek (file, 0);
- grub_loader_unset ();
This is implicit in loader_set. Please add a comment why it needs to be explicit. I suppose it's to avoid unloading oneself.
- xen_hypervisor =
- (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
- if (!xen_hypervisor)
- return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
Ditto
- xen_hypervisor->name = XEN_HYPERVISOR_NAME;
- xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
- grub_errno = xen_boot_binary_load (xen_hypervisor, file, argc, argv);
- if (grub_errno == GRUB_ERR_NONE)
- {
grub_loader_set (xen_boot, xen_unload, 0);
*loaded = 1;
- }
+fail:
- if (file)
- grub_file_close (file);
- if (grub_errno != GRUB_ERR_NONE)
- {
*loaded = 0;
all_binaries_unload ();
grub_dl_unref (linux_mod);
- }
- return grub_errno;
+}
+static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
+void +grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *linux_loaded) +{
- cmd_xen_hypervisor =
- grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
N_("Load a xen hypervisor."));
- cmd_xen_module =
- grub_register_command ("xen_module", grub_cmd_xen_module, 0,
N_("Load a xen module."));
- linux_mod = mod;
- loaded = linux_loaded;
+}
+void +grub_arm64_linux_unregister_xen_boot_command (void) +{
- grub_unregister_command (cmd_xen_hypervisor);
- grub_unregister_command (cmd_xen_module);
+} diff --git a/include/grub/arm64/xen_boot.h b/include/grub/arm64/xen_boot.h new file mode 100644 index 0000000..8e8f6cb --- /dev/null +++ b/include/grub/arm64/xen_boot.h @@ -0,0 +1,115 @@ +/*
- xen_boot.h - Xen boot header file for Xen boot via FDT
- on AArch64 architecture.
- 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/.
- */
+#ifndef XEN_BOOT_HEADER +#define XEN_BOOT_HEADER 1
+#include <grub/list.h> +#include <grub/types.h> +#include <grub/efi/pe32.h> /* required by struct xen_hypervisor_header */
This file doesn't really look like having anything reusable. Please put it directly into .c
+#define XEN_HYPERVISOR_NAME "xen_hypervisor"
+#define MODULE_DEFAULT_ALIGN (0x0) +#define MODULE_IMAGE_MIN_ALIGN MODULE_DEFAULT_ALIGN +#define MODULE_INITRD_MIN_ALIGN MODULE_DEFAULT_ALIGN +#define MODULE_OTHER_MIN_ALIGN MODULE_DEFAULT_ALIGN +#define MODULE_CUSTOM_MIN_ALIGN MODULE_DEFAULT_ALIGN
+#define MODULE_IMAGE_COMPATIBLE "multiboot,kernel\0multiboot,module" +#define MODULE_INITRD_COMPATIBLE "multiboot,ramdisk\0multiboot,module" +#define MODULE_OTHER_COMPATIBLE "multiboot,module"
+/* This maximum size is defined in Power.org ePAPR V1.1
- 2.2.1.1 Node Name Requirements
- node-name@unit-address
- 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
- */
+#define FDT_NODE_NAME_MAX_SIZE (49)
+#define ARG_SHIFT(argc, argv) \
- do { \
- (argc)--; \
- (argv)++; \
- } while (0)
+struct compat_string_struct +{
- grub_size_t size;
- const char *compat_string;
+}; +typedef struct compat_string_struct compat_string_struct_t; +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
+enum module_type +{
- MODULE_IMAGE,
- MODULE_INITRD,
- MODULE_OTHER,
- MODULE_CUSTOM
+}; +typedef enum module_type module_type_t;
+struct fdt_node_info +{
- module_type_t type;
- const char *compat_string;
- grub_size_t compat_string_size;
+};
+struct xen_hypervisor_header +{
- struct grub_arm64_linux_kernel_header efi_head;
- /* This is always PE\0\0. */
- grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
- /* The COFF file header. */
- struct grub_pe32_coff_header coff_header;
- /* The Optional header. */
- struct grub_pe64_optional_header optional_header;
+};
+struct xen_boot_binary +{
- struct xen_boot_binary *next;
- struct xen_boot_binary **prev;
- const char *name;
- grub_addr_t start;
- grub_size_t size;
- grub_size_t align;
- char *cmdline;
- int cmdline_size;
- struct fdt_node_info node_info;
+};
+void grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *loaded); +void grub_arm64_linux_unregister_xen_boot_command (void);
+static __inline grub_addr_t +xen_boot_address_align (grub_addr_t start, grub_size_t align) +{
- return (align ? (ALIGN_UP (start, align)) : start);
+}
+#endif /* ! XEN_BOOT_HEADER */
On Wed, 2015-07-15 at 18:18 +0200, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
On 13.07.2015 10:53, fu.wei@linaro.org wrote:
From: Fu Wei fu.wei@linaro.org
This patch adds Xen boot support file: grub-core/loader/arm64/xen_boot.c include/grub/arm64/xen_boot.h
This patch also adds commands register code and hearder file into grub-core/loader/arm64/linux.c
- This adds support for the Xen boot on ARM specification for arm64.
- The implementation for Xen is following <Multiboot on ARM Specification>: http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
Please don't refer to this protocol as multiboot anywhere in grub or around because it's NOT multiboot and we don't want to confuse those 2 protocols.
That's fair enough, my hope was that the docs and communal knowledge about how to write a grub.cfg for Xen x86/multiboot could remain unchanged for Xen on arm (e.g. by using the same multiboot1 command names, which surely won't be reused on arm), but I can see why you would object to that and updating 20_linux_xen to DTRT on both arches solves the majority of that concern.
WRT to what to call it instead: I did try and design it[0] to not be Xen specific, so it would be nice to avoid making it so in the command names if possible. I suspect this may lead to a certain amount of bikeshedding, if so we should just call it something Xen specific and move on I think.
For a non-Xen specific name how about "fbm -- fdt boot module" protocol and associated commands fbm_kernel + fbm_module?
Ian.
[0] http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
Hi Vladimir,
I have submitted a new patchset (v3) for xen boot. this patchset follows all your comment here.
please help me again on this, Great thanks for your help.
On 16 July 2015 at 00:18, Vladimir 'φ-coder/phcoder' Serbinenko phcoder@gmail.com wrote:
On 13.07.2015 10:53, fu.wei@linaro.org wrote:
From: Fu Wei fu.wei@linaro.org
This patch adds Xen boot support file: grub-core/loader/arm64/xen_boot.c include/grub/arm64/xen_boot.h
This patch also adds commands register code and hearder file into grub-core/loader/arm64/linux.c
- This adds support for the Xen boot on ARM specification for arm64.
- The implementation for Xen is following <Multiboot on ARM Specification>: http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot
Please don't refer to this protocol as multiboot anywhere in grub or around because it's NOT multiboot and we don't want to confuse those 2 protocols.
and xen/docs/misc/arm/device-tree/booting.txt in Xen source code.
- The multiboot/module commands have existed, so we use xen_hypervisor/xen_module instead.
- This Xen boot support is built into linux module for aarch64.
- Adding this functionality to the existing "linux" module is for reusing the existing code of devicetree.
Please create separate module. Modules are dynamically linked.
Signed-off-by: Fu Wei fu.wei@linaro.org
grub-core/Makefile.core.def | 1 + grub-core/loader/arm64/linux.c | 6 + grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++ include/grub/arm64/xen_boot.h | 115 +++++++ 4 files changed, 737 insertions(+) create mode 100644 grub-core/loader/arm64/xen_boot.c create mode 100644 include/grub/arm64/xen_boot.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index a6101de..01f8261 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1659,6 +1659,7 @@ module = { ia64_efi = loader/ia64/efi/linux.c; arm = loader/arm/linux.c; arm64 = loader/arm64/linux.c;
- arm64 = loader/arm64/xen_boot.c; fdt = lib/fdt.c; common = loader/linux.c; common = lib/cmdline.c;
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c index 987f5b9..7ae9bde 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/xen_boot.h> #include <grub/efi/efi.h> #include <grub/efi/pe32.h> #include <grub/i18n.h> @@ -477,6 +478,9 @@ GRUB_MOD_INIT (linux) cmd_devicetree = grub_register_command ("devicetree", grub_cmd_devicetree, 0, N_("Load DTB file."));
- grub_arm64_linux_register_xen_boot_command (mod, &loaded);
- my_mod = mod;
}
@@ -485,4 +489,6 @@ GRUB_MOD_FINI (linux) grub_unregister_command (cmd_linux); grub_unregister_command (cmd_initrd); grub_unregister_command (cmd_devicetree);
- grub_arm64_linux_unregister_xen_boot_command ();
}
Not needed with separate module.
diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c new file mode 100644 index 0000000..23bd00e --- /dev/null +++ b/grub-core/loader/arm64/xen_boot.c @@ -0,0 +1,615 @@ +/*
- 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/xen_boot.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 int *loaded;
+static struct xen_boot_binary *xen_hypervisor; +static struct xen_boot_binary *module_head; +static const grub_size_t module_default_align[] = {
- MODULE_IMAGE_MIN_ALIGN,
- MODULE_INITRD_MIN_ALIGN,
- MODULE_OTHER_MIN_ALIGN,
- MODULE_CUSTOM_MIN_ALIGN
+};
+static void *xen_boot_fdt; +static const compat_string_struct_t default_compat_string[] = {
- FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
- FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
- FDT_COMPATIBLE (MODULE_OTHER_COMPATIBLE)
+};
+/* Parse all the options of xen_module command. For now, we support
- (1) --type <the compatible stream>
- (2) --nounzip
- We also set up the type of module in this function.
- If there are some "--type" options in the command line,
- we make a custom compatible stream in this function. */
+static grub_err_t +set_module_type (struct xen_boot_binary *module, int argc, char *argv[],
int *file_name_index)
+{
- char **compat_string_temp_array =
- (char **) grub_zalloc (sizeof (char *) * argc);
- static module_type_t default_type = MODULE_IMAGE;
- grub_size_t total_size = 0;
- int num_types = 0, i;
- char *temp = NULL;
- *file_name_index = 0;
- /* if there are some options we need to process. */
- while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
- {
if (!grub_strcmp (argv[0], "--type"))
{
module->node_info.type = MODULE_CUSTOM;
ARG_SHIFT (argc, argv);
total_size += grub_strlen (argv[0]) + 1;
compat_string_temp_array[num_types++] = argv[0];
ARG_SHIFT (argc, argv);
(*file_name_index) += 2;
This (and subsequent) parsing is unecessarily complicated. Please create separate commands for different types
}
else if (!grub_strcmp (argv[0], "--nounzip"))
{
grub_file_filter_disable_compression ();
ARG_SHIFT (argc, argv);
(*file_name_index) += 1;
}
else /* we can add more options process code here. */
{
grub_dprintf ("xen_boot_loader",
"Unknown option %s, skip.\n", argv[0]);
ARG_SHIFT (argc, argv);
(*file_name_index) += 1;
}
- }
- /* To prevent some wrong command lines using "--type" option */
- if (!argc)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
- /* For the default module type :
The implementation is following <Multiboot on ARM Specification>:
Each module will be given a default compatibility property
based on the order in which the modules are added.
The 1st module: compatible = "multiboot,kernel", "multiboot,module"
The 2nd module: compatible = "multiboot,ramdisk", "multiboot,module"
All subsequent modules: compatible = "multiboot,module"
But this order will NOT be interfered with "--type"(MODULE_CUSTOM)
For more detail, please refer to:
http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot */
- if (module->node_info.type != MODULE_CUSTOM)
- {
/* the module type is set by the load order */
module->node_info.type = default_type;
Please don't make it order-dependent more than necessarry.
switch (default_type)
{
case MODULE_IMAGE:
default_type = MODULE_INITRD;
break;
case MODULE_INITRD:
default_type = MODULE_OTHER;
break;
case MODULE_OTHER:
break;
default:
default_type = MODULE_IMAGE; /* error, reset the type */
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
}
- }
- else
- {
/* the module type is set by "--type"(MODULE_CUSTOM) */
module->node_info.compat_string = temp =
(char *) grub_zalloc (total_size);
module->node_info.compat_string_size = total_size;
for (i = 0; num_types > 0; num_types--, i++, temp++)
{
grub_strcpy (temp, compat_string_temp_array[i]);
temp += grub_strlen (compat_string_temp_array[i]);
}
- }
- grub_free (compat_string_temp_array);
- return GRUB_ERR_NONE;
+}
+static grub_err_t +prepare_xen_hypervisor_params (void) +{
- int chosen_node = 0;
- int retval;
- xen_boot_fdt = grub_linux_get_fdt ();
- if (!xen_boot_fdt)
- return grub_error (GRUB_ERR_BAD_OS, "failed to get FDT");
- chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
- if (chosen_node < 0)
- chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
- if (chosen_node < 1)
- return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
BAD_OS means that OS images are invalid. ERR_IO is a generic error for such cases.
- grub_dprintf ("xen_boot_loader",
"Xen Hypervisor cmdline : %s @ %p size:%d\n",
xen_hypervisor->cmdline, xen_hypervisor->cmdline,
xen_hypervisor->cmdline_size);
No need for "boot_". xen_loader is fine and mre consistent.
- retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
xen_hypervisor->cmdline,
xen_hypervisor->cmdline_size);
- if (retval)
- return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
ditto
- return GRUB_ERR_NONE;
+}
+static grub_err_t +prepare_xen_module_params (struct xen_boot_binary *module) +{
- int retval, chosen_node = 0, module_node = 0;
- char module_name[FDT_NODE_NAME_MAX_SIZE];
- retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
xen_boot_address_align (module->start,
module->align));
- grub_dprintf ("xen_boot_loader", "Module node name %s \n", module_name);
- if (retval < (int) sizeof ("module@"))
- return grub_error (GRUB_ERR_BAD_OS, N_("failed to get FDT"));
- chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
- if (chosen_node < 0)
- chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
- if (chosen_node < 1)
- return grub_error (GRUB_ERR_BAD_OS, "failed to get chosen node in FDT");
- module_node =
- grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
- if (module_node < 0)
- module_node =
grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
- retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
module->node_info.compat_string,
(grub_uint32_t) module->node_info.
compat_string_size);
- if (retval)
- return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
- grub_dprintf ("xen_boot_loader", "Module %s compatible = %s size = 0x%lx\n",
module->name, module->node_info.compat_string,
module->node_info.compat_string_size);
- retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
xen_boot_address_align (module->start,
module->align),
module->size);
- if (retval)
- return grub_error (GRUB_ERR_BAD_OS, N_("failed to update FDT"));
- if (module->cmdline && module->cmdline_size > 0)
- {
grub_dprintf ("xen_boot_loader",
"Module %s cmdline : %s @ %p size:%d\n", module->name,
module->cmdline, module->cmdline, module->cmdline_size);
retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
module->cmdline, module->cmdline_size + 1);
if (retval)
return grub_error (GRUB_ERR_BAD_OS, "failed to update FDT");
- }
- else
- {
grub_dprintf ("xen_boot_loader", "Module %s has not bootargs!\n",
module->name);
- }
- return GRUB_ERR_NONE;
+}
+static grub_err_t +install_all_params (void) +{
- grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
- 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, xen_boot_fdt);
- if (status != GRUB_EFI_SUCCESS)
- return grub_error (GRUB_ERR_BAD_OS, "failed to install FDT");
- grub_dprintf ("xen_boot_loader",
"Installed/updated FDT configuration table @ %p\n",
xen_boot_fdt);
- return GRUB_ERR_NONE;
+}
+static grub_err_t +clean_all_params (void) +{
- if (xen_boot_fdt)
- {
grub_efi_free_pages ((grub_efi_physical_address_t) xen_boot_fdt,
BYTES_TO_PAGES (grub_fdt_get_totalsize
(xen_boot_fdt)));
xen_boot_fdt = NULL;
- }
- return GRUB_ERR_NONE;
+}
+static grub_err_t +finalize_params_xen_boot (void) +{
- struct xen_boot_binary *module;
- if (xen_hypervisor)
- {
if (prepare_xen_hypervisor_params () != GRUB_ERR_NONE)
goto fail;
- }
- else
- {
grub_dprintf ("xen_boot_loader",
"Failed to get Xen Hypervisor info!\n");
goto fail;
- }
- /* Set module params info */
- FOR_LIST_ELEMENTS (module, module_head)
- {
- if (module->start && module->size > 0)
{
grub_dprintf ("xen_boot_loader", "Module %s @ 0x%lx size:0x%lx\n",
module->name,
xen_boot_address_align (module->start, module->align),
module->size);
if (prepare_xen_module_params (module) != GRUB_ERR_NONE)
goto fail;
}
- else
{
grub_dprintf ("xen_boot_loader", "Module info error: %s!\n",
module->name);
goto fail;
}
- }
- if (install_all_params () == GRUB_ERR_NONE)
- return GRUB_ERR_NONE;
+fail:
- clean_all_params ();
- return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
+}
+static grub_err_t +xen_boot (void) +{
- if (finalize_params_xen_boot () != GRUB_ERR_NONE)
- return grub_errno;
Better use err = finalize_params_xen_boot (); if (err) return err;
- return grub_arm64_uefi_boot_image (xen_hypervisor->start,
xen_hypervisor->size,
xen_hypervisor->cmdline);
+}
+static void +single_binary_unload (struct xen_boot_binary *binary) +{
Just put if (!binary) return; It will save a lot of if's.
- if (binary && binary->start && binary->size > 0)
- {
grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
BYTES_TO_PAGES (binary->size + binary->align));
- }
- if (binary && binary->cmdline && binary->cmdline_size > 0)
- {
grub_free (binary->cmdline);
grub_dprintf ("xen_boot_loader",
"Module %s cmdline memory free @ %p size: %d\n",
binary->name, binary->cmdline, binary->cmdline_size);
- }
- if (binary)
- {
if (binary->node_info.type == MODULE_CUSTOM)
grub_free ((void *) binary->node_info.compat_string);
if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
grub_list_remove (GRUB_AS_LIST (binary));
grub_dprintf ("xen_boot_loader",
"Module %s struct memory free @ %p size: 0x%lx\n",
binary->name, binary, sizeof (binary));
grub_free (binary);
- }
- return;
+}
+static void +all_binaries_unload (void) +{
- struct xen_boot_binary *binary;
- FOR_LIST_ELEMENTS (binary, module_head)
- {
- single_binary_unload (binary);
- }
- if (xen_hypervisor)
- single_binary_unload (xen_hypervisor);
- return;
+}
+static grub_err_t +xen_unload (void) +{
- *loaded = 0;
- all_binaries_unload ();
- clean_all_params ();
- grub_dl_unref (linux_mod);
- return GRUB_ERR_NONE;
+}
+static grub_err_t +xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
int argc, char *argv[])
+{
- binary->size = grub_file_size (file);
- grub_dprintf ("xen_boot_loader", "Xen_boot %s file size: 0x%lx\n",
binary->name, binary->size);
- binary->start = (grub_addr_t) grub_efi_allocate_pages (0,
(BYTES_TO_PAGES
(binary->size +
binary->align)));
- if (!binary->start)
- return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
- grub_dprintf ("xen_boot_loader", "Xen_boot %s numpages: 0x%lx\n",
binary->name, BYTES_TO_PAGES (binary->size + binary->align));
- if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
binary->align),
binary->size) < (grub_ssize_t) binary->size)
- {
We use != throughout. It's safer.
single_binary_unload (binary);
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
argv[0]);
- }
- /* Skip the xen_boot binary file name */
- ARG_SHIFT (argc, argv);
There shouldn't be any need for shifting. Just use argc - 1 and argv + 1
- if (argc > 0)
- {
binary->cmdline_size = grub_loader_cmdline_size (argc, argv);
binary->cmdline = grub_zalloc (binary->cmdline_size);
if (!binary->cmdline)
{
single_binary_unload (binary);
return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
}
grub_create_loader_cmdline (argc, argv, binary->cmdline,
binary->cmdline_size);
grub_dprintf ("xen_boot_loader",
"Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
binary->cmdline, binary->cmdline, binary->cmdline_size);
- }
- else
- {
binary->cmdline_size = 0;
binary->cmdline = NULL;
- }
- return GRUB_ERR_NONE;
+}
+static grub_err_t +grub_cmd_xen_module (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
+{
- struct xen_boot_binary *module = NULL;
- int file_name_index = 0;
- grub_file_t file = 0;
- if (!argc)
- {
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
goto fail;
- }
- if (!*loaded)
- {
grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the Xen Hypervisor first"));
goto fail;
- }
- module =
- (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
- if (!module)
- return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
Just return grub_errno; zalloc already calls grub_error
- /* process all the options and get module type */
- if (set_module_type (module, argc, argv, &file_name_index) != GRUB_ERR_NONE)
- goto fail;
- switch (module->node_info.type)
- {
- case MODULE_IMAGE:
- case MODULE_INITRD:
- case MODULE_OTHER:
module->node_info.compat_string =
default_compat_string[module->node_info.type].compat_string;
module->node_info.compat_string_size =
default_compat_string[module->node_info.type].size;
break;
- case MODULE_CUSTOM:
/* we have set the node_info in set_module_type */
break;
- default:
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
- }
- module->name = module->node_info.compat_string;
- module->align = module_default_align[module->node_info.type];
- grub_dprintf ("xen_boot_loader", "Init %s module and node info:\n"
"compatible %s\ncompat_string_size 0x%lx\n",
module->name, module->node_info.compat_string,
module->node_info.compat_string_size);
- file = grub_file_open (argv[file_name_index]);
- if (!file)
- goto fail;
- grub_errno = xen_boot_binary_load (module, file, argc - file_name_index,
argv + file_name_index);
When you call grub_error. grub_errno is already set
- 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_binary_unload (module);
- return grub_errno;
+}
+static grub_err_t +grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
+{
- struct xen_hypervisor_header sh;
- grub_file_t file = NULL;
- grub_dl_ref (linux_mod);
- if (!argc)
- {
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
goto fail;
- }
- /* For now, we don't support any option in xen_hypervisor command.
If there are some options, we skip them. */
- while (argc > 1 && !grub_strncmp (argv[0], "--", 2))
- {
grub_dprintf ("xen_boot_loader", "Unknown option %s, skip.\n", argv[0]);
ARG_SHIFT (argc, argv);
- }
Why do you need this? Just delete it.
- file = grub_file_open (argv[0]);
- if (!file)
- goto fail;
- if (grub_file_read (file, &sh, sizeof (sh)) < (long) sizeof (sh))
- goto fail;
- if (grub_arm64_uefi_check_image
((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
- goto fail;
- grub_file_seek (file, 0);
- grub_loader_unset ();
This is implicit in loader_set. Please add a comment why it needs to be explicit. I suppose it's to avoid unloading oneself.
- xen_hypervisor =
- (struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
- if (!xen_hypervisor)
- return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
Ditto
- xen_hypervisor->name = XEN_HYPERVISOR_NAME;
- xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
- grub_errno = xen_boot_binary_load (xen_hypervisor, file, argc, argv);
- if (grub_errno == GRUB_ERR_NONE)
- {
grub_loader_set (xen_boot, xen_unload, 0);
*loaded = 1;
- }
+fail:
- if (file)
- grub_file_close (file);
- if (grub_errno != GRUB_ERR_NONE)
- {
*loaded = 0;
all_binaries_unload ();
grub_dl_unref (linux_mod);
- }
- return grub_errno;
+}
+static grub_command_t cmd_xen_hypervisor, cmd_xen_module;
+void +grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *linux_loaded) +{
- cmd_xen_hypervisor =
- grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
N_("Load a xen hypervisor."));
- cmd_xen_module =
- grub_register_command ("xen_module", grub_cmd_xen_module, 0,
N_("Load a xen module."));
- linux_mod = mod;
- loaded = linux_loaded;
+}
+void +grub_arm64_linux_unregister_xen_boot_command (void) +{
- grub_unregister_command (cmd_xen_hypervisor);
- grub_unregister_command (cmd_xen_module);
+} diff --git a/include/grub/arm64/xen_boot.h b/include/grub/arm64/xen_boot.h new file mode 100644 index 0000000..8e8f6cb --- /dev/null +++ b/include/grub/arm64/xen_boot.h @@ -0,0 +1,115 @@ +/*
- xen_boot.h - Xen boot header file for Xen boot via FDT
- on AArch64 architecture.
- 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/.
- */
+#ifndef XEN_BOOT_HEADER +#define XEN_BOOT_HEADER 1
+#include <grub/list.h> +#include <grub/types.h> +#include <grub/efi/pe32.h> /* required by struct xen_hypervisor_header */
This file doesn't really look like having anything reusable. Please put it directly into .c
+#define XEN_HYPERVISOR_NAME "xen_hypervisor"
+#define MODULE_DEFAULT_ALIGN (0x0) +#define MODULE_IMAGE_MIN_ALIGN MODULE_DEFAULT_ALIGN +#define MODULE_INITRD_MIN_ALIGN MODULE_DEFAULT_ALIGN +#define MODULE_OTHER_MIN_ALIGN MODULE_DEFAULT_ALIGN +#define MODULE_CUSTOM_MIN_ALIGN MODULE_DEFAULT_ALIGN
+#define MODULE_IMAGE_COMPATIBLE "multiboot,kernel\0multiboot,module" +#define MODULE_INITRD_COMPATIBLE "multiboot,ramdisk\0multiboot,module" +#define MODULE_OTHER_COMPATIBLE "multiboot,module"
+/* This maximum size is defined in Power.org ePAPR V1.1
- 2.2.1.1 Node Name Requirements
- node-name@unit-address
- 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
- */
+#define FDT_NODE_NAME_MAX_SIZE (49)
+#define ARG_SHIFT(argc, argv) \
- do { \
- (argc)--; \
- (argv)++; \
- } while (0)
+struct compat_string_struct +{
- grub_size_t size;
- const char *compat_string;
+}; +typedef struct compat_string_struct compat_string_struct_t; +#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
+enum module_type +{
- MODULE_IMAGE,
- MODULE_INITRD,
- MODULE_OTHER,
- MODULE_CUSTOM
+}; +typedef enum module_type module_type_t;
+struct fdt_node_info +{
- module_type_t type;
- const char *compat_string;
- grub_size_t compat_string_size;
+};
+struct xen_hypervisor_header +{
- struct grub_arm64_linux_kernel_header efi_head;
- /* This is always PE\0\0. */
- grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
- /* The COFF file header. */
- struct grub_pe32_coff_header coff_header;
- /* The Optional header. */
- struct grub_pe64_optional_header optional_header;
+};
+struct xen_boot_binary +{
- struct xen_boot_binary *next;
- struct xen_boot_binary **prev;
- const char *name;
- grub_addr_t start;
- grub_size_t size;
- grub_size_t align;
- char *cmdline;
- int cmdline_size;
- struct fdt_node_info node_info;
+};
+void grub_arm64_linux_register_xen_boot_command (grub_dl_t mod, int *loaded); +void grub_arm64_linux_unregister_xen_boot_command (void);
+static __inline grub_addr_t +xen_boot_address_align (grub_addr_t start, grub_size_t align) +{
- return (align ? (ALIGN_UP (start, align)) : start);
+}
+#endif /* ! XEN_BOOT_HEADER */
From: Fu Wei fu.wei@linaro.org
This patch adds the support of boot command on arm64 for XEN: xen_hypervisor xen_module
Signed-off-by: Fu Wei fu.wei@linaro.org --- util/grub.d/20_linux_xen.in | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index f532fb9..b52c50d 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -120,16 +120,16 @@ linux_entry () else xen_rm_opts="no-real-mode edd=off" fi - multiboot ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} ${xen_rm_opts} + ${multiboot_cmd} ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} ${xen_rm_opts} echo '$(echo "$lmessage" | grub_quote)' - module ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args} + ${module_cmd} ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args} EOF if test -n "${initrd}" ; then # TRANSLATORS: ramdisk isn't identifier. Should be translated. message="$(gettext_printf "Loading initial ramdisk ...")" sed "s/^/$submenu_indentation/" << EOF echo '$(echo "$message" | grub_quote)' - module --nounzip ${rel_dirname}/${initrd} + ${module_cmd} --nounzip ${rel_dirname}/${initrd} EOF fi sed "s/^/$submenu_indentation/" << EOF @@ -185,6 +185,14 @@ case "$machine" in *) GENKERNEL_ARCH="$machine" ;; esac
+if [ "x$machine" != xaarch64 ]; then + multiboot_cmd="multiboot" + module_cmd="module" +else + multiboot_cmd="xen_hypervisor" + module_cmd="xen_module" +fi + # Extra indentation to add to menu entries in a submenu. We're not in a submenu # yet, so it's empty. In a submenu it will be equal to '\t' (one tab). submenu_indentation=""
В Mon, 13 Jul 2015 16:53:59 +0800 fu.wei@linaro.org пишет:
From: Fu Wei fu.wei@linaro.org
This patch adds the support of boot command on arm64 for XEN: xen_hypervisor xen_module
Signed-off-by: Fu Wei fu.wei@linaro.org
util/grub.d/20_linux_xen.in | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index f532fb9..b52c50d 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -120,16 +120,16 @@ linux_entry () else xen_rm_opts="no-real-mode edd=off" fi
- multiboot ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} ${xen_rm_opts}
- ${multiboot_cmd} ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} ${xen_rm_opts} echo '$(echo "$lmessage" | grub_quote)'
- module ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
- ${module_cmd} ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
EOF if test -n "${initrd}" ; then # TRANSLATORS: ramdisk isn't identifier. Should be translated. message="$(gettext_printf "Loading initial ramdisk ...")" sed "s/^/$submenu_indentation/" << EOF echo '$(echo "$message" | grub_quote)'
- module --nounzip ${rel_dirname}/${initrd}
- ${module_cmd} --nounzip ${rel_dirname}/${initrd}
EOF fi sed "s/^/$submenu_indentation/" << EOF @@ -185,6 +185,14 @@ case "$machine" in *) GENKERNEL_ARCH="$machine" ;; esac +if [ "x$machine" != xaarch64 ]; then
- multiboot_cmd="multiboot"
- module_cmd="module"
+else
- multiboot_cmd="xen_hypervisor"
- module_cmd="xen_module"
+fi
Strictly speaking, this is boot-time decision. As mentioned by Vladimir, better would be to provide alias xen_hypervisor and xen_module in multiboot for platforms supporting Xen (is MIPS really supported?) and use it consistently.
# Extra indentation to add to menu entries in a submenu. We're not in a submenu # yet, so it's empty. In a submenu it will be equal to '\t' (one tab). submenu_indentation=""
On Tue, 2015-07-14 at 06:53 +0300, Andrei Borzenkov wrote:
+if [ "x$machine" != xaarch64 ]; then
- multiboot_cmd="multiboot"
- module_cmd="module"
+else
- multiboot_cmd="xen_hypervisor"
- module_cmd="xen_module"
+fi
Strictly speaking, this is boot-time decision. As mentioned by Vladimir, better would be to provide alias xen_hypervisor and xen_module in multiboot for platforms supporting Xen (is MIPS really supported?) and use it consistently.
I had been thinking of this the other way around, e.g. on platforms which support Xen but not multiboot1 "multiboot" would be added as an alias for xen_hypervisor.
However so long as grub-mkconfig (via 20_linux_xen) work for everyone and that peoples existing hand-crafted x86/multiboot/Xen grub.cfg's continue to work then I think having the alias go either way would be fine.
BTW I had been going to suggest a function at the grub.cfg level which dispatched to the correct command, but I suppose an actual alias is better.
Ian.
On Tue, Jul 14, 2015 at 10:41:28AM +0100, Ian Campbell wrote:
On Tue, 2015-07-14 at 06:53 +0300, Andrei Borzenkov wrote:
+if [ "x$machine" != xaarch64 ]; then
- multiboot_cmd="multiboot"
- module_cmd="module"
And we should use the grub-file --is-multiboot2 to figure out if the Xen binary can also do that - and use multiboot2 protocol.
But that patch I can cobble after this one is done.
+else
- multiboot_cmd="xen_hypervisor"
- module_cmd="xen_module"
+fi
Strictly speaking, this is boot-time decision. As mentioned by Vladimir, better would be to provide alias xen_hypervisor and xen_module in multiboot for platforms supporting Xen (is MIPS really supported?) and use it consistently.
I had been thinking of this the other way around, e.g. on platforms which support Xen but not multiboot1 "multiboot" would be added as an alias for xen_hypervisor.
However so long as grub-mkconfig (via 20_linux_xen) work for everyone and that peoples existing hand-crafted x86/multiboot/Xen grub.cfg's continue to work then I think having the alias go either way would be fine.
BTW I had been going to suggest a function at the grub.cfg level which dispatched to the correct command, but I suppose an actual alias is better.
Ian.
Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Hi Andrei,
Great thanks for your review.
So Are you suggesting this: (1) in util/grub.d/20_linux_xen.in, we only use xen_hypervisor/xen_module. (2) in xen_boot.c, we only register command xen_hypervisor/xen_module. (3) in grub-core/loader/i386/xen.c, we *add* --------------- cmd_xen_hypervisort = grub_register_command ("xen_hypervisor", grub_cmd_xen, 0, N_("Load Linux.")); cmd_xen_module = grub_register_command ("xen_module", grub_cmd_module, 0, N_("Load module.")); --------------- (4)in grub-core/loader/multiboot.c, we *add* --------------- #if defined (__i386__) || defined (__aarch64__) cmd_xen_hypervisort = grub_register_command ("xen_hypervisor", grub_cmd_multiboot, 0, N_("Load a multiboot kernel.")); cmd_xen_module = grub_register_command ("xen_module", grub_cmd_module, 0, N_("Load a multiboot module.")); #endif ---------------
BTW, from the source code, MIPS isn't supported by multiboot, IS supported by multiboot2.
Please correct me. If I misunderstand your suggestion. :-)
Thanks again!
On 14 July 2015 at 11:53, Andrei Borzenkov arvidjaar@gmail.com wrote:
В Mon, 13 Jul 2015 16:53:59 +0800 fu.wei@linaro.org пишет:
From: Fu Wei fu.wei@linaro.org
This patch adds the support of boot command on arm64 for XEN: xen_hypervisor xen_module
Signed-off-by: Fu Wei fu.wei@linaro.org
util/grub.d/20_linux_xen.in | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index f532fb9..b52c50d 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -120,16 +120,16 @@ linux_entry () else xen_rm_opts="no-real-mode edd=off" fi
multiboot ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
${multiboot_cmd} ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts} echo '$(echo "$lmessage" | grub_quote)'
module ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
${module_cmd} ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
EOF if test -n "${initrd}" ; then # TRANSLATORS: ramdisk isn't identifier. Should be translated. message="$(gettext_printf "Loading initial ramdisk ...")" sed "s/^/$submenu_indentation/" << EOF echo '$(echo "$message" | grub_quote)'
module --nounzip ${rel_dirname}/${initrd}
${module_cmd} --nounzip ${rel_dirname}/${initrd}
EOF fi sed "s/^/$submenu_indentation/" << EOF @@ -185,6 +185,14 @@ case "$machine" in *) GENKERNEL_ARCH="$machine" ;; esac
+if [ "x$machine" != xaarch64 ]; then
multiboot_cmd="multiboot"
module_cmd="module"
+else
multiboot_cmd="xen_hypervisor"
module_cmd="xen_module"
+fi
Strictly speaking, this is boot-time decision. As mentioned by Vladimir, better would be to provide alias xen_hypervisor and xen_module in multiboot for platforms supporting Xen (is MIPS really supported?) and use it consistently.
# Extra indentation to add to menu entries in a submenu. We're not in a submenu # yet, so it's empty. In a submenu it will be equal to '\t' (one tab). submenu_indentation=""
On 14.07.2015 15:09, Fu Wei wrote:
Hi Andrei,
Great thanks for your review.
So Are you suggesting this: (1) in util/grub.d/20_linux_xen.in, we only use xen_hypervisor/xen_module. (2) in xen_boot.c, we only register command xen_hypervisor/xen_module. (3) in grub-core/loader/i386/xen.c, we *add*
cmd_xen_hypervisort = grub_register_command ("xen_hypervisor", grub_cmd_xen, 0, N_("Load Linux.")); cmd_xen_module = grub_register_command ("xen_module", grub_cmd_module, 0, N_("Load module."));
No. This is for pvgrub2.
(4)in grub-core/loader/multiboot.c, we *add*
#if defined (__i386__) || defined (__aarch64__) cmd_xen_hypervisort = grub_register_command ("xen_hypervisor", grub_cmd_multiboot, 0, N_("Load a multiboot kernel.")); cmd_xen_module = grub_register_command ("xen_module", grub_cmd_module, 0, N_("Load a multiboot module.")); #endif
No. Don't mix arm64 xen with multiboot. Neither in command names nor in the descriptions.
BTW, from the source code, MIPS isn't supported by multiboot, IS supported by multiboot2.
Please correct me. If I misunderstand your suggestion. :-)
Thanks again!
On 14 July 2015 at 11:53, Andrei Borzenkov arvidjaar@gmail.com wrote:
В Mon, 13 Jul 2015 16:53:59 +0800 fu.wei@linaro.org пишет:
From: Fu Wei fu.wei@linaro.org
This patch adds the support of boot command on arm64 for XEN: xen_hypervisor xen_module
Signed-off-by: Fu Wei fu.wei@linaro.org
util/grub.d/20_linux_xen.in | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index f532fb9..b52c50d 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -120,16 +120,16 @@ linux_entry () else xen_rm_opts="no-real-mode edd=off" fi
multiboot ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts}
${multiboot_cmd} ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} \${xen_rm_opts} echo '$(echo "$lmessage" | grub_quote)'
module ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
${module_cmd} ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args}
EOF if test -n "${initrd}" ; then # TRANSLATORS: ramdisk isn't identifier. Should be translated. message="$(gettext_printf "Loading initial ramdisk ...")" sed "s/^/$submenu_indentation/" << EOF echo '$(echo "$message" | grub_quote)'
module --nounzip ${rel_dirname}/${initrd}
${module_cmd} --nounzip ${rel_dirname}/${initrd}
EOF fi sed "s/^/$submenu_indentation/" << EOF @@ -185,6 +185,14 @@ case "$machine" in *) GENKERNEL_ARCH="$machine" ;; esac
+if [ "x$machine" != xaarch64 ]; then
multiboot_cmd="multiboot"
module_cmd="module"
+else
multiboot_cmd="xen_hypervisor"
module_cmd="xen_module"
+fi
Strictly speaking, this is boot-time decision. As mentioned by Vladimir, better would be to provide alias xen_hypervisor and xen_module in multiboot for platforms supporting Xen (is MIPS really supported?) and use it consistently.
# Extra indentation to add to menu entries in a submenu. We're not in a submenu # yet, so it's empty. In a submenu it will be equal to '\t' (one tab). submenu_indentation=""
From: Fu Wei fu.wei@linaro.org
This patch adds the introduction of xen_hypervisor/xen_module commands in docs/grub.texi
Signed-off-by: Fu Wei fu.wei@linaro.org --- docs/grub.texi | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/docs/grub.texi b/docs/grub.texi index b9f41a7..3bd2fc3 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -3839,6 +3839,9 @@ you forget a command, you can run the command @command{help} @comment * vbeinfo:: List available video modes * verify_detached:: Verify detached digital signature * videoinfo:: List available video modes +@comment * xen_hypervisor/xen_module:: Xen boot command, for arm64 only +* xen_hypervisor:: Load xen hypervisor binary on arm64 +* xen_module:: Load module for xen hypervisor on arm64 @end menu
@@ -5102,6 +5105,30 @@ successfully. If validation fails, it is set to a non-zero value. List available video modes. If resolution is given, show only matching modes. @end deffn
+@node xen_hypervisor +@subsection xen_hypervisor + +@deffn Command xen_hypervisor file [arguments] @dots{} +Load a Xen hypervisor binary from @var{file}. The rest of the +line is passed verbatim as the @dfn{kernel command-line}. Any Xen module must +be reloaded after using this command (@pxref{xen_module}). +This command is only available on ARM64 systems. +@end deffn + +@node xen_module +@subsection xen_module + +@deffn Command xen_module [--type <compatible stream>] file [arguments] +Load a module for xen hypervisor binary. The rest of the +line is passed verbatim as the module command line. +This command is only available on ARM64 systems. + +--type is an option which allow the module command to take "compatible" string. +This would override default compatible string for this module. +See @uref{http://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/Multiboot%7D, +to obtain more information. +@end deffn + @node Networking commands @section The list of networking commands
On Mon, 2015-07-13 at 16:53 +0800, fu.wei@linaro.org wrote:
From: Fu Wei fu.wei@linaro.org
- This adds support for the Xen boot on ARM specification for arm64.
I have used this to PXE boot Xen on a mustang board. My (handcrafted) grub.cfg was:
set default=0 set timeout=5 menuentry 'pxe multiboot xen' { echo "xen_hypervisor /trap/xen.efi" xen_hypervisor /trap/xen.efi conswitch=x watchdog console=dtuart dtuart=/soc/serial@1c020000 dom0_mem=512M,max:512M echo "xen_module /trap/vmlinuz" xen_module /trap/vmlinuz root=/dev/mapper/trap--vg-root ro console=hvc0 echo "xen_module /trap/initrd.gz" xen_module /trap/initrd.gz boot }
Tested-by: Ian Campbell ian.campbell@citrix.com
I didn't yet try a local boot from hdd since I'm sure it would work equivalently and there still seems to be some discussion around how the update-grub side should fit together.
Thanks!
Ian.
Hi Ian, Great thanks for your testing, will add your tested-by in my next patchset :-)
On 14 July 2015 at 17:29, Ian Campbell ian.campbell@citrix.com wrote:
On Mon, 2015-07-13 at 16:53 +0800, fu.wei@linaro.org wrote:
From: Fu Wei fu.wei@linaro.org
- This adds support for the Xen boot on ARM specification for arm64.
I have used this to PXE boot Xen on a mustang board. My (handcrafted) grub.cfg was:
set default=0 set timeout=5 menuentry 'pxe multiboot xen' { echo "xen_hypervisor /trap/xen.efi" xen_hypervisor /trap/xen.efi conswitch=x watchdog console=dtuart dtuart=/soc/serial@1c020000 dom0_mem=512M,max:512M echo "xen_module /trap/vmlinuz" xen_module /trap/vmlinuz root=/dev/mapper/trap--vg-root ro console=hvc0 echo "xen_module /trap/initrd.gz" xen_module /trap/initrd.gz boot }
Tested-by: Ian Campbell ian.campbell@citrix.com
I didn't yet try a local boot from hdd since I'm sure it would work equivalently and there still seems to be some discussion around how the update-grub side should fit together.
Thanks!
Ian.
On 13.07.2015 10:53, fu.wei@linaro.org wrote:
From: Fu Wei fu.wei@linaro.org
This adds support for the Xen boot on ARM specification for arm64.
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.
The multiboot/module commands have existed, so we use xen_hypervisor/xen_module instead.
This Xen boot support is built into linux module for aarch64, and can not be used alone.
Adding this functionality to the existing "linux" module is for reusing the existing code of devicetree.
This is a misguided decision. Modules can depend on other modules. Ideally shared functionality should be in a separate module but having xen depend on linux is an OK stopgap solution. Putting everything in one module is bad.
Add the support of xen_hypervisor/xen_module commands in util/grub.d/20_linux_xen.in
Add the introduction of xen_hypervisor/xen_module commands in docs/grub.texi
The example of this support is <How to boot Xen with GRUB on AArch64 the Foundation FVP model> https://wiki.linaro.org/LEG/Engineering/Grub2/Xen_booting_on_Foundation_FVP_...
Changelog: v2: remove the patches which have been accepted. according to Vladimir's suggestion, change the command manes and relevant code: multiboot-->xen_hypervisor module-->xen_module improve the option parsing support for xen_hypervisor/xen_module commands. add a patch for adding xen_hypervisor/xen_module support in util/grub.d/20_linux_xen.in. update docs/grub.texi patch for the new command names.
v1: The first version upstream patchset to grub-devel mailing list
Fu Wei (3): arm64: Add Xen boot support file
- util/grub.d/20_linux_xen.in: Add support of the XEN boot on aarch64
arm64: Add the introduction of xen_hypervisor/xen_module command in docs/grub.texi
docs/grub.texi | 27 ++ grub-core/Makefile.core.def | 1 + grub-core/loader/arm64/linux.c | 6 + grub-core/loader/arm64/xen_boot.c | 615 ++++++++++++++++++++++++++++++++++++++ include/grub/arm64/xen_boot.h | 115 +++++++ util/grub.d/20_linux_xen.in | 14 +- 6 files changed, 775 insertions(+), 3 deletions(-) create mode 100644 grub-core/loader/arm64/xen_boot.c create mode 100644 include/grub/arm64/xen_boot.h