grub-devel
[Top][All Lists]
Advanced

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

[RFC PATCH 1/4] util/grub-wrap: New tool to wrap a file as a PE image


From: Zhang Boyang
Subject: [RFC PATCH 1/4] util/grub-wrap: New tool to wrap a file as a PE image
Date: Mon, 5 Dec 2022 21:06:02 +0800

This new tool can wrap a non-PE file as a PE image, which can be
subsequently digitally signed (and verified by shim).

It's important that this type of PE images must be rejected when trying
to execute them. This is done by making them look like plain Windows
DLLs instead of UEFI images. Major differences between these wrappers
and normal UEFI images are:

 * DLL flag is set (nobody cares)
 * Entry point is set to 0 (shim rejects this)
 * Subsystem is set to Windows GUI instead of EFI Application (tianocore
   rejects this)

Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
---
 .gitignore                  |   2 +
 Makefile.util.def           |  20 +++
 docs/man/grub-wrap.h2m      |   4 +
 include/grub/efi/pe32.h     |   4 +
 include/grub/util/install.h |   3 +-
 util/grub-install-common.c  |   2 +-
 util/grub-mkimage.c         |   3 +-
 util/grub-wrap.c            | 160 ++++++++++++++++++++++++
 util/mkimage.c              | 239 ++++++++++++++++++++++--------------
 9 files changed, 341 insertions(+), 96 deletions(-)
 create mode 100644 docs/man/grub-wrap.h2m
 create mode 100644 util/grub-wrap.c

diff --git a/.gitignore b/.gitignore
index f6a1bd051..e2802578e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -179,6 +179,8 @@ widthspec.bin
 /grub-sparc64-setup.exe
 /grub-syslinux2cfg
 /grub-syslinux2cfg.exe
+/grub-wrap
+/grub-wrap.exe
 /grub_cmd_date
 /grub_cmd_echo
 /grub_cmd_regexp
diff --git a/Makefile.util.def b/Makefile.util.def
index d919c562c..c02632fbd 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -1385,3 +1385,23 @@ program = {
   ldadd = grub-core/lib/gnulib/libgnu.a;
   ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
 };
+
+program = {
+  name = grub-wrap;
+  mansection = 1;
+
+  common = util/grub-wrap.c;
+  common = util/mkimage.c;
+  common = util/grub-mkimage32.c;
+  common = util/grub-mkimage64.c;
+  common = util/resolve.c;
+  common = grub-core/kern/emu/argp_common.c;
+  common = grub-core/osdep/init.c;
+
+  ldadd = '$(LIBLZMA)';
+  ldadd = libgrubmods.a;
+  ldadd = libgrubgcry.a;
+  ldadd = libgrubkern.a;
+  ldadd = grub-core/lib/gnulib/libgnu.a;
+  ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
+};
diff --git a/docs/man/grub-wrap.h2m b/docs/man/grub-wrap.h2m
new file mode 100644
index 000000000..f9d44fcd7
--- /dev/null
+++ b/docs/man/grub-wrap.h2m
@@ -0,0 +1,4 @@
+[NAME]
+grub-wrap \- Wrap a file as a PE image
+[DESCRIPTION]
+grub-wrap wraps a file as a PE image.
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
index 98c4ff177..7609b5198 100644
--- a/include/grub/efi/pe32.h
+++ b/include/grub/efi/pe32.h
@@ -227,8 +227,12 @@ struct grub_pe64_optional_header
 #define GRUB_PE32_PE32_MAGIC   0x10b
 #define GRUB_PE32_PE64_MAGIC   0x20b
 
+#define GRUB_PE32_SUBSYSTEM_WINDOWS_GUI                2
 #define GRUB_PE32_SUBSYSTEM_EFI_APPLICATION    10
 
+#define GRUB_PE32_DLLCHARACTERISTICS_DYNAMIC_BASE      0x0040
+#define GRUB_PE32_DLLCHARACTERISTICS_NX_COMPAT         0x0100
+
 #define GRUB_PE32_NUM_DATA_DIRECTORIES 16
 
 struct grub_pe32_section_table
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 7d7445af9..eac34abaf 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -190,7 +190,8 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
                             const struct grub_install_image_target_desc 
