diff -purN '--exclude=*o' '--exclude=tags' elilo-3.8-3.35-orig1//alloc.c elilo-3.8-3.35-orig_c//alloc.c
--- elilo-3.8-3.35-orig1//alloc.c	2008-12-08 06:03:05.000000000 -0600
+++ elilo-3.8-3.35-orig_c//alloc.c	2008-12-08 04:51:28.000000000 -0600
@@ -213,6 +213,19 @@ free_all(VOID)
 }
 
 INTN
+alloc_kmem_anywhere(VOID **start_addr, UINTN pgcnt)
+{
+	void * tmp;
+	if ((tmp = alloc_pages(pgcnt, EfiLoaderData, AllocateAnyPages, *start_addr)) == 0) return -1;
+
+	kmem_addr  = tmp;
+	kmem_pgcnt = pgcnt;
+	*start_addr = tmp;
+
+	return 0;
+}
+
+INTN
 alloc_kmem(VOID *start_addr, UINTN pgcnt)
 {
 	if (alloc_pages(pgcnt, EfiLoaderData, AllocateAddress, start_addr) == 0) return -1;
diff -purN '--exclude=*o' '--exclude=tags' elilo-3.8-3.35-orig1//elilo.c elilo-3.8-3.35-orig_c//elilo.c
--- elilo-3.8-3.35-orig1//elilo.c	2008-12-08 06:03:05.000000000 -0600
+++ elilo-3.8-3.35-orig_c//elilo.c	2008-12-08 05:01:33.000000000 -0600
@@ -132,6 +132,9 @@ kernel_load(EFI_HANDLE image, CHAR16 *kn
 
 	if (elilo_opt.initrd[0]) {
 
+		/*
+		 * fix me? -- load_file() ignores address from sysdeps_initrd_get_addr()
+		 */
 		if (sysdeps_initrd_get_addr(kd, imem) == -1) goto exit_error;
 
 		switch(load_file(elilo_opt.initrd, imem)) {
Files elilo-3.8-3.35-orig1//elilo.efi and elilo-3.8-3.35-orig_c//elilo.efi differ
Files elilo-3.8-3.35-orig1//tools/eliloalt and elilo-3.8-3.35-orig_c//tools/eliloalt differ
diff -purN '--exclude=*o' '--exclude=tags' elilo-3.8-3.35-orig1//x86_64/bzimage.c elilo-3.8-3.35-orig_c//x86_64/bzimage.c
--- elilo-3.8-3.35-orig1//x86_64/bzimage.c	2008-12-08 06:03:05.000000000 -0600
+++ elilo-3.8-3.35-orig_c//x86_64/bzimage.c	2008-12-08 05:04:52.000000000 -0600
@@ -158,13 +158,37 @@ bzImage_probe(CHAR16 *kname)
 	 * Allocate memory for kernel.
 	 */
 
+	/*
+	 * Get correct address for kernel from header, if applicable & available. 
+	 */
+	if ((param_start->s.hdr_major == 2) &&
+	    (param_start->s.hdr_minor >= 0) &&
+	    (param_start->s.kernel_start >= DEFAULT_KERNEL_START)) {
+		kernel_start = kernel_load_address = param_start->s.kernel_start;
+		VERB_PRT(3, Print(L"kernel header suggests kernel start at address 0x%x\n", 
+			kernel_start));
+	}
+
+	kernel_load_address = kernel_start;
+
 	if (alloc_kmem(kernel_start, EFI_SIZE_TO_PAGES(kernel_size))) {
-		ERR_PRT((L"Could not allocate kernel memory."));
-		return -1;
-	} else {
-		VERB_PRT(3, Print(L"kernel_start: 0x%x  kernel_size: %d\n", 
-			kernel_start, kernel_size));
+		/*
+		 * Couldn't get desired address--just load it anywhere and move it later.
+		 * (Easier than relocating kernel, and also works with non-relocatable kernels.)
+		 */
+		if (alloc_kmem_anywhere(&kernel_load_address, EFI_SIZE_TO_PAGES(kernel_size))) {
+			ERR_PRT((L"Could not allocate memory for kernel."));
+			free(param_start);
+			param_start = NULL;
+			param_size = 0;
+			fops_close(fd);
+			return -1;
+		}
 	}
+
+	VERB_PRT(3, Print(L"kernel_start: 0x%x  kernel_size: %d  loading at: 0x%x\n", 
+		kernel_start, kernel_size, kernel_load_address));
+
 	/*
 	 * Now read the rest of the kernel image into memory.
 	 */
@@ -172,7 +196,7 @@ bzImage_probe(CHAR16 *kname)
 	DBG_PRT((L"reading kernel image...\n"));
 
 	size = kernel_size;
-	efi_status = fops_read(fd, kernel_start, &size);
+	efi_status = fops_read(fd, kernel_load_address, &size);
 	if (EFI_ERROR(efi_status) || size < 0x10000) {
 		ERR_PRT((L"Error reading kernel image %s.", kname));
 		free(param_start);
diff -purN '--exclude=*o' '--exclude=tags' elilo-3.8-3.35-orig1//x86_64/sysdeps.h elilo-3.8-3.35-orig_c//x86_64/sysdeps.h
--- elilo-3.8-3.35-orig1//x86_64/sysdeps.h	2008-12-08 06:03:05.000000000 -0600
+++ elilo-3.8-3.35-orig_c//x86_64/sysdeps.h	2008-12-08 06:01:52.000000000 -0600
@@ -48,6 +48,11 @@
 #define INITRD_START   (50*1024*1024)
 
 /*
+ * Default start address for kernel.
+ */
+#define DEFAULT_KERNEL_START	0x100000
+
+/*
  * This version must match the one in the kernel.
  *
  * This table was put together using information from the
@@ -307,10 +312,16 @@ typedef union x86_64_boot_params {
 	UINT8 *t = (UINT8 *)(to); \
 	UINT8 *f = (UINT8 *)(from); \
 	UINTN n = cnt; \
-	if (t && f && n) { \
+	if (t && f && n && (t<f)) { \
 		while (n--) { \
 			*t++ = *f++; \
 		} \
+	} else if (t && f && n && (t>f)) { \
+		t += n; \
+		f += n; \
+		while (n--) { \
+			*t-- = *f--; \
+		} \
 	} \
 }
 
@@ -343,6 +354,7 @@ extern UINTN param_size;
 
 extern VOID *kernel_start;
 extern UINTN kernel_size;
+extern VOID *kernel_load_address;
 
 extern VOID *initrd_start;
 extern UINTN initrd_size;
@@ -379,13 +391,23 @@ start_kernel(VOID *kentry, boot_params_t
 	asm volatile ( "cli" : : );
 
 	/*
-	 * Relocate initrd, if present.
+	 * Relocate and kernel (if needed), and initrd (if present).
+	 * Copy kernel first, in case kernel was loaded overlapping where we're
+	 * planning to copy the initrd.  This assumes that the initrd didn't
+	 * get loaded overlapping where we're planning to copy the kernel, but
+	 * that's pretty unlikely since we couldn't alloc that space for the
+	 * kernel (or the kernel would already be there).
 	 */
 
+	if (kernel_start != kernel_load_address) {
+		MEMCPY(kernel_start, kernel_load_address, kernel_size);
+	}
+
 	if (bp->s.initrd_start) {
 		MEMCPY(INITRD_START, bp->s.initrd_start, bp->s.initrd_size);
 		bp->s.initrd_start = INITRD_START;
 	}
+	
 	/*
 	 * Copy boot sector, setup data and command line
 	 * to final resting place.  We need to copy
diff -purN '--exclude=*o' '--exclude=tags' elilo-3.8-3.35-orig1//x86_64/system.c elilo-3.8-3.35-orig_c//x86_64/system.c
--- elilo-3.8-3.35-orig1//x86_64/system.c	2008-12-08 06:03:25.000000000 -0600
+++ elilo-3.8-3.35-orig_c//x86_64/system.c	2008-12-08 04:51:28.000000000 -0600
@@ -105,7 +105,9 @@ UINTN high_base_mem = 0x90000;
 UINTN high_ext_mem = 32 * 1024 * 1024;
 
 /* This starting address will hold true for all of the loader types for now */
-VOID *kernel_start = (VOID *)0x100000;	/* 1M */
+VOID *kernel_start = DEFAULT_KERNEL_START;
+/* The kernel may load elsewhere if EFI firmware reserves kernel_start */
+VOID *kernel_load_address = DEFAULT_KERNEL_START; 
 
 VOID *initrd_start = NULL;
 UINTN initrd_size = 0;
