28f7f8
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
28f7f8
From: Andrei Borzenkov <arvidjaar@gmail.com>
28f7f8
Date: Wed, 16 May 2018 13:06:04 -0400
28f7f8
Subject: [PATCH] efi/uga: use 64 bit for fb_base
28f7f8
28f7f8
We get 64 bit from PCI BAR but then truncate by assigning to 32 bit.
28f7f8
Make sure to check that pointer does not overflow on 32 bit platform.
28f7f8
28f7f8
Closes: 50931
28f7f8
---
28f7f8
 grub-core/video/efi_uga.c | 31 ++++++++++++++++---------------
28f7f8
 1 file changed, 16 insertions(+), 15 deletions(-)
28f7f8
28f7f8
diff --git a/grub-core/video/efi_uga.c b/grub-core/video/efi_uga.c
28f7f8
index 464ede874da..1d4091c5631 100644
28f7f8
--- a/grub-core/video/efi_uga.c
28f7f8
+++ b/grub-core/video/efi_uga.c
28f7f8
@@ -34,7 +34,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
28f7f8
 
28f7f8
 static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
28f7f8
 static struct grub_efi_uga_draw_protocol *uga;
28f7f8
-static grub_uint32_t uga_fb;
28f7f8
+static grub_uint64_t uga_fb;
28f7f8
 static grub_uint32_t uga_pitch;
28f7f8
 
28f7f8
 static struct
28f7f8
@@ -52,7 +52,7 @@ static struct
28f7f8
 #define FBTEST_COUNT	8
28f7f8
 
28f7f8
 static int
28f7f8
-find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
28f7f8
+find_line_len (grub_uint64_t *fb_base, grub_uint32_t *line_len)
28f7f8
 {
28f7f8
   grub_uint32_t *base = (grub_uint32_t *) (grub_addr_t) *fb_base;
28f7f8
   int i;
28f7f8
@@ -67,7 +67,7 @@ find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
28f7f8
 	    {
28f7f8
 	      if ((base[j] & RGB_MASK) == RGB_MAGIC)
28f7f8
 		{
28f7f8
-		  *fb_base = (grub_uint32_t) (grub_addr_t) base;
28f7f8
+		  *fb_base = (grub_uint64_t) (grub_addr_t) base;
28f7f8
 		  *line_len = j << 2;
28f7f8
 
28f7f8
 		  return 1;
28f7f8
@@ -84,7 +84,7 @@ find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
28f7f8
 /* Context for find_framebuf.  */
28f7f8
 struct find_framebuf_ctx
28f7f8
 {
28f7f8
-  grub_uint32_t *fb_base;
28f7f8
+  grub_uint64_t *fb_base;
28f7f8
   grub_uint32_t *line_len;
28f7f8
   int found;
28f7f8
 };
28f7f8
@@ -120,7 +120,9 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
28f7f8
 	      if (i == 5)
28f7f8
 		break;
28f7f8
 
28f7f8
-	      old_bar2 = grub_pci_read (addr + 4);
28f7f8
+	      i++;
28f7f8
+	      addr += 4;
28f7f8
+	      old_bar2 = grub_pci_read (addr);
28f7f8
 	    }
28f7f8
 	  else
28f7f8
 	    old_bar2 = 0;
28f7f8
@@ -129,10 +131,15 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
28f7f8
 	  base64 <<= 32;
28f7f8
 	  base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK);
28f7f8
 
28f7f8
-	  grub_dprintf ("fb", "%s(%d): 0x%llx\n",
28f7f8
+	  grub_dprintf ("fb", "%s(%d): 0x%" PRIxGRUB_UINT64_T "\n",
28f7f8
 			((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ?
28f7f8
-			"VMEM" : "MMIO"), i,
28f7f8
-		       (unsigned long long) base64);
28f7f8
+			"VMEM" : "MMIO"), type == GRUB_PCI_ADDR_MEM_TYPE_64 ? i - 1 : i,
28f7f8
+			base64);
28f7f8
+
28f7f8
+#if GRUB_CPU_SIZEOF_VOID_P == 4
28f7f8
+	  if (old_bar2)
28f7f8
+	    continue;
28f7f8
+#endif
28f7f8
 
28f7f8
 	  if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! ctx->found))
28f7f8
 	    {
28f7f8
@@ -140,12 +147,6 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
28f7f8
 	      if (find_line_len (ctx->fb_base, ctx->line_len))
28f7f8
 		ctx->found++;
28f7f8
 	    }
28f7f8
-
28f7f8
-	  if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
28f7f8
-	    {
28f7f8
-	      i++;
28f7f8
-	      addr += 4;
28f7f8
-	    }
28f7f8
 	}
28f7f8
     }
28f7f8
 
28f7f8
@@ -153,7 +154,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
28f7f8
 }
28f7f8
 
28f7f8
 static int
28f7f8
-find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len)
28f7f8
+find_framebuf (grub_uint64_t *fb_base, grub_uint32_t *line_len)
28f7f8
 {
28f7f8
   struct find_framebuf_ctx ctx = {
28f7f8
     .fb_base = fb_base,