*image_target,
                             int note,
                             grub_compression_t comp, const char *dtb_file,
-                            const char *sbat_path, const int 
disable_shim_lock);
+                            const char *sbat_path, const int disable_shim_lock,
+                            const char *wrap_path, const char *wrap_section);
 
 const struct grub_install_image_target_desc *
 grub_install_get_image_target (const char *arg);
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index e45fb2903..c64a061b7 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -681,7 +681,7 @@ grub_install_make_image_wrap_file (const char *dir, const 
char *prefix,
                               modules.entries, memdisk_path,
                               pubkeys, npubkeys, config_path, tgt,
                               note, compression, dtb, sbat,
-                              disable_shim_lock);
+                              disable_shim_lock, NULL, NULL);
   while (dc--)
     grub_install_pop_module ();
 }
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
index c0d559937..51aebb40e 100644
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -325,7 +325,8 @@ main (int argc, char *argv[])
                               arguments.npubkeys, arguments.config,
                               arguments.image_target, arguments.note,
                               arguments.comp, arguments.dtb,
-                              arguments.sbat, arguments.disable_shim_lock);
+                              arguments.sbat, arguments.disable_shim_lock,
+                              NULL, NULL);
 
   if (grub_util_file_sync (fp) < 0)
     grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout",
diff --git a/util/grub-wrap.c b/util/grub-wrap.c
new file mode 100644
index 000000000..d54190b2d
--- /dev/null
+++ b/util/grub-wrap.c
@@ -0,0 +1,160 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2022 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 <config.h>
+
+#include <grub/util/misc.h>
+#include <grub/i18n.h>
+#include <grub/term.h>
+#include <grub/util/install.h>
+
+#define _GNU_SOURCE    1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#pragma GCC diagnostic ignored "-Wmissing-prototypes"
+#pragma GCC diagnostic ignored "-Wmissing-declarations"
+#include <argp.h>
+#pragma GCC diagnostic error "-Wmissing-prototypes"
+#pragma GCC diagnostic error "-Wmissing-declarations"
+
+#include "progname.h"
+
+struct arguments
+{
+  char *input;
+  char *name;
+  char *sbat;
+  char *output;
+  const struct grub_install_image_target_desc *image_target;
+  int verbosity;
+};
+
+static struct argp_option options[] = {
+  {"input",  'i', N_("FILE"), 0, N_("set input filename."), 0},
+  {"name",  'n', N_("NAME"), 0, N_("set section name."), 0},
+  {"sbat",  's', N_("FILE"), 0, N_("SBAT metadata"), 0},
+  {"output",  'o', N_("FILE"), 0, N_("set output filename."), 0},
+  {"format",  'O', N_("FORMAT"), 0, N_("generate an image in FORMAT"), 0},
+  {"verbose",     'v', 0,      0, N_("print verbose messages."), 0},
+  { 0, 0, 0, 0, 0, 0 }
+};
+
+static error_t
+argp_parser (int key, char *arg, struct argp_state *state)
+{
+  /* Get the input argument from argp_parse, which we
+     know is a pointer to our arguments structure. */
+  struct arguments *arguments = state->input;
+
+  switch (key)
+    {
+    case 'i':
+      free (arguments->input);
+      arguments->input = xstrdup (arg);
+      break;
+
+    case 'n':
+      free (arguments->name);
+      arguments->name = xstrdup (arg);
+      break;
+
+    case 's':
+      free (arguments->sbat);
+      arguments->sbat = xstrdup (arg);
+      break;
+
+    case 'o':
+      free (arguments->output);
+      arguments->output = xstrdup (arg);
+      break;
+
+    case 'O':
+      {
+       arguments->image_target = grub_install_get_image_target (arg);
+       if (!arguments->image_target)
+         {
+           printf (_("unknown target format %s\n"), arg);
+           argp_usage (state);
+           exit (1);
+         }
+       break;
+      }
+
+    case 'v':
+      arguments->verbosity++;
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+
+  return 0;
+}
+
+static struct argp argp = {
+  options, argp_parser, N_("[OPTIONS]"),
+  N_("Wrap a file as a PE image."),
+  NULL, NULL, NULL
+};
+
+int
+main (int argc, char *argv[])
+{
+  FILE *out;
+
+  struct arguments arguments;
+
+  grub_util_host_init (&argc, &argv);
+
+  /* Check for options.  */
+  memset (&arguments, 0, sizeof (struct arguments));
+  if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0)
+    {
+      fprintf (stderr, "%s", _("Error in parsing command line arguments\n"));
+      exit(1);
+    }
+
+  if (!arguments.input)
+    grub_util_error ("%s", _("input file must be specified"));
+
+  if (!arguments.name)
+    grub_util_error ("%s", _("section name must be specified"));
+
+  if (!arguments.output)
+    grub_util_error ("%s", _("output file must be specified"));
+
+  if (!arguments.image_target)
+    grub_util_error ("%s", _("target format must be specified"));
+
+  out = grub_util_fopen (arguments.output, "wb");
+  if (!out)
+    grub_util_error (_("cannot open `%s': %s"), arguments.output, strerror 
(errno));
+
+  grub_install_generate_image (NULL, NULL, out, NULL, NULL, NULL, NULL, 0,
+                              NULL, arguments.image_target,
+                              0, GRUB_COMPRESSION_NONE, NULL,
+                              arguments.sbat, 0,
+                              arguments.input, arguments.name);
+
+  return 0;
+}
diff --git a/util/mkimage.c b/util/mkimage.c
index 43078c71c..349f055bb 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -61,18 +61,20 @@
 /* use 2015-01-01T00:00:00+0000 as a stock timestamp */
 #define STABLE_EMBEDDING_TIMESTAMP 1420070400
 
