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