forked from pool/elilo
This commit is contained in:
parent
212982063b
commit
d2abc5e393
225
elilo-bzimage-alloc.diff
Normal file
225
elilo-bzimage-alloc.diff
Normal file
@ -0,0 +1,225 @@
|
||||
From: Stuart_Hayes@Dell.com
|
||||
Subject: Re: [elilo-discuss] Follow-Up to 1MB Allocation Problem
|
||||
Message-ID: <DFEF91B22ED07447AB6AA4B237F913F90218586E@ausx3mpc125.aus.amer.dell.com>
|
||||
|
||||
Here's one solution to the problem, for bzImages in x86_64 (which could
|
||||
easily be ported to the other image types and architecture). I tried to
|
||||
make this minimally invasive. If bzImage_probe() can't load the kernel
|
||||
where it should be, it will just load the kernel anywhere, and it will
|
||||
be moved to the right address after elilo exits EFI boot services. (I
|
||||
also made it read where the kernel should be from the kernel header.)
|
||||
It looks like it was already loading the initrd just anywhere and then
|
||||
moving it after exiting boot services.
|
||||
|
||||
(I also enhanced the "MEMCPY" macro in x86_64/sysdeps.h so it will copy
|
||||
to an overlapping area correctly regardless of whether the "from"
|
||||
address is higher or lower than the "to" address.)
|
||||
|
||||
I originally wrote code that would actually check if the kernel was
|
||||
relocatable and then relocate it, like the ia64 code does. That worked
|
||||
fine, except that the address that was found overlapped the area where
|
||||
elilo copies the initrd in start_kernel() after EFI boot services are
|
||||
exited! Instead of modifying the initrd addresses, too, I decided it
|
||||
would be easier and less likely to break anyting else (and would work
|
||||
with non-relocatable kernels, too) to just do it the other way.
|
||||
|
||||
Any chance we could get this patch into elilo? I can modify and
|
||||
resubmit if there are any issues with this approach.
|
||||
|
||||
Thanks!
|
||||
|
||||
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 = (VOID *)((UINTN)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,14 +391,24 @@ start_kernel(VOID *kentry, boot_params_t
|
||||
asm volatile ( "cli" : : );
|
||||
|
||||
/*
|
||||
- * Relocate initrd, if present.
|
||||
+ * Relocate 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) {
|
||||
temp = bp->s.initrd_start;
|
||||
MEMCPY(INITRD_START, temp , 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 = (VOID *)DEFAULT_KERNEL_START;
|
||||
+/* The kernel may load elsewhere if EFI firmware reserves kernel_start */
|
||||
+VOID *kernel_load_address = (VOID *)DEFAULT_KERNEL_START;
|
||||
|
||||
VOID *initrd_start = NULL;
|
||||
UINTN initrd_size = 0;
|
||||
--- elilo/fs/localfs.c
|
||||
+++ elilo/fs/localfs.c
|
||||
@@ -98,7 +98,7 @@
|
||||
|
||||
DBG_PRT((L"localfs_open on %s\n", name));
|
||||
|
||||
- status = uefi_call_wrapper(lfs->volume->Open, 5, lfs->volume, &fh, name, EFI_FILE_MODE_READ, 0);
|
||||
+ status = uefi_call_wrapper(lfs->volume->Open, 5, lfs->volume, &fh, name, EFI_FILE_MODE_READ, (UINT64)0);
|
||||
if (status == EFI_SUCCESS) {
|
||||
*fd = LOCALFS_F2FD(fh);
|
||||
}
|
||||
--- elilo/elilo.h
|
||||
+++ elilo/elilo.h
|
||||
@@ -151,6 +151,7 @@
|
||||
extern VOID free_pages(VOID *);
|
||||
extern VOID free_all(VOID);
|
||||
extern INTN alloc_kmem(VOID *, UINTN);
|
||||
+extern INTN alloc_kmem_anywhere(VOID **, UINTN);
|
||||
extern VOID free_kmem(VOID);
|
||||
extern VOID free_all_memory(VOID);
|
||||
|
@ -1,108 +0,0 @@
|
||||
--- elilo/x86_64/bzimage.c
|
||||
+++ elilo/x86_64/bzimage.c
|
||||
@@ -160,7 +160,9 @@
|
||||
|
||||
if (alloc_kmem(kernel_start, EFI_SIZE_TO_PAGES(kernel_size))) {
|
||||
ERR_PRT((L"Could not allocate kernel memory."));
|
||||
- return -1;
|
||||
+ if (x86_64_allow_alloc_fail() != 1) {
|
||||
+ return -1;
|
||||
+ }
|
||||
} else {
|
||||
VERB_PRT(3, Print(L"kernel_start: 0x%x kernel_size: %d\n",
|
||||
kernel_start, kernel_size));
|
||||
@@ -169,7 +171,7 @@
|
||||
* Now read the rest of the kernel image into memory.
|
||||
*/
|
||||
|
||||
- DBG_PRT((L"reading kernel image...\n"));
|
||||
+ Print(L"Loading kernel %s... ", kname);
|
||||
|
||||
size = kernel_size;
|
||||
efi_status = fops_read(fd, kernel_start, &size);
|
||||
@@ -181,6 +183,8 @@
|
||||
fops_close(fd);
|
||||
free_kmem();
|
||||
return -1;
|
||||
+ } else {
|
||||
+ Print(L" done\n");
|
||||
}
|
||||
|
||||
DBG_PRT((L"kernel image read: %d bytes, %d Kbytes\n", size, size / 1024));
|
||||
--- elilo/x86_64/config.c
|
||||
+++ elilo/x86_64/config.c
|
||||
@@ -33,15 +33,24 @@
|
||||
|
||||
typedef struct {
|
||||
UINTN legacy_free_boot;
|
||||
+ UINTN allow_alloc_fail;
|
||||
} x86_64_global_config_t;
|
||||
|
||||
|
||||
+#define x86_64_opt_offsetof(option) (&((sys_img_options_t *)(0x0))->option)
|
||||
+
|
||||
static x86_64_global_config_t x86_64_gconf;
|
||||
|
||||
static config_option_t sysdeps_global_options[]={
|
||||
- {OPT_BOOL, OPT_GLOBAL, L"legacy-free", NULL, NULL, &x86_64_gconf.legacy_free_boot}
|
||||
+ {OPT_BOOL, OPT_GLOBAL, L"legacy-free", NULL, NULL, &x86_64_gconf.legacy_free_boot},
|
||||
+ {OPT_BOOL, OPT_GLOBAL, L"skid-alloc", NULL, NULL, &x86_64_gconf.allow_alloc_fail},
|
||||
+};
|
||||
+
|
||||
+static config_option_t sysdeps_image_options[]={
|
||||
+ {OPT_BOOL, OPT_IMAGE_SYS, L"skid-alloc", NULL, NULL, x86_64_opt_offsetof(allow_alloc_fail)},
|
||||
};
|
||||
|
||||
+
|
||||
/*
|
||||
* X86_64 operations that need to be done only once and just before
|
||||
* entering the main loop of the loader
|
||||
@@ -82,6 +91,13 @@
|
||||
}
|
||||
|
||||
INTN
|
||||
+x86_64_allow_alloc_fail(VOID)
|
||||
+{
|
||||
+ return x86_64_gconf.allow_alloc_fail == TRUE
|
||||
+ || (elilo_opt.sys_img_opts && elilo_opt.sys_img_opts->allow_alloc_fail ==TRUE) ? 1 : 0;
|
||||
+}
|
||||
+
|
||||
+INTN
|
||||
sysdeps_register_options(VOID)
|
||||
{
|
||||
INTN ret;
|
||||
@@ -89,14 +105,11 @@
|
||||
ret = register_config_options(sysdeps_global_options,
|
||||
sizeof(sysdeps_global_options)/sizeof(config_option_t),
|
||||
OPTIONS_GROUP_GLOBAL);
|
||||
-#if 0
|
||||
- /* no per image options yet */
|
||||
if (ret == -1 ) return ret;
|
||||
|
||||
ret = register_config_options(sysdeps_image_options,
|
||||
sizeof(sysdeps_image_options)/sizeof(config_option_t),
|
||||
OPTIONS_GROUP_IMAGE);
|
||||
-#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
--- elilo/x86_64/sysdeps.h
|
||||
+++ elilo/x86_64/sysdeps.h
|
||||
@@ -357,6 +357,7 @@
|
||||
extern UINTN rmswitch_size;
|
||||
|
||||
extern INTN x86_64_use_legacy_free_boot();
|
||||
+extern INTN x86_64_allow_alloc_fail();
|
||||
|
||||
/*
|
||||
* How to jump to kernel code
|
||||
@@ -449,7 +450,8 @@
|
||||
}
|
||||
|
||||
typedef struct sys_img_options {
|
||||
- UINT8 nothing_yet;
|
||||
+ UINT8 dummy; /* forces non-zero offset for first field */
|
||||
+ UINT8 allow_alloc_fail; /* ignore failure of alloc_kmem */
|
||||
} sys_img_options_t;
|
||||
|
||||
#endif /* __ELILO_SYSDEPS_X86_64_H__ */
|
@ -1,3 +1,11 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Dec 9 16:34:53 CET 2008 - rw@suse.de
|
||||
|
||||
- elilo.efi
|
||||
* Second attempt to work around firmware problem. (bnc#437486)
|
||||
- elilo.conf
|
||||
* Provide stub man page. (bnc#435648)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Nov 21 15:56:50 CET 2008 - rw@suse.de
|
||||
|
||||
|
11
elilo.conf.man5
Normal file
11
elilo.conf.man5
Normal file
@ -0,0 +1,11 @@
|
||||
.TH ELILO.CONF 5 "2008-12-06"
|
||||
.SH NAME
|
||||
elilo.conf \- elilo configuration file
|
||||
.SH SYNOPSIS
|
||||
/etc/elilo.conf
|
||||
.SH FILES
|
||||
.IR /etc/elilo.conf ,
|
||||
.I /boot/efi/efi/SuSE/elilo.conf
|
||||
.SH SEE ALSO
|
||||
.IR /usr/share/doc/packages/elilo/elilo.txt
|
||||
(Section III)
|
27
elilo.spec
27
elilo.spec
@ -21,7 +21,7 @@
|
||||
Name: elilo
|
||||
Summary: EFI Linux Loader
|
||||
Version: 3.8
|
||||
Release: 24
|
||||
Release: 25
|
||||
ExclusiveArch: ia64 %ix86 x86_64
|
||||
Group: System/Boot
|
||||
AutoReqProv: on
|
||||
@ -30,16 +30,17 @@ License: GPL v2 or later
|
||||
Url: http://elilo.sourceforge.net/
|
||||
Source: http://dl.sourceforge.net/elilo/elilo-3.8.tar.gz
|
||||
Source1: elilo.pl
|
||||
Source2: eliloalt.debian.man8
|
||||
Source3: rpmlintrc
|
||||
Source2: debian.eliloalt.man8
|
||||
Source3: elilo.conf.man5
|
||||
Source9: rpmlintrc
|
||||
Patch0: elilo-3.8-cvs20080127.diff
|
||||
Patch1: elilo-MAC.diff
|
||||
Patch2: elilo-spelling.diff
|
||||
Patch3: elilo-longer-commandline.diff
|
||||
Patch4: elilo-fix-possible-overflow.diff
|
||||
Patch5: elilo-avoid-tab.diff
|
||||
Patch6: eliloalt-sysfs.diff
|
||||
Patch7: elilo-uEFI-no-alloc_kmem.diff
|
||||
Patch6: elilo-bzimage-alloc.diff
|
||||
Patch9: eliloalt-sysfs.diff
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
BuildRequires: gnu-efi >= 3.0e
|
||||
|
||||
@ -64,7 +65,7 @@ Authors:
|
||||
%patch4 -p1
|
||||
%patch5 -p1
|
||||
%patch6 -p1
|
||||
%patch7 -p1
|
||||
%patch9 -p1
|
||||
perl -pe 's{\@EDITION\@}{%{version}-%{release}};
|
||||
s{\@LIBEXECDIR\@}{%{_libexecdir}};
|
||||
s{\@ARCH\@}{%{_target_cpu}};
|
||||
@ -72,7 +73,6 @@ perl -pe 's{\@EDITION\@}{%{version}-%{release}};
|
||||
perl -pi -e 's{/usr/lib}{%{_libexecdir}}' Make.defaults
|
||||
chmod 555 elilo.pl && touch -r %{SOURCE1} elilo.pl
|
||||
! fgrep '%%{version}-%%{release}' elilo.pl
|
||||
cp --preserve=time %{SOURCE2} eliloalt.8
|
||||
|
||||
%build
|
||||
make OPTIMFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing -fno-stack-protector"
|
||||
@ -85,11 +85,9 @@ install -d $RPM_BUILD_ROOT%{_libexecdir}/efi $RPM_BUILD_ROOT/sbin
|
||||
install -m 444 elilo.efi $RPM_BUILD_ROOT%{_libexecdir}/efi
|
||||
install tools/eliloalt $RPM_BUILD_ROOT/sbin
|
||||
install -p -m 555 elilo.pl $RPM_BUILD_ROOT/sbin/elilo
|
||||
%if 0
|
||||
install -D -p -m 644 elilo.5 $RPM_BUILD_ROOT/usr/share/man/man5/elilo.conf.5
|
||||
%endif
|
||||
install -D -p -m 644 elilo.8 $RPM_BUILD_ROOT/usr/share/man/man8/elilo.8
|
||||
install -D -p -m 644 eliloalt.8 $RPM_BUILD_ROOT/usr/share/man/man8/eliloalt.8
|
||||
install -D -p -m 644 %{SOURCE2} $RPM_BUILD_ROOT/usr/share/man/man8/eliloalt.8
|
||||
install -D -p -m 644 %{SOURCE3} $RPM_BUILD_ROOT/usr/share/man/man5/elilo.conf.5
|
||||
|
||||
%clean
|
||||
rm -fr $RPM_BUILD_ROOT
|
||||
@ -104,12 +102,15 @@ echo "Please run /sbin/elilo!"
|
||||
%{_libexecdir}/efi
|
||||
/sbin/elilo
|
||||
/sbin/eliloalt
|
||||
%if 0
|
||||
/usr/share/man/man5/*
|
||||
%endif
|
||||
/usr/share/man/man8/*
|
||||
|
||||
%changelog
|
||||
* Tue Dec 09 2008 rw@suse.de
|
||||
- elilo.efi
|
||||
* Second attempt to work around firmware problem. (bnc#437486)
|
||||
- elilo.conf
|
||||
* Provide stub man page. (bnc#435648)
|
||||
* Fri Nov 21 2008 rw@suse.de
|
||||
- elilo.efi
|
||||
* Significant code cleanup from CVS. (bnc#443565)
|
||||
|
Loading…
Reference in New Issue
Block a user