arm64: Add multiboot support file grub-core/loader/arm64/multiboot.c include/grub/arm64/multiboot.h
Add commands register code and hearder file into grub-core/loader/arm64/linux.c
- This multiboot support is built into linux module for aarch64.
- 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.
- This adds support for the Xen Multiboot on ARM specification for arm64, enabling config file portability across the architectures.
- The multiboot command is currently x86-only, so reusing these command names should not conflict with any future additions of ARM support to multiboot2.
- The reason of adding this functionality to the existing "linux" module rather than "multiboot(2)" (1)multiboot is x86 only (2)Multiboot is added to "linux" module because it reuses existing code.
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/multiboot.c | 593 +++++++++++++++++++++++++++++++++++++ include/grub/arm64/multiboot.h | 115 +++++++ 4 files changed, 715 insertions(+)
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 42443bc..b963a62 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1673,6 +1673,7 @@ module = { ia64_efi = loader/ia64/efi/linux.c; arm = loader/arm/linux.c; arm64 = loader/arm64/linux.c; + arm64 = loader/arm64/multiboot.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 e9e9a29..4416535 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> @@ -470,6 +471,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; }
@@ -478,4 +482,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..1aadf16 --- /dev/null +++ b/grub-core/loader/arm64/multiboot.c @@ -0,0 +1,593 @@ +/* + * 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/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 multiboot_binary *multiboot_kernel = NULL; +static struct multiboot_binary *module_head = NULL; +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 *multiboot_fdt = NULL; +static const compat_string_struct_t default_compat_string[] = { + FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE), + FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE), + FDT_COMPATIBLE (MODULE_OTHER_COMPATIBLE) +}; + +static grub_err_t +set_module_type (struct multiboot_binary *module, + int argc, char *argv[], int *file_name_index) +{ + static module_type_t default_type = MODULE_IMAGE; + char *temp = NULL; + grub_size_t total_size = 0; + int num_types = 0, i; + char **compat_string_temp_array = + (char **) grub_zalloc (sizeof (char *) * argc); + + *file_name_index = 0; + + /* if there are some options we need to process. */ + if (argc >= 3) + { + while (argc > 1) + { + if (grub_strcmp (argv[0], "--type") == 0) + { + 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 + /* we can add more options process code here. */ + break; + } + } + + /* 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_kernel_params (void) +{ + int retval; + int chosen_node = 0; + + multiboot_fdt = grub_linux_get_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")); + + grub_dprintf ("multiboot_loader", + "Multiboot Kernel cmdline : %s @ %p size:%d\n", + multiboot_kernel->cmdline, multiboot_kernel->cmdline, + multiboot_kernel->cmdline_size); + + retval = grub_fdt_set_prop (multiboot_fdt, chosen_node, "bootargs", + multiboot_kernel->cmdline, + multiboot_kernel->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_module_params (struct multiboot_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", + multiboot_address_align (module->start, + module->align)); + grub_dprintf ("multiboot_loader", "Module node name %s \n", module_name); + + if (retval < (int) sizeof ("module@")) + return (grub_error (GRUB_ERR_BAD_OS, + N_("failed to set node name for module"))); + + 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")); + + 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", + 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 get module node in chosen node"))); + + grub_dprintf ("multiboot_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 (multiboot_fdt, module_node, + multiboot_address_align (module->start, + module->align), + module->size); + if (retval) + return (grub_error (GRUB_ERR_BAD_OS, + N_("failed to set reg info in module node"))); + + if ((module->cmdline) && (module->cmdline_size > 0)) + { + grub_dprintf ("multiboot_loader", + "Module %s cmdline : %s @ %p size:%d\n", module->name, + module->cmdline, module->cmdline, module->cmdline_size); + + retval = grub_fdt_set_prop (multiboot_fdt, module_node, + "bootargs", 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 ("multiboot_loader", "Module %s has not bootargs!\n", + module->name); + } + + return (GRUB_ERR_NONE); +} + +static grub_err_t +install_all_params (void) +{ + grub_efi_boot_services_t *b; + grub_efi_status_t status; + grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID; + + b = grub_efi_system_table->boot_services; + status = b->install_configuration_table (&fdt_guid, multiboot_fdt); + if (status != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT"); + + grub_dprintf ("multiboot_loader", + "Installed/updated FDT configuration table @ %p\n", + multiboot_fdt); + return (GRUB_ERR_NONE); +} + +static grub_err_t +clean_all_params (void) +{ + if (multiboot_fdt) + { + grub_efi_free_pages ((grub_efi_physical_address_t) multiboot_fdt, + BYTES_TO_PAGES (grub_fdt_get_totalsize + (multiboot_fdt))); + multiboot_fdt = NULL; + } + return (GRUB_ERR_NONE); +} + +static grub_err_t +finalize_params_multiboot (void) +{ + struct multiboot_binary *module; + + if (multiboot_kernel) + { + if (prepare_kernel_params () != GRUB_ERR_NONE) + goto fail; + } + else + { + grub_dprintf ("multiboot_loader", + "Failed to get Multiboot Kernel info!\n"); + goto fail; + } + + /* Set module params info */ + FOR_LIST_ELEMENTS (module, module_head) + { + if (module->start && module->size > 0) + { + grub_dprintf ("multiboot_loader", "Module %s @ 0x%lx size:0x%lx\n", + module->name, + multiboot_address_align (module->start, module->align), + module->size); + if (prepare_module_params (module) != GRUB_ERR_NONE) + goto fail; + } + else + { + grub_dprintf ("multiboot_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 +multiboot_boot (void) +{ + if (finalize_params_multiboot () != GRUB_ERR_NONE) + return (grub_errno); + + return (grub_arm64_uefi_boot_image + (multiboot_kernel->start, multiboot_kernel->size, + multiboot_kernel->cmdline)); +} + +static void +single_binary_unload (struct multiboot_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 ("multiboot_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, MULTIBOOT_KERNEL_NAME) != 0) + grub_list_remove (GRUB_AS_LIST (binary)); + grub_dprintf ("multiboot_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 multiboot_binary *binary; + + FOR_LIST_ELEMENTS (binary, module_head) + { + single_binary_unload (binary); + } + + if (multiboot_kernel) + single_binary_unload (multiboot_kernel); + + return; +} + +static grub_err_t +multiboot_unload (void) +{ + loaded = 0; + all_binaries_unload (); + clean_all_params (); + grub_dl_unref (linux_mod); + + return (GRUB_ERR_NONE); +} + +static grub_err_t +multiboot_binary_load (struct multiboot_binary *binary, grub_file_t file, + int argc, char *argv[]) +{ + binary->size = grub_file_size (file); + grub_dprintf ("multiboot_loader", "Multiboot %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 ("multiboot_loader", "Multiboot %s numpages: 0x%lx\n", + binary->name, BYTES_TO_PAGES (binary->size + binary->align)); + + if (grub_file_read (file, + (void *) multiboot_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 multiboot 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 ("multiboot_loader", + "Multiboot %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_module (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + + grub_file_t file = 0; + struct multiboot_binary *module = NULL; + int file_name_index = 0; + + if (argc == 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + goto fail; + } + + if (!loaded) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("Please use multiboot command first")); + goto fail; + } + + module = + (struct multiboot_binary *) + grub_zalloc (sizeof (struct multiboot_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 ("multiboot_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 = multiboot_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_multiboot (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_file_t file = NULL; + struct kernel_header sh; + + 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; + + 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 (); + + multiboot_kernel = + (struct multiboot_binary *) + grub_zalloc (sizeof (struct multiboot_binary)); + if (!multiboot_kernel) + return (grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"))); + + multiboot_kernel->name = MULTIBOOT_KERNEL_NAME; + multiboot_kernel->align = (grub_size_t) sh.optional_header.section_alignment; + + grub_errno = multiboot_binary_load (multiboot_kernel, file, argc, argv); + if (grub_errno == GRUB_ERR_NONE) + { + grub_loader_set (multiboot_boot, multiboot_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_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/include/grub/arm64/multiboot.h b/include/grub/arm64/multiboot.h new file mode 100644 index 0000000..d69c92a --- /dev/null +++ b/include/grub/arm64/multiboot.h @@ -0,0 +1,115 @@ +/* + * multiboot.h - Multiboot header file for Xen multiboot 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 MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1 + +#include <grub/list.h> +#include <grub/types.h> +#include <grub/efi/pe32.h> /* required by struct kernel_header */ + +#define MULTIBOOT_KERNEL_NAME "multiboot_kernel" + +#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 kernel_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 multiboot_binary +{ + struct multiboot_binary *next; + struct multiboot_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_multiboot_command (grub_dl_t mod); +void grub_arm64_linux_unregister_multiboot_command (void); + +static __inline grub_addr_t +multiboot_address_align (grub_addr_t start, grub_size_t align) +{ + return (align ? (ALIGN_UP (start, align)) : start); +} + +#endif /* ! MULTIBOOT_HEADER */
Hi Fu Wei,
The series looks good - I just need two more things: - Have a scan through the output strings, and see if you can find more strings to replace with existing ones. Then send me a list of the ones you can't see how to replace, and we can go through them together. - We need the documentation.
Regards,
Leif
On Sat, Nov 01, 2014 at 01:47:28AM +0800, Fu Wei wrote:
arm64: Add multiboot support file grub-core/loader/arm64/multiboot.c include/grub/arm64/multiboot.h
Add commands register code and hearder file into grub-core/loader/arm64/linux.c
This multiboot support is built into linux module for aarch64.
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.
This adds support for the Xen Multiboot on ARM specification for arm64, enabling config file portability across the architectures.
The multiboot command is currently x86-only, so reusing these command names should not conflict with any future additions of ARM support to multiboot2.
The reason of adding this functionality to the existing "linux" module rather than "multiboot(2)" (1)multiboot is x86 only (2)Multiboot is added to "linux" module because it reuses existing code.
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/multiboot.c | 593 +++++++++++++++++++++++++++++++++++++ include/grub/arm64/multiboot.h | 115 +++++++ 4 files changed, 715 insertions(+)
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 42443bc..b963a62 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1673,6 +1673,7 @@ module = { ia64_efi = loader/ia64/efi/linux.c; arm = loader/arm/linux.c; arm64 = loader/arm64/linux.c;
- arm64 = loader/arm64/multiboot.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 e9e9a29..4416535 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> @@ -470,6 +471,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;
} @@ -478,4 +482,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..1aadf16 --- /dev/null +++ b/grub-core/loader/arm64/multiboot.c @@ -0,0 +1,593 @@ +/*
- 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/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 multiboot_binary *multiboot_kernel = NULL; +static struct multiboot_binary *module_head = NULL; +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 *multiboot_fdt = NULL; +static const compat_string_struct_t default_compat_string[] = {
- FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
- FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
- FDT_COMPATIBLE (MODULE_OTHER_COMPATIBLE)
+};
+static grub_err_t +set_module_type (struct multiboot_binary *module,
int argc, char *argv[], int *file_name_index)
+{
- static module_type_t default_type = MODULE_IMAGE;
- char *temp = NULL;
- grub_size_t total_size = 0;
- int num_types = 0, i;
- char **compat_string_temp_array =
- (char **) grub_zalloc (sizeof (char *) * argc);
- *file_name_index = 0;
- /* if there are some options we need to process. */
- if (argc >= 3)
- {
while (argc > 1)
- {
if (grub_strcmp (argv[0], "--type") == 0)
{
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
/* we can add more options process code here. */
break;
- }
- }
- /* 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:
- */
- 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_kernel_params (void) +{
- int retval;
- int chosen_node = 0;
- multiboot_fdt = grub_linux_get_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"));
- grub_dprintf ("multiboot_loader",
"Multiboot Kernel cmdline : %s @ %p size:%d\n",
multiboot_kernel->cmdline, multiboot_kernel->cmdline,
multiboot_kernel->cmdline_size);
- retval = grub_fdt_set_prop (multiboot_fdt, chosen_node, "bootargs",
multiboot_kernel->cmdline,
multiboot_kernel->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_module_params (struct multiboot_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",
multiboot_address_align (module->start,
module->align));
- grub_dprintf ("multiboot_loader", "Module node name %s \n", module_name);
- if (retval < (int) sizeof ("module@"))
- return (grub_error (GRUB_ERR_BAD_OS,
N_("failed to set node name for module")));
- 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"));
- 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",
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 get module node in chosen node")));
- grub_dprintf ("multiboot_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 (multiboot_fdt, module_node,
multiboot_address_align (module->start,
module->align),
module->size);
- if (retval)
- return (grub_error (GRUB_ERR_BAD_OS,
N_("failed to set reg info in module node")));
- if ((module->cmdline) && (module->cmdline_size > 0))
- {
grub_dprintf ("multiboot_loader",
"Module %s cmdline : %s @ %p size:%d\n", module->name,
module->cmdline, module->cmdline, module->cmdline_size);
retval = grub_fdt_set_prop (multiboot_fdt, module_node,
"bootargs", 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 ("multiboot_loader", "Module %s has not bootargs!\n",
module->name);
- }
- return (GRUB_ERR_NONE);
+}
+static grub_err_t +install_all_params (void) +{
- grub_efi_boot_services_t *b;
- grub_efi_status_t status;
- grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
- b = grub_efi_system_table->boot_services;
- status = b->install_configuration_table (&fdt_guid, multiboot_fdt);
- if (status != GRUB_EFI_SUCCESS)
- return grub_error (GRUB_ERR_BAD_OS, "failed to install/update FDT");
- grub_dprintf ("multiboot_loader",
"Installed/updated FDT configuration table @ %p\n",
multiboot_fdt);
- return (GRUB_ERR_NONE);
+}
+static grub_err_t +clean_all_params (void) +{
- if (multiboot_fdt)
- {
grub_efi_free_pages ((grub_efi_physical_address_t) multiboot_fdt,
BYTES_TO_PAGES (grub_fdt_get_totalsize
(multiboot_fdt)));
multiboot_fdt = NULL;
- }
- return (GRUB_ERR_NONE);
+}
+static grub_err_t +finalize_params_multiboot (void) +{
- struct multiboot_binary *module;
- if (multiboot_kernel)
- {
if (prepare_kernel_params () != GRUB_ERR_NONE)
- goto fail;
- }
- else
- {
grub_dprintf ("multiboot_loader",
"Failed to get Multiboot Kernel info!\n");
goto fail;
- }
- /* Set module params info */
- FOR_LIST_ELEMENTS (module, module_head)
- {
- if (module->start && module->size > 0)
{
- grub_dprintf ("multiboot_loader", "Module %s @ 0x%lx size:0x%lx\n",
module->name,
multiboot_address_align (module->start, module->align),
module->size);
- if (prepare_module_params (module) != GRUB_ERR_NONE)
goto fail;
}
- else
{
- grub_dprintf ("multiboot_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 +multiboot_boot (void) +{
- if (finalize_params_multiboot () != GRUB_ERR_NONE)
- return (grub_errno);
- return (grub_arm64_uefi_boot_image
(multiboot_kernel->start, multiboot_kernel->size,
multiboot_kernel->cmdline));
+}
+static void +single_binary_unload (struct multiboot_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 ("multiboot_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, MULTIBOOT_KERNEL_NAME) != 0)
- grub_list_remove (GRUB_AS_LIST (binary));
grub_dprintf ("multiboot_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 multiboot_binary *binary;
- FOR_LIST_ELEMENTS (binary, module_head)
- {
- single_binary_unload (binary);
- }
- if (multiboot_kernel)
- single_binary_unload (multiboot_kernel);
- return;
+}
+static grub_err_t +multiboot_unload (void) +{
- loaded = 0;
- all_binaries_unload ();
- clean_all_params ();
- grub_dl_unref (linux_mod);
- return (GRUB_ERR_NONE);
+}
+static grub_err_t +multiboot_binary_load (struct multiboot_binary *binary, grub_file_t file,
int argc, char *argv[])
+{
- binary->size = grub_file_size (file);
- grub_dprintf ("multiboot_loader", "Multiboot %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 ("multiboot_loader", "Multiboot %s numpages: 0x%lx\n",
binary->name, BYTES_TO_PAGES (binary->size + binary->align));
- if (grub_file_read (file,
(void *) multiboot_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 multiboot 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 ("multiboot_loader",
"Multiboot %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_module (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
+{
- grub_file_t file = 0;
- struct multiboot_binary *module = NULL;
- int file_name_index = 0;
- if (argc == 0)
- {
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
goto fail;
- }
- if (!loaded)
- {
grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("Please use multiboot command first"));
goto fail;
- }
- module =
- (struct multiboot_binary *)
- grub_zalloc (sizeof (struct multiboot_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 ("multiboot_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 = multiboot_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_multiboot (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
+{
- grub_file_t file = NULL;
- struct kernel_header sh;
- 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;
- 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 ();
- multiboot_kernel =
- (struct multiboot_binary *)
- grub_zalloc (sizeof (struct multiboot_binary));
- if (!multiboot_kernel)
- return (grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")));
- multiboot_kernel->name = MULTIBOOT_KERNEL_NAME;
- multiboot_kernel->align = (grub_size_t) sh.optional_header.section_alignment;
- grub_errno = multiboot_binary_load (multiboot_kernel, file, argc, argv);
- if (grub_errno == GRUB_ERR_NONE)
- {
grub_loader_set (multiboot_boot, multiboot_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_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/include/grub/arm64/multiboot.h b/include/grub/arm64/multiboot.h new file mode 100644 index 0000000..d69c92a --- /dev/null +++ b/include/grub/arm64/multiboot.h @@ -0,0 +1,115 @@ +/*
- multiboot.h - Multiboot header file for Xen multiboot 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 MULTIBOOT_HEADER +#define MULTIBOOT_HEADER 1
+#include <grub/list.h> +#include <grub/types.h> +#include <grub/efi/pe32.h> /* required by struct kernel_header */
+#define MULTIBOOT_KERNEL_NAME "multiboot_kernel"
+#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 kernel_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 multiboot_binary +{
- struct multiboot_binary *next;
- struct multiboot_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_multiboot_command (grub_dl_t mod); +void grub_arm64_linux_unregister_multiboot_command (void);
+static __inline grub_addr_t +multiboot_address_align (grub_addr_t start, grub_size_t align) +{
- return (align ? (ALIGN_UP (start, align)) : start);
+}
+#endif /* ! MULTIBOOT_HEADER */
1.8.3.1