SHA256
1
0
forked from pool/elilo
OBS User unknown 2008-12-15 11:28:48 +00:00 committed by Git OBS Bridge
parent 212982063b
commit d2abc5e393
6 changed files with 258 additions and 121 deletions

225
elilo-bzimage-alloc.diff Normal file
View 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);

View File

@ -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__ */

View File

@ -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
View 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)

View File

@ -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)