a5bd9f6
From 6002efaf14b06075755a6c552989a463c4bd8e4f Mon Sep 17 00:00:00 2001
a5bd9f6
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
a5bd9f6
Date: Thu, 28 Feb 2013 22:48:41 +0100
a5bd9f6
Subject: [PATCH 170/364] 	Enable linux16 on non-BIOS systems for i.a.
a5bd9f6
 memtest.
a5bd9f6
a5bd9f6
	* grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Handle hole at 0
a5bd9f6
	correctly.
a5bd9f6
	* grub-core/Makefile.core.def (linux16): Enable on all x86 flavours.
a5bd9f6
---
a5bd9f6
 ChangeLog                        |  8 ++++++
a5bd9f6
 grub-core/Makefile.core.def      |  6 ++--
a5bd9f6
 grub-core/loader/i386/pc/linux.c | 60 ++++++++++++++++++++++++++++------------
a5bd9f6
 3 files changed, 54 insertions(+), 20 deletions(-)
a5bd9f6
a5bd9f6
diff --git a/ChangeLog b/ChangeLog
a5bd9f6
index 0eb0516..135586c 100644
a5bd9f6
--- a/ChangeLog
a5bd9f6
+++ b/ChangeLog
a5bd9f6
@@ -1,5 +1,13 @@
a5bd9f6
 2013-02-28  Vladimir Serbinenko  <phcoder@gmail.com>
a5bd9f6
 
a5bd9f6
+	Enable linux16 on non-BIOS systems for i.a. memtest.
a5bd9f6
+
a5bd9f6
+	* grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Handle hole at 0
a5bd9f6
+	correctly.
a5bd9f6
+	* grub-core/Makefile.core.def (linux16): Enable on all x86 flavours.
a5bd9f6
+
a5bd9f6
+2013-02-28  Vladimir Serbinenko  <phcoder@gmail.com>
a5bd9f6
+
a5bd9f6
 	* grub-core/kern/i386/coreboot/mmap.c (grub_linuxbios_table_iterate):
a5bd9f6
 	Fix end of table condition.
a5bd9f6
 
a5bd9f6
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
a5bd9f6
index 4b0e6e6..93ff2a8 100644
a5bd9f6
--- a/grub-core/Makefile.core.def
a5bd9f6
+++ b/grub-core/Makefile.core.def
a5bd9f6
@@ -1390,9 +1390,9 @@ module = {
a5bd9f6
 
a5bd9f6
 module = {
a5bd9f6
   name = linux16;
a5bd9f6
-  i386_pc = loader/i386/pc/linux.c;
a5bd9f6
-  i386_pc = lib/cmdline.c;
a5bd9f6
-  enable = i386_pc;
a5bd9f6
+  common = loader/i386/pc/linux.c;
a5bd9f6
+  common = lib/cmdline.c;
a5bd9f6
+  enable = x86;
a5bd9f6
 };
a5bd9f6
 
a5bd9f6
 module = {
a5bd9f6
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
a5bd9f6
index 4eeb1b6..39206c8 100644
a5bd9f6
--- a/grub-core/loader/i386/pc/linux.c
a5bd9f6
+++ b/grub-core/loader/i386/pc/linux.c
a5bd9f6
@@ -79,6 +79,42 @@ grub_linux_unload (void)
a5bd9f6
   return GRUB_ERR_NONE;
a5bd9f6
 }
a5bd9f6
 
a5bd9f6
+static int
a5bd9f6
+target_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
a5bd9f6
+	    void *data)
a5bd9f6
+{
a5bd9f6
+  grub_uint64_t *result = data;
a5bd9f6
+  grub_uint64_t candidate;
a5bd9f6
+
a5bd9f6
+  if (type != GRUB_MEMORY_AVAILABLE)
a5bd9f6
+    return 0;
a5bd9f6
+  if (addr >= 0xa0000)
a5bd9f6
+    return 0;
a5bd9f6
+  if (addr + size >= 0xa0000)
a5bd9f6
+    size = 0xa0000 - addr;
a5bd9f6
+
a5bd9f6
+  /* Put the real mode part at as a high location as possible.  */
a5bd9f6
+  candidate = addr + size - (GRUB_LINUX_CL_OFFSET + maximal_cmdline_size);
a5bd9f6
+  /* But it must not exceed the traditional area.  */
a5bd9f6
+  if (candidate > GRUB_LINUX_OLD_REAL_MODE_ADDR)
a5bd9f6
+    candidate = GRUB_LINUX_OLD_REAL_MODE_ADDR;
a5bd9f6
+  if (candidate < addr)
a5bd9f6
+    return 0;
a5bd9f6
+
a5bd9f6
+  if (candidate > *result || *result == (grub_uint64_t) -1)
a5bd9f6
+    *result = candidate;
a5bd9f6
+  return 0;
a5bd9f6
+}
a5bd9f6
+
a5bd9f6
+static grub_addr_t
a5bd9f6
+grub_find_real_target (void)
a5bd9f6
+{
a5bd9f6
+  grub_uint64_t result = (grub_uint64_t) -1;
a5bd9f6
+
a5bd9f6
+  grub_mmap_iterate (target_hook, &result);
a5bd9f6
+  return result;
a5bd9f6
+}
a5bd9f6
+
a5bd9f6
 static grub_err_t