+#define EFI_MAX_SECTIONS 5
+
 #define EFI32_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE          \
                                    + GRUB_PE32_SIGNATURE_SIZE          \
                                    + sizeof (struct grub_pe32_coff_header) \
                                    + sizeof (struct grub_pe32_optional_header) 
\
-                                   + 4 * sizeof (struct 
grub_pe32_section_table), \
+                                   + EFI_MAX_SECTIONS * sizeof (struct 
grub_pe32_section_table), \
                                    GRUB_PE32_FILE_ALIGNMENT)
 
 #define EFI64_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE          \
                                    + GRUB_PE32_SIGNATURE_SIZE          \
                                    + sizeof (struct grub_pe32_coff_header) \
                                    + sizeof (struct grub_pe64_optional_header) 
\
-                                   + 4 * sizeof (struct 
grub_pe32_section_table), \
+                                   + EFI_MAX_SECTIONS * sizeof (struct 
grub_pe32_section_table), \
                                    GRUB_PE32_FILE_ALIGNMENT)
 
 static const struct grub_install_image_target_desc image_targets[] =
@@ -819,9 +821,9 @@ grub_install_get_image_targets_string (void)
 /*
  * The image_target parameter is used by the grub_host_to_target32() macro.
  */
-static struct grub_pe32_section_table *
+static void
 init_pe_section(const struct grub_install_image_target_desc *image_target,
-               struct grub_pe32_section_table *section,
+               struct grub_pe32_section_table *section, int *n_sections,
                const char * const name,
                grub_uint32_t *vma, grub_uint32_t vsz, grub_uint32_t valign,
                grub_uint32_t *rda, grub_uint32_t rsz,
@@ -829,6 +831,13 @@ init_pe_section(const struct 
grub_install_image_target_desc *image_target,
 {
   size_t len = strlen (name);
 
+  if (vsz == 0)
+    return;
+
+  if (*n_sections >= EFI_MAX_SECTIONS)
+    grub_util_error (_("too many sections"));
+  section = &section[(*n_sections)++];
+
   if (len > sizeof (section->name))
     grub_util_error (_("section name %s length is bigger than %lu"),
                     name, (unsigned long) sizeof (section->name));
@@ -844,8 +853,6 @@ init_pe_section(const struct grub_install_image_target_desc 
*image_target,
   (*rda) = ALIGN_UP (*rda + rsz, GRUB_PE32_FILE_ALIGNMENT);
 
   section->characteristics = grub_host_to_target32 (characteristics);
-
-  return section + 1;
 }
 
 /*
@@ -870,17 +877,22 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
                             size_t npubkeys, char *config_path,
                             const struct grub_install_image_target_desc 
*image_target,
                             int note, grub_compression_t comp, const char 
*dtb_path,
-                            const char *sbat_path, int disable_shim_lock)
+                            const char *sbat_path, int disable_shim_lock,
+                            const char *wrap_path, const char *wrap_section)
 {
-  char *kernel_img, *core_img;
+  char *kernel_img = NULL, *core_img;
   size_t total_module_size, core_size;
   size_t memdisk_size = 0, config_size = 0;
   size_t prefix_size = 0, dtb_size = 0, sbat_size = 0;
-  char *kernel_path;
-  size_t offset;
-  struct grub_util_path_list *path_list, *p;
+  char *kernel_path = NULL;
+  size_t offset = 0;
+  struct grub_util_path_list *path_list = NULL, *p;
   size_t decompress_size = 0;
   struct grub_mkimage_layout layout;
+  memset (&layout, 0, sizeof (layout));
+
+  if (wrap_path != NULL && image_target->id != IMAGE_EFI)
+    grub_util_error (_("wrapping is not supported by this target"));
 
   if (comp == GRUB_COMPRESSION_AUTO)
     comp = image_target->default_compression;
@@ -890,9 +902,12 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
       || image_target->id == IMAGE_I386_PC_ELTORITO)
     comp = GRUB_COMPRESSION_LZMA;
 
-  path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
+  if (dir)
+    {
+      path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
 
-  kernel_path = grub_util_get_path (dir, "kernel.img");
+      kernel_path = grub_util_get_path (dir, "kernel.img");
+    }
 
   if (image_target->voidp_sizeof == 8)
     total_module_size = sizeof (struct grub_module_info64);
@@ -953,12 +968,16 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
   grub_util_info ("the total module size is 0x%" GRUB_HOST_PRIxLONG_LONG,
                  (unsigned long long) total_module_size);
 
-  if (image_target->voidp_sizeof == 4)
-    kernel_img = grub_mkimage_load_image32 (kernel_path, total_module_size,
-                                           &layout, image_target);
-  else
-    kernel_img = grub_mkimage_load_image64 (kernel_path, total_module_size,
-                                           &layout, image_target);
+  if (kernel_path)
+    {
+      if (image_target->voidp_sizeof == 4)
+       kernel_img = grub_mkimage_load_image32 (kernel_path, total_module_size,
+                                               &layout, image_target);
+      else
+       kernel_img = grub_mkimage_load_image64 (kernel_path, total_module_size,
+                                               &layout, image_target);
+    }
+
   if ((image_target->id == IMAGE_XEN || image_target->id == IMAGE_XEN_PVH) &&
       layout.align < 4096)
     layout.align = 4096;
@@ -974,37 +993,40 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
       memset (kernel_img, 0, total_module_size);
     }
 
-  if (image_target->voidp_sizeof == 8)
+  if (kernel_img)
     {
-      /* Fill in the grub_module_info structure.  */
-      struct grub_module_info64 *modinfo;
-      if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
-       modinfo = (struct grub_module_info64 *) kernel_img;
-      else
-       modinfo = (struct grub_module_info64 *) (kernel_img + 
layout.kernel_size);
-      modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
-      modinfo->offset = grub_host_to_target_addr (sizeof (struct 
grub_module_info64));
-      modinfo->size = grub_host_to_target_addr (total_module_size);
-      if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
-       offset = sizeof (struct grub_module_info64);
-      else
-       offset = layout.kernel_size + sizeof (struct grub_module_info64);
-    }
-  else
-    {
-      /* Fill in the grub_module_info structure.  */
-      struct grub_module_info32 *modinfo;
-      if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
-       modinfo = (struct grub_module_info32 *) kernel_img;
-      else
-       modinfo = (struct grub_module_info32 *) (kernel_img + 
layout.kernel_size);
-      modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
-      modinfo->offset = grub_host_to_target_addr (sizeof (struct 
grub_module_info32));
-      modinfo->size = grub_host_to_target_addr (total_module_size);
-      if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
-       offset = sizeof (struct grub_module_info32);
+      if (image_target->voidp_sizeof == 8)
+       {
+         /* Fill in the grub_module_info structure.  */
+         struct grub_module_info64 *modinfo;
+         if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+           modinfo = (struct grub_module_info64 *) kernel_img;
+         else
+           modinfo = (struct grub_module_info64 *) (kernel_img + 
layout.kernel_size);
+         modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
+         modinfo->offset = grub_host_to_target_addr (sizeof (struct 
grub_module_info64));
+         modinfo->size = grub_host_to_target_addr (total_module_size);
+         if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+           offset = sizeof (struct grub_module_info64);
+         else
+           offset = layout.kernel_size + sizeof (struct grub_module_info64);
+       }
       else
-       offset = layout.kernel_size + sizeof (struct grub_module_info32);
+       {
+         /* Fill in the grub_module_info structure.  */
+         struct grub_module_info32 *modinfo;
+         if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+           modinfo = (struct grub_module_info32 *) kernel_img;
+         else
+           modinfo = (struct grub_module_info32 *) (kernel_img + 
layout.kernel_size);
+         modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
+         modinfo->offset = grub_host_to_target_addr (sizeof (struct 
grub_module_info32));
+         modinfo->size = grub_host_to_target_addr (total_module_size);
+         if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
+           offset = sizeof (struct grub_module_info32);
+         else
+           offset = layout.kernel_size + sizeof (struct grub_module_info32);
+       }
     }
 
   for (p = path_list; p; p = p->next)
@@ -1104,12 +1126,21 @@ grub_install_generate_image (const char *dir, const 
char *prefix,
       offset += prefix_size;
     }
 
-  grub_util_info ("kernel_img=%p, kernel_size=0x%" GRUB_HOST_PRIxLONG_LONG,
-                 kernel_img,
-                 (unsigned long long) layout.kernel_size);
-  compress_kernel (image_target, kernel_img, layout.kernel_size + 
total_module_size,
-                  &core_img, &core_size, comp);
-  free (kernel_img);
+  if (kernel_img)
+    {
+      grub_util_info ("kernel_img=%p, kernel_size=0x%" GRUB_HOST_PRIxLONG_LONG,
+                     kernel_img,
+                     (unsigned long long) layout.kernel_size);
+      compress_kernel (image_target, kernel_img, layout.kernel_size + 
total_module_size,
+                      &core_img, &core_size, comp);
+      free (kernel_img);
+    }
+
+  if (wrap_path)
+    {
+      core_size = grub_util_get_image_size (wrap_path);
+      core_img = grub_util_read_image (wrap_path);
+    }
 
   grub_util_info ("the core size is 0x%" GRUB_HOST_PRIxLONG_LONG,
                  (unsigned long long) core_size);
@@ -1308,7 +1339,7 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
       {
        char *pe_img, *pe_sbat, *header;
        struct grub_pe32_section_table *section;
-       size_t n_sections = 4;
+       int n_sections = 0;
        size_t scn_size;
        grub_uint32_t vma, raw_data;
        size_t pe_size, header_size;
@@ -1345,17 +1376,15 @@ grub_install_generate_image (const char *dir, const 
char *prefix,
        c = (struct grub_pe32_coff_header *) (header + GRUB_PE32_MSDOS_STUB_SIZE
                                              + GRUB_PE32_SIGNATURE_SIZE);
        c->machine = grub_host_to_target16 (image_target->pe_target);
-
-       if (sbat_path != NULL)
-         n_sections++;
-
-       c->num_sections = grub_host_to_target16 (n_sections);
        c->time = grub_host_to_target32 (STABLE_EMBEDDING_TIMESTAMP);
        c->characteristics = grub_host_to_target16 (GRUB_PE32_EXECUTABLE_IMAGE
                                                    | 
GRUB_PE32_LINE_NUMS_STRIPPED
                                                    | 
((image_target->voidp_sizeof == 4)
                                                       ? GRUB_PE32_32BIT_MACHINE
                                                       : 0)
+                                                   | ((wrap_path == NULL)
+                                                      ? 0
+                                                      : GRUB_PE32_DLL)
                                                    | 
GRUB_PE32_LOCAL_SYMS_STRIPPED
                                                    | GRUB_PE32_DEBUG_STRIPPED);
 
@@ -1393,7 +1422,13 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
        PE_OHDR (o32, o64, image_size) = grub_host_to_target32 (pe_size);
        PE_OHDR (o32, o64, section_alignment) = grub_host_to_target32 
(image_target->section_align);
        PE_OHDR (o32, o64, file_alignment) = grub_host_to_target32 
(GRUB_PE32_FILE_ALIGNMENT);
-       PE_OHDR (o32, o64, subsystem) = grub_host_to_target16 
(GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
+       PE_OHDR (o32, o64, subsystem) = grub_host_to_target16 ((wrap_path == 
NULL)
+                                                              ? 
GRUB_PE32_SUBSYSTEM_EFI_APPLICATION
+                                                              : 
GRUB_PE32_SUBSYSTEM_WINDOWS_GUI);
+       PE_OHDR (o32, o64, dll_characteristics) = grub_host_to_target16 
((wrap_path == NULL)
+                                                                        ? 0
+                                                                        : 
GRUB_PE32_DLLCHARACTERISTICS_DYNAMIC_BASE
+                                                                          | 
GRUB_PE32_DLLCHARACTERISTICS_NX_COMPAT);
 
        /* Do these really matter? */
        PE_OHDR (o32, o64, stack_reserve_size) = grub_host_to_target32 
(0x10000);
@@ -1409,13 +1444,13 @@ grub_install_generate_image (const char *dir, const 
char *prefix,
 #if __GNUC__ >= 12
 #pragma GCC diagnostic pop
 #endif
-       section = init_pe_section (image_target, section, ".text",
-                                  &vma, layout.exec_size,
-                                  image_target->section_align,
-                                  &raw_data, layout.exec_size,
-                                  GRUB_PE32_SCN_CNT_CODE |
-                                  GRUB_PE32_SCN_MEM_EXECUTE |
-                                  GRUB_PE32_SCN_MEM_READ);
+       init_pe_section (image_target, section, &n_sections, ".text",
+                        &vma, layout.exec_size,
+                        image_target->section_align,
+                        &raw_data, layout.exec_size,
+                        GRUB_PE32_SCN_CNT_CODE |
+                        GRUB_PE32_SCN_MEM_EXECUTE |
+                        GRUB_PE32_SCN_MEM_READ);
 
        scn_size = ALIGN_UP (layout.kernel_size - layout.exec_size, 
GRUB_PE32_FILE_ALIGNMENT);
 #if __GNUC__ >= 12
@@ -1423,39 +1458,55 @@ grub_install_generate_image (const char *dir, const 
char *prefix,
 #pragma GCC diagnostic ignored "-Wdangling-pointer"
 #endif
        /* ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT) is done earlier. */
-       PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + 
sbat_size +
-                                                              ALIGN_UP 
(total_module_size,
-                                                                        
GRUB_PE32_FILE_ALIGNMENT));
+       PE_OHDR (o32, o64, data_size) = grub_host_to_target32 ((wrap_path == 
NULL)
+                                                              ? scn_size + 
sbat_size +
+                                                                ALIGN_UP 
(total_module_size,
+                                                                          
GRUB_PE32_FILE_ALIGNMENT)
+                                                              : sbat_size +
+                                                                ALIGN_UP 
(core_size,
+                                                                          
GRUB_PE32_FILE_ALIGNMENT));
 #if __GNUC__ >= 12
 #pragma GCC diagnostic pop
 #endif
 
-       section = init_pe_section (image_target, section, ".data",
-                                  &vma, scn_size, image_target->section_align,
-                                  &raw_data, scn_size,
-                                  GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
-                                  GRUB_PE32_SCN_MEM_READ |
-                                  GRUB_PE32_SCN_MEM_WRITE);
-
-       scn_size = pe_size - layout.reloc_size - sbat_size - raw_data;
-       section = init_pe_section (image_target, section, "mods",
-                                  &vma, scn_size, image_target->section_align,
-                                  &raw_data, scn_size,
-                                  GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
-                                  GRUB_PE32_SCN_MEM_READ |
-                                  GRUB_PE32_SCN_MEM_WRITE);
+       init_pe_section (image_target, section, &n_sections, ".data",
+                        &vma, scn_size, image_target->section_align,
+                        &raw_data, scn_size,
+                        GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+                        GRUB_PE32_SCN_MEM_READ |
+                        GRUB_PE32_SCN_MEM_WRITE);
+
+        if (wrap_path == NULL)
+         {
+           scn_size = pe_size - layout.reloc_size - sbat_size - raw_data;
+           init_pe_section (image_target, section, &n_sections, "mods",
+                            &vma, scn_size, image_target->section_align,
+                            &raw_data, scn_size,
+                            GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+                            GRUB_PE32_SCN_MEM_READ |
+                            GRUB_PE32_SCN_MEM_WRITE);
+         }
+       else
+         {
+           init_pe_section (image_target, section, &n_sections, wrap_section,
+                            &vma, core_size,
+                            image_target->section_align,
+                            &raw_data, ALIGN_UP(core_size, 
GRUB_PE32_FILE_ALIGNMENT),
+                            GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+                            GRUB_PE32_SCN_MEM_READ);
+         }
 
        if (sbat_path != NULL)
          {
            pe_sbat = pe_img + raw_data;
            grub_util_load_image (sbat_path, pe_sbat);
 
-           section = init_pe_section (image_target, section, ".sbat",
-                                      &vma, sbat_size,
-                                      image_target->section_align,
-                                      &raw_data, sbat_size,
-                                      GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
-                                      GRUB_PE32_SCN_MEM_READ);
+           init_pe_section (image_target, section, &n_sections, ".sbat",
+                            &vma, sbat_size,
+                            image_target->section_align,
+                            &raw_data, sbat_size,
+                            GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+                            GRUB_PE32_SCN_MEM_READ);
          }
 
        scn_size = layout.reloc_size;
@@ -1463,19 +1514,21 @@ grub_install_generate_image (const char *dir, const 
char *prefix,
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdangling-pointer"
 #endif
-       PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 
(vma);
+       PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 
((scn_size > 0) ? vma : 0);
        PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 
(scn_size);
 #if __GNUC__ >= 12
 #pragma GCC diagnostic pop
 #endif
        memcpy (pe_img + raw_data, layout.reloc_section, scn_size);
-       init_pe_section (image_target, section, ".reloc",
+       init_pe_section (image_target, section, &n_sections, ".reloc",
                         &vma, scn_size, image_target->section_align,
                         &raw_data, scn_size,
                         GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
                         GRUB_PE32_SCN_MEM_DISCARDABLE |
                         GRUB_PE32_SCN_MEM_READ);
 
+       c->num_sections = grub_host_to_target16 (n_sections);
+
        free (core_img);
        core_img = pe_img;
        core_size = pe_size;
-- 
2.30.2




reply via email to

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