File elilo-x86-64-e820-max.diff of Package elilo

---
 bootparams.c    |    2 
 x86_64/system.c |  139 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 134 insertions(+), 7 deletions(-)

--- a/bootparams.c
+++ b/bootparams.c
@@ -96,6 +96,8 @@ create_boot_params(CHAR16 *args, memdesc
 	 */
 	Memset(bp, 0, BOOT_PARAM_MEMSIZE);
 
+	U2ascii(args, cp, cmdline_size);
+
 	if (sysdeps_create_boot_params(bp, cp, initrd, vmcode, cookie) == -1) return 0;
 
 	/*
--- a/x86_64/system.c
+++ b/x86_64/system.c
@@ -38,11 +38,19 @@
  */
 #include <efi.h>
 #include <efilib.h>
+#include <string.h>
 
 #include "elilo.h"
 #include "loader.h"
 #include "rmswitch.h"
 
+#define DEBUG_CREATE_BOOT_PARAMS 0
+#if DEBUG_CREATE_BOOT_PARAMS
+#define DPR(a) do { if (elilo_opt.debug) { Print a; } } while ( 0 )
+#else
+#define DPR(a)
+#endif
+
 extern loader_ops_t bzimage_loader, plain_loader, gzip_loader; 
 
 /*
@@ -113,6 +121,8 @@ VOID *kernel_load_address = (VOID *)DEFA
 VOID *initrd_start = NULL;
 UINTN initrd_size = 0;
 
+INTN e820_map_overflow = 0;
+
 INTN
 sysdeps_init(EFI_HANDLE dev)
 {
@@ -368,10 +378,56 @@ static INTN get_video_info(boot_params_t
 	return 0;
 }
 
+CHAR16 *
+StrStr(IN const CHAR16 *h, IN const CHAR16 *n)
+{
+	const CHAR16 *t = h;
+	CHAR16 *res;
+	int len = 0, i;
+
+	len = StrLen((CHAR16 *)n);
+	while(*t != CHAR_NULL) {
+	  res = StrChr( t, n[0]);
+	  if (!res) return res;
+	  for( i = 1; i < len && res[i] != CHAR_NULL && res[i] == n[i]; i++);
+	  if ( i == len ) return res;
+	  t = res + 1;
+	  if (t > h + CMDLINE_MAXLEN) return (CHAR16 *)0;
+	}
+
+	return (CHAR16 *)0;
+}
+
+CHAR8 *
+StrStr8(IN const CHAR8 *h, IN const CHAR8 *n)
+{
+	const CHAR8 *t = h;
+	CHAR8 *res;
+	int len = 0, i;
+
+	len = strlena((CHAR8 *)n);
+	while(*t != 0) {
+	  res = strchra( t, n[0]);
+	  if (!res) return res;
+	  for( i = 1; i < len && res[i] != 0 && res[i] == n[i]; i++);
+	  if ( i == len ) return res;
+	  t = res + 1;
+	  if (t > (h + CMDLINE_MAXLEN)) return (CHAR8 *)0;
+	}
+
+	return (CHAR8 *)0;
+}
+
 /* Convert EFI memory map to E820 map for the operating system 
  * This code is based on a Linux kernel patch submitted by Edgar Hucek
  */
 
+#if DEBUG_CREATE_BOOT_PARAMS
+static int e820_max = 6;
+#else
+static int e820_max = E820_MAX;
+#endif
+
 /* Add a memory region to the e820 map */
 static void add_memory_region (struct e820entry *e820_map,
 			       int *e820_nr_map,
@@ -380,21 +436,56 @@ static void add_memory_region (struct e8
 			       unsigned int type)
 {
 	int x = *e820_nr_map;
+	static unsigned long long estart = 0ULL;
+	static unsigned long esize = 0L;
+	static unsigned int etype = -1;
+	static int merge = 0;
+
+	if (x == 0)
+		DPR((L"AMR: %3s %4s %16s/%12s/%s\n",
+			L"idx", L" ", L"start", L"size", L"type"));
 
-	if (x == E820_MAX) {
-		Print(L"Too many entries in the memory map!\n");
-		return;
-	}
-
+	/* merge adjacent regions of same type */
 	if ((x > 0) && e820_map[x-1].addr + e820_map[x-1].size == start
-	    && e820_map[x-1].type == type)
+	    && e820_map[x-1].type == type) {
 		e820_map[x-1].size += size;
-	else {
+		estart = e820_map[x-1].addr;
+		esize  = e820_map[x-1].size;
+		etype  = e820_map[x-1].type;
+		merge++;
+		return;
+	}
+	/* fill up to E820_MAX */
+	if ( x < e820_max ) {
 		e820_map[x].addr = start;
 		e820_map[x].size = size;
 		e820_map[x].type = type;
 		(*e820_nr_map)++;
+		if (merge) DPR((L"AMR: %3d ==>  %016llx/%012lx/%d (%d)\n",
+				x-1, estart, esize, etype, merge));
+		merge=0;
+		DPR((L"AMR: %3d add  %016llx/%012lx/%d\n",
+			x, start, size, type));
+		return;
+	}
+	/* different type means another region didn't fit */
+	/* or same type, but there's a hole */
+	if (etype != type || (estart + esize) != start) {
+		if (merge) DPR((L"AMR: %3d ===> %016llx/%012lx/%d (%d)\n",
+			e820_map_overflow, estart, esize, etype, merge));
+		merge = 0;
+		estart = start;
+		esize = size;
+		etype = type;
+		e820_map_overflow++;
+		DPR((L"AMR: %3d OVER %016llx/%012lx/%d\n",
+			 e820_map_overflow, start, size, type));
+		return;
 	}
+	/* same type and no hole, merge it */
+	estart += esize;
+	esize += size;
+	merge++;
 }
 
 void fill_e820map(boot_params_t *bp, mmap_desc_t *mdesc)
@@ -473,6 +564,7 @@ void fill_e820map(boot_params_t *bp, mma
 			break;
 		default:
 			/* We should not hit this case */
+			DBG_PRT((L"hit default!?"));
 			add_memory_region(e820_map, &e820_nr_map,
 					  md->PhysicalStart,
 					  md->NumberOfPages << EFI_PAGE_SHIFT,
@@ -486,6 +578,8 @@ void fill_e820map(boot_params_t *bp, mma
 
 /*
  * x86_64 specific boot parameters initialization routine
+ *
+ * Note: debug and verbose messages have already been turned off!
  */
 INTN
 sysdeps_create_boot_params(
@@ -501,6 +595,12 @@ sysdeps_create_boot_params(
 	UINT8 row, col;
 	UINT8 mode;
 	UINT16 hdr_version;
+	UINT8 e820_map_overflow_warned = 0;
+
+#if DEBUG_CREATE_BOOT_PARAMS
+	elilo_opt.debug=1;
+	elilo_opt.verbose=5;
+#endif
 
 	DBG_PRT((L"fill_boot_params()\n"));
 
@@ -834,6 +934,31 @@ do_memmap:
 	 * and update the bootparam accordingly
 	 */
 	fill_e820map(bp, &mdesc);
+
+#if DEBUG_CREATE_BOOT_PARAMS
+	if ( e820_map_overflow == 0 )
+		e820_map_overflow = -1; /* force second get_memmap()! */
+#endif
+	if (e820_map_overflow && !e820_map_overflow_warned) {
+		CHAR8 *aem = (CHAR8 *)"add_efi_memmap";
+		e820_map_overflow_warned++;
+
+#if DEBUG_CREATE_BOOT_PARAMS
+		elilo_opt.debug=0;
+		elilo_opt.verbose=0;
+#endif
+		if (e820_map_overflow == -1 || StrStr8(cmdline, aem)) {
+			/* Print(L"...mapping again, silently!\n"); */
+			goto do_memmap;
+		}
+
+		Print(L"\nCAUTION: EFI memory map has %d more entr%a"
+			" than E820 map supports.\n"
+			"To access all memory, '%a' may be necessary.\n\n",
+			e820_map_overflow, (e820_map_overflow==1)?"y":"ies",
+			aem);
+		goto do_memmap;
+	}
 	
 	return 0;
 }
openSUSE Build Service is sponsored by