SHA256
1
0
forked from pool/elilo
elilo/elilo-x86-64-e820-max.diff

231 lines
5.6 KiB
Diff

---
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;
}