ed1787d
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
ed1787d
From: Jeremy Linton <jeremy.linton@arm.com>
ed1787d
Date: Tue, 6 Sep 2022 15:33:03 -0500
ed1787d
Subject: [PATCH] Correct BSS zeroing on aarch64
ed1787d
ed1787d
The aarch64 loader doesn't use efi bootservices, and
ed1787d
therefor it has a very minimal loader which makes a lot
ed1787d
of assumptions about the kernel layout. With the ZBOOT
ed1787d
changes, the layout has changed a bit and we not should
ed1787d
really be parsing the PE sections to determine how much
ed1787d
data to copy, otherwise the BSS won't be setup properly.
ed1787d
ed1787d
This code still makes a lot of assumptions about the
ed1787d
the kernel layout, so its far from ideal, but it works.
ed1787d
ed1787d
Resolves: rhbz#2125069
ed1787d
ed1787d
Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
ed1787d
---
ed1787d
 grub-core/loader/arm64/linux.c | 27 ++++++++++++++++++++++-----
ed1787d
 1 file changed, 22 insertions(+), 5 deletions(-)
ed1787d
ed1787d
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
ed1787d
index 489d0c7173..419f2201df 100644
ed1787d
--- a/grub-core/loader/arm64/linux.c
ed1787d
+++ b/grub-core/loader/arm64/linux.c
ed1787d
@@ -316,10 +316,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
ed1787d
 static grub_err_t
ed1787d
 parse_pe_header (void *kernel, grub_uint64_t *total_size,
ed1787d
 		 grub_uint32_t *entry_offset,
ed1787d
-		 grub_uint32_t *alignment)
ed1787d
+		 grub_uint32_t *alignment,grub_uint32_t *code_size)
ed1787d
 {
ed1787d
   struct linux_arch_kernel_header *lh = kernel;
ed1787d
   struct grub_armxx_linux_pe_header *pe;
ed1787d
+  grub_uint16_t i;
ed1787d
+  struct grub_pe32_section_table *sections;
ed1787d
 
ed1787d
   pe = (void *)((unsigned long)kernel + lh->hdr_offset);
ed1787d
 
ed1787d
@@ -329,6 +331,19 @@ parse_pe_header (void *kernel, grub_uint64_t *total_size,
ed1787d
   *total_size   = pe->opt.image_size;
ed1787d
   *entry_offset = pe->opt.entry_addr;
ed1787d
   *alignment    = pe->opt.section_alignment;
ed1787d
+  *code_size    = pe->opt.section_alignment;
ed1787d
+
ed1787d
+  sections = (struct grub_pe32_section_table *) ((char *)&pe->opt +
ed1787d
+						 pe->coff.optional_header_size);
ed1787d
+  grub_dprintf ("linux", "num_sections     : %d\n",  pe->coff.num_sections );
ed1787d
+  for (i = 0 ; i < pe->coff.num_sections; i++)
ed1787d
+    {
ed1787d
+      grub_dprintf ("linux", "raw_size   : %lld\n",
ed1787d
+		    (long long) sections[i].raw_data_size);
ed1787d
+      grub_dprintf ("linux", "virt_size  : %lld\n",
ed1787d
+		    (long long) sections[i].virtual_size);
ed1787d
+      *code_size += sections[i].raw_data_size;
ed1787d
+    }
ed1787d
 
ed1787d
   return GRUB_ERR_NONE;
ed1787d
 }
ed1787d
@@ -341,6 +356,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
ed1787d
   grub_err_t err;
ed1787d
   grub_off_t filelen;
ed1787d
   grub_uint32_t align;
ed1787d
+  grub_uint32_t code_size;
ed1787d
   void *kernel = NULL;
ed1787d
   int nx_supported = 1;
ed1787d
 
ed1787d
@@ -373,11 +389,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
ed1787d
 
ed1787d
   if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE)
ed1787d
     goto fail;
ed1787d
-  if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE)
ed1787d
+  if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align, &code_size) != GRUB_ERR_NONE)
ed1787d
     goto fail;
ed1787d
   grub_dprintf ("linux", "kernel mem size     : %lld\n", (long long) kernel_size);
ed1787d
   grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset);
ed1787d
   grub_dprintf ("linux", "kernel alignment    : 0x%x\n", align);
ed1787d
+  grub_dprintf ("linux", "kernel size         : 0x%x\n", code_size);
ed1787d
 
ed1787d
   err = grub_efi_check_nx_image_support((grub_addr_t)kernel, filelen, &nx_supported);
ed1787d
   if (err != GRUB_ERR_NONE)
ed1787d
@@ -396,9 +413,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
ed1787d
   kernel_addr = (void *)ALIGN_UP((grub_uint64_t)kernel_alloc_addr, align);
ed1787d
 
ed1787d
   grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
ed1787d
-  grub_memcpy (kernel_addr, kernel, grub_min(filelen, kernel_size));
ed1787d
-  if (kernel_size > filelen)
ed1787d
-    grub_memset ((char *)kernel_addr + filelen, 0, kernel_size - filelen);
ed1787d
+  grub_memcpy (kernel_addr, kernel, grub_min(code_size, kernel_size));
ed1787d
+  if (kernel_size > code_size)
ed1787d
+    grub_memset ((char *)kernel_addr + code_size, 0, kernel_size - code_size);
ed1787d
   grub_free(kernel);
ed1787d
   kernel = NULL;
ed1787d