grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH V2] multiboot2: Implement the new module_relocatable_tag


From: Zide Chen
Subject: [PATCH V2] multiboot2: Implement the new module_relocatable_tag
Date: Fri, 24 Apr 2020 09:58:04 -0700

In contrast to Mulitboot, in Mulitboot2, there is currently no way to
control where to load the modules to. This could be a problem, e.g., the
OS loaded by Multiboot2 needs to reserve low address for some particular
purposes and not for loading modules.

This new tag gives it flexibility to control the modules load addresses,
which is independent to whether the kernel relocatable tag is present or
not.

V2: declare size as grub_ssize_t to resolve Werror=sign-compare
compiling issue.

Signed-off-by: Zide Chen <address@hidden>
---
 grub-core/loader/multiboot.c      | 26 ++++++++++++++++++++++----
 grub-core/loader/multiboot_mbi2.c | 23 +++++++++++++++++++++++
 include/grub/multiboot2.h         |  9 +++++++++
 include/multiboot2.h              | 11 +++++++++++
 4 files changed, 65 insertions(+), 4 deletions(-)

diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index 4a98d7082598..fd58de3c9313 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -363,12 +363,14 @@ grub_cmd_module (grub_command_t cmd __attribute__ 
((unused)),
                 int argc, char *argv[])
 {
   grub_file_t file = 0;
-  grub_ssize_t size;
+  grub_size_t size;
   void *module = NULL;
   grub_addr_t target;
   grub_err_t err;
   int nounzip = 0;
   grub_uint64_t lowest_addr = 0;
+  grub_uint64_t max_addr;
+  int preference = GRUB_RELOCATOR_PREFERENCE_NONE;
 
   if (argc == 0)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@@ -401,11 +403,27 @@ grub_cmd_module (grub_command_t cmd __attribute__ 
((unused)),
   size = grub_file_size (file);
   if (size)
   {
+    max_addr = (0xffffffff - size) + 1;
+
+#ifdef GRUB_USE_MULTIBOOT2
+    if (grub_multiboot2_mri.relocatable)
+      {
+        lowest_addr = grub_multiboot2_mri.min_addr;
+        max_addr = grub_multiboot2_mri.max_addr;
+        preference = grub_multiboot2_mri.preference;
+        if (size > max_addr || lowest_addr > max_addr - size)
+          {
+            grub_file_close (file);
+            return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid min/max address 
and/or load size for modules");
+          }
+      }
+#endif
+
     grub_relocator_chunk_t ch;
     err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch,
-                                           lowest_addr, (0xffffffff - size) + 
1,
+                                           lowest_addr, max_addr,
                                            size, MULTIBOOT_MOD_ALIGN,
-                                           GRUB_RELOCATOR_PREFERENCE_NONE, 1);
+                                           preference, 1);
     if (err)
       {
        grub_file_close (file);
@@ -427,7 +445,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ 
((unused)),
       return err;
     }
 
-  if (size && grub_file_read (file, module, size) != size)
+  if (size && grub_file_read (file, module, size) != (grub_ssize_t)size)
     {
       grub_file_close (file);
       if (!grub_errno)
diff --git a/grub-core/loader/multiboot_mbi2.c 
b/grub-core/loader/multiboot_mbi2.c
index 18e766c7b31c..c2639623228e 100644
--- a/grub-core/loader/multiboot_mbi2.c
+++ b/grub-core/loader/multiboot_mbi2.c
@@ -75,6 +75,7 @@ static unsigned elf_sec_shstrndx;
 static void *elf_sections;
 static int keep_bs = 0;
 static grub_uint32_t load_base_addr;
+struct module_relocatable_info grub_multiboot2_mri;
 
 void
 grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize,
@@ -114,6 +115,7 @@ grub_multiboot2_load (grub_file_t file, const char 
*filename)
   struct multiboot_header_tag *tag;
   struct multiboot_header_tag_address *addr_tag = NULL;
   struct multiboot_header_tag_relocatable *rel_tag;
+  struct multiboot_header_tag_module_relocatable *mod_rel_tag;
   int entry_specified = 0, efi_entry_specified = 0;
   grub_addr_t entry = 0, efi_entry = 0;
   grub_uint32_t console_required = 0;
@@ -123,6 +125,7 @@ grub_multiboot2_load (grub_file_t file, const char 
*filename)
 
   mld.mbi_ver = 2;
   mld.relocatable = 0;
+  grub_multiboot2_mri.relocatable = 0;
 
   mld.buffer = grub_malloc (MULTIBOOT_SEARCH);
   if (!mld.buffer)
@@ -248,6 +251,26 @@ grub_multiboot2_load (grub_file_t file, const char 
*filename)
          }
        break;
 
+      case MULTIBOOT_HEADER_TAG_MODULE_RELOCATABLE:
+       mod_rel_tag = (struct multiboot_header_tag_module_relocatable *) tag;
+       grub_multiboot2_mri.relocatable = 1;
+       grub_multiboot2_mri.min_addr = mod_rel_tag->min_addr;
+       grub_multiboot2_mri.max_addr = mod_rel_tag->max_addr;
+       switch (mod_rel_tag->preference)
+         {
+         case MULTIBOOT_LOAD_PREFERENCE_LOW:
+           grub_multiboot2_mri.preference = GRUB_RELOCATOR_PREFERENCE_LOW;
+           break;
+
+         case MULTIBOOT_LOAD_PREFERENCE_HIGH:
+           grub_multiboot2_mri.preference = GRUB_RELOCATOR_PREFERENCE_HIGH;
+           break;
+
+         default:
+           grub_multiboot2_mri.preference = GRUB_RELOCATOR_PREFERENCE_NONE;
+         }
+       break;
+
        /* GRUB always page-aligns modules.  */
       case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
        break;
diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h
index 502d34ef1804..6d7598eeffcc 100644
--- a/include/grub/multiboot2.h
+++ b/include/grub/multiboot2.h
@@ -92,6 +92,14 @@ struct mbi_load_data
 };
 typedef struct mbi_load_data mbi_load_data_t;
 