a5bd9f6
 grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
a5bd9f6
 		int argc, char *argv[])
a5bd9f6
@@ -141,12 +177,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
a5bd9f6
       if (grub_le_to_cpu16 (lh.version) >= 0x0206)
a5bd9f6
 	maximal_cmdline_size = grub_le_to_cpu32 (lh.cmdline_size) + 1;
a5bd9f6
 
a5bd9f6
-      /* Put the real mode part at as a high location as possible.  */
a5bd9f6
-      grub_linux_real_target = grub_mmap_get_lower () 
a5bd9f6
-	- (GRUB_LINUX_CL_OFFSET + maximal_cmdline_size);
a5bd9f6
-      /* But it must not exceed the traditional area.  */
a5bd9f6
-      if (grub_linux_real_target > GRUB_LINUX_OLD_REAL_MODE_ADDR)
a5bd9f6
-	grub_linux_real_target = GRUB_LINUX_OLD_REAL_MODE_ADDR;
a5bd9f6
+      grub_linux_real_target = grub_find_real_target ();
a5bd9f6
+      if (grub_linux_real_target == (grub_addr_t)-1)
a5bd9f6
+	{
a5bd9f6
+	  grub_error (GRUB_ERR_OUT_OF_RANGE,
a5bd9f6
+		      "no appropriate low memory found");
a5bd9f6
+	  goto fail;
a5bd9f6
+	}
a5bd9f6
 
a5bd9f6
       if (grub_le_to_cpu16 (lh.version) >= 0x0201)
a5bd9f6
 	{
a5bd9f6
@@ -193,17 +230,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
a5bd9f6
       goto fail;
a5bd9f6
     }
a5bd9f6
 
a5bd9f6
-  if (grub_linux_real_target + GRUB_LINUX_CL_OFFSET + maximal_cmdline_size
a5bd9f6
-      > grub_mmap_get_lower ())
a5bd9f6
-    {
a5bd9f6
-      grub_error (GRUB_ERR_OUT_OF_RANGE,
a5bd9f6
-		 "too small lower memory (0x%x > 0x%x)",
a5bd9f6
-		  grub_linux_real_target + GRUB_LINUX_CL_OFFSET
a5bd9f6
-		  + maximal_cmdline_size,
a5bd9f6
-		  (int) grub_mmap_get_lower ());
a5bd9f6
-      goto fail;
a5bd9f6
-    }
a5bd9f6
-
a5bd9f6
   grub_dprintf ("linux", "[Linux-%s, setup=0x%x, size=0x%x]\n",
a5bd9f6
 		grub_linux_is_bzimage ? "bzImage" : "zImage", real_size,
a5bd9f6
 		grub_linux16_prot_size);
a5bd9f6
-- 
a5bd9f6
1.8.1.4
a5bd9f6