+struct module_relocatable_info
+{
+  int relocatable;
+  grub_uint32_t min_addr;
+  grub_uint32_t max_addr;
+  grub_uint32_t preference;
+};
+
 /* Load ELF32 or ELF64.  */
 grub_err_t
 grub_multiboot2_load_elf (mbi_load_data_t *mld);
@@ -99,6 +107,7 @@ grub_multiboot2_load_elf (mbi_load_data_t *mld);
 extern grub_size_t grub_multiboot2_pure_size;
 extern grub_size_t grub_multiboot2_alloc_mbi;
 extern grub_uint32_t grub_multiboot2_payload_eip;
+extern struct module_relocatable_info grub_multiboot2_mri;
 
 
 #endif /* ! GRUB_MULTIBOOT_HEADER */
diff --git a/include/multiboot2.h b/include/multiboot2.h
index 5693923c014f..41b973aed193 100644
--- a/include/multiboot2.h
+++ b/include/multiboot2.h
@@ -74,6 +74,7 @@
 #define MULTIBOOT_HEADER_TAG_EFI_BS  7
 #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64  9
 #define MULTIBOOT_HEADER_TAG_RELOCATABLE  10
+#define MULTIBOOT_HEADER_TAG_MODULE_RELOCATABLE  11
 
 #define MULTIBOOT2_ARCHITECTURE_I386  0
 #define MULTIBOOT2_ARCHITECTURE_MIPS32  4
@@ -178,6 +179,16 @@ struct multiboot_header_tag_relocatable
   multiboot_uint32_t preference;
 };
 
+struct multiboot_header_tag_module_relocatable
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t min_addr;
+  multiboot_uint32_t max_addr;
+  multiboot_uint32_t preference;
+};
+
 struct multiboot_color
 {
   multiboot_uint8_t red;
-- 
2.17.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]