Compare commits
7 Commits
Author | SHA1 | Date |
---|---|---|
Stephane Eranian | 2b5c5002e1 | |
Stephane Eranian | 82f7288853 | |
Stephane Eranian | e351d8fbea | |
Stephane Eranian | 4e87874a03 | |
Stephane Eranian | 34d8003a54 | |
Stephane Eranian | 97b2a7df25 | |
Stephane Eranian | 64cdcfed2c |
244
ChangeLog
244
ChangeLog
|
@ -1,3 +1,215 @@
|
|||
2013-03-27 signed off by Jason Fleischli <fleischli@users.sourceforge.net>
|
||||
* ADD CROSSBUILD
|
||||
* intake edited version of Debian x86x crossbuild patches.
|
||||
* Fixed Makefile clean to include crossbuild envs.
|
||||
* Fixed ia32 system.c compile warning
|
||||
* Simplified efi no GOP warning so it doesnt look like an error.
|
||||
* MAJOR: Fixed Fault crash when EFI memory map changes from under elilo.
|
||||
(from an outside interrupt in this case). When the EFI Memory map
|
||||
changes after elilo has already built boot params to pass to the
|
||||
kernel the EFI call to ExitBootSvcs just prior to boot will fail
|
||||
because elilo has the old map key. This is valid EFI behavior, elilo
|
||||
retries to pick up the new memory map and valid key but had already
|
||||
freed the start params portion of boot params resulting in a NULL
|
||||
DEREF crash reset.
|
||||
* Add console reset call during initialization. thanks A. Steinmetz
|
||||
* minor bugfix, fixed -m option broken. thanks Allan-lsk.
|
||||
* tag 3_16 for release
|
||||
|
||||
2011-1-10 signed off by Jason Fleischli <fleischli@users.sourceforge.net>
|
||||
* Uptake of SUSE patches
|
||||
- add sysfs support for efi vars (formerly /proc/efi/vars)
|
||||
- fix strncpy overflow
|
||||
- fix bzimage alloc
|
||||
- cleanups
|
||||
- support longer command line
|
||||
- yet some more mac fixes
|
||||
- align elilo with latest kernel boot protocol format.
|
||||
- new memory management strategy for initrd and kernel image loading.
|
||||
* add force text mode command line option.
|
||||
* replace error output on GOP handle failed, downgraded to normal
|
||||
print status with more informative output.
|
||||
|
||||
2009-10-22 signed off by Jason Fleischli <fleischli@users.sourceforge.net>
|
||||
* elilo 3.12 release commit
|
||||
* Added additional #defines for debug levels to reduce the output
|
||||
* Added Mac console patch rework from Julien Blache @ debian
|
||||
this fixes the invisible console output from elilo on Macs
|
||||
* Moved static ELILO_VERSION variable from elilo.c to elilo.h
|
||||
so that elilo will print its version string and arch on startup.
|
||||
* Fixed bug 2825044 ExitBootServices error handling, correctly deal
|
||||
with changed memory map key if memory map changes from under elilo.
|
||||
* Added memory map key to map debug output.
|
||||
* Fixed bug 2874380 netbooting just flat broken. fixed ia64, x86_64
|
||||
ia32, fixed handling of server side support of tfpt options (get file size)
|
||||
elilo now attempts to get file size before attempting read of file
|
||||
to set the buffers up correctly and deal with tftp servers that dont
|
||||
support options extensions a little better.
|
||||
* netboot, fixed bad blocksize handling
|
||||
* netboot, fixed filename length for elilo-x86_64.conf type on tftp
|
||||
server.
|
||||
* increased bzimage kernel max length sizes to 4mb on i386 and 8mb on
|
||||
x86_64... this is a legacy design hold over from original design and
|
||||
needs to be re-written to do dynamic size memory management based on
|
||||
the size of the actual vmlinuz image, as ia64/gzip does.
|
||||
|
||||
2008-04-02 signed off by Jason Fleischli <fleischli@users.sourceforge.net>
|
||||
* elilo 3.10 release commit
|
||||
* Bumped version string to 3.10
|
||||
* added PTR_FMT 32bit & 64bit pointer translation for correct output
|
||||
* elilo hang bugfix x86_64 non-standard kernels with non-traditional start address
|
||||
elilo will pull the start address from the kernel elf header for 2.6
|
||||
or newer kernels, map memory and use that start address, else use standard
|
||||
1MB default start address. And handle case of overlapping kernels
|
||||
and initrds in memory. Patch contributor Stuart Hayes @ Dell,
|
||||
thanks Stuart!
|
||||
* ported kernel start adress fix to ia32
|
||||
* eliminated all possible compiler warnings except those actually
|
||||
caused by gnu-efi that cant be fixed here.
|
||||
* Debug output improvement, added pauses with visual feedback when
|
||||
user sets debug & verbose options.
|
||||
* bugfix added missing find_bits function definition back into ia32
|
||||
subtree
|
||||
* bugfix loader_probe now correctly errors out if no loaders
|
||||
registered.
|
||||
|
||||
2008-01-11 signed off by Jason Fleischli <fleischli@users.sourceforge.net>
|
||||
* Various compile warning cleanups.
|
||||
|
||||
2008-01-03 signed off by Jason Fleischli <fleischli@users.sourceforge.net>
|
||||
* Patch contribution from Scott Davilla <davilla@4pi.com>
|
||||
when x is zero for the first call to add_memory_region, e820_map[-1]
|
||||
will access memory outside the bounds of e820_map. While this does
|
||||
not result in any problems as there is a UINT32 unused_8[41] block
|
||||
above the e820_map[0] location that should have been zeroed by the
|
||||
bootloader, the code should not access outside the bounds of
|
||||
structures.
|
||||
|
||||
2008-01-03 Jason Fleischli <fleischli@users.sourceforge.net>
|
||||
* initrd.c -- Let the allocator decide where to grab the memory from
|
||||
the efi memory map. Current start_addr=image->start_addr forces the
|
||||
same efi region everytime, and has a 7mb limit. ramdisk (initrd.img)
|
||||
files larger than 7MB wouldnt fit into the memory region assumed by
|
||||
the image->start_addr resulting in an elilo hang. Leaving start_addr
|
||||
NULL at initialization forces alloc_pages to get a memory region
|
||||
sufficient for the size of the initrd image.
|
||||
|
||||
2007-12-19 Jason Fleischli <fleischli@users.sourceforge.net>
|
||||
* bumping version string to 3.8
|
||||
|
||||
2007-12-19 Jason Fleischli <fleischli@users.sourceforge.net>
|
||||
* MORE PATCHES FROM INTEL FOR IA32 X86_64.
|
||||
* Fix compile warning for cmdline_addr assignment.
|
||||
* Fix an issue caused by uninitialized e820_nr_map in fill_e820map.
|
||||
* On some machines, there are too many EFI memory map entries, so that,
|
||||
the number of E820 map entries converted from EFI memory map exceeds
|
||||
the limit (128). This patch fixes this bug by merging consecutive
|
||||
memory map entries with the same type.
|
||||
* CL_MAGIC is not supported by 32-bit boot protocol. So, the kernel
|
||||
command line passing code is changed accordingly.
|
||||
* EFI-2.0 boot support patches have been accepted into Linux kernel
|
||||
2.6.24-rc4 and EFI runtime service patches have been accepted by
|
||||
Linux kernel 2.6.24-rc4-mm1. There are some changes during the
|
||||
merging, so there are some updates for elilo ia32/x86_64 too.
|
||||
* The x86_64 boot parameters of Linux kernel is rearranged to line up
|
||||
with ia32 boot parameters.
|
||||
* The boot loader signature of IA32 and x86_64 is redefined to
|
||||
make it possible for Linux kernel to distinguish whether the
|
||||
underlying firmware is EFI 32 or EFI 64.
|
||||
* The EFI framebuffer type ID is changed in Linux kernel to
|
||||
conform to Linux kernel framebuffer type ID grouping rules. So the
|
||||
EFI framebuffer type ID setting code in ELILO is changed accordingly.
|
||||
* E820 memory map is added to IA32 to make it possible for
|
||||
Linux kernel not to depend on EFI memory map on EFI 32.
|
||||
|
||||
2007-09-27 Jason Fleischli <fleischli@users.sourceforge.net>
|
||||
* updating changelog for last commit that was omitted
|
||||
* incorporating AGriffis patches to enhance parsing
|
||||
passes root= option to kernel options and accounts for -- option
|
||||
designation.
|
||||
|
||||
2007-07-19 Jason Fleischli <fleischli@users.sourceforge.net>
|
||||
* Integrated x86_64 support patches from Chandramouli Narayanan
|
||||
<mouli@linux.intel.com> changes summarized in following bullets.
|
||||
* alloc.c -- adds patch contributors credit to copyright
|
||||
* alloc.c -- adds uefi_call_wrapper around BS->function calls
|
||||
* alloc.c -- adds call to Print on VERB_PRT
|
||||
* alternate.c -- adds patch contributors credit around copyright
|
||||
* alternate.c -- adds uefi_call_wrapper around RT->function calls
|
||||
* simple.c -- adds patch contributors credit to copyright
|
||||
* simple.c -- adds uefi_call_wrapper around ip->ReadKeyStroke
|
||||
* textmenu.c -- adds patch contributors credit to copyright
|
||||
* textmenu.c -- adds uefi_call_wrapper around ClearScreen &
|
||||
SetTextAttr
|
||||
* textmenu.c -- adds uefi_call_wrapper around ip->ReadKeyStroke
|
||||
* elilo.c -- adds patch contributors credit to copyright
|
||||
* elilo.c -- fixes version number for ELILO_VERSION macro to current
|
||||
* elilo.c -- adds uefi_call_wrapper around BS->function calls
|
||||
* elilo.c -- adds uefi_call_wrapper around RT->function calls
|
||||
* fileops.c -- adds patch contributors credit to copyright
|
||||
* fileops.c -- adds uefi_call_wrapper around BS->function calls
|
||||
* fileops.c -- adds uefi_call_wrapper around RT->function calls
|
||||
* fileops.c -- adds uefi_call_wrapper around blkio->function calls
|
||||
* localfs.c -- adds patch contributors credit to copyright
|
||||
* localfs.c -- changed EFI_HANDLE *dev declaration to non-pointer type
|
||||
* localfs.c -- adds uefi_call_wrapper around lfs->volume->functions
|
||||
* localfs.c -- adds uefi_call_wrapper around BS->function calls
|
||||
* netfs.c -- adds patch contributors credit to copyright
|
||||
* netfs.c -- adds uefi_call_wrapper around nfs->pxe->function calls
|
||||
* netfs.c -- adds uefi_call_wrapper around BS->function calls
|
||||
* getopt.c -- changed int to char in StrChr() function
|
||||
* Make.defaults -- adds patch contributors credit to copyright
|
||||
* Make.defaults -- adds cflag for efi function wrapper
|
||||
* Makefile -- adds patch contributors credit to copyright
|
||||
* Makefile -- x86_64 subdir and a new rule for .S
|
||||
* util.c -- adds patch contributors credit to copyright
|
||||
* util.c -- adds uefi_call_wrapper to systab->functions
|
||||
* util.c -- adds uefi_call_wrapper to conin->functions
|
||||
* util.c -- adds uefi_call_wrapper to BS->functions
|
||||
* util.c -- doubles ELILO_MEMMAP_SIZE_DEFAULT in get_memmap() function
|
||||
* bootparams.c -- uses ia32 params for x86_64 addition.. hmmmm?
|
||||
* config.c -- adds patch contributors credit to copyright
|
||||
* config.c -- adds define reference for x86_64.conf
|
||||
* config.c -- in config_error() removes use of va_list which maps to
|
||||
the gnu C-lib iface __gnuc_va_list. Replaces the use of _IPrint on
|
||||
the va_list with direct use of IPrint(systab->ConOut, msg);
|
||||
*maintainer note, this probably introduces a bug, in light of this
|
||||
note from the patch submitter --> "On some x86_64 systems with
|
||||
EFI1.10 firmware I tested, early boot messages did not appear on console.
|
||||
However, I didn't encounter this behavior on x86_64 systems with UEFI2.0
|
||||
firmware"
|
||||
* elf.h -- adds #def for x86_64
|
||||
* glue_netfs.c -- adds patch contributors credit to copyright
|
||||
* glue_netfs.c -- adds define for x86_64.conf
|
||||
* sysdeps.h -- adds patch contributors credit to copyright
|
||||
* sysdeps.h -- add include reference for new x86_64 subdir
|
||||
* x86_64/ -- new subdir - all based on elilo/ia32 subdir
|
||||
* x86_64/bin_to_h.c -- new file, stream fed binary to hex converter
|
||||
* x86_64/bzimage.c -- new file, binary compressed kernel support
|
||||
* x86_64/gzip.c -- new file, embedded gzip
|
||||
* x86_64/gzip_loader.c -- new file, embedded gzip
|
||||
* x86_64/gzip.h -- new file, embedded gzip
|
||||
* x86_64/inflate.c -- new file, a pkzip method 8 embedded decompressor
|
||||
* x86_64/Makefile -- new file
|
||||
* x86_64/plain_loader.c -- new file, for loading non-compressed kernels
|
||||
* x86_64/private.h -- new file
|
||||
* x86_64/rmswitch.S -- new file, RealMode assembly module
|
||||
* x86_64/sysdeps.h -- new file, system stuff for x86_64, e820 mapping
|
||||
added.
|
||||
* x86_64/sysdeps.c -- new file, system stuff for x86_64
|
||||
* elilo.txt -- documentation update, add Intel to copyright
|
||||
* README.gnu-efi -- documentation update for x86_64
|
||||
|
||||
2006-01-27 Alex Williamson <alex.williamson@hp.com>
|
||||
* Found a couple more places where vmcode isn't zeroed, causing the
|
||||
option to get carried over to labels it shouldn't.
|
||||
|
||||
2006-01-09 Brett Johnson <brett@hp.com>
|
||||
* Released 3.6
|
||||
|
||||
2005-12-22 Alex Williamson <alex.williamson@hp.com>
|
||||
* Fixed vmcode_name initialization in textmenu chooser
|
||||
|
||||
2005-12-01 Alex Williamson <alex.williamson@hp.com>
|
||||
* Applied patch from Fred Yang <fred.yang@intel.com> to support the
|
||||
vmm= boot option. This option specifies the kernel image for a
|
||||
|
@ -11,29 +223,37 @@
|
|||
image will be uncompressed into memory before it is provided to the
|
||||
hypervisor. Any combination of compressed and uncompressed images
|
||||
can be used for the image and vmm options.
|
||||
|
||||
2005-09-15 Brett Johnson <brett@hp.com>
|
||||
* Applied patch from Tristan Gingold to add dcache flush and sync with
|
||||
icache to gzip and plain loaders. This ommision was just noticed now
|
||||
due to the much larger caches in Montecito, and the smaller size of
|
||||
Xen (as compared to the linux kernel).
|
||||
|
||||
2004-09-27 Brett Johnson <brett@hp.com>
|
||||
* Increase the hardcoded size of the texmenu chooser menu from 16 to 64
|
||||
|
||||
2004-09-23 Brett Johnson <brett@hp.com>
|
||||
* Fix for 924147. Thanks to Stephanie Schaaf <sas@sgi.com> for a patch
|
||||
that the fix is based on.
|
||||
|
||||
2004-02-19 Brett Johnson <brett@hp.com>
|
||||
* Fixed bug where default image initrd would carry over to another
|
||||
image that was selected interactively (iff the newly selected image
|
||||
did not have an initrd).
|
||||
* Added support for subnet-specific config files in netfs.
|
||||
|
||||
2004-02-17 Brett Johnson <brett@hp.com>
|
||||
* integrated ia32 compressed kernel support from Matt Tolentino
|
||||
<matthew.e.tolentino@intel.com>
|
||||
|
||||
2003-08-20 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* released 3.4
|
||||
|
||||
2003-08-19 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* integrated ia32 updates from Matt
|
||||
Tolentino <matthew.e.tolentino@intel.com>
|
||||
|
||||
2003-08-13 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* updated elilo.txt and netbooting.txt
|
||||
* fix a bug in choosers/simple.c:print_infos().
|
||||
|
@ -46,37 +266,47 @@
|
|||
* updated simple chooser set of builtin command keys
|
||||
* command keys are only valid if first on the line
|
||||
* increase default buffer size and increment when netbooting
|
||||
|
||||
2003-06-04 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* fix fs/netfs.c to work with recent version
|
||||
of EFI (14.61 or higher) which do not have the
|
||||
TFTP problem anymore. fix submitted by Guy Laborde
|
||||
|
||||
2003-04-21 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* ext2fs support is turned off by default to avoid
|
||||
problems with ext3-formatted partitions.
|
||||
* added gcc version check. MUST use 3.0 or higher
|
||||
|
||||
2003-03-03 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* added check on dev_tab in fs/*fs.c:*_uninstall()
|
||||
|
||||
2003-02-07 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* clean up in glue_localfs.c w.r.t. CHAR16 in set_default_path()
|
||||
* added support for extracting basename of bootloader path
|
||||
when using BOOTP (DHCP) only. The prefix is then used for all files
|
||||
open via netfs. Suggestion and initial patch by Guy Laborde from HP.
|
||||
|
||||
2003-01-28 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* fix the set_default_path() routine in glue_localfs.c. It would not
|
||||
correctly get the basename of the devpath. This caused the
|
||||
elilo.conf not to be found sometimes.
|
||||
|
||||
2003-01-21 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* fix bug in glue_netfs.c convert_ip2decstr() which caused some IP
|
||||
addresses to be incorrectly converted to strings.
|
||||
|
||||
2002-11-01 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* fix bug in -r option for IA64. There is no argument to this option.
|
||||
|
||||
2002-10-15 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* fixed a double free bug for the kernel memory in case of abort.
|
||||
(bug spotted by Levent Akyl from Intel)
|
||||
* released 3.3a
|
||||
|
||||
2002-09-14 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* applied patch from Andreas Schwab <schwab@suse.de> to eliloalt.c.
|
||||
eliloalt dynamically selects a variable in /proc/efi/vars.
|
||||
|
||||
2002-09-12 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* removed extra free() from fs/ext2fs.c:ext2fs_init_state().
|
||||
Bug report and fix by NOMURA Jun'ichi <j-nomura@ce.jp.nec.com>
|
||||
|
@ -84,25 +314,31 @@
|
|||
was bigger than the 128KB limit of EFI causing some weird fimrware
|
||||
errors. bug reported by OMURA Jun'ichi <j-nomura@ce.jp.nec.com>
|
||||
* on IA-64 forbid the use of f32-f127 by the compiler (EFI spec)
|
||||
|
||||
2002-09-10 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* fix a bug in argify() that was causing an EFI assertion
|
||||
when aborting at the elilo prompt when netbooted.
|
||||
|
||||
2002-08-26 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* fixed devschemes/simple.c to use SPrint() instead of its own buggy
|
||||
conversion code (spotted by Richard Hirst).
|
||||
* fix bug in argify() when there was no NULL character in the string.
|
||||
* released 3.3
|
||||
|
||||
2002-08-19 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* added fpswa.txt in the docs directory
|
||||
* updated elilo.txt
|
||||
|
||||
2002-08-15 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* added -F file option for IA-64 to allow a specific fpswa driver to be loaded
|
||||
* fixed fpswa.c to try and load the driver from all accessible partitions
|
||||
* added support to load (plain or gzipped) big-endian ELF/ia64 binaries using p_paddr.
|
||||
* fixed problem in fs/netfs.c causing large (>4MB) binaries to fail the Mftp() call
|
||||
|
||||
2002-06-13 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Changed the despecialization character for the variables from \\ to &
|
||||
to avoid conflicts with \\ as a path separator
|
||||
|
||||
2002-06-11 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* fixed the return value in efi_main(). elilo was always returning
|
||||
success even in case of failure. Bug reported by Egan Ford <egan@sense.net>
|
||||
|
@ -112,11 +348,13 @@
|
|||
compliant with EFI spec with regards to where it looks for files.
|
||||
With this patch, elilo will look in the directory it was loaded
|
||||
from, not on the root of the partition anymore.
|
||||
|
||||
2002-03-04 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* released version 3.2
|
||||
* cleanup some GNU extension in fs/ext2fs.c (variable size array)
|
||||
* updated all documentation. Added netbooting.txt, simple_chooser.txt,
|
||||
eliloalt.txt, elilovar.txt
|
||||
|
||||
2002-02-21 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* added a Linux utility program (elilovar in tools) to set/read/delete
|
||||
the EliloAlt EFI variable used to specify an alternate kernel to boot.
|
||||
|
@ -124,19 +362,24 @@
|
|||
* added support for hostname,domain name extraction in fs/netfs.c
|
||||
* fixed all known bugs in alternate.c
|
||||
* integrated patch from SGI to fix load offset for relocatable kernels (Jack Steiner, Brent Casavant)
|
||||
|
||||
2002-02-21 Michael Johnston <michael.johnston@intel.com> and Chris Ahna <christopher.j.ahna@intel.com>
|
||||
* major update to ia32 support: can now boot 2.4.x, and 2.2.x kernels
|
||||
|
||||
2002-02-20 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* fixed missing netfs_fd_free() in case of file not found in netfs.c
|
||||
|
||||
2002-02-19 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* added support for substitution variables (vars.c)
|
||||
* changed the bootparam structure size back to 4kB
|
||||
* added support to simple to print final command line option with tab key
|
||||
* got rid of all the \r characters in strings use only \n (adjust emulator)
|
||||
* added EFICRT0 variable in Makefile to indicate location of loader script+crt0
|
||||
|
||||
2002-02-14 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* added support for message= option to simple chooser
|
||||
* added support for description= option to simple chooser
|
||||
|
||||
2002-02-13 Stephane Eranian <eranian@hpl.hp.com>
|
||||
* choosers/textmenu.c: new textmenu chooser (by rhirst@linuxcare.com) used by Debian
|
||||
* config.c: added support for dynamic global/per-image option management
|
||||
|
@ -165,6 +408,7 @@
|
|||
mode was specified in config file. In this case, we now autoboot
|
||||
and ignore the prompt directive.
|
||||
* updated elilo.txt
|
||||
|
||||
2001-08-15 Brent Casavant <bcasavan@sgi.com>
|
||||
* fix a bug in config.c:find_option() where it would do
|
||||
a strXcmp() on a NULL string.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#
|
||||
# Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
# Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
# Contributed by Chandramouli Narayanan<mouli@linux.intel.com>
|
||||
#
|
||||
# This file is part of ELILO, the LINUX EFI boot loader.
|
||||
#
|
||||
|
@ -54,20 +55,23 @@ CONFIG_machspec_netconfig=y
|
|||
# They are installed as part of the GNU-EFI package installation
|
||||
#
|
||||
EFIINC = /usr/include/efi
|
||||
GNUEFILIB = /usr/lib
|
||||
GNUEFILIB = /usr/lib
|
||||
EFILIB = /usr/lib
|
||||
EFICRT0 = /usr/lib
|
||||
|
||||
CDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
|
||||
TOPDIR =
|
||||
ALLSUBDIRS = ia32 ia64 x86_64 fs choosers devschemes tools
|
||||
|
||||
ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
|
||||
INCDIR = -I. -I$(TOPDIR) -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol
|
||||
HOSTARCH = $(shell dpkg-architecture -qDEB_BUILD_ARCH | sed s,i[3456789]86,ia32, | sed s,amd64,x86_64, )
|
||||
ARCH := $(shell dpkg-architecture -qDEB_BUILD_ARCH | sed s,i[3456789]86,ia32, | sed s,amd64,x86_64, )
|
||||
INCDIR = -I. -I$(TOPDIR) -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol -I$(TOPDIR)/efi110
|
||||
CPPFLAGS = -DCONFIG_$(ARCH)
|
||||
|
||||
OPTIMFLAGS = -O2
|
||||
DEBUGFLAGS = -Wall
|
||||
CFLAGS = $(OPTIMFLAGS) -fpic -fshort-wchar $(DEBUGFLAGS)
|
||||
CFLAGS = $(ARCH3264) $(OPTIMFLAGS) -fno-stack-protector -fno-strict-aliasing -fpic -fshort-wchar $(DEBUGFLAGS)
|
||||
ASFLAGS = $(ARCH3264)
|
||||
LDFLAGS = -nostdlib -znocombreloc
|
||||
INSTALL = install
|
||||
|
||||
|
@ -105,6 +109,32 @@ AR = $(prefix)ar
|
|||
RANLIB = $(prefix)ranlib
|
||||
OBJCOPY = $(prefix)objcopy
|
||||
|
||||
# Use Modified binutils that supports x86_64 using UEFI ABI
|
||||
ifeq ($(ARCH), x86_64)
|
||||
ifeq ($(HOSTARCH), ia32)
|
||||
ARCH3264 = -m64
|
||||
LD3264 = -melf_x86_64
|
||||
|
||||
GNUEFILIB := $(GNUEFILIB)64
|
||||
EFILIB := $(EFILIB)64
|
||||
EFICRT0 := $(EFICRT0)64
|
||||
endif
|
||||
|
||||
CFLAGS += -DEFI_FUNCTION_WRAPPER
|
||||
OBJCOPY = /usr/bin/objcopy
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH), ia32)
|
||||
ifeq ($(HOSTARCH), x86_64)
|
||||
ARCH3264 = -m32
|
||||
LD3264 = -melf_i386
|
||||
|
||||
GNUEFILIB := /usr/lib32
|
||||
EFILIB := /usr/lib32
|
||||
EFICRT0 := /usr/lib32
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),ia64)
|
||||
GCC_VERSION=$(shell $(CROSS_COMPILE)$(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')
|
||||
|
||||
|
|
|
@ -32,4 +32,7 @@
|
|||
|
||||
%.o: %.c
|
||||
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||
# a rule for .S
|
||||
%.o: %.S
|
||||
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||
|
||||
|
|
27
Makefile
27
Makefile
|
@ -1,6 +1,8 @@
|
|||
#
|
||||
# Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
# Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
# Contributed by Fenghua Yu<fenghua.yu@intel.com>
|
||||
# Contributed by Chandramouli Narayanan<mouli@linux.intel.com>
|
||||
#
|
||||
# This file is part of ELILO, the LINUX EFI boot loader.
|
||||
#
|
||||
|
@ -23,15 +25,19 @@
|
|||
# to use this program.
|
||||
#
|
||||
|
||||
include Make.defaults
|
||||
TOPDIR=.
|
||||
SRCDIR = .
|
||||
|
||||
VPATH = $(SRCDIR)
|
||||
|
||||
include $(SRCDIR)/Make.defaults
|
||||
TOPDIR = $(SRCDIR)
|
||||
|
||||
|
||||
CRTOBJS = $(EFICRT0)/crt0-efi-$(ARCH).o
|
||||
LDSCRIPT = $(EFICRT0)/elf_$(ARCH)_efi.lds
|
||||
|
||||
LDFLAGS += -T $(LDSCRIPT) -shared -Bsymbolic -L$(EFILIB) -L$(GNUEFILIB) $(CRTOBJS)
|
||||
LOADLIBES = -lefi -lgnuefi $(shell $(CC) -print-libgcc-file-name)
|
||||
LOADLIBES = -lefi -lgnuefi $(shell $(CC) $(ARCH3264) -print-libgcc-file-name)
|
||||
FORMAT = efi-app-$(ARCH)
|
||||
|
||||
FILESYSTEM =
|
||||
|
@ -58,10 +64,14 @@ ifeq ($(ARCH),ia32)
|
|||
SUBDIRS += ia32
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),x86_64)
|
||||
SUBDIRS += x86_64
|
||||
endif
|
||||
|
||||
FILES = elilo.o getopt.o strops.o loader.o \
|
||||
fileops.o util.o vars.o alloc.o chooser.o \
|
||||
config.o initrd.o alternate.o bootparams.o \
|
||||
gunzip.o fs/fs.o \
|
||||
gunzip.o console.o fs/fs.o \
|
||||
choosers/choosers.o \
|
||||
devschemes/devschemes.o \
|
||||
$(ARCH)/sysdeps.o \
|
||||
|
@ -75,18 +85,19 @@ elilo.efi: elilo.so
|
|||
|
||||
elilo.so: $(FILES)
|
||||
|
||||
elilo.o : elilo.c
|
||||
elilo.o : elilo.c $(ARCH)/sysdeps.h
|
||||
|
||||
fileops.o : Make.defaults
|
||||
chooser.o : Make.defaults
|
||||
|
||||
$(SUBDIRS): dummy
|
||||
$(MAKE) -C $@
|
||||
mkdir -p $@
|
||||
$(MAKE) -C $@ -f $(SRCDIR)/../$@/Makefile SRCDIR=$(SRCDIR)/../$@ ARCH=$(ARCH)
|
||||
|
||||
dummy:
|
||||
|
||||
clean:
|
||||
@set -e ; for d in $(SUBDIRS) ; do $(MAKE) -C $$d $@ ; done
|
||||
@set -e ; for d in $(ALLSUBDIRS) ; do $(MAKE) -C $$d $@ ; done
|
||||
rm -f $(TARGETS) *~ *.so $(FILES)
|
||||
|
||||
.PRECIOUS: elilo.so
|
||||
|
@ -100,4 +111,4 @@ ifeq ($(GCC_VERSION),2)
|
|||
@exit 1
|
||||
endif
|
||||
|
||||
include Make.rules
|
||||
include $(SRCDIR)/Make.rules
|
||||
|
|
15
README
15
README
|
@ -1,14 +1,15 @@
|
|||
ELILO: the IA-32 and IA-64 Linux Loader
|
||||
---------------------------------------
|
||||
ELILO: the IA-32,IA-64 and x86_64 Linux Loader
|
||||
----------------------------------------------
|
||||
Stephane Eranian <eranian@hpl.hp.com>
|
||||
|
||||
August 2003
|
||||
|
||||
Copyright (C) 2000-2003 Hewlett-Packard Co.
|
||||
Copyright (C) 2006-2010 Intel Co.
|
||||
|
||||
|
||||
This package contains version 3.4 of elilo, the EFI boot loader
|
||||
for IA-64(IPF) and IA-32(x86) EFI-based platforms.
|
||||
This package contains version 3.7 of elilo, the EFI boot loader
|
||||
for IA-64(IPF),IA-32(x86) and x86_64 EFI-based platforms.
|
||||
|
||||
|
||||
RELEASE NOTES:
|
||||
|
@ -65,6 +66,12 @@ RELEASE NOTES:
|
|||
|
||||
The Redhat 9.0 toolchain does not work at the moment.
|
||||
|
||||
For x86_64, a toolchain known to produce working binaries is:
|
||||
gcc-4.1.1 or above
|
||||
binutils-2.17.50.0.14 with Intel64 EFI support
|
||||
For x86_64, the following libraries are required for the elilo build
|
||||
gnu-efi library with x86_64
|
||||
|
||||
DOCUMENTATION:
|
||||
--------------
|
||||
PLEASE READ THE docs/elilo.txt file for some documentation on how
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
IMPORTANT Information related to the gnu-efi package
|
||||
and x86_64 efi support
|
||||
----------------------------------------------------
|
||||
August 2003
|
||||
|
||||
|
@ -12,6 +13,10 @@ As of version elilo-3.0, the gnu-efi package is now split in two different packa
|
|||
Note that X.y don't need to match for both packages. However elilo-3.x requires at
|
||||
least gnu-efi >= 3.0. When using a version of gcc >3.0 you MUST use at least gnu-efi-3.0a.
|
||||
|
||||
Note that EFI support for x86_64 has been added as a patch to gnu-efi-3.0c.
|
||||
|
||||
For x86_64, see the important notes under x86_64.
|
||||
|
||||
IMPORTANT NOTE FOR IA-32:
|
||||
-------------------------
|
||||
For IA-32, the Redhat 8.0 toolchain is known to produce
|
||||
|
@ -29,3 +34,32 @@ IMPORTANT NOTE FOR IA-32:
|
|||
The gnu-efi package can be downloaded from:
|
||||
|
||||
ftp://ftp.hpl.hp.com/pub/linux-ia64/gnu-efi-X.y.tar.gz
|
||||
|
||||
IMPORTANT NOTE FOR x86_64:
|
||||
-------------------------
|
||||
|
||||
EFI x86_64 elilo support requires the following libraries:
|
||||
|
||||
1. gnu-efi-3.0c library with x86_64 support.
|
||||
|
||||
2. The toolchain known to produce working x86_64 efi binary are:
|
||||
|
||||
gcc-4.1.1 or above
|
||||
binutils-2.17.50.0.14 with Intel64 EFI support
|
||||
|
||||
Implementation:
|
||||
--------------
|
||||
Calls to EFI services in x86_64 require a wrapper to pass the arguments
|
||||
in the appropriate manner. This is implemented with efi wrapper.
|
||||
For IA32 and IA64, the wrapper is a macro that merely calls the
|
||||
EFI services directly. The elilo source has been modified to use the
|
||||
efi wrapper implemented in gnu-efi-3.0c library.
|
||||
elilo for x86_64 and its dependent libraries are built and the final
|
||||
ELF image is converted into PE-COFF image using the objcopy supported
|
||||
by binutils-2.17.50.0.14 or above with Intel64 EFI support.
|
||||
|
||||
On UEFI 2.0 firmware, only Graphics Output Protocol (GOP) is supported.
|
||||
The x86_64 elilo first queries video information from GOP failing which
|
||||
it queries for text mode support. The video information is passed to
|
||||
Linux kernel via boot parameter. The GOP support requires
|
||||
Linux kernel EFI framebuffer driver (kernel configuration option).
|
||||
|
|
69
alloc.c
69
alloc.c
|
@ -1,6 +1,9 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Contributed by Fenghua Yu <Fenghua.Yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
|
@ -100,15 +103,15 @@ alloc(UINTN size, EFI_MEMORY_TYPE type)
|
|||
|
||||
if (type == 0) type = EfiLoaderData;
|
||||
|
||||
status = BS->AllocatePool (type, size, &tmp);
|
||||
status = uefi_call_wrapper(BS->AllocatePool, 3, type, size, &tmp);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"allocator: AllocatePool(%d, %d, 0x%x) failed (%r)\n", type, size, status));
|
||||
ERR_PRT((L"allocator: AllocatePool(%d, %d) failed (%r)\n", type, size, status));
|
||||
return NULL;
|
||||
}
|
||||
alloc_add(tmp, size, ALLOC_POOL);
|
||||
|
||||
DBG_PRT((L"alloc: allocated %d bytes @[0x%lx-0x%lx]\n", size, tmp, tmp+size));
|
||||
|
||||
#ifdef DEBUG_MEM
|
||||
DBG_PRT((L"alloc: allocated %d bytes @[" PTR_FMT "-" PTR_FMT "]", size, tmp, tmp+size));
|
||||
#endif
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
@ -127,9 +130,9 @@ alloc_pages(UINTN pgcnt, EFI_MEMORY_TYPE type, EFI_ALLOCATE_TYPE where, VOID *ad
|
|||
return NULL;
|
||||
}
|
||||
|
||||
status = BS->AllocatePages(where, type , pgcnt, &tmp);
|
||||
status = uefi_call_wrapper(BS->AllocatePages, 4, where, type , pgcnt, &tmp);
|
||||
if (EFI_ERROR(status)) {
|
||||
VERB_PRT(1, (L"allocator: AllocatePages(%d, %d, %d, 0x%lx) failed (%r)\n", where, type, pgcnt, tmp, status));
|
||||
VERB_PRT(1, Print(L"allocator: AllocatePages(%d, %d, %d, 0x%lx) failed (%r)\n", where, type, pgcnt, tmp, status));
|
||||
return NULL;
|
||||
}
|
||||
/* XXX: will cause warning on IA-32 */
|
||||
|
@ -137,7 +140,7 @@ alloc_pages(UINTN pgcnt, EFI_MEMORY_TYPE type, EFI_ALLOCATE_TYPE where, VOID *ad
|
|||
|
||||
alloc_add(addr, pgcnt, ALLOC_PAGES);
|
||||
|
||||
DBG_PRT((L"allocator: allocated %d pages @0x%lx\n", pgcnt, tmp));
|
||||
DBG_PRT((L"allocator: allocated %d pages @" PTR_FMT, pgcnt, tmp));
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
@ -155,17 +158,18 @@ free(VOID *addr)
|
|||
if (p->addr == addr) goto found;
|
||||
}
|
||||
/* not found */
|
||||
VERB_PRT(1, (L"allocator: invalid free @ 0x%lx\n", addr));
|
||||
VERB_PRT(1, Print(L"allocator: invalid free @ " PTR_FMT "\n", addr));
|
||||
return;
|
||||
found:
|
||||
DBG_PRT((L"free: %s @0x%lx size=%ld\n",
|
||||
#ifdef DEBUG_MEM
|
||||
DBG_PRT((L"free: %s @" PTR_FMT " size=%d",
|
||||
p->type == ALLOC_POOL ? L"Pool": L"Page",
|
||||
addr, p->size));
|
||||
|
||||
#endif
|
||||
if (p->type == ALLOC_POOL)
|
||||
BS->FreePool(addr);
|
||||
uefi_call_wrapper(BS->FreePool, 1, addr);
|
||||
else
|
||||
BS->FreePages((EFI_PHYSICAL_ADDRESS)addr, p->size);
|
||||
uefi_call_wrapper(BS->FreePages, 2, (EFI_PHYSICAL_ADDRESS)addr, p->size);
|
||||
|
||||
/* remove from used list */
|
||||
if (p->next)
|
||||
|
@ -191,13 +195,13 @@ free_all(VOID)
|
|||
alloc_entry_t *tmp;
|
||||
|
||||
while(used_allocs) {
|
||||
|
||||
DBG_PRT((L"free_all %a @ 0x%lx\n", used_allocs->type == ALLOC_POOL ? "pool" : "pages", used_allocs->addr));
|
||||
|
||||
#ifdef DEBUG_MEM
|
||||
DBG_PRT((L"free_all %a @ " PTR_FMT, used_allocs->type == ALLOC_POOL ? "pool" : "pages", used_allocs->addr));
|
||||
#endif
|
||||
if (used_allocs->type == ALLOC_POOL)
|
||||
BS->FreePool(used_allocs->addr);
|
||||
uefi_call_wrapper(BS->FreePool, 1, used_allocs->addr);
|
||||
else
|
||||
BS->FreePages((EFI_PHYSICAL_ADDRESS)used_allocs->addr, used_allocs->size);
|
||||
uefi_call_wrapper(BS->FreePages, 2, (EFI_PHYSICAL_ADDRESS)used_allocs->addr, used_allocs->size);
|
||||
|
||||
tmp = used_allocs->next;
|
||||
|
||||
|
@ -209,6 +213,27 @@ free_all(VOID)
|
|||
}
|
||||
}
|
||||
|
||||
INTN
|
||||
alloc_kmem_anywhere(VOID **start_addr, UINTN pgcnt)
|
||||
{
|
||||
void * tmp;
|
||||
/*
|
||||
* During "AllocateAnyPages" *start_addr will be ignored.
|
||||
* Therefore we can safely subvert it to reuse this function with
|
||||
* an alloc_kmem_anyhwere_below() semantic...
|
||||
*/
|
||||
tmp = alloc_pages(pgcnt, EfiLoaderData,
|
||||
(*start_addr) ? AllocateMaxAddress : AllocateAnyPages,
|
||||
*start_addr);
|
||||
if (tmp == NULL) return -1;
|
||||
|
||||
kmem_addr = tmp;
|
||||
kmem_pgcnt = pgcnt;
|
||||
*start_addr = tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INTN
|
||||
alloc_kmem(VOID *start_addr, UINTN pgcnt)
|
||||
{
|
||||
|
@ -223,13 +248,17 @@ alloc_kmem(VOID *start_addr, UINTN pgcnt)
|
|||
VOID
|
||||
free_kmem(VOID)
|
||||
{
|
||||
DBG_PRT((L"free_kmem before (%lx, %ld)\n", kmem_addr, kmem_pgcnt));
|
||||
#ifdef DEBUG_MEM
|
||||
DBG_PRT((L"free_kmem before (" PTR_FMT ", %d)", kmem_addr, kmem_pgcnt));
|
||||
#endif
|
||||
if (kmem_addr && kmem_pgcnt != 0) {
|
||||
free(kmem_addr);
|
||||
kmem_addr = NULL;
|
||||
kmem_pgcnt = 0;
|
||||
}
|
||||
DBG_PRT((L"free_kmem after (%lx, %ld)\n", kmem_addr, kmem_pgcnt));
|
||||
#ifdef DEBUG_MEM
|
||||
DBG_PRT((L"free_kmem after (" PTR_FMT ", %d)", kmem_addr, kmem_pgcnt));
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan<mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
|
@ -53,7 +56,7 @@ static EFI_GUID altk_guid={0,};
|
|||
* Please note that no fatal error is reported by this function
|
||||
*/
|
||||
INTN
|
||||
alternate_kernel(CHAR16 *buffer, INTN size)
|
||||
alternate_kernel(CHAR16 *buffer, UINTN size)
|
||||
{
|
||||
EFI_STATUS status;
|
||||
INTN ret = -1;
|
||||
|
@ -77,7 +80,7 @@ alternate_kernel(CHAR16 *buffer, INTN size)
|
|||
* - the variable does not exist
|
||||
* - our buffer size is too small.
|
||||
*/
|
||||
status = RT->GetVariable(ELILO_ALTK_VAR, &altk_guid, NULL, &size, buffer);
|
||||
status = uefi_call_wrapper(RT->GetVariable, 5, ELILO_ALTK_VAR, &altk_guid, NULL, &size, buffer);
|
||||
if (EFI_ERROR(status)) {
|
||||
DBG_PRT((L"cannot access variable %s: %r", ELILO_ALTK_VAR, status));
|
||||
|
||||
|
@ -110,7 +113,7 @@ alternate_kernel(CHAR16 *buffer, INTN size)
|
|||
|
||||
ret = 0;
|
||||
delete_var:
|
||||
status = RT->SetVariable(ELILO_ALTK_VAR, &altk_guid, 0, 0, NULL);
|
||||
status = uefi_call_wrapper(RT->SetVariable, 5, ELILO_ALTK_VAR, &altk_guid, 0, 0, NULL);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"cannot erase variable %s", ELILO_ALTK_VAR));
|
||||
}
|
||||
|
|
|
@ -67,9 +67,6 @@ create_boot_params(CHAR16 *args, memdesc_t *initrd, memdesc_t *vmcode, UINTN *co
|
|||
|
||||
/*
|
||||
* Allocate memory for boot parameters.
|
||||
* This CANNOT be EfiLoaderData or EfiLoaderCode as the kernel
|
||||
* frees this region when initializing.
|
||||
* FIXME: Is this a bug? (since the memory type *is* EfiLoaderData)
|
||||
*/
|
||||
|
||||
bp = (boot_params_t *)alloc(BOOT_PARAM_MEMSIZE, EfiLoaderData);
|
||||
|
@ -78,12 +75,12 @@ create_boot_params(CHAR16 *args, memdesc_t *initrd, memdesc_t *vmcode, UINTN *co
|
|||
return 0;
|
||||
}
|
||||
|
||||
VERB_PRT(3, Print(L"boot params @ 0x%lx\n", bp));
|
||||
VERB_PRT(3, Print(L"boot params @ " PTR_FMT "\n", bp));
|
||||
|
||||
/* XXX: need to fix this for 3.5 */
|
||||
#ifdef CONFIG_ia64
|
||||
cp = ((CHAR8 *)bp) + BOOT_PARAM_MEMSIZE - cmdline_size;
|
||||
#elif defined CONFIG_ia32
|
||||
#elif defined CONFIG_ia32 || CONFIG_x86_64
|
||||
cp = ((CHAR8 *)bp) + BOOT_PARAM_MEMSIZE - 2048;
|
||||
#endif
|
||||
|
||||
|
@ -96,6 +93,8 @@ create_boot_params(CHAR16 *args, memdesc_t *initrd, memdesc_t *vmcode, UINTN *co
|
|||
*/
|
||||
Memset(bp, 0, BOOT_PARAM_MEMSIZE);
|
||||
|
||||
U2ascii(args, cp, cmdline_size);
|
||||
|
||||
if (sysdeps_create_boot_params(bp, cp, initrd, vmcode, cookie) == -1) return 0;
|
||||
|
||||
/*
|
||||
|
|
|
@ -23,10 +23,15 @@
|
|||
# to use this program.
|
||||
#
|
||||
|
||||
include ../Make.defaults
|
||||
include ../Make.rules
|
||||
SRCDIR = .
|
||||
|
||||
VPATH = $(SRCDIR)
|
||||
|
||||
include $(SRCDIR)/../Make.defaults
|
||||
include $(SRCDIR)/../Make.rules
|
||||
|
||||
TOPDIR=$(SRCDIR)/..
|
||||
|
||||
TOPDIR=$(CDIR)/..
|
||||
|
||||
FILES=
|
||||
|
||||
|
@ -42,17 +47,14 @@ TARGET=choosers.o
|
|||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): check-choosers $(TOPDIR)/Make.defaults $(FILES)
|
||||
$(LD) -o $@ -r $(FILES)
|
||||
|
||||
clean:
|
||||
$(RM) -f $(TARGET) $(FILES)
|
||||
|
||||
check-choosers:
|
||||
@if [ -n "$(FILES)" ]; then \
|
||||
exit 0; \
|
||||
else \
|
||||
$(TARGET): $(TOPDIR)/Make.defaults $(FILES)
|
||||
@if [ -z "$(FILES)" ]; then \
|
||||
echo "You need to define at least one chooser in Make.defaults"; \
|
||||
exit 1; \
|
||||
fi
|
||||
$(LD) $(LD3264) -o $@ -r $(FILES)
|
||||
|
||||
|
||||
clean:
|
||||
$(RM) -f $(TARGET) $(FILES)
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
|
@ -28,6 +32,7 @@
|
|||
|
||||
#include "elilo.h"
|
||||
#include "vars.h"
|
||||
#include "console.h"
|
||||
|
||||
/* static is ugly but does the job here! */
|
||||
static CHAR16 **alt_argv;
|
||||
|
@ -36,8 +41,8 @@ static VOID
|
|||
display_label_info(CHAR16 *name)
|
||||
{
|
||||
CHAR16 *desc;
|
||||
CHAR16 initrd_name[CMDLINE_MAXLEN];
|
||||
CHAR16 vmcode_name[CMDLINE_MAXLEN];
|
||||
CHAR16 initrd_name[PATHNAME_MAXLEN];
|
||||
CHAR16 vmcode_name[PATHNAME_MAXLEN];
|
||||
CHAR16 options_tmp[CMDLINE_MAXLEN];
|
||||
CHAR16 options[CMDLINE_MAXLEN];
|
||||
CHAR16 kname[FILENAME_MAXLEN];
|
||||
|
@ -136,7 +141,8 @@ reprint:
|
|||
first_time = 0;
|
||||
|
||||
for (;;) {
|
||||
while ((status=ip->ReadKeyStroke(ip, &key)) == EFI_NOT_READY);
|
||||
while ((status = uefi_call_wrapper(ip->ReadKeyStroke, 2, ip, &key))
|
||||
== EFI_NOT_READY);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"select_kernel readkey: %r", status));
|
||||
return -1;
|
||||
|
@ -215,7 +221,7 @@ display_message(VOID)
|
|||
{
|
||||
fops_fd_t fd;
|
||||
EFI_STATUS status;
|
||||
INTN len, i;
|
||||
UINTN len, i;
|
||||
CHAR16 *filename;
|
||||
CHAR8 buf[256];
|
||||
|
||||
|
@ -248,10 +254,10 @@ simple_choose(CHAR16 **argv, INTN argc, INTN index, CHAR16 *kname, CHAR16 *cmdli
|
|||
# define BOOT_IMG_STR L"BOOT_IMAGE="
|
||||
CHAR16 buffer[CMDLINE_MAXLEN];
|
||||
CHAR16 alt_buffer[CMDLINE_MAXLEN];
|
||||
CHAR16 initrd_name[CMDLINE_MAXLEN];
|
||||
CHAR16 vmcode_name[CMDLINE_MAXLEN];
|
||||
CHAR16 initrd_name[PATHNAME_MAXLEN];
|
||||
CHAR16 vmcode_name[PATHNAME_MAXLEN];
|
||||
CHAR16 args[CMDLINE_MAXLEN];
|
||||
CHAR16 devname[CMDLINE_MAXLEN];
|
||||
CHAR16 devname[PATHNAME_MAXLEN];
|
||||
CHAR16 dpath[FILENAME_MAXLEN];
|
||||
CHAR16 *slash_pos, *colon_pos, *backslash_pos;
|
||||
UINTN len;
|
||||
|
@ -274,7 +280,7 @@ restart:
|
|||
argc = argify(alt_buffer,sizeof(alt_buffer), argv);
|
||||
alt_argv = argv;
|
||||
index = 0;
|
||||
args[0] = initrd_name[0] = 0;
|
||||
args[0] = initrd_name[0] = vmcode_name[0] = 0;
|
||||
/*
|
||||
* don't check twice because the variable is deleted after
|
||||
* first access
|
||||
|
@ -283,8 +289,10 @@ restart:
|
|||
}
|
||||
|
||||
if (elilo_opt.prompt) {
|
||||
ret = select_kernel(buffer, sizeof(buffer));
|
||||
console_textmode();
|
||||
ret = select_kernel(buffer, CMDLINE_MAXLEN);
|
||||
if (ret == -1) return -1;
|
||||
/* this function takes really the number of bytes ... */
|
||||
argc = argify(buffer,sizeof(buffer), argv);
|
||||
index = 0;
|
||||
}
|
||||
|
@ -350,11 +358,11 @@ restart:
|
|||
|
||||
if (elilo_opt.prompt == 0) {
|
||||
/* minimal printing */
|
||||
Print(L"ELILO\n");
|
||||
Print(L"ELILO v%s for EFI/%a\n", ELILO_VERSION, ELILO_ARCH);
|
||||
ret = wait_timeout(elilo_opt.delay);
|
||||
if (ret != 0) {
|
||||
elilo_opt.prompt = 1;
|
||||
elilo_opt.initrd[0] = CHAR_NULL;
|
||||
elilo_opt.initrd[0] = elilo_opt.vmcode[0] = CHAR_NULL;
|
||||
elilo_opt.timeout = ELILO_TIMEOUT_INFINITY;
|
||||
goto restart;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Richard Hirst <rhirst@linuxcare.com>
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
|
@ -27,6 +31,7 @@
|
|||
#include <efilib.h>
|
||||
|
||||
#include "elilo.h"
|
||||
#include "console.h"
|
||||
|
||||
#define MAX_LABELS 64
|
||||
#define MSGBUFLEN 4096
|
||||
|
@ -45,8 +50,8 @@ static CHAR16 PromptBuf[CMDLINE_MAXLEN];
|
|||
#define DEF_ATTR EFI_TEXT_ATTR(EFI_LIGHTGRAY,EFI_BLACK)
|
||||
|
||||
|
||||
#define ClearScreen() ST->ConOut->ClearScreen(ST->ConOut)
|
||||
#define SetTextAttr(a) ST->ConOut->SetAttribute(ST->ConOut, a)
|
||||
#define ClearScreen() uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut)
|
||||
#define SetTextAttr(a) uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, a)
|
||||
|
||||
static INTN
|
||||
tohex(INTN c)
|
||||
|
@ -182,12 +187,12 @@ paint_menu(VOID)
|
|||
}
|
||||
|
||||
static INTN
|
||||
read_message_file(INTN msg, INT8 *buf, INTN max)
|
||||
read_message_file(INTN msg, UINT8 *buf, UINTN max)
|
||||
{
|
||||
CHAR16 *filename;
|
||||
fops_fd_t message_fd;
|
||||
EFI_STATUS status;
|
||||
INTN len = max;
|
||||
UINTN len = max;
|
||||
|
||||
if (msg > 10) return 0;
|
||||
|
||||
|
@ -249,7 +254,8 @@ reprint:
|
|||
SetTextAttr(CurrentAttr);
|
||||
|
||||
for (;;) {
|
||||
while ((status=ip->ReadKeyStroke(ip, &key)) == EFI_NOT_READY);
|
||||
while ((status = uefi_call_wrapper(ip->ReadKeyStroke, 2, ip, &key))
|
||||
== EFI_NOT_READY);
|
||||
if (EFI_ERROR(status)) {
|
||||
SetTextAttr(EFI_TEXT_ATTR(EFI_LIGHTGRAY,EFI_BLACK));
|
||||
ClearScreen();
|
||||
|
@ -295,7 +301,7 @@ reprint:
|
|||
if (i) {
|
||||
msgbuf[i] = 0;
|
||||
paint_msg(msgbuf);
|
||||
while ((status=ip->ReadKeyStroke(ip, &key)) == EFI_NOT_READY);
|
||||
while ((status= uefi_call_wrapper(ip->ReadKeyStroke, 2, ip, &key)) == EFI_NOT_READY);
|
||||
goto reprint;
|
||||
}
|
||||
}
|
||||
|
@ -357,10 +363,10 @@ textmenu_choose(CHAR16 **argv, INTN argc, INTN index, CHAR16 *kname, CHAR16 *cmd
|
|||
{
|
||||
# define BOOT_IMG_STR L"BOOT_IMAGE="
|
||||
CHAR16 label[CMDLINE_MAXLEN];
|
||||
CHAR16 initrd_name[CMDLINE_MAXLEN];
|
||||
CHAR16 vmcode_name[CMDLINE_MAXLEN];
|
||||
CHAR16 initrd_name[PATHNAME_MAXLEN];
|
||||
CHAR16 vmcode_name[PATHNAME_MAXLEN];
|
||||
CHAR16 args[CMDLINE_MAXLEN];
|
||||
CHAR16 devname[CMDLINE_MAXLEN];
|
||||
CHAR16 devname[PATHNAME_MAXLEN];
|
||||
CHAR16 dpath[FILENAME_MAXLEN];
|
||||
CHAR16 *slash_pos, *colon_pos, *backslash_pos;
|
||||
UINTN len;
|
||||
|
@ -383,12 +389,13 @@ textmenu_choose(CHAR16 **argv, INTN argc, INTN index, CHAR16 *kname, CHAR16 *cmd
|
|||
nlabels++;
|
||||
}
|
||||
restart:
|
||||
initrd_name[0] = kname[0] = cmdline[0] = args[0] = CHAR_NULL;
|
||||
vmcode_name[0] = initrd_name[0] = kname[0] = cmdline[0] = args[0] = CHAR_NULL;
|
||||
|
||||
/* reset per image loader options */
|
||||
Memset(&elilo_opt.img_opt, 0, sizeof(elilo_opt.img_opt));
|
||||
|
||||
if (elilo_opt.prompt) {
|
||||
console_textmode();
|
||||
ret = select_kernel(label, sizeof(label));
|
||||
if (ret == -1) return -1;
|
||||
argc = argify(PromptBuf,sizeof(PromptBuf), argv);
|
||||
|
@ -401,7 +408,7 @@ restart:
|
|||
if (elilo_opt.alt_check && alternate_kernel(PromptBuf, sizeof(PromptBuf)) == 0) {
|
||||
argc = argify(PromptBuf,sizeof(PromptBuf), argv);
|
||||
index = 0;
|
||||
label[0] = args[0] = initrd_name[0] = 0;
|
||||
label[0] = args[0] = initrd_name[0] = vmcode_name[0] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -461,11 +468,11 @@ restart:
|
|||
|
||||
if (elilo_opt.prompt == 0) {
|
||||
/* minimal printing */
|
||||
Print(L"ELILO\n");
|
||||
Print(L"ELILO v%s for EFI/%a\n", ELILO_VERSION, ELILO_ARCH);
|
||||
ret = wait_timeout(elilo_opt.delay);
|
||||
if (ret != 0) {
|
||||
elilo_opt.prompt = 1;
|
||||
elilo_opt.initrd[0] = CHAR_NULL;
|
||||
elilo_opt.initrd[0] = elilo_opt.vmcode[0] = CHAR_NULL;
|
||||
elilo_opt.timeout = ELILO_TIMEOUT_INFINITY;
|
||||
goto restart;
|
||||
}
|
||||
|
|
132
config.c
132
config.c
|
@ -1,6 +1,9 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
|
@ -42,6 +45,8 @@
|
|||
#define ELILO_ARCH_DEFAULT_CONFIG L"elilo-ia64.conf"
|
||||
#elif defined (CONFIG_ia32)
|
||||
#define ELILO_ARCH_DEFAULT_CONFIG L"elilo-ia32.conf"
|
||||
#elif defined (CONFIG_x86_64)
|
||||
#define ELILO_ARCH_DEFAULT_CONFIG L"elilo-x86_64.conf"
|
||||
#else
|
||||
#error "You need to specfy your default arch config file"
|
||||
#endif
|
||||
|
@ -51,7 +56,7 @@
|
|||
*/
|
||||
#define ELILO_DEFAULT_CONFIG L"elilo.conf"
|
||||
|
||||
#define MAX_STRING CMDLINE_MAXLEN
|
||||
#define MAX_STRING 512
|
||||
#define CONFIG_BUFSIZE 512 /* input buffer size */
|
||||
|
||||
/*
|
||||
|
@ -66,7 +71,7 @@ typedef struct boot_image {
|
|||
struct boot_image *next;
|
||||
CHAR16 label[MAX_STRING];
|
||||
CHAR16 kname[FILENAME_MAXLEN];
|
||||
CHAR16 options[MAX_STRING];
|
||||
CHAR16 options[CMDLINE_MAXLEN];
|
||||
CHAR16 initrd[FILENAME_MAXLEN];
|
||||
CHAR16 vmcode[FILENAME_MAXLEN];
|
||||
CHAR16 root[FILENAME_MAXLEN];
|
||||
|
@ -95,7 +100,7 @@ typedef struct {
|
|||
CHAR16 root[FILENAME_MAXLEN]; /* globally defined root fs */
|
||||
CHAR16 initrd[FILENAME_MAXLEN];/* globally defined initrd */
|
||||
CHAR16 vmcode[FILENAME_MAXLEN];/* globally defined boot-time module */
|
||||
CHAR16 options[MAX_STRING];
|
||||
CHAR16 options[CMDLINE_MAXLEN];
|
||||
CHAR16 default_image_name[MAX_STRING];
|
||||
CHAR16 message_file[MAX_MESSAGES][FILENAME_MAXLEN];
|
||||
CHAR16 chooser[FILENAME_MAXLEN];/* which image chooser to use */
|
||||
|
@ -204,14 +209,8 @@ static fops_fd_t config_fd;
|
|||
static VOID
|
||||
config_error(CHAR16 *msg,...)
|
||||
{
|
||||
va_list ap;
|
||||
extern UINTN _IPrint (UINTN, UINTN, SIMPLE_TEXT_OUTPUT_INTERFACE *, CHAR16 *, CHAR8 *, va_list);
|
||||
|
||||
Print(L"near line %d: ",line_num);
|
||||
|
||||
va_start(ap,msg);
|
||||
_IPrint((UINTN)-1, (UINTN)-1, systab->ConOut, msg, NULL, ap);
|
||||
va_end(ap);
|
||||
IPrint(systab->ConOut, msg);
|
||||
Print(L"\n");
|
||||
}
|
||||
|
||||
|
@ -256,7 +255,16 @@ next(VOID)
|
|||
back = 0;
|
||||
return ch;
|
||||
}
|
||||
return getc();
|
||||
/*
|
||||
* config files served from pxe/tftpboot windows servers can contain
|
||||
* extraneous '\r' characters, often the first char in the file, and
|
||||
* we need to simply skip over those and continue on
|
||||
*/
|
||||
ch = getc();
|
||||
if(ch == '\r')
|
||||
ch = getc();
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -305,23 +313,23 @@ find_option(config_option_group_t *grp, CHAR16 *str)
|
|||
* - TOK_ERR: in case of (parsing) error
|
||||
*/
|
||||
static token_t
|
||||
get_token(CHAR16 *str, UINTN maxlen)
|
||||
get_token_core(CHAR16 *str, UINTN maxlen, BOOLEAN rhs)
|
||||
{
|
||||
INTN ch, escaped;
|
||||
CHAR16 *here;
|
||||
|
||||
for (;;) {
|
||||
while ((ch = next()), ch == ' ' || ch == '\t' || ch == '\n') if (ch == '\n') line_num++;
|
||||
while ((ch = next()), ch == ' ' || ch == '\t' || ch == '\n') if (ch == '\n' ) line_num++;
|
||||
|
||||
if (ch == CHAR_EOF) return TOK_EOF;
|
||||
|
||||
/* skip comment line */
|
||||
if (ch != '#') break;
|
||||
|
||||
/* skip comment line */
|
||||
while ((ch = next()), ch != '\n') if (ch == CHAR_EOF) return TOK_EOF;
|
||||
line_num++;
|
||||
}
|
||||
if (ch == '=') return TOK_EQUAL;
|
||||
if (ch == '=' && !rhs) return TOK_EQUAL;
|
||||
|
||||
if (ch == '"') {
|
||||
here = str;
|
||||
|
@ -374,7 +382,7 @@ get_token(CHAR16 *str, UINTN maxlen)
|
|||
}
|
||||
else {
|
||||
if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '#' ||
|
||||
ch == '=' || ch == CHAR_EOF) {
|
||||
ch == CHAR_EOF || (ch == '=' && !rhs)) {
|
||||
again(ch);
|
||||
*here = 0;
|
||||
return TOK_STR;
|
||||
|
@ -387,6 +395,18 @@ get_token(CHAR16 *str, UINTN maxlen)
|
|||
return TOK_ERR;
|
||||
}
|
||||
|
||||
static token_t
|
||||
get_token(CHAR16 *str, UINTN maxlen)
|
||||
{
|
||||
return get_token_core(str, maxlen, FALSE);
|
||||
}
|
||||
|
||||
static token_t
|
||||
get_token_rhs(CHAR16 *str, UINTN maxlen)
|
||||
{
|
||||
return get_token_core(str, maxlen, TRUE);
|
||||
}
|
||||
|
||||
static INTN
|
||||
image_check(boot_image_t *img)
|
||||
{
|
||||
|
@ -680,7 +700,7 @@ do_string_core(config_option_t *p, CHAR16 *str, UINTN maxlen, CHAR16 *msg)
|
|||
/*
|
||||
* now get the value
|
||||
*/
|
||||
tok = get_token(str, maxlen);
|
||||
tok = get_token_rhs(str, maxlen);
|
||||
if (tok != TOK_STR) {
|
||||
config_error(L"Option %s expects %s", p->name, msg);
|
||||
return -1;
|
||||
|
@ -751,7 +771,10 @@ config_parse(VOID)
|
|||
|
||||
if (tok == TOK_EOF) break;
|
||||
|
||||
if (tok == TOK_ERR) return -1;
|
||||
if (tok == TOK_ERR) {
|
||||
Print(L"Bad Token from elilo config file, parser read: %s\n elilo exiting\n", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( (p = find_option(current_options, str)) == NULL) {
|
||||
config_error(L"Unkown option %s", str);
|
||||
|
@ -886,10 +909,10 @@ print_label_list(VOID)
|
|||
{
|
||||
boot_image_t *img, *dfl = global_config.default_image;
|
||||
|
||||
if (dfl) Print(L"\t%s\n", dfl->label);
|
||||
if (dfl) Print(L" %s\n", dfl->label);
|
||||
|
||||
for (img = image_list; img; img = img->next) {
|
||||
if (img != dfl) Print(L"\t%s\n", img->label);
|
||||
if (img != dfl) Print(L" %s\n", img->label);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -936,6 +959,37 @@ find_description(CHAR16 *label)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
add_root_to_options(CHAR16 *options, CHAR16 *root, CHAR16 *vmcode)
|
||||
{
|
||||
CHAR16 *o, ko[CMDLINE_MAXLEN];
|
||||
|
||||
if (vmcode[0]) {
|
||||
for (o = options; *o; o++) {
|
||||
if (*o == '-' && *(o+1) == '-')
|
||||
break;
|
||||
}
|
||||
if (! *o) {
|
||||
/* no separator found, add one */
|
||||
StrCpy(o, L" -- ");
|
||||
o++;
|
||||
}
|
||||
|
||||
/* advance past separator and whitespace */
|
||||
o += 2;
|
||||
while (*o == ' ') o++;
|
||||
} else {
|
||||
o = options;
|
||||
}
|
||||
|
||||
/* insert root param at this point */
|
||||
StrCpy(ko, o);
|
||||
StrCpy(o, L"root=");
|
||||
StrCat(o, root);
|
||||
StrCat(o, L" ");
|
||||
StrCat(o, ko);
|
||||
}
|
||||
|
||||
INTN
|
||||
find_label(CHAR16 *label, CHAR16 *kname, CHAR16 *options, CHAR16 *initrd, CHAR16 *vmcode)
|
||||
{
|
||||
|
@ -958,15 +1012,12 @@ find_label(CHAR16 *label, CHAR16 *kname, CHAR16 *options, CHAR16 *initrd, CHAR16
|
|||
/*
|
||||
* when the label does not exist, we still propagate the global options
|
||||
*/
|
||||
if (global_config.root[0]) {
|
||||
StrCpy(options, L" root=");
|
||||
StrCat(options, global_config.root);
|
||||
}
|
||||
|
||||
if (global_config.options[0]) {
|
||||
StrCat(options, L" ");
|
||||
StrCat(options, global_config.options);
|
||||
}
|
||||
if (global_config.root[0])
|
||||
add_root_to_options(options, global_config.root, global_config.vmcode);
|
||||
if (global_config.readonly) StrCat(options, L" ro");
|
||||
|
||||
if (global_config.initrd[0]) StrCpy(initrd, global_config.initrd);
|
||||
|
@ -979,21 +1030,33 @@ find_label(CHAR16 *label, CHAR16 *kname, CHAR16 *options, CHAR16 *initrd, CHAR16
|
|||
found:
|
||||
StrCpy(kname, img->kname);
|
||||
|
||||
/* per image initrd has precedence over global initrd */
|
||||
if (img->initrd[0])
|
||||
StrCpy(initrd, img->initrd);
|
||||
else
|
||||
StrCpy(initrd, global_config.initrd);
|
||||
|
||||
/* per image vmcode has precedence over global vmcode */
|
||||
if (img->vmcode[0])
|
||||
StrCpy(vmcode, img->vmcode);
|
||||
else
|
||||
StrCpy(vmcode, global_config.vmcode);
|
||||
|
||||
/*
|
||||
* literal option overrides any other image-based or global option
|
||||
*
|
||||
* In any case, the image option has priority over the global option
|
||||
*/
|
||||
if (img->literal == 0) {
|
||||
if (img->root[0] || global_config.root[0]) {
|
||||
StrCat(options, L"root=");
|
||||
StrCat(options, img->root[0] ? img->root : global_config.root);
|
||||
}
|
||||
/* XXX: check max length */
|
||||
if (img->options[0] || global_config.options[0]) {
|
||||
StrCat(options, L" ");
|
||||
StrCat(options, img->options[0] ? img->options: global_config.options);
|
||||
}
|
||||
if (img->root[0] || global_config.root[0]) {
|
||||
add_root_to_options(options, img->root[0]
|
||||
? img->root : global_config.root, vmcode);
|
||||
}
|
||||
if (img->readonly || global_config.readonly) {
|
||||
StrCat(options, L" ro");
|
||||
}
|
||||
|
@ -1002,17 +1065,6 @@ found:
|
|||
StrCpy(options, img->options);
|
||||
}
|
||||
|
||||
/* per image initrd has precedence over global initrd */
|
||||
if (img->initrd[0])
|
||||
StrCpy(initrd, img->initrd);
|
||||
else if (global_config.initrd[0])
|
||||
StrCpy(initrd, global_config.initrd);
|
||||
|
||||
if (img->vmcode[0])
|
||||
StrCpy(vmcode, img->vmcode);
|
||||
else if (global_config.vmcode[0])
|
||||
StrCpy(vmcode, global_config.vmcode);
|
||||
|
||||
/*
|
||||
* point to architecture dependent options for this image
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* console.c - Console screen handling functions
|
||||
*
|
||||
* Copyright (C) 2006 Christoph Pfisterer
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* ELILO is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ELILO; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Please check out the elilo.txt for complete documentation on how
|
||||
* to use this program.
|
||||
*/
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
|
||||
#include "elilo.h"
|
||||
|
||||
#include <efiConsoleControl.h>
|
||||
|
||||
static EFI_GUID console_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
|
||||
|
||||
static BOOLEAN console_inited = FALSE;
|
||||
|
||||
static EFI_CONSOLE_CONTROL_PROTOCOL *console_control;
|
||||
|
||||
/*
|
||||
* Initialize console functions
|
||||
*/
|
||||
static VOID console_init(VOID)
|
||||
{
|
||||
EFI_STATUS status;
|
||||
|
||||
if (!console_inited) {
|
||||
console_inited = TRUE;
|
||||
|
||||
status = LibLocateProtocol(&console_guid, (VOID **) &console_control);
|
||||
if (EFI_ERROR(status))
|
||||
console_control = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch the console to text mode
|
||||
*/
|
||||
|
||||
VOID console_textmode(VOID)
|
||||
{
|
||||
EFI_CONSOLE_CONTROL_SCREEN_MODE console_mode;
|
||||
|
||||
console_init();
|
||||
|
||||
if (console_control != NULL) {
|
||||
uefi_call_wrapper(console_control->GetMode, 4, console_control, &console_mode, NULL, NULL);
|
||||
if (console_mode == EfiConsoleControlScreenGraphics)
|
||||
uefi_call_wrapper(console_control->SetMode, 2, console_control, EfiConsoleControlScreenText);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* console.h - Console screen handling functions
|
||||
*
|
||||
* Copyright (C) 2006 Christoph Pfisterer
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* ELILO is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ELILO; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Please check out the elilo.txt for complete documentation on how
|
||||
* to use this program.
|
||||
*/
|
||||
|
||||
#ifndef __ELILO_CONSOLE_H__
|
||||
#define __ELILO_CONSOLE_H__
|
||||
|
||||
extern VOID console_textmode(VOID);
|
||||
|
||||
#endif /* __ELILO_CONSOLE_H__ */
|
|
@ -23,10 +23,15 @@
|
|||
# to use this program.
|
||||
#
|
||||
|
||||
include ../Make.defaults
|
||||
include ../Make.rules
|
||||
SRCDIR = .
|
||||
|
||||
VPATH = $(SRCDIR)
|
||||
|
||||
include $(SRCDIR)/../Make.defaults
|
||||
include $(SRCDIR)/../Make.rules
|
||||
|
||||
TOPDIR=$(SRCDIR)/..
|
||||
|
||||
TOPDIR=$(CDIR)/..
|
||||
|
||||
FILES=simple.o
|
||||
|
||||
|
@ -40,7 +45,7 @@ all: $(TARGET)
|
|||
# without doing make clean.
|
||||
#
|
||||
$(TARGET): $(FILES)
|
||||
$(LD) -r -o $@ $(FILES)
|
||||
$(LD) $(LD3264) -r -o $@ $(FILES)
|
||||
|
||||
clean:
|
||||
$(RM) -f $(TARGET) $(FILES)
|
||||
|
|
|
@ -0,0 +1,522 @@
|
|||
--------------------------------------------------------------------
|
||||
ELILO.EFI: Linux boot loader for
|
||||
EFI/IA-64,EFI/IA-32 and EFI/x86_64 based systems
|
||||
--------------------------------------------------------------------
|
||||
Stephane Eranian <eranian@hpl.hp.com>
|
||||
|
||||
August 2003
|
||||
|
||||
Copyright (C) 2000-2012 Hewlett-Packard Co.
|
||||
Copyright (C) 2006-2010 Intel Co.
|
||||
|
||||
|
||||
I/ Introduction
|
||||
------------
|
||||
|
||||
This document describes how to use ELILO on for IA-64, IA-32 and x86_64 EFI-based platforms.
|
||||
This document describes ELILO version 3.7 - 3.14.
|
||||
|
||||
II/ Command line options
|
||||
--------------------
|
||||
|
||||
elilo [-hDpPVvaE] [-d nsec] [-C config] [-i initrd] [-c chooser] [kernel [kernel options...]]
|
||||
|
||||
-h Display a list of all possible command line options.
|
||||
|
||||
-V Print the version number and exit.
|
||||
|
||||
-d nsec Specify the number of 10th of seconds before loading the
|
||||
kernel.
|
||||
|
||||
-C file Specify the config file to use. The default is elilo.conf in the directory
|
||||
that elilo.efi was loaded from.
|
||||
|
||||
-P Verify config file syntax only. this option causes ELILO to
|
||||
parse the config file and generate a report on the console.
|
||||
No kernel is loaded.
|
||||
|
||||
-v Turn on verbose mode. ELILO prints more message about what it
|
||||
is doing. For each occurrence of this option the verbosity level
|
||||
is increased by one. The maximum level is 5.
|
||||
|
||||
-a Always check for alternate kernel image. The default behavior
|
||||
of ELILO is to NOT look for an alternate image. This
|
||||
option overrides this behavior and ELILO is checking for
|
||||
alternate images no matter what. Alternate images are
|
||||
specified using the EliloAlt EFI variable.
|
||||
|
||||
-p force interactive prompt mode. Valid when no kernel image is
|
||||
specified on the command line.
|
||||
|
||||
-D print debug output.
|
||||
|
||||
-E don't force EDD30 variable to TRUE when FALSE.
|
||||
|
||||
-i file Use file as the initial ramdisk (initrd).
|
||||
|
||||
-c name Specify which kernel chooser to use. Default is 'simple', and
|
||||
the only other choice at present is 'textmenu'.
|
||||
|
||||
In addition, elilo supports platform specific options:
|
||||
|
||||
For IA-64:
|
||||
----------
|
||||
-r the kernel image can be relocated if initial load address is not
|
||||
available. This options requires a special version of the kernel.
|
||||
|
||||
-F file will try to load the FPSWA driver indicated by 'file'. Only this file
|
||||
will be attempted. When no specific file is given, elilo will try
|
||||
loading \efi\intel firmware\fpswa.efi from all accessible EFI system
|
||||
partitions.
|
||||
For IA-32:
|
||||
----------
|
||||
no option defined.
|
||||
|
||||
All file names (including the kernel file) can include a device name using the
|
||||
following syntax:
|
||||
|
||||
dev_name:/path/to/my/kernel
|
||||
|
||||
The 'dev_name' component depends on the naming scheme selected and the detected
|
||||
devices for your system. Some choosers may print the information automatically
|
||||
or on demand, see chooser specific documentation for more on this. See README.devschemes
|
||||
for more information on device naming schemes. The slash character '/' can be used as
|
||||
a directory separator on any file systems including the EFI file system (FAT32).
|
||||
|
||||
For x86_64:
|
||||
----------
|
||||
none
|
||||
|
||||
III/ Configuration File
|
||||
------------------
|
||||
|
||||
ELILO supports a config file with options similar to the LILO/x86 boot loader.
|
||||
|
||||
Elilo will use the following sequence (shown in order) when looking for its config
|
||||
file when none is specified on the command line:
|
||||
|
||||
1/ AABBCCDD.conf (netbooting with regular DHCP)
|
||||
where AABBCCDD is the hexadecimal representation
|
||||
of the IP address assigned during the DHCP phase.
|
||||
|
||||
2/ elilo-ia64.conf or elilo-ia32.conf or elilo-x86_64.conf
|
||||
The choice depends on the client platform. This step allows
|
||||
the same DHCP/PXE server to provide files for both types of clients.
|
||||
|
||||
3/ elilo.conf
|
||||
|
||||
Unless explicitly specified on the command line, elilo looks for its config file
|
||||
in the filesystem and directory it was loaded from. For instance, if elilo.efi
|
||||
is invoked as:
|
||||
|
||||
fs0:\> \efi\debian\elilo.efi
|
||||
|
||||
Then elilo will look for its configuration file in fs0:\efi\debian and not
|
||||
in the root directory of fs0:. The prefix fs0:\efi\debian will be used for
|
||||
all other files that elilo needs to download when their paths are specified
|
||||
as being relative.
|
||||
|
||||
IMPORTANT:
|
||||
This rule also applies when a specific config file is passed via the -C
|
||||
option. For example:
|
||||
|
||||
fs0:\> \efi\debian\elilo.efi -C elilo.conf
|
||||
|
||||
This will look for elilo.conf in fs0:\efi\debian and not in fs0:\.
|
||||
To get to the elilo.conf in fs0:\, you need to specify the absolute
|
||||
path:
|
||||
|
||||
fs0:\> \efi\debian\elilo.efi -C \elilo.conf
|
||||
|
||||
|
||||
The configuration file is an ASCII file and not a UNICODE file.
|
||||
|
||||
The config file contains additional options to change the behavior of the loader.
|
||||
If the same option is specified in the config file AND on the command line, the
|
||||
latter takes precedence. Not all options available in the config file have an
|
||||
equivalent on command line.
|
||||
|
||||
When elilo is invoked with the -h option, it prints the list of support command line
|
||||
options but also the list of config file options. For each option it also prints
|
||||
the type of data expected.
|
||||
|
||||
The config file options are divided in 2 groups:
|
||||
|
||||
|
||||
- image options which are specific to a particular kernel image. Each kernel image
|
||||
must be identified with a logical name called a label.
|
||||
|
||||
- global options which affect the behavior of ELILO and apply to all images.
|
||||
|
||||
The ELILO config file follows the LILO/x86 syntax. First come the global
|
||||
options, then the list of images and options for each of them, if
|
||||
necessary. At least one image MUST be defined and it is possible to have
|
||||
an empty list of global options.
|
||||
|
||||
Options have types. Three types are defined:
|
||||
- boolean: set or not set
|
||||
- string : a string of characters which can be quoted if necessary
|
||||
- number (in decimal)
|
||||
- filename: a string interpreted as a file name
|
||||
|
||||
|
||||
The config file supports the following options:
|
||||
|
||||
Global Options:
|
||||
---------------
|
||||
default=value Name the default image to boot. If not defined ELILO
|
||||
will boot the first defined image.
|
||||
|
||||
timeout=number The number of 10th of seconds to wait while in
|
||||
interactive mode before auto booting default kernel.
|
||||
Default is infinity.
|
||||
|
||||
delay=number The number of 10th of seconds to wait before
|
||||
auto booting when not in interactive mode.
|
||||
Default is 0.
|
||||
|
||||
prompt Force interactive mode
|
||||
|
||||
verbose=number Set level of verbosity [0-5]. Default 0 (no verbose)
|
||||
|
||||
root=filename Set global root filesystem for Linux/ia64
|
||||
|
||||
read-only Force root filesystem to be mounted read-only
|
||||
|
||||
append=string Append a string of options to kernel command line
|
||||
|
||||
initrd=filename Name of initrd file
|
||||
|
||||
image=filename Define a new image
|
||||
|
||||
chooser=name Specify kernel chooser to use: 'simple' or 'textmenu'.
|
||||
|
||||
message=filename a message that is printed on the main screen if supported by
|
||||
the chooser.
|
||||
|
||||
fX=filename Some choosers may take advantage of this option to
|
||||
display the content of a file when a certain function
|
||||
key X is pressed. X can vary from 1-12 to cover
|
||||
function keys F1 to F12.
|
||||
|
||||
noedd30 do not force the EDD30 EFI variable to TRUE when FALSE. In other
|
||||
words, don't force the EDD30 mode if not set.
|
||||
|
||||
Image options:
|
||||
--------------
|
||||
root=filename Set root filesystem for kernel
|
||||
|
||||
read-only Force root filesystem to be mounted read-only
|
||||
|
||||
append=string Append a string of options to kernel command line
|
||||
|
||||
initrd=filename Name of initrd file
|
||||
|
||||
label=string Logical name of image (used in interactive mode)
|
||||
|
||||
description=string One line text description of the image.
|
||||
|
||||
IA-64 specific options:
|
||||
-----------------------
|
||||
|
||||
Global options:
|
||||
---------------
|
||||
fpswa=file Specify the filename for a specific FPSWA to load.
|
||||
If this option is used then no other file will be tried.
|
||||
|
||||
relocatable In case of memory allocation error at initial load point of
|
||||
kernel, allow attempt to relocate (assume kernels is relocatable)
|
||||
|
||||
Image options:
|
||||
--------------
|
||||
relocatable In case of memory allocation error at initial load point of
|
||||
kernel, allow attempt to relocate (assume this kernel is relocatable)
|
||||
|
||||
IA-32 specific options:
|
||||
-----------------------
|
||||
legacy-free Indicate that the host machine does not have a legacy BIOS at all.
|
||||
|
||||
|
||||
The user can specify a kernel and related kernel options using the image label. Alternatively,
|
||||
the user can also specify a kernel file that is not specified in the config file. In any case,
|
||||
some of the global options (such as append) are always concatenated to whatever the user type.
|
||||
|
||||
x86_64 specific options:
|
||||
-----------------------
|
||||
text-mode elilo>=3.14 boolean, image config option to force text console mode.
|
||||
|
||||
IV/ Booting from the local system
|
||||
-----------------------------
|
||||
|
||||
The elilo.efi binary must be in an EFI system partition (FAT32). The config
|
||||
file, kernel image, and optional initrd ramdisk can be on the same partition
|
||||
or even another EFI partition. In the following discussion we assume that all
|
||||
files are on the same EFI partition which is recognized by the EFI shell (nshell)
|
||||
as fs0. The kernel and initrd can be copied from the any linux filesystems to the
|
||||
EFI partition using either the mtools (mcopy) or by mounting the EFI partition as
|
||||
a vfat partition. However you do not really need this because most linux
|
||||
distributions install both files in the EFI partition and mount this partition in /boot/efi.
|
||||
|
||||
To boot a kernel, simply power cycle the machine. Once you get to the EFI
|
||||
shell prompt, change to the filesystem that maps to the partition where elilo is.
|
||||
|
||||
Shell> fs0:
|
||||
fs0:\>
|
||||
|
||||
You might need to make sure that the Shell Path is set such that it will load
|
||||
ELILO from fs0:. You can verify this by typing:
|
||||
fs0:\> set
|
||||
path : fs0:\
|
||||
|
||||
At this point you can invoke ELILO:
|
||||
|
||||
fs0:\> elilo
|
||||
|
||||
If there is no config file, then it will:
|
||||
- pick up the kernel image named vmlinux if it exists, otherwise it will abort.
|
||||
- pass no argument to the kernel.
|
||||
|
||||
You can specify the kernel image and its options on the command line.
|
||||
For instance you can do:
|
||||
|
||||
fs0:\> elilo vmlinux root=/dev/sda5
|
||||
|
||||
You can specify as many parameters as you want. The syntax follows the kernel
|
||||
rule, i.e., list of value pairs (or even single values) separated by space.
|
||||
A more complicated example would be:
|
||||
|
||||
fs0:\> elilo -i initrd-2.4.9 vmlinuz-2.4.9 root=/dev/sda2 console=tty0 console="ttyS0,115200n8"
|
||||
|
||||
In this example, notice the double quotes. They are required because the comma is a control
|
||||
character for nshell.
|
||||
|
||||
In the case a config file is found, then elilo will behave according to
|
||||
the options in that file. However if elilo is invoked with command line options, they
|
||||
will be combined or they will override (if conflicting) what is defined in the config file.
|
||||
|
||||
As of version 3.3, elilo is fully compliant with the EFI specification (1.10) with regards
|
||||
to where the bootloader (elilo.efi) must be located in the EFI system partition. In
|
||||
section 11.2.1.3 of the EFI1.10 specification, it is said that in order to avoid conflicts
|
||||
between various loaders for various OSes or distributions of the same OS, every vendor MUST
|
||||
use a dedicated directory: \EFI\vendor\. The bootloader must be placed in this directory.
|
||||
This has always been possible as this is a matter of creating the directory and copying
|
||||
the elilo.efi file in it. However up until version 3.3, elilo would look for its config file
|
||||
and kernel/initrd in the root (/) of the partition it was loaded from. As of version 3.3,
|
||||
elilo will now ONLY look for its configuration file FROM THE DIRECTORY IT WAS LOADED FROM.
|
||||
The same applies to the kernel and initrd files unless absolute paths are specified. Let us
|
||||
look at a simple example:
|
||||
|
||||
- suppose elilo.efi is in \EFI\DIST if fs0: (for the EFI Shell)
|
||||
|
||||
- if you invoke elilo as follows:
|
||||
|
||||
fs0:\> \efi\dist\elilo -v -p
|
||||
default file path: \efi\dist\
|
||||
config file : \efi\dist\elilo.conf
|
||||
ELILO boot:
|
||||
|
||||
|
||||
Note that this is the same if you invoke elilo directly from \efi or \efi\dist.
|
||||
|
||||
File references in the configuration file are treated as relative to the directory
|
||||
elilo was loaded from except if they use an absolute path.
|
||||
|
||||
As of version 3.4 a similar rule applies to the network boot sequence, see netbooting.txt
|
||||
for details.
|
||||
|
||||
V/ Interactive mode
|
||||
----------------
|
||||
|
||||
Elilo can be forced into interactive mode using the "prompt" option in the config
|
||||
file or with the -p option. In this mode, the user can select a kernel to load.
|
||||
|
||||
The interface depends on the chooser, it may be a simple command line prompt as provided
|
||||
by the simple chooser or a more sophisticated screen with scroll menus as provided by
|
||||
textmenu. Most choosers depends on the elilo config file to get the information they
|
||||
display. The simple chooser can operated without the elilo config file. However it
|
||||
is always better to have this file, to create handy logical names for each possible
|
||||
boot choices. The logical names are specified with the "label" option in the config
|
||||
file. They represent a specific kernel "image" and its specific options.
|
||||
|
||||
In elilo, the user can select a particular kernel image using the corresponding label
|
||||
name. A simple example is as follows:
|
||||
|
||||
If we suppose that the following is defined in elilo.conf:
|
||||
|
||||
image=vmlinuz-2.4.9
|
||||
label=linux-up
|
||||
initrd=initrd-2.4.9
|
||||
root=/dev/sda2
|
||||
append="console=tty0 console=ttyS0,115200n8"
|
||||
|
||||
then the user can specify linux-up at the prompt and elilo will load the
|
||||
vmlinuz-2.4.9 kernel file and the initrd-2.4.9 ramdisk and will pass
|
||||
|
||||
"root=/dev/sda2 console=tty0 console=ttyS0,115200n8"
|
||||
|
||||
as command line arguments to the kernel.
|
||||
|
||||
This behavior is identical to Lilo/x86. However, elilo further allows the user
|
||||
to specify actual kernel files names as well, i.e., kernels that are not defined
|
||||
in the configuration file. If we reuse the above example and the simple chooser,
|
||||
the user can type:
|
||||
|
||||
ELILO boot: vmlinux-2.4.18 root=/dev/sda2
|
||||
|
||||
and elilo will boot the vmlinuz-2.4.18 kernel if it exists.
|
||||
|
||||
VI/ The alternate kernel image
|
||||
--------------------------
|
||||
|
||||
Oftentimes when debugging kernels you want to reboot the machine once with
|
||||
your test kernel and, if something goes wrong, you want to fall back to a more
|
||||
stable kernel. In addition you want to be able to do this from a remote machine.
|
||||
Many things can go wrong when doing kernel debugging. It could be that you don't
|
||||
even reach user-mode. In this case however, you still want to fall back to
|
||||
a stable kernel. The feature you'd like from a boot loader is 'boot once and
|
||||
then fall back to safe kernel'.
|
||||
|
||||
Elilo offers this feature and it's called 'alternate kernel image'.
|
||||
You can configure elilo to load a kernel only once and then whatever
|
||||
happens the next reboot falls back to a different kernel hopefully more stable.
|
||||
|
||||
To do this, elilo relies on an EFI variable called 'EliloAlt' with a NULL GUID.
|
||||
The content of this variable is a UNICODE string containing the kernel file name
|
||||
and its command line options.
|
||||
|
||||
When the -a option is specified on the command line or if the "checkalt" option
|
||||
is present in the config file, elilo will check for the presence of this variable.
|
||||
If found and the content is a valid UNICODE string, elilo will use it as the kernel
|
||||
to boot. There is no verification made on the validity of the kernel name or options.
|
||||
Then the variable is deleted. If the variable is rejected because it does not look
|
||||
sane, it is also deleted.
|
||||
|
||||
The variable can be set from a running Linux system using the /proc/efi/vars
|
||||
interface. In the tools directory of this package, there is a Linux tool called
|
||||
elilovar which can be used to create, modify, print, and delete the EliloAlt
|
||||
variable. Refer to eliloalt.txt for more information on this tool.
|
||||
|
||||
VII/ Auto booting the machine
|
||||
-----------------------
|
||||
|
||||
Once you're satisfied with your machine setup, it is good to install an
|
||||
auto boot procedure. You have two options to do this:
|
||||
- from the EFI boot manager menu
|
||||
- from the EFI shell
|
||||
|
||||
The first option is preferred and is used by most Linux distributions.
|
||||
Elilo can be invoked directly from the boot manager. You need to get into
|
||||
the 'boot maintenance' menu and use load file a file. This can be tedious
|
||||
so instead it is recommended that you use a Linux tool called efibootmgr
|
||||
which is also shipped in most distributions. With this tool, you can
|
||||
create your own boot option and change the boot order.
|
||||
|
||||
|
||||
|
||||
The second approach use the EFI shell and a shell script with a special name: 'startup.nsh'.
|
||||
|
||||
When the system boots, it looks for EFI partitions and if it finds
|
||||
a 'startup.nsh' file in ANY of these it will jumpstart execution from it.
|
||||
|
||||
So the typical way of auto booting your Linux/ia64 system is to simply create
|
||||
such a file with the following content:
|
||||
|
||||
# cat /boot/startup.nsh
|
||||
elilo vmlinuz root=/dev/sda2
|
||||
|
||||
Of course, this can be simplified if there is a configuration file.
|
||||
|
||||
|
||||
VII/ Netbooting
|
||||
----------
|
||||
|
||||
Please refer to netbooting.txt for a complete description of how to boot
|
||||
from the network.
|
||||
|
||||
|
||||
XII/ Booting on EFI/ia32 platforms
|
||||
-----------------------------
|
||||
|
||||
Until PC comes with the EFI firmware built in, you need to boot from a
|
||||
floppy that has the EFI firmware on it. Such floppy can be
|
||||
constructed from the EFI sample implementation and toolkit that is
|
||||
available from the Intel Developer Web site at:
|
||||
|
||||
http://developer.intel.com/technology/efi/
|
||||
|
||||
To use elilo on IA-32, you can put it on a floppy and
|
||||
on a FAT32 partition (msdos partition). You can also
|
||||
netbooting if you network adapter has support for UNDI/PXE.
|
||||
|
||||
Elilo/ia32 is capable of booting unmodified 2.2.x. and 2.4.x kernels
|
||||
as they are shipped by distributors today (such as Redhat7.2). You don't need
|
||||
to recompile the kernel with special options. Elilo ONLY takes compressed kernel
|
||||
image which are typically obtained via a 'make bzImage'. Plain elf/32 kernel can't
|
||||
be booted (plain vmlinux will not work). Similarly, existing initial ramdisks can
|
||||
be used without modifications.
|
||||
|
||||
XIII/ Booting on EFI/x86_64 platforms
|
||||
-----------------------------
|
||||
|
||||
To use elilo on x86_64, you can put it on a floppy and
|
||||
on a FAT32 partition (msdos partition). You can also
|
||||
netboot if your network adapter has support for UNDI/PXE.
|
||||
|
||||
Elilo/x86_64 requires efi64 enabled linux kernel (> 2.6.21).
|
||||
You need to compile the kernel with CONFIG_EFI option.
|
||||
x86_64 platforms with UEFI 2.0 firmware deprecate UGA protocol
|
||||
and therefore only the Graphics Output Protocol (GOP) is supported. For
|
||||
such platforms, the kernel must be configured with EFI_FB option. This
|
||||
will enable early boot messages on the console. The elilo for x86_64
|
||||
attempts to query the firmware for GOP and if it fails it defaults to
|
||||
text mode. Elilo ONLY takes compressed kernel image which are
|
||||
typically obtained via a 'make bzImage'. Plain elf/x86_64 kernel can't
|
||||
be booted (plain vmlinux will not work). Similarly, existing initial
|
||||
ramdisks can be used without modifications.
|
||||
|
||||
The x86_64 implementation converts the EFI memory map into E820 map and
|
||||
passes it in the bootparameter supplied to the OS. For details on
|
||||
bootparameter, see x86_64/sysdeps.h.
|
||||
|
||||
IX/ Credits
|
||||
-------
|
||||
|
||||
Contributors:
|
||||
Intel Corp.
|
||||
Stephane Eranian <eranian@hpl.hp.com>
|
||||
David Mosberger <davidm@hpl.hp.com>
|
||||
Johannes Erdfelt <jerdfelt@valinux.com>
|
||||
Richard Hirst <rhirst@linuxcare.com>
|
||||
Chris Ahna <christopher.j.ahna@intel.com>
|
||||
Mike Johnston <michael.johnston@intel.com>
|
||||
Fenghua Yu <fenghua.yu@intel.com>
|
||||
Bibo Mao <bibo.mao@intel.com>
|
||||
Brett Johnson <brett@hp.com>
|
||||
Jason Fleischli <Jason.Fleischli@hp.com>
|
||||
Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
|
||||
Maintainers:
|
||||
Jason Fleischli <Jason.Fleischli@hp.com>
|
||||
|
||||
X/ Bug reports
|
||||
-----------
|
||||
|
||||
Use the sourceforge bug submission system on the elilo sourceforge
|
||||
project page for reporting including errors or descrepancies in this
|
||||
document.
|
||||
|
||||
XIII/ Reference
|
||||
---------
|
||||
|
||||
UEFI 2.0 specifications are available from the following web site:
|
||||
|
||||
http://www.uefi.org/home
|
||||
|
||||
EFI v1.02 specifications are available from the following web site:
|
||||
|
||||
http://developer.intel.com/technology/efi/
|
||||
|
||||
The latest sources of ELILO can be downloaded at:
|
||||
|
||||
https://sourceforge.net/projects/elilo/files/
|
||||
|
|
@ -1,18 +1,20 @@
|
|||
--------------------------------------------------------------------
|
||||
ELILO.EFI: Linux boot loader for EFI/IA-64 and EFI/IA-32 based systems
|
||||
ELILO.EFI: Linux boot loader for
|
||||
EFI/IA-64,EFI/IA-32 and EFI/x86_64 based systems
|
||||
--------------------------------------------------------------------
|
||||
Stephane Eranian <eranian@hpl.hp.com>
|
||||
|
||||
August 2003
|
||||
|
||||
Copyright (C) 2000-2003 Hewlett-Packard Co.
|
||||
Copyright (C) 2000-2012 Hewlett-Packard Co.
|
||||
Copyright (C) 2006-2010 Intel Co.
|
||||
|
||||
|
||||
I/ Introduction
|
||||
------------
|
||||
|
||||
This document describes how to use ELILO on for both IA-64 and IA-32 EFI-based platforms.
|
||||
This document describes ELILO version 3.4.
|
||||
This document describes how to use ELILO on for IA-64, IA-32 and x86_64 EFI-based platforms.
|
||||
This document describes ELILO version 3.7 - 3.14.
|
||||
|
||||
II/ Command line options
|
||||
--------------------
|
||||
|
@ -81,6 +83,9 @@ II/ Command line options
|
|||
for more information on device naming schemes. The slash character '/' can be used as
|
||||
a directory separator on any file systems including the EFI file system (FAT32).
|
||||
|
||||
For x86_64:
|
||||
----------
|
||||
none
|
||||
|
||||
III/ Configuration File
|
||||
------------------
|
||||
|
@ -94,7 +99,7 @@ III/ Configuration File
|
|||
where AABBCCDD is the hexadecimal representation
|
||||
of the IP address assigned during the DHCP phase.
|
||||
|
||||
2/ elilo-ia64.conf or elilo-ia32.conf
|
||||
2/ elilo-ia64.conf or elilo-ia32.conf or elilo-x86_64.conf
|
||||
The choice depends on the client platform. This step allows
|
||||
the same DHCP/PXE server to provide files for both types of clients.
|
||||
|
||||
|
@ -236,6 +241,9 @@ III/ Configuration File
|
|||
the user can also specify a kernel file that is not specified in the config file. In any case,
|
||||
some of the global options (such as append) are always concatenated to whatever the user type.
|
||||
|
||||
x86_64 specific options:
|
||||
-----------------------
|
||||
text-mode elilo>=3.14 boolean, image config option to force text console mode.
|
||||
|
||||
IV/ Booting from the local system
|
||||
-----------------------------
|
||||
|
@ -447,9 +455,33 @@ XII/ Booting on EFI/ia32 platforms
|
|||
be booted (plain vmlinux will not work). Similarly, existing initial ramdisks can
|
||||
be used without modifications.
|
||||
|
||||
XIII/ Booting on EFI/x86_64 platforms
|
||||
-----------------------------
|
||||
|
||||
To use elilo on x86_64, you can put it on a floppy and
|
||||
on a FAT32 partition (msdos partition). You can also
|
||||
netboot if your network adapter has support for UNDI/PXE.
|
||||
|
||||
Elilo/x86_64 requires efi64 enabled linux kernel (> 2.6.21).
|
||||
You need to compile the kernel with CONFIG_EFI option.
|
||||
x86_64 platforms with UEFI 2.0 firmware deprecate UGA protocol
|
||||
and therefore only the Graphics Output Protocol (GOP) is supported. For
|
||||
such platforms, the kernel must be configured with EFI_FB option. This
|
||||
will enable early boot messages on the console. The elilo for x86_64
|
||||
attempts to query the firmware for GOP and if it fails it defaults to
|
||||
text mode. Elilo ONLY takes compressed kernel image which are
|
||||
typically obtained via a 'make bzImage'. Plain elf/x86_64 kernel can't
|
||||
be booted (plain vmlinux will not work). Similarly, existing initial
|
||||
ramdisks can be used without modifications.
|
||||
|
||||
The x86_64 implementation converts the EFI memory map into E820 map and
|
||||
passes it in the bootparameter supplied to the OS. For details on
|
||||
bootparameter, see x86_64/sysdeps.h.
|
||||
|
||||
IX/ Credits
|
||||
-------
|
||||
|
||||
Contributors:
|
||||
Intel Corp.
|
||||
Stephane Eranian <eranian@hpl.hp.com>
|
||||
David Mosberger <davidm@hpl.hp.com>
|
||||
|
@ -457,22 +489,34 @@ IX/ Credits
|
|||
Richard Hirst <rhirst@linuxcare.com>
|
||||
Chris Ahna <christopher.j.ahna@intel.com>
|
||||
Mike Johnston <michael.johnston@intel.com>
|
||||
Fenghua Yu <fenghua.yu@intel.com>
|
||||
Bibo Mao <bibo.mao@intel.com>
|
||||
Brett Johnson <brett@hp.com>
|
||||
Jason Fleischli <Jason.Fleischli@hp.com>
|
||||
Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
|
||||
Maintainers:
|
||||
Jason Fleischli <Jason.Fleischli@hp.com>
|
||||
|
||||
X/ Bug reports
|
||||
-----------
|
||||
|
||||
You can submit bugs to <eranian@hpl.hp.com> or to the Linux/ia64
|
||||
mailing list at linux-ia64@linuxia64.org. Visit http://www.linuxia64.org
|
||||
to subscribe to this list.
|
||||
Use the sourceforge bug submission system on the elilo sourceforge
|
||||
project page for reporting including errors or descrepancies in this
|
||||
document.
|
||||
|
||||
XIII/ Reference
|
||||
---------
|
||||
|
||||
UEFI 2.0 specifications are available from the following web site:
|
||||
|
||||
http://www.uefi.org/home
|
||||
|
||||
EFI v1.02 specifications are available from the following web site:
|
||||
|
||||
http://developer.intel.com/technology/efi/
|
||||
|
||||
The latest sources of ELILO can be downloaded at:
|
||||
|
||||
ftp://ftp.hpl.hp.com/pub/linux-ia64
|
||||
https://sourceforge.net/projects/elilo/files/
|
||||
|
||||
|
|
|
@ -3,8 +3,11 @@ How to netboot using ELILO
|
|||
|
||||
Copyright (C) 2002-2003 Hewlett-Packard Co.
|
||||
Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
Updated by Jason Fleischli <jason.fleischli@hp.com>
|
||||
|
||||
Last updated: 03/08/11
|
||||
Last updated: 10/19/2009
|
||||
|
||||
x86_64 and uefi support was added @ elilo version 3.8 and linux kernel >= 2.6.24
|
||||
|
||||
EFI has full support for the PXE and DHCP protocol. As such
|
||||
it is relatively easy to boot a machine from the network using EFI.
|
||||
|
@ -126,7 +129,7 @@ only on two very common cases:
|
|||
|
||||
This filename is an opportunity to specify a machine specific configuration file.
|
||||
|
||||
2) AA[BB[CC]][-ia32|ia64].conf
|
||||
2) AA[BB[CC]][-ia32|ia64|x86_64].conf
|
||||
As of version 3.5, elilo will also look for IPv4 class A,B,C
|
||||
subnet-specific versions of the config file. This is useful when you
|
||||
want to have a common config file for all machines connected to a
|
||||
|
@ -140,14 +143,14 @@ only on two very common cases:
|
|||
config files first (So for example, on an Itanium system,
|
||||
"0A0000-ia64.conf" will be tried before "0A0000.conf")
|
||||
|
||||
3) elilo-ia32.config or elilo-ia64.conf
|
||||
3) elilo-ia32.conf, elilo-x86_64.conf, or elilo-ia64.conf
|
||||
|
||||
Depending on the machine (client side) architecture elilo will try the IA-32 or
|
||||
IA-64 file.
|
||||
Depending on the machine (client side) architecture elilo will try the matching
|
||||
architecture specific filename.
|
||||
|
||||
This filename is an opportunity to specify a architecture specific configuration file.
|
||||
This distinction between the architectures is useful when the same TFTP server services
|
||||
the two types of clients : IA32- and IA-64 machines.
|
||||
the three types of clients : ia32, x86_64, and ia64 machines.
|
||||
|
||||
4) elilo.conf
|
||||
|
||||
|
@ -244,7 +247,7 @@ only on two very common cases:
|
|||
|
||||
- use the name provide by the PXE server Layer 1 or
|
||||
|
||||
- elilo-ia64.conf/elilo-ia32.conf or
|
||||
- elilo-ia64.conf/elilo-ia32.conf/elilo-x86_64 or
|
||||
|
||||
- elilo.conf
|
||||
|
||||
|
@ -390,7 +393,7 @@ only on two very common cases:
|
|||
|
||||
|
||||
In the case of a DHCP boot, this type of customization makes sense only for
|
||||
the shared configuration file, elilo-ia64.conf/elilo-ia32.conf or elilo.conf.
|
||||
the shared configuration file, elilo-ia64.conf/elilo-ia32.conf/elilo-x86_64 or elilo.conf.
|
||||
The configuration file based on the IP address (such as C0A80205.conf in this
|
||||
case) would provide another way of customizing parameters for a specific
|
||||
client (IP address). The same thing holds if the name of the config file
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) 2004, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
ConsoleControl.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Abstraction of a Text mode or UGA screen
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __CONSOLE_CONTROL_H__
|
||||
#define __CONSOLE_CONTROL_H__
|
||||
|
||||
#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \
|
||||
{ 0xf42f7782, 0x12e, 0x4c12, { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } }
|
||||
|
||||
/* typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL; */
|
||||
struct _EFI_CONSOLE_CONTROL_PROTOCOL;
|
||||
|
||||
|
||||
typedef enum {
|
||||
EfiConsoleControlScreenText,
|
||||
EfiConsoleControlScreenGraphics,
|
||||
EfiConsoleControlScreenMaxValue
|
||||
} EFI_CONSOLE_CONTROL_SCREEN_MODE;
|
||||
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) (
|
||||
IN struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
|
||||
OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
|
||||
OUT BOOLEAN *UgaExists, OPTIONAL
|
||||
OUT BOOLEAN *StdInLocked OPTIONAL
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Return the current video mode information. Also returns info about existence
|
||||
of UGA Draw devices in system, and if the Std In device is locked. All the
|
||||
arguments are optional and only returned if a non NULL pointer is passed in.
|
||||
|
||||
Arguments:
|
||||
This - Protocol instance pointer.
|
||||
Mode - Are we in text of grahics mode.
|
||||
UgaExists - TRUE if UGA Spliter has found a UGA device
|
||||
StdInLocked - TRUE if StdIn device is keyboard locked
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Mode information returned.
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) (
|
||||
IN struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
|
||||
OUT EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Set the current mode to either text or graphics. Graphics is
|
||||
for Quiet Boot.
|
||||
|
||||
Arguments:
|
||||
This - Protocol instance pointer.
|
||||
Mode - Mode to set the
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Mode information returned.
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN) (
|
||||
IN struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
|
||||
IN CHAR16 *Password
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Lock Std In devices until Password is typed.
|
||||
|
||||
Arguments:
|
||||
This - Protocol instance pointer.
|
||||
Password - Password needed to unlock screen. NULL means unlock keyboard
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Mode information returned.
|
||||
EFI_DEVICE_ERROR - Std In not locked
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
|
||||
|
||||
typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL {
|
||||
EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode;
|
||||
EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode;
|
||||
EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn;
|
||||
} EFI_CONSOLE_CONTROL_PROTOCOL;
|
||||
|
||||
extern EFI_GUID gEfiConsoleControlProtocolGuid;
|
||||
|
||||
#endif
|
1
elf.h
1
elf.h
|
@ -103,6 +103,7 @@ typedef UINT64 Elf64_Word;
|
|||
|
||||
#define EM_IA_64 50 /* HP/Intel IA-64 */
|
||||
|
||||
#define EM_X86_64 62 /* Intel/AMD x86-64 */
|
||||
/*
|
||||
* This is an interim value that we will use until the committee comes
|
||||
* up with a final number.
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
84
elilo.c
84
elilo.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* elilo.c - IA-64/IA-32 EFI Linux loader
|
||||
* elilo.c - IA-64/IA-32/x86_64 EFI Linux loader
|
||||
*
|
||||
* Copyright (C) 1999-2003 Hewlett-Packard Co.
|
||||
* Contributed by David Mosberger <davidm@hpl.hp.com>.
|
||||
|
@ -8,6 +8,11 @@
|
|||
* Copyright (C) 1999-2000 VA Linux Systems
|
||||
* Contributed by Johannes Erdfelt <jerdfelt@valinux.com>.
|
||||
*
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
|
@ -41,13 +46,14 @@
|
|||
#include "loader.h"
|
||||
#include "config.h" /* for config_init() */
|
||||
|
||||
#define ELILO_VERSION L"3.4"
|
||||
#define ELILO_SHARED_CMDLINE_OPTS L"pPMC:aDhd:i:vVc:E"
|
||||
#define ELILO_SHARED_CMDLINE_OPTS L"pPMC:aDhd:i:m:vVc:E"
|
||||
|
||||
elilo_config_t elilo_opt;
|
||||
|
||||
EFI_SYSTEM_TABLE *systab; /* pointer to EFI system table */
|
||||
|
||||
extern INTN wait_timeout (UINTN);
|
||||
|
||||
/*
|
||||
* Load the Linux kernel in memory from the boot media
|
||||
* Output:
|
||||
|
@ -87,7 +93,7 @@ do_kernel_load(CHAR16 *kname, kdesc_t *kd)
|
|||
INTN
|
||||
kernel_load(EFI_HANDLE image, CHAR16 *kname, kdesc_t *kd, memdesc_t *imem, memdesc_t *mmem)
|
||||
{
|
||||
CHAR16 kernel[CMDLINE_MAXLEN];
|
||||
CHAR16 kernel[FILENAME_MAXLEN];
|
||||
|
||||
/*
|
||||
* Do the vm image switch here
|
||||
|
@ -122,11 +128,12 @@ kernel_load(EFI_HANDLE image, CHAR16 *kname, kdesc_t *kd, memdesc_t *imem, memde
|
|||
return ELILO_LOAD_RETRY;
|
||||
}
|
||||
|
||||
VERB_PRT(3, Print(L"kernel loaded in [0x%lx-0x%lx] entry=0x%lx\n",
|
||||
(unsigned long)kd->kstart, (unsigned long)kd->kend, (unsigned long)kd->kentry));
|
||||
VERB_PRT(3, Print(L"kernel loaded in [" PTR_FMT "-" PTR_FMT "] entry=" PTR_FMT "\n",
|
||||
kd->kstart, kd->kend, kd->kentry));
|
||||
|
||||
if (elilo_opt.initrd[0]) {
|
||||
|
||||
/* ramdisk image is moved to the top of available extended memory later by start_kernel() */
|
||||
if (sysdeps_initrd_get_addr(kd, imem) == -1) goto exit_error;
|
||||
|
||||
switch(load_file(elilo_opt.initrd, imem)) {
|
||||
|
@ -207,7 +214,7 @@ main_loop(EFI_HANDLE dev, CHAR16 **argv, INTN argc, INTN index, EFI_HANDLE image
|
|||
EFI_STATUS status = EFI_SUCCESS;
|
||||
kdesc_t kd;
|
||||
memdesc_t imem, mmem;
|
||||
INTN r;
|
||||
INTN r, retries=0;
|
||||
|
||||
/*
|
||||
* First place where we potentially do system dependent
|
||||
|
@ -233,19 +240,53 @@ main_loop(EFI_HANDLE dev, CHAR16 **argv, INTN argc, INTN index, EFI_HANDLE image
|
|||
}
|
||||
|
||||
do_launch:
|
||||
r =subst_vars(cmdline_tmp, cmdline, CMDLINE_MAXLEN);
|
||||
r = subst_vars(cmdline_tmp, cmdline, CMDLINE_MAXLEN);
|
||||
|
||||
VERB_PRT(3, Print(L"final cmdline(%d): %s\n", r, cmdline));
|
||||
|
||||
/* Give user time to see the output before launch */
|
||||
if (elilo_opt.debug || elilo_opt.verbose) {
|
||||
r = wait_timeout(150);
|
||||
/* have to turn off all console output(except error output) now before final get_mmemap()
|
||||
* call or it can cause the efi map key to change and the ExitBootSvc call to fail,
|
||||
* forcing debug and verbose options off is the surest way to enforce this.
|
||||
*/
|
||||
elilo_opt.debug=0;
|
||||
elilo_opt.verbose=0;
|
||||
}
|
||||
|
||||
/* free resources associated with file accesses (before ExitBootServices) */
|
||||
close_devices();
|
||||
|
||||
/* No console output permitted after create_boot_params()! */
|
||||
if ((bp=create_boot_params(cmdline, &imem, &mmem, &cookie)) == 0) goto error;
|
||||
|
||||
/* terminate bootservices */
|
||||
status = BS->ExitBootServices(image, cookie);
|
||||
if (EFI_ERROR(status)) goto bad_exit;
|
||||
/* terminate bootservices
|
||||
* efi ExitBootSvcs spec: *note, get_memmap is called by create_boot_params()
|
||||
* An EFI OS loader must ensure that it has the system's current memory map at the time
|
||||
* it calls ExitBootServices(). This is done by passing in the current memory map's
|
||||
* MapKey value as returned by GetMemoryMap(). Care must be taken to ensure that the
|
||||
* memory map does not change between these two calls. It is suggested that
|
||||
* GetMemoryMap()be called immediately before calling ExitBootServices(). */
|
||||
|
||||
retry:
|
||||
status = uefi_call_wrapper(BS->ExitBootServices, 2, image, cookie);
|
||||
if (EFI_ERROR(status))
|
||||
{
|
||||
ERR_PRT((L"\nExitBootSvcs: failed, memory map has changed.\n"));
|
||||
if (retries < 2)
|
||||
{
|
||||
ERR_PRT((L"Main_Loop: Retrying,... have to rebuild boot params"));
|
||||
retries++;
|
||||
free_boot_params(bp);
|
||||
if ((bp=create_boot_params(cmdline, &imem, &mmem, &cookie)) == 0) goto error;
|
||||
goto retry;
|
||||
} else {
|
||||
ERR_PRT((L"\nMain_Loop: tried ExitBootSvcs 3 times... retries exceeded.... giving up\n"));
|
||||
goto bad_exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
start_kernel(kd.kentry, bp);
|
||||
/* NOT REACHED */
|
||||
|
@ -259,6 +300,7 @@ bad_exit:
|
|||
error:
|
||||
free_kmem();
|
||||
if (imem.start_addr) free(imem.start_addr);
|
||||
if (mmem.start_addr) free(mmem.start_addr);
|
||||
if (bp) free_boot_params(bp);
|
||||
exit_error:
|
||||
return ELILO_LOAD_ERROR;
|
||||
|
@ -307,7 +349,7 @@ fixupargs(EFI_LOADED_IMAGE *info)
|
|||
|
||||
#define FAKE_ELILONAME L"elilo-forced"
|
||||
|
||||
status = BS->HandleProtocol (info->DeviceHandle, &PxeBaseCodeProtocol, (VOID **)&pxe);
|
||||
status = uefi_call_wrapper(BS->HandleProtocol, 3, info->DeviceHandle, &PxeBaseCodeProtocol, (VOID **)&pxe);
|
||||
if (EFI_ERROR(status)) return;
|
||||
|
||||
default_load_options = info->LoadOptions;
|
||||
|
@ -365,7 +407,7 @@ check_edd30(VOID)
|
|||
UINT8 bool = FALSE;
|
||||
INTN ret = -1;
|
||||
|
||||
status = RT->GetVariable(L"EDD30", &edd30_guid, NULL, &l, &bool);
|
||||
status = uefi_call_wrapper(RT->GetVariable, 5, L"EDD30", &edd30_guid, NULL, &l, &bool);
|
||||
if (status == EFI_BUFFER_TOO_SMALL || (bool != TRUE && bool != FALSE)) {
|
||||
ERR_PRT((L"Warning: EDD30 EFI variable is not boolean value: forcing it to TRUE"));
|
||||
return -1;
|
||||
|
@ -395,7 +437,7 @@ force_edd30(VOID)
|
|||
UINT8 bool;
|
||||
|
||||
bool = TRUE;
|
||||
status = RT->SetVariable(L"EDD30", &edd30_guid, EDD30_ATTR, l, &bool);
|
||||
status = uefi_call_wrapper(RT->SetVariable, 5, L"EDD30", &edd30_guid, EDD30_ATTR, l, &bool);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"can't set EDD30 variable: ignoring it"));
|
||||
return -1;
|
||||
|
@ -439,19 +481,23 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *system_tab)
|
|||
* mode.
|
||||
* XXX: clean this up !
|
||||
*/
|
||||
BS->SetWatchdogTimer(0, 0x0, 0, NULL);
|
||||
uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x0, 0, NULL);
|
||||
|
||||
/*
|
||||
* start a clean console
|
||||
*/
|
||||
uefi_call_wrapper(systab->ConOut->Reset, 2, systab->ConOut, FALSE);
|
||||
|
||||
/* initialize memory allocator */
|
||||
if (alloc_init() == -1) return EFI_LOAD_ERROR;
|
||||
|
||||
status = BS->HandleProtocol(image, &LoadedImageProtocol, (VOID **) &info);
|
||||
status = uefi_call_wrapper(BS->HandleProtocol, 3, image, &LoadedImageProtocol, (VOID **) &info);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"image handle does not support LOADED_IMAGE protocol"));
|
||||
return EFI_LOAD_ERROR;
|
||||
}
|
||||
|
||||
VERB_PRT(5,Print(L"Loaded at 0x%lx size=%d bytes code=%d data=%d\n", info->ImageBase, info->ImageSize, info->ImageCodeType, info->ImageDataType));
|
||||
|
||||
VERB_PRT(5,Print(L"Loaded at " PTR_FMT " size=%ld bytes code=%d data=%d\n", info->ImageBase, info->ImageSize, info->ImageCodeType, info->ImageDataType));
|
||||
/*
|
||||
* verify EDD3.0 status. Users may have to reboot
|
||||
*/
|
||||
|
@ -595,7 +641,7 @@ efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *system_tab)
|
|||
goto do_exit;
|
||||
}
|
||||
}
|
||||
DBG_PRT((L"Optind=%d optarg=%x argc=%d", Optind, Optarg, argc));
|
||||
DBG_PRT((L"Optind=%d optarg=" PTR_FMT " argc=%d", Optind, Optarg, argc));
|
||||
|
||||
/*
|
||||
* we can't defer this phase any longer...
|
||||
|
|
19
elilo.h
19
elilo.h
|
@ -29,8 +29,16 @@
|
|||
#ifndef __ELILO_H__
|
||||
#define __ELILO_H__
|
||||
|
||||
#define ELILO_VERSION L"3.16"
|
||||
|
||||
#include <efi.h>
|
||||
|
||||
#ifdef CONFIG_ia32
|
||||
#define PTR_FMT L"0x%x"
|
||||
#else
|
||||
#define PTR_FMT L"0x%lx"
|
||||
#endif
|
||||
|
||||
#include "elilo_debug.h"
|
||||
|
||||
#include "fileops.h"
|
||||
|
@ -46,6 +54,10 @@
|
|||
#define ROUNDUP(x,a) (((x) + (a) - 1) & ~((a) - 1))
|
||||
#define ROUNDDOWN(x,a) ((x) & ~((a) - 1))
|
||||
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX ((UINT32)-1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Elilo Boot modes
|
||||
*/
|
||||
|
@ -57,7 +69,8 @@
|
|||
#define ELILO_DEFAULT_TIMEOUT ELILO_TIMEOUT_INFINITY
|
||||
#define ELILO_TIMEOUT_INFINITY (~0UL)
|
||||
|
||||
#define CMDLINE_MAXLEN 512 /* needed by ia32 */
|
||||
#define CMDLINE_MAXLEN 2048
|
||||
#define PATHNAME_MAXLEN 512
|
||||
#define FILENAME_MAXLEN 256
|
||||
#define MAX_ARGS 256
|
||||
/* Just pick an arbitrary number that's high enough for now :o) */
|
||||
|
@ -150,6 +163,7 @@ extern VOID *alloc_pages(UINTN, EFI_MEMORY_TYPE, EFI_ALLOCATE_TYPE, VOID *);
|
|||
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);
|
||||
|
||||
|
@ -183,7 +197,7 @@ extern CHAR16 *get_config_file(VOID);
|
|||
extern INTN load_file(CHAR16 *, memdesc_t *);
|
||||
|
||||
/* from alternate.c */
|
||||
extern INTN alternate_kernel(CHAR16 *, INTN);
|
||||
extern INTN alternate_kernel(CHAR16 *, UINTN);
|
||||
|
||||
/* from bootparams.c */
|
||||
extern VOID *create_boot_params (CHAR16 *, memdesc_t *, memdesc_t *, UINTN *);
|
||||
|
@ -203,6 +217,7 @@ extern CHAR16 *sysdeps_get_cmdline_opts(VOID);
|
|||
extern INTN sysdeps_getopt(INTN, INTN, CHAR16 *);
|
||||
extern VOID sysdeps_print_cmdline_opts(VOID);
|
||||
extern INTN sysdeps_register_options(VOID);
|
||||
extern VOID *sysdeps_checkfix_initrd(VOID *, memdesc_t *);
|
||||
|
||||
#define CHAR_SLASH L'/'
|
||||
#define CHAR_BACKSLASH L'\\'
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
#ifndef __ELILO_DEBUG__
|
||||
#define __ELILO_DEBUG__
|
||||
|
||||
//#define DEBUG_MEM
|
||||
//#define DEBUG_GZIP
|
||||
//#define DEBUG_BZ
|
||||
|
||||
#define ELILO_DEBUG 1
|
||||
|
||||
#define ERR_PRT(a) do { Print(L"%a(line %d):", __FILE__, __LINE__); Print a; Print(L"\n"); } while (0);
|
||||
|
|
15
fileops.c
15
fileops.c
|
@ -1,6 +1,9 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
|
@ -135,7 +138,7 @@ glue_filesystem(EFI_GUID *proto, EFI_HANDLE dev, fops_fs_glue_t glue)
|
|||
VOID *intf = NULL;
|
||||
EFI_STATUS status;
|
||||
|
||||
status = BS->HandleProtocol(dev, proto, &intf);
|
||||
status = uefi_call_wrapper(BS->HandleProtocol, 3, dev, proto, &intf);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"unable to locate %g: should not happen", proto));
|
||||
return NULL; /* should not happen */
|
||||
|
@ -358,6 +361,8 @@ fops_setdefaults(struct config_file *defconf, CHAR16 *kname, UINTN maxlen, CHAR1
|
|||
#define FILEOPS_ARCH_DEFAULT_CONFIG L"elilo-ia64.conf"
|
||||
#elif defined (CONFIG_ia32)
|
||||
#define FILEOPS_ARCH_DEFAULT_CONFIG L"elilo-ia32.conf"
|
||||
#elif defined (CONFIG_x86_64)
|
||||
#define FILEOPS_ARCH_DEFAULT_CONFIG L"elilo-x86_64.conf"
|
||||
#else
|
||||
#error "You need to specfy your default arch config file"
|
||||
#endif
|
||||
|
@ -455,7 +460,7 @@ add_dev_tab(EFI_GUID *proto, EFI_HANDLE boot_handle, UINTN size, fops_fs_glue_t
|
|||
/*
|
||||
* get the actual device handles now
|
||||
*/
|
||||
status = BS->LocateHandle(ByProtocol, proto, NULL, &size, tab);
|
||||
status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, proto, NULL, &size, tab);
|
||||
if (status != EFI_SUCCESS) {
|
||||
ERR_PRT((L"failed to get handles for proto %g size=%d: %r", proto, size, status));
|
||||
free(tab);
|
||||
|
@ -492,7 +497,7 @@ add_dev_tab(EFI_GUID *proto, EFI_HANDLE boot_handle, UINTN size, fops_fs_glue_t
|
|||
|
||||
str2 = str == NULL ? L"Unknown" : str;
|
||||
|
||||
DBG_PRT((L"%s : %-8s : %s\n", dev_tab[idx].name,
|
||||
DBG_PRT((L"%s : %-8s : %s", dev_tab[idx].name,
|
||||
(dev_tab[idx].fops ? dev_tab[idx].fops->name: L"N/A"), str2));
|
||||
|
||||
if (str) FreePool(str);
|
||||
|
@ -536,7 +541,7 @@ find_filesystems(EFI_HANDLE boot_handle)
|
|||
*/
|
||||
for(fs = fs_tab; *fs; fs++) {
|
||||
size = 0;
|
||||
BS->LocateHandle(ByProtocol, &(*fs)->proto, NULL, &size, NULL);
|
||||
uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &(*fs)->proto, NULL, &size, NULL);
|
||||
total += size;
|
||||
}
|
||||
if (total == 0) {
|
||||
|
@ -560,7 +565,7 @@ find_filesystems(EFI_HANDLE boot_handle)
|
|||
for(fs = fs_tab; *fs; fs++) {
|
||||
size = 0;
|
||||
|
||||
BS->LocateHandle(ByProtocol, &(*fs)->proto, NULL, &size, NULL);
|
||||
uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &(*fs)->proto, NULL, &size, NULL);
|
||||
if (size == 0) continue;
|
||||
|
||||
add_dev_tab(&(*fs)->proto, boot_handle, size, (*fs)->glue);
|
||||
|
|
27
fs/Makefile
27
fs/Makefile
|
@ -23,10 +23,15 @@
|
|||
# to use this program.
|
||||
#
|
||||
|
||||
include ../Make.defaults
|
||||
include ../Make.rules
|
||||
SRCDIR = .
|
||||
|
||||
VPATH = $(SRCDIR)
|
||||
|
||||
include $(SRCDIR)/../Make.defaults
|
||||
include $(SRCDIR)/../Make.rules
|
||||
|
||||
TOPDIR=$(SRCDIR)/..
|
||||
|
||||
TOPDIR=$(CDIR)/..
|
||||
|
||||
FILES=
|
||||
ifeq ($(CONFIG_localfs),y)
|
||||
|
@ -54,17 +59,13 @@ all: $(TARGET)
|
|||
# XXX: does not trigger recompile when changing filesystem selection
|
||||
# without doing make clean.
|
||||
#
|
||||
$(TARGET): check-filesystems $(TOPDIR)/Make.defaults $(FILES)
|
||||
$(LD) -r -o $@ $(FILES)
|
||||
$(TARGET): $(TOPDIR)/Make.defaults $(FILES)
|
||||
@if [ -z "$(FILES)" ]; then \
|
||||
echo "You need to define at least one filesystem in Make.defaults"; \
|
||||
exit 1; \
|
||||
fi
|
||||
$(LD) $(LD3264) -r -o $@ $(FILES)
|
||||
|
||||
clean:
|
||||
$(RM) -f $(TARGET) $(FILES)
|
||||
|
||||
check-filesystems:
|
||||
@if [ -n "$(FILES)" ]; then \
|
||||
exit 0; \
|
||||
else \
|
||||
echo "You need to define at least one filesystem in Make.defaults"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
|
|
17
fs/ext2fs.c
17
fs/ext2fs.c
|
@ -142,9 +142,9 @@ read_bytes(EFI_BLOCK_IO *blkio, UINT32 mediaid, UINTN offset, VOID *addr, UINTN
|
|||
return ret;
|
||||
}
|
||||
|
||||
DBG_PRT((L"readblock(%x, %d, %d, %d, %x)", blkio, mediaid, base, buffer_size, buffer));
|
||||
DBG_PRT((L"readblock(PTR_FMT ", %d, %ld, %d, " PTR_FMT ")", blkio, mediaid, base, buffer_size, buffer));
|
||||
|
||||
status = blkio->ReadBlocks(blkio, mediaid, base, buffer_size, buffer);
|
||||
status = uefi_call_wrapper(blkio->ReadBlocks, 5, blkio, mediaid, base, buffer_size, buffer);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"readblock(%d,%d)=%r", base, buffer_size, status));
|
||||
goto error;
|
||||
|
@ -866,13 +866,13 @@ ext2fs_install_one(EFI_HANDLE dev, VOID **intf)
|
|||
EFI_BLOCK_IO *blkio;
|
||||
ext2fs_t *ext2fs;
|
||||
|
||||
status = BS->HandleProtocol (dev, &Ext2FsProtocol, (VOID **)&ext2fs);
|
||||
status = uefi_call_wrapper(BS->HandleProtocol, 3, dev, &Ext2FsProtocol, (VOID **)&ext2fs);
|
||||
if (status == EFI_SUCCESS) {
|
||||
ERR_PRT((L"Warning: found existing %s protocol on device", FS_NAME));
|
||||
goto found;
|
||||
}
|
||||
|
||||
status = BS->HandleProtocol(dev, &BlockIoProtocol, (VOID **)&blkio);
|
||||
status = uefi_call_wrapper(BS->HandleProtocol, 3, dev, &BlockIoProtocol, (VOID **)&blkio);
|
||||
if (EFI_ERROR(status)) return EFI_INVALID_PARAMETER;
|
||||
|
||||
VERB_PRT(5,
|
||||
|
@ -903,7 +903,7 @@ ext2fs_install_one(EFI_HANDLE dev, VOID **intf)
|
|||
}
|
||||
|
||||
if (sb.s_magic != EXT2_SUPER_MAGIC) {
|
||||
DBG_PRT((L"bad magic 0x%x\n", sb.s_magic));
|
||||
DBG_PRT((L"bad magic "PTR_FMT"\n", sb.s_magic));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
|
@ -944,7 +944,7 @@ ext2fs_install(VOID)
|
|||
EFI_STATUS status;
|
||||
VOID *intf;
|
||||
|
||||
BS->LocateHandle(ByProtocol, &BlockIoProtocol, NULL, &size, NULL);
|
||||
uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &BlockIoProtocol, NULL, &size, NULL);
|
||||
if (size == 0) return EFI_UNSUPPORTED; /* no device found, oh well */
|
||||
|
||||
DBG_PRT((L"size=%d", size));
|
||||
|
@ -955,7 +955,8 @@ ext2fs_install(VOID)
|
|||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
status = BS->LocateHandle(ByProtocol, &BlockIoProtocol, NULL, &size, (VOID **)dev_tab);
|
||||
status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &BlockIoProtocol, NULL,
|
||||
&size, (VOID **)dev_tab);
|
||||
if (status != EFI_SUCCESS) {
|
||||
ERR_PRT((L"failed to get handles: %r", status));
|
||||
free(dev_tab);
|
||||
|
@ -984,7 +985,7 @@ ext2fs_uninstall(VOID)
|
|||
for(i=0; i < ndev; i++) {
|
||||
if (dev_tab[i].intf == NULL) continue;
|
||||
e2fs = FS_PRIVATE(dev_tab[i].intf);
|
||||
status = BS->UninstallProtocolInterface(e2fs->dev, &Ext2FsProtocol, dev_tab[i].intf);
|
||||
status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, e2fs->dev, &Ext2FsProtocol, dev_tab[i].intf);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"Uninstall %s error: %r", FS_NAME, status));
|
||||
continue;
|
||||
|
|
33
fs/localfs.c
33
fs/localfs.c
|
@ -1,6 +1,10 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
|
@ -61,7 +65,7 @@ static EFI_GUID LocalFsProtocol = LOCALFS_PROTOCOL;
|
|||
* let's be clean here
|
||||
*/
|
||||
typedef union {
|
||||
EFI_HANDLE *dev;
|
||||
EFI_HANDLE dev;
|
||||
localfs_t *intf;
|
||||
} dev_tab_t;
|
||||
|
||||
|
@ -94,7 +98,7 @@ localfs_open(localfs_interface_t *this, CHAR16 *name, UINTN *fd)
|
|||
|
||||
DBG_PRT((L"localfs_open on %s\n", name));
|
||||
|
||||
status = lfs->volume->Open(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);
|
||||
}
|
||||
|
@ -110,7 +114,7 @@ localfs_read(localfs_interface_t *this, UINTN fd, VOID *buf, UINTN *size)
|
|||
|
||||
lfs = FS_PRIVATE(this);
|
||||
|
||||
return lfs->volume->Read(LOCALFS_FD2F(fd), size, buf);
|
||||
return uefi_call_wrapper(lfs->volume->Read, 3, LOCALFS_FD2F(fd), size, buf);
|
||||
}
|
||||
|
||||
static EFI_STATUS
|
||||
|
@ -122,7 +126,7 @@ localfs_close(localfs_interface_t *this, UINTN fd)
|
|||
|
||||
lfs = FS_PRIVATE(this);
|
||||
|
||||
return lfs->volume->Close(LOCALFS_FD2F(fd));
|
||||
return uefi_call_wrapper(lfs->volume->Close, 1, LOCALFS_FD2F(fd));
|
||||
}
|
||||
|
||||
static EFI_STATUS
|
||||
|
@ -140,7 +144,7 @@ localfs_infosize(localfs_interface_t *this, UINTN fd, UINT64 *sz)
|
|||
|
||||
*sz = info->FileSize;
|
||||
|
||||
FreePool(info);
|
||||
uefi_call_wrapper(BS->FreePool, 1, info);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@ -154,7 +158,7 @@ localfs_seek(localfs_interface_t *this, UINTN fd, UINT64 newpos)
|
|||
|
||||
lfs = FS_PRIVATE(this);
|
||||
|
||||
return lfs->volume->SetPosition(LOCALFS_FD2F(fd), newpos);
|
||||
return uefi_call_wrapper(lfs->volume->SetPosition, 2, LOCALFS_FD2F(fd), newpos);
|
||||
}
|
||||
|
||||
static VOID
|
||||
|
@ -185,16 +189,16 @@ localfs_install_one(EFI_HANDLE dev, VOID **intf)
|
|||
EFI_FILE_IO_INTERFACE *volume;
|
||||
EFI_FILE_HANDLE volume_fh;
|
||||
|
||||
status = BS->HandleProtocol (dev, &LocalFsProtocol, (VOID **)&localfs);
|
||||
status = uefi_call_wrapper(BS->HandleProtocol, 3, dev, &LocalFsProtocol, (VOID **)&localfs);
|
||||
if (status == EFI_SUCCESS) {
|
||||
ERR_PRT((L"Warning: found existing %s protocol on device", FS_NAME));
|
||||
goto found;
|
||||
}
|
||||
|
||||
status = BS->HandleProtocol (dev, &FileSystemProtocol, (VOID **)&volume);
|
||||
status = uefi_call_wrapper(BS->HandleProtocol, 3, dev, &FileSystemProtocol, (VOID **)&volume);
|
||||
if (EFI_ERROR(status)) return EFI_INVALID_PARAMETER;
|
||||
|
||||
status = volume->OpenVolume(volume, &volume_fh);
|
||||
status = uefi_call_wrapper(volume->OpenVolume, 2, volume, &volume_fh);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"cannot open volume"));
|
||||
return status;
|
||||
|
@ -221,7 +225,7 @@ found:
|
|||
dp = DevicePathFromHandle(dev);
|
||||
str = DevicePathToStr(dp);
|
||||
Print(L"attached %s to %s\n", FS_NAME, str);
|
||||
FreePool(str);
|
||||
uefi_call_wrapper(BS->FreePool, 1, str);
|
||||
});
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
@ -235,7 +239,7 @@ localfs_install(VOID)
|
|||
EFI_STATUS status;
|
||||
VOID *intf;
|
||||
|
||||
BS->LocateHandle(ByProtocol, &FileSystemProtocol, NULL, &size, NULL);
|
||||
uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &FileSystemProtocol, NULL, &size, NULL);
|
||||
if (size == 0) return EFI_UNSUPPORTED; /* no device found, oh well */
|
||||
|
||||
DBG_PRT((L"size=%d", size));
|
||||
|
@ -245,8 +249,7 @@ localfs_install(VOID)
|
|||
ERR_PRT((L"failed to allocate handle table"));
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
status = BS->LocateHandle(ByProtocol, &FileSystemProtocol, NULL, &size, (VOID **)dev_tab);
|
||||
status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &FileSystemProtocol, NULL, &size, (VOID **)dev_tab);
|
||||
if (status != EFI_SUCCESS) {
|
||||
ERR_PRT((L"failed to get handles: %r", status));
|
||||
free(dev_tab);
|
||||
|
@ -275,7 +278,7 @@ localfs_uninstall(VOID)
|
|||
for(i=0; i < ndev; i++) {
|
||||
if (dev_tab[i].intf == NULL) continue;
|
||||
lfs = FS_PRIVATE(dev_tab[i].intf);
|
||||
status = BS->UninstallProtocolInterface(lfs->dev, &LocalFsProtocol, dev_tab[i].intf);
|
||||
status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, lfs->dev, &LocalFsProtocol, dev_tab[i].intf);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"Uninstall %s error: %r", FS_NAME, status));
|
||||
continue;
|
||||
|
@ -285,7 +288,7 @@ localfs_uninstall(VOID)
|
|||
dp = DevicePathFromHandle(lfs->dev);
|
||||
str = DevicePathToStr(dp);
|
||||
Print(L"uninstalled %s on %s\n", FS_NAME, str);
|
||||
FreePool(str);
|
||||
uefi_call_wrapper(BS->FreePool, 1, str);
|
||||
});
|
||||
free(dev_tab[i].intf);
|
||||
}
|
||||
|
|
174
fs/netfs.c
174
fs/netfs.c
|
@ -1,6 +1,11 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Copyright (C) 2001-2009 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Contributed by Jason Fleischli <jason.fleischli@hp.com>
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
|
@ -34,6 +39,13 @@
|
|||
|
||||
#define NETFS_DEFAULT_BUFSIZE 16*MB
|
||||
#define NETFS_DEFAULT_BUFSIZE_INC 8*MB
|
||||
#define NETFS_DEFAULT_BLOCKSIZE 1024 /* setting to zero is supposed to default the underlying */
|
||||
/* pxe implementation to largest blocksize supported,... */
|
||||
/* in reality on original older efi implementations its */
|
||||
/* never set causing the pxe transfer to timeout. */
|
||||
/* the spec defines the minimum supported blocksize default */
|
||||
/* to be 512 bytes... a bit extreme, 1024 should work for */
|
||||
/* everything */
|
||||
|
||||
#define NETFS_DEFAULT_SERVER_TYPE EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
|
||||
#define NETFS_FD_MAX 2
|
||||
|
@ -217,7 +229,7 @@ netfs_extract_ip(netfs_priv_state_t *nfs)
|
|||
if (pxe->Mode->RouteTableEntries>0)
|
||||
Memcpy(&nfs->gw_ip, &pxe->Mode->RouteTable[0].GwAddr, sizeof(EFI_IP_ADDRESS));
|
||||
|
||||
VERB_PRT(1, Print(L"PXE PxeDiscoverValid: %s\n", pxe->Mode->PxeDiscoverValid? L"Yes (PXE-aware DHCPD)" : L"No (Regular DHCPD)"));
|
||||
VERB_PRT(1, Print(L"PXE PxeDiscoverValid: %s\n", pxe->Mode->PxeDiscoverValid? L"Yes (PXE-aware DHCPD)\n" : L"No (Regular DHCPD)\n"));
|
||||
#if 0
|
||||
status = BS->HandleProtocol(dev, &PxeCallbackProtocol, (VOID **)&netfs_callback);
|
||||
status = LibInstallProtocolInterfaces(&dev, &PxeCallbackProtocol, &netfs_callback, NULL);
|
||||
|
@ -262,7 +274,7 @@ netfs_start(EFI_PXE_BASE_CODE *pxe)
|
|||
{
|
||||
EFI_STATUS status;
|
||||
|
||||
status = pxe->Start(pxe, FALSE);
|
||||
status = uefi_call_wrapper(pxe->Start, 2, pxe, FALSE);
|
||||
if (EFI_ERROR(status)) return status;
|
||||
|
||||
return pxe->Dhcp(pxe, FALSE);
|
||||
|
@ -275,7 +287,9 @@ netfs_open(netfs_interface_t *this, CHAR16 *name, UINTN *fd)
|
|||
netfs_fd_t *f;
|
||||
EFI_STATUS status;
|
||||
CHAR8 ascii_name[FILENAME_MAXLEN];
|
||||
UINTN blocksize = 0, prev_netbufsize;
|
||||
UINTN blocksize = NETFS_DEFAULT_BLOCKSIZE;
|
||||
UINTN prev_netbufsize, retries = 0;
|
||||
BOOLEAN server_provided_filesize = FALSE;
|
||||
|
||||
if (this == NULL || name == NULL || fd == NULL) return EFI_INVALID_PARAMETER;
|
||||
|
||||
|
@ -301,6 +315,7 @@ netfs_open(netfs_interface_t *this, CHAR16 *name, UINTN *fd)
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
f->netbuf_maxsize = NETFS_DEFAULT_BUFSIZE;
|
||||
f->netbuf_size = 0;
|
||||
|
||||
if (f->netbuf == NULL && netbuf_alloc(f) == -1) {
|
||||
netfs_fd_free(nfs, f);
|
||||
|
@ -311,58 +326,108 @@ netfs_open(netfs_interface_t *this, CHAR16 *name, UINTN *fd)
|
|||
|
||||
U2ascii(name, ascii_name, FILENAME_MAXLEN);
|
||||
|
||||
VERB_PRT(2, Print(L"downloading %a from %d.%d.%d.%d...", ascii_name,
|
||||
VERB_PRT(2, Print(L"downloading %a from %d.%d.%d.%d...\n", ascii_name,
|
||||
nfs->srv_ip.v4.Addr[0],
|
||||
nfs->srv_ip.v4.Addr[1],
|
||||
nfs->srv_ip.v4.Addr[2],
|
||||
nfs->srv_ip.v4.Addr[3]));
|
||||
retry:
|
||||
f->netbuf_size = f->netbuf_maxsize;
|
||||
if (retries == 2) {
|
||||
netfs_fd_free(nfs, f);
|
||||
VERB_PRT(2, Print(L"Failed: %r\n", status));
|
||||
return status;
|
||||
}
|
||||
|
||||
DBG_PRT((L"\nbefore netbuf:0x%lx netbuf_size=%ld\n", f->netbuf, f->netbuf_size));
|
||||
|
||||
/*
|
||||
* For EFI versions older than 14.61:
|
||||
* it seems like there is an EFI bug (or undocumented behavior) when the buffer size
|
||||
* is too small AND the blocksize parameter is NULL, i.e., used the largest possible.
|
||||
* In this case, Mtftp() never returns EFI_BUFFER_TOO_SMALL but EFI_TIMEOUT instead.
|
||||
* This is true for 1.02 and also 1.10 it seems. Here we set it to the minimal value (512).
|
||||
*
|
||||
* Also it seems like on a READ_FILE which returns EFI_BUFFER_TOO_SMALL, the buffersize
|
||||
* is NOT updated to reflect the required size for the next attempt.
|
||||
*
|
||||
* For EFI versions 14.61 and higher:
|
||||
* In case the buffer is too small AND the TFTP server reports the file size (see RFC 2349),
|
||||
* the f->netbuf_size will report the exact size for the buffer.
|
||||
/*
|
||||
* netboot bugfix SF tracker 2874380
|
||||
* EFI 1.10 spec
|
||||
* For read operations, the return data will be placed in the buffer specified by BufferPtr. If
|
||||
* BufferSize is too small to contain the entire downloaded file, then
|
||||
* EFI_BUFFER_TOO_SMALL will be returned and BufferSize will be set to zero or the size of
|
||||
* the requested file (the size of the requested file is only returned if the TFTP server supports TFTP
|
||||
* options). If BufferSize is large enough for the read operation, then BufferSize will be set to
|
||||
* the size of the downloaded file, and EFI_SUCCESS will be returned. Applications using the
|
||||
* PxeBc.Mtftp() services should use the get-file-size operations to determine the size of the
|
||||
* downloaded file prior to using the read-file operations—especially when downloading large
|
||||
* (greater than 64 MB) files—instead of making two calls to the read-file operation. Following this
|
||||
* recommendation will save time if the file is larger than expected and the TFTP server does not
|
||||
* support TFTP option extensions. Without TFTP option extension support, the client has to
|
||||
* download the entire file, counting and discarding the received packets, to determine the file size.
|
||||
* ...
|
||||
* For TFTP “get file size” operations, the size of the requested file or directory is returned in
|
||||
* BufferSize, and EFI_SUCCESS will be returned. If the TFTP server does not support options,
|
||||
* the file will be downloaded into a bit bucket and the length of the downloaded file will be returned.
|
||||
*/
|
||||
status = uefi_call_wrapper(nfs->pxe->Mtftp, 10,
|
||||
nfs->pxe,
|
||||
EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
|
||||
f->netbuf,
|
||||
FALSE,
|
||||
&(f->netbuf_size), // PXE writes size of file from server here
|
||||
&blocksize,
|
||||
&nfs->srv_ip,
|
||||
ascii_name,
|
||||
NULL,
|
||||
FALSE);
|
||||
/*
|
||||
* If options are not supported by this tftp server, according to the spec the file will be
|
||||
* downloaded into a bit bucket, the size calculated by efi fw and returned in the status
|
||||
* field of this call. YUK!!... in this case we will default to currently allocated max
|
||||
* if thats still not big enough it will be caught and increased following the read file attempt
|
||||
* then retried.
|
||||
* XXX need to research how this is handled or changed in the latest UEFI spec.
|
||||
*/
|
||||
if (status != EFI_SUCCESS) {
|
||||
f->netbuf_size = f->netbuf_maxsize;
|
||||
VERB_PRT(2, Print(L"setting default buffer size of %d for %a, no filesize recd from tftp server\n",
|
||||
f->netbuf_size, ascii_name));
|
||||
}
|
||||
|
||||
if (status == EFI_SUCCESS) {
|
||||
server_provided_filesize = TRUE;
|
||||
VERB_PRT(2, Print(L"received file size of %d for %a from tftp server.\n",
|
||||
f->netbuf_size, ascii_name));
|
||||
}
|
||||
|
||||
if (f->netbuf_size > f->netbuf_maxsize) { // we need a bigger buffer
|
||||
VERB_PRT(2, Print(L"allocated buffer too small, attempting to increase\n"));
|
||||
f->netbuf_maxsize += f->netbuf_size;
|
||||
free(f->netbuf);
|
||||
f->netbuf = NULL;
|
||||
if (netbuf_alloc(f) == -1) return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
/* paranoid catch any corner case missed */
|
||||
if (f->netbuf_size == 0) f->netbuf_size = f->netbuf_maxsize;
|
||||
|
||||
DBG_PRT((L"\nbefore read: netbuf:" PTR_FMT " netbuf_size=%d blocksize=%d\n",
|
||||
f->netbuf,
|
||||
f->netbuf_size,
|
||||
blocksize));
|
||||
|
||||
prev_netbufsize = f->netbuf_size;
|
||||
|
||||
status = nfs->pxe->Mtftp(nfs->pxe, EFI_PXE_BASE_CODE_TFTP_READ_FILE, f->netbuf, FALSE,
|
||||
&(f->netbuf_size),
|
||||
blocksize > 0 ? &blocksize : NULL,
|
||||
&nfs->srv_ip,
|
||||
ascii_name,
|
||||
NULL,
|
||||
FALSE);
|
||||
/* now try and download this file from the tftp server */
|
||||
status = uefi_call_wrapper(nfs->pxe->Mtftp, 10,
|
||||
nfs->pxe,
|
||||
EFI_PXE_BASE_CODE_TFTP_READ_FILE,
|
||||
f->netbuf,
|
||||
FALSE,
|
||||
&(f->netbuf_size),
|
||||
&blocksize,
|
||||
&nfs->srv_ip,
|
||||
ascii_name,
|
||||
NULL,
|
||||
FALSE);
|
||||
|
||||
DBG_PRT((L"after Mftp=%r netbuf:0x%lx netbuf_size=%ld blocksize=%ld\n",
|
||||
DBG_PRT((L"after: status=%r netbuf:" PTR_FMT " netbuf_size=%d blocksize=%d\n",
|
||||
status,
|
||||
f->netbuf,
|
||||
f->netbuf_size,
|
||||
blocksize));
|
||||
|
||||
if (status == EFI_TIMEOUT && blocksize == 0) {
|
||||
/*
|
||||
* XXX: if blocksize is not adjusted we could loop forever here
|
||||
*/
|
||||
//blocksize = 512;
|
||||
status = EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
/*
|
||||
* check if we need to increase our buffer size
|
||||
*/
|
||||
if (status == EFI_BUFFER_TOO_SMALL) {
|
||||
DBG_PRT((L"buffer too small, need netbuf_size=%d", f->netbuf_size));
|
||||
if ((status == EFI_TIMEOUT || status == EFI_BUFFER_TOO_SMALL) && !server_provided_filesize) {
|
||||
Print(L"buffer too small, need netbuf_size=%d\n", f->netbuf_size);
|
||||
/*
|
||||
* if the TFTP server supports TFTP options, then we should
|
||||
* get the required size. So we test to see if the size
|
||||
|
@ -374,16 +439,22 @@ retry:
|
|||
} else {
|
||||
/* we got an answer from the TFTP server, let's try it */
|
||||
f->netbuf_maxsize = f->netbuf_size;
|
||||
server_provided_filesize = TRUE;
|
||||
}
|
||||
free(f->netbuf);
|
||||
|
||||
f->netbuf = NULL; /* will force reallocation */
|
||||
|
||||
if (netbuf_alloc(f) == 0) goto retry;
|
||||
if (netbuf_alloc(f) == 0) {
|
||||
retries++;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* fall through in case of error */
|
||||
} else if (status == EFI_TIMEOUT) { //if just a simple timeout, buffers are good just retry
|
||||
VERB_PRT(2, Print(L"TFTP returned EFI_TIMEOUT ERROR... %d retries left.\n", (2 - retries)));
|
||||
retries++;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (status == EFI_SUCCESS) {
|
||||
/* start at the beginning of the file */
|
||||
f->netbuf_pos = 0;
|
||||
|
@ -627,7 +698,7 @@ netfs_query_layer(netfs_interface_t *this, UINT16 server_type, UINT16 layer, UIN
|
|||
|
||||
if (server_type == 0) server_type = find_pxe_server_type(nfs->pxe);
|
||||
|
||||
status = nfs->pxe->Discover(nfs->pxe, server_type, &layer, FALSE, 0);
|
||||
status = uefi_call_wrapper(nfs->pxe->Discover, 5, nfs->pxe, server_type, &layer, FALSE, 0);
|
||||
if(status == EFI_SUCCESS) {
|
||||
ascii2U(nfs->pxe->Mode->PxeReply.Dhcpv4.BootpBootFile, str, maxlen);
|
||||
}
|
||||
|
@ -680,13 +751,13 @@ netfs_install_one(EFI_HANDLE dev, VOID **intf)
|
|||
netfs_t *netfs;
|
||||
EFI_PXE_BASE_CODE *pxe;
|
||||
|
||||
status = BS->HandleProtocol (dev, &NetFsProtocol, (VOID **)&netfs);
|
||||
status = uefi_call_wrapper(BS->HandleProtocol, 3, dev, &NetFsProtocol, (VOID **)&netfs);
|
||||
if (status == EFI_SUCCESS) {
|
||||
ERR_PRT((L"Warning: found existing %s protocol on device", FS_NAME));
|
||||
goto found;
|
||||
}
|
||||
|
||||
status = BS->HandleProtocol (dev, &PxeBaseCodeProtocol, (VOID **)&pxe);
|
||||
status = uefi_call_wrapper(BS->HandleProtocol, 3, dev, &PxeBaseCodeProtocol, (VOID **)&pxe);
|
||||
if (EFI_ERROR(status)) return EFI_INVALID_PARAMETER;
|
||||
|
||||
|
||||
|
@ -727,7 +798,7 @@ netfs_install(VOID)
|
|||
EFI_STATUS status;
|
||||
VOID *intf;
|
||||
|
||||
BS->LocateHandle(ByProtocol, &PxeBaseCodeProtocol, NULL, &size, NULL);
|
||||
uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &PxeBaseCodeProtocol, NULL, &size, NULL);
|
||||
if (size == 0) return EFI_UNSUPPORTED; /* no device found, oh well */
|
||||
|
||||
DBG_PRT((L"size=%d", size));
|
||||
|
@ -738,7 +809,7 @@ netfs_install(VOID)
|
|||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
status = BS->LocateHandle(ByProtocol, &PxeBaseCodeProtocol, NULL, &size, (VOID **)dev_tab);
|
||||
status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &PxeBaseCodeProtocol, NULL, &size, (VOID **)dev_tab);
|
||||
if (status != EFI_SUCCESS) {
|
||||
ERR_PRT((L"failed to get handles: %r", status));
|
||||
free(dev_tab);
|
||||
|
@ -767,7 +838,7 @@ netfs_uninstall(VOID)
|
|||
for(i=0; i < ndev; i++) {
|
||||
if (dev_tab[i].intf == NULL) continue;
|
||||
nfs = FS_PRIVATE(dev_tab[i].intf);
|
||||
status = BS->UninstallProtocolInterface(nfs->dev, &NetFsProtocol, dev_tab[i].intf);
|
||||
status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, nfs->dev, &NetFsProtocol, dev_tab[i].intf);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"Uninstall %s error: %r", FS_NAME, status));
|
||||
continue;
|
||||
|
@ -780,7 +851,8 @@ netfs_uninstall(VOID)
|
|||
FreePool(str);
|
||||
});
|
||||
|
||||
if (nfs->pxe->Mode->Started == TRUE) nfs->pxe->Stop(nfs->pxe);
|
||||
if (nfs->pxe->Mode->Started == TRUE)
|
||||
uefi_call_wrapper(nfs->pxe->Stop, 1, nfs->pxe);
|
||||
|
||||
free(dev_tab[i].intf);
|
||||
}
|
||||
|
|
3
getopt.c
3
getopt.c
|
@ -25,7 +25,6 @@
|
|||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
|
||||
|
@ -36,7 +35,7 @@
|
|||
#define BADCH (INTN)'?'
|
||||
#define BADARG (INTN)':'
|
||||
|
||||
extern CHAR16 * StrChr(IN const CHAR16 *s, INT16 c);
|
||||
extern CHAR16 * StrChr(IN const CHAR16 *s, CHAR16 c);
|
||||
|
||||
CHAR16 *Optarg;
|
||||
INTN Optind = 1;
|
||||
|
|
40
glue_netfs.c
40
glue_netfs.c
|
@ -1,6 +1,10 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
|
@ -60,6 +64,19 @@ static CHAR16 netfs_default_path[FILENAME_MAXLEN];
|
|||
|
||||
static CHAR16 *hexa=L"0123456789ABCDEF";
|
||||
|
||||
static VOID
|
||||
convert_mac2hex(UINT8 *hw_addr,INTN l, CHAR16 *str)
|
||||
{
|
||||
UINTN i;
|
||||
|
||||
for (i=0 ; i < l; i++) {
|
||||
str[3*i] = hexa[(hw_addr[i] & 0xf0)>>4];
|
||||
str[3*i+1] = hexa[hw_addr[i] & 0x0f];
|
||||
str[3*i+2] = ':';
|
||||
}
|
||||
str[3*l-1]='\0';
|
||||
}
|
||||
|
||||
static VOID
|
||||
convert_ip2hex(UINT8 *ip, INTN l, CHAR16 *str)
|
||||
{
|
||||
|
@ -149,6 +166,8 @@ netfs_setdefaults(VOID *intf, config_file_t *config, CHAR16 *kname, UINTN maxlen
|
|||
set_var(VAR_NETFS_DOMAINAME, info.domainame);
|
||||
|
||||
if (info.using_pxe) {
|
||||
DBG_PRT((L"netfs_setdefaults: using_pxe"));
|
||||
|
||||
status = netfs->netfs_query_layer(netfs, 0, NETFS_CONFIG_LAYER, maxlen, config[0].fname);
|
||||
if (EFI_ERROR(status)) {
|
||||
StrnCpy(config[0].fname, NETFS_DEFAULT_CONFIG, maxlen-1);
|
||||
|
@ -165,13 +184,20 @@ netfs_setdefaults(VOID *intf, config_file_t *config, CHAR16 *kname, UINTN maxlen
|
|||
|
||||
# if defined(CONFIG_ia64)
|
||||
# define CONFIG_ARCH_EXTENSION L"-ia64.conf\0"
|
||||
# define EXTENSION_LENGTH 11
|
||||
# elif defined (CONFIG_ia32)
|
||||
# define CONFIG_ARCH_EXTENSION L"-ia64.conf\0"
|
||||
# define CONFIG_ARCH_EXTENSION L"-ia32.conf\0"
|
||||
# define EXTENSION_LENGTH 11
|
||||
# elif defined (CONFIG_x86_64)
|
||||
# define CONFIG_ARCH_EXTENSION L"-x86_64.conf\0"
|
||||
# define EXTENSION_LENGTH 13
|
||||
# else
|
||||
# error "You need to specfy your default arch config file"
|
||||
# endif
|
||||
|
||||
# define CONFIG_EXTENSION L".conf\0"
|
||||
|
||||
DBG_PRT((L"netfs_setdefaults: machine specific (!using_pxe)"));
|
||||
/*
|
||||
* will try machine/subnet specific files first.
|
||||
* the filenames are constructed based on the IP(v4) address
|
||||
|
@ -181,22 +207,28 @@ netfs_setdefaults(VOID *intf, config_file_t *config, CHAR16 *kname, UINTN maxlen
|
|||
StrnCpy(config[0].fname+8, CONFIG_EXTENSION, 6);
|
||||
|
||||
StrnCpy(config[1].fname, str, maxlen-1);
|
||||
StrnCpy(config[1].fname+6, CONFIG_ARCH_EXTENSION, 11);
|
||||
StrnCpy(config[1].fname+6, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH);
|
||||
|
||||
StrnCpy(config[2].fname, str, maxlen-1);
|
||||
StrnCpy(config[2].fname+6, CONFIG_EXTENSION, 6);
|
||||
|
||||
StrnCpy(config[3].fname, str, maxlen-1);
|
||||
StrnCpy(config[3].fname+4, CONFIG_ARCH_EXTENSION, 11);
|
||||
StrnCpy(config[3].fname+4, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH);
|
||||
|
||||
StrnCpy(config[4].fname, str, maxlen-1);
|
||||
StrnCpy(config[4].fname+4, CONFIG_EXTENSION, 6);
|
||||
|
||||
StrnCpy(config[5].fname, str, maxlen-1);
|
||||
StrnCpy(config[5].fname+2, CONFIG_ARCH_EXTENSION, 11);
|
||||
StrnCpy(config[5].fname+2, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH);
|
||||
|
||||
StrnCpy(config[6].fname, str, maxlen-1);
|
||||
StrnCpy(config[6].fname+2, CONFIG_EXTENSION, 6);
|
||||
|
||||
/* use the MAC address as a possible file name as well */
|
||||
convert_mac2hex(info.hw_addr,6,str);
|
||||
StrnCpy(config[7].fname, str, maxlen-1);
|
||||
StrnCpy(config[7].fname+17, CONFIG_EXTENSION, 6);
|
||||
|
||||
#else
|
||||
StrnCpy(config[0].fname, NETFS_DEFAULT_CONFIG, maxlen-1);
|
||||
config[0].fname[maxlen-1] = CHAR_NULL;
|
||||
|
|
|
@ -23,10 +23,15 @@
|
|||
# to use this program.
|
||||
#
|
||||
|
||||
include ../Make.defaults
|
||||
include ../Make.rules
|
||||
SRCDIR = .
|
||||
|
||||
VPATH = $(SRCDIR)
|
||||
|
||||
include $(SRCDIR)/../Make.defaults
|
||||
include $(SRCDIR)/../Make.rules
|
||||
|
||||
TOPDIR=$(SRCDIR)/..
|
||||
|
||||
TOPDIR=$(CDIR)/..
|
||||
|
||||
FILES=system.o config.o bzimage.o plain_loader.o gzip_loader.o gzip.o
|
||||
|
||||
|
@ -37,13 +42,13 @@ all: $(TARGET)
|
|||
system.o: rmswitch.h
|
||||
|
||||
rmswitch.h: bin_to_h.c rmswitch.S
|
||||
$(CC) -o bin_to_h bin_to_h.c
|
||||
$(AS) -o rmswitch.o rmswitch.S
|
||||
$(CC) -o bin_to_h $(SRCDIR)/bin_to_h.c
|
||||
$(AS) -o rmswitch.o $(SRCDIR)/rmswitch.S
|
||||
$(LD) -Ttext 0x0 -s --oformat binary -o rmswitch rmswitch.o
|
||||
./bin_to_h <rmswitch >rmswitch.h
|
||||
|
||||
$(TARGET): $(FILES)
|
||||
$(LD) -r -o $@ $(FILES)
|
||||
$(LD) $(LD3264) -r -o $@ $(FILES)
|
||||
|
||||
clean:
|
||||
$(RM) -f $(TARGET) $(FILES)
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
boot_params_t *param_start = NULL;
|
||||
UINTN param_size = 0;
|
||||
|
||||
UINTN kernel_size = 0x200000; /* 2M (largest x86 bzImage kernel image) */
|
||||
UINTN kernel_size = 0x400000; /* 4M (default x86 bzImage size limit) */
|
||||
|
||||
static INTN
|
||||
bzImage_probe(CHAR16 *kname)
|
||||
|
@ -47,7 +47,7 @@ bzImage_probe(CHAR16 *kname)
|
|||
DBG_PRT((L"probe_bzImage_boot()\n"));
|
||||
|
||||
if (!kname) {
|
||||
ERR_PRT((L"kname == %xh", kname));
|
||||
ERR_PRT((L"kname == " PTR_FMT, kname));
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ bzImage_probe(CHAR16 *kname)
|
|||
param_size = (bootsect[0x1F1] + 1) * 512;
|
||||
param_start = alloc(param_size, EfiLoaderData);
|
||||
|
||||
DBG_PRT((L"param_size=%d param_start=%x", param_size, param_start));
|
||||
DBG_PRT((L"param_size=%d param_start=" PTR_FMT, param_size, param_start));
|
||||
|
||||
if (!param_start) {
|
||||
ERR_PRT((L"Could not allocate %d bytes of setup data.",
|
||||
|
@ -141,7 +141,7 @@ bzImage_probe(CHAR16 *kname)
|
|||
|
||||
{
|
||||
UINT8 *c = ((UINT8 *)param_start)+514;
|
||||
DBG_PRT((L"param_start(c=%x): %c-%c-%c-%c",
|
||||
DBG_PRT((L"param_start(c=" PTR_FMT "): %c-%c-%c-%c",
|
||||
c, (CHAR16)c[0],(CHAR16) c[1], (CHAR16)c[2], (CHAR16)c[3]));
|
||||
}
|
||||
if (CompareMem(((UINT8 *)param_start) + 514, "HdrS", 4)) {
|
||||
|
@ -158,13 +158,38 @@ bzImage_probe(CHAR16 *kname)
|
|||
* Allocate memory for kernel.
|
||||
*/
|
||||
|
||||
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));
|
||||
}
|
||||
/*
|
||||
* Get correct address for kernel from header, if applicable & available.
|
||||
*/
|
||||
if ((param_start->s.hdr_major == 2) &&
|
||||
(param_start->s.hdr_minor >= 6) &&
|
||||
(param_start->s.kernel_start >= DEFAULT_KERNEL_START)) {
|
||||
kernel_start = (void *)param_start->s.kernel_start;
|
||||
VERB_PRT(3, Print(L"kernel header suggests kernel start at address "PTR_FMT"\n",
|
||||
kernel_start));
|
||||
}
|
||||
|
||||
kernel_load_address = NULL; /* allocate anywhere! */
|
||||
|
||||
if (alloc_kmem(kernel_start, EFI_SIZE_TO_PAGES(kernel_size)) != 0) {
|
||||
/*
|
||||
* 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)) != 0) {
|
||||
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: "PTR_FMT" kernel_size: %d loading at: "PTR_FMT"\n",
|
||||
kernel_start, kernel_size, kernel_load_address));
|
||||
|
||||
|
||||
/*
|
||||
* Now read the rest of the kernel image into memory.
|
||||
*/
|
||||
|
@ -172,7 +197,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);
|
||||
|
@ -200,7 +225,7 @@ bzImage_load(CHAR16 *kname, kdesc_t *kd)
|
|||
DBG_PRT((L"load_bzImage_boot()\n"));
|
||||
|
||||
if (!kname || !kd) {
|
||||
ERR_PRT((L"kname=0x%x kd=0x%x", kname, kd));
|
||||
ERR_PRT((L"kname=" PTR_FMT " kd=" PTR_FMT, kname, kd));
|
||||
free(param_start);
|
||||
param_start = NULL;
|
||||
param_size = 0;
|
||||
|
@ -210,7 +235,7 @@ bzImage_load(CHAR16 *kname, kdesc_t *kd)
|
|||
kd->kstart = kd->kentry = kernel_start;
|
||||
kd->kend = ((UINT8 *)kd->kstart) + kernel_size;
|
||||
|
||||
DBG_PRT((L"kstart=0x%x kentry=0x%x kend=0x%x\n", kd->kstart, kd->kentry, kd->kend));
|
||||
DBG_PRT((L"kstart=" PTR_FMT " kentry=" PTR_FMT " kend=" PTR_FMT "\n", kd->kstart, kd->kentry, kd->kend));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
35
ia32/gzip.c
35
ia32/gzip.c
|
@ -153,7 +153,7 @@ gzip_free(void *where)
|
|||
int
|
||||
fill_inbuf(void)
|
||||
{
|
||||
INTN expected, nread;
|
||||
UINTN expected, nread;
|
||||
EFI_STATUS status;
|
||||
|
||||
expected = nread = INBUFSIZE;
|
||||
|
@ -162,7 +162,9 @@ fill_inbuf(void)
|
|||
if (EFI_ERROR(status)) {
|
||||
error("elilo: Read failed");
|
||||
}
|
||||
#ifdef DEBUG_GZIP
|
||||
DBG_PRT((L"%s : read %d bytes of %d bytes\n", LD_NAME, nread, expected));
|
||||
#endif
|
||||
|
||||
insize = nread;
|
||||
inptr = 1;
|
||||
|
@ -277,7 +279,7 @@ analyze_chunks(void)
|
|||
* the relevant header information.
|
||||
*/
|
||||
int
|
||||
first_block (const char *buf, long blocksize)
|
||||
first_block (const unsigned char *buf, long blocksize)
|
||||
{
|
||||
Elf32_Ehdr *elf;
|
||||
Elf32_Phdr *phdrs;
|
||||
|
@ -297,13 +299,13 @@ first_block (const char *buf, long blocksize)
|
|||
phnum = elf->e_phnum;
|
||||
|
||||
VERB_PRT(3, {
|
||||
Print(L"Entry point 0x%lx\n", elf->e_entry);
|
||||
Print(L"Entry point "PTR_FMT"\n", elf->e_entry);
|
||||
Print(L"%d program headers\n", phnum);
|
||||
Print(L"%d segment headers\n", elf->e_shnum);
|
||||
});
|
||||
|
||||
if (offs + phnum * sizeof(*phdrs) > (unsigned) blocksize) {
|
||||
ERR_PRT((L"%s : ELF program headers not in first block (%ld)\n", LD_NAME, offs));
|
||||
ERR_PRT((L"%s : ELF program headers not in first block (%d)\n", LD_NAME, offs));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -345,15 +347,15 @@ first_block (const char *buf, long blocksize)
|
|||
|
||||
if (phdrs[i].p_type != PT_LOAD) {
|
||||
CHUNK_NO_LOAD(i); /* mark no load chunk */
|
||||
DBG_PRT((L"%s : skipping segment %ld\n", LD_NAME, i));
|
||||
DBG_PRT((L"%s : skipping segment %d\n", LD_NAME, i));
|
||||
continue;
|
||||
}
|
||||
|
||||
CHUNK_CAN_LOAD(i); /* mark no load chunk */
|
||||
|
||||
VERB_PRT(3,
|
||||
Print(L"\n%s : segment %ld vaddr [0x%lx-0x%lx] offset %ld filesz %ld "
|
||||
"memsz=%ld bss_sz=%ld\n",
|
||||
Print(L"\n%s : segment %d vaddr ["PTR_FMT"-"PTR_FMT"] offset %d filesz %d "
|
||||
"memsz=%d bss_sz=%d\n",
|
||||
LD_NAME, 1+i, chunks[i].addr, chunks[i].addr+phdrs[i].p_filesz,
|
||||
chunks[i].offset, chunks[i].size, memsz, chunks[i].bss_sz));
|
||||
|
||||
|
@ -364,12 +366,12 @@ first_block (const char *buf, long blocksize)
|
|||
}
|
||||
|
||||
if (low_addr & (EFI_PAGE_SIZE - 1)) {
|
||||
ERR_PRT((L"%s : low_addr not page aligned 0x%lx\n", LD_NAME, low_addr));
|
||||
ERR_PRT((L"%s : low_addr not page aligned "PTR_FMT"\n", LD_NAME, low_addr));
|
||||
goto error;
|
||||
}
|
||||
analyze_chunks();
|
||||
|
||||
DBG_PRT((L"%s : %d program headers entry=0x%lx\nlowest_addr=0x%lx highest_addr=0x%lx\n",
|
||||
DBG_PRT((L"%s : %d program headers entry=" PTR_FMT "\nlowest_addr="PTR_FMT" highest_addr="PTR_FMT"\n",
|
||||
LD_NAME,
|
||||
phnum, kernel_entry, low_addr, max_addr));
|
||||
|
||||
|
@ -384,9 +386,9 @@ first_block (const char *buf, long blocksize)
|
|||
|
||||
/* allocate memory for the kernel */
|
||||
if (alloc_kmem((void *)low_addr, pages) == -1) {
|
||||
ERR_PRT((L"%s : AllocatePages(%d, 0x%lx) for kernel failed\n",
|
||||
ERR_PRT((L"%s : AllocatePages(%d, "PTR_FMT") for kernel failed\n",
|
||||
LD_NAME, pages, low_addr));
|
||||
ERR_PRT((L"%s : Could not load kernel at 0x%lx\n", LD_NAME, low_addr));
|
||||
ERR_PRT((L"%s : Could not load kernel at "PTR_FMT"\n", LD_NAME, low_addr));
|
||||
ERR_PRT((L"%s : Bailing\n", LD_NAME));
|
||||
goto error;
|
||||
}
|
||||
|
@ -430,12 +432,13 @@ flush_window(void)
|
|||
static const CHAR8 helicopter[4] = { '|' , '/' , '-' , '\\' };
|
||||
static UINTN heli_count;
|
||||
struct segment *cp;
|
||||
char *src, *dst;
|
||||
unsigned char *src, *dst;
|
||||
long cnt;
|
||||
|
||||
if (!outcnt) return;
|
||||
|
||||
DBG_PRT((L"%s : flush_window outnct=%d file_offset=%ld\n", LD_NAME, outcnt, file_offset));
|
||||
#ifdef DEBUG_GZIP
|
||||
DBG_PRT((L"%s : flush_window outnct=%d file_offset=%d\n", LD_NAME, outcnt, file_offset));
|
||||
#endif
|
||||
|
||||
Print(L"%c\b",helicopter[heli_count++%4]);
|
||||
|
||||
|
@ -468,7 +471,7 @@ tail:
|
|||
file_offset += skip;
|
||||
outcnt -= skip;
|
||||
}
|
||||
dst = (char *)cp->addr + (file_offset - cp->offset);
|
||||
dst = (unsigned char *)cp->addr + (file_offset - cp->offset);
|
||||
cnt = cp->offset + cp->size - file_offset;
|
||||
if (cnt > outcnt)
|
||||
cnt = outcnt;
|
||||
|
@ -482,7 +485,7 @@ tail:
|
|||
/* See if we are at the end of this chunk */
|
||||
if (file_offset == cp->offset + cp->size) {
|
||||
if (cp->bss_sz) {
|
||||
dst = (char *)cp->addr + cp->size;
|
||||
dst = (unsigned char *)cp->addr + cp->size;
|
||||
Memset(dst, 0, cp->bss_sz);
|
||||
}
|
||||
nextchunk();
|
||||
|
|
|
@ -111,7 +111,7 @@ load_elf(fops_fd_t fd, kdesc_t *kd)
|
|||
}
|
||||
VERB_PRT(3, {
|
||||
Print(L"ELF Header information: \n");
|
||||
Print(L"\tEntry point 0x%x\n", (ehdr.e_entry & PADDR_MASK));
|
||||
Print(L"\tEntry point "PTR_FMT"\n", (ehdr.e_entry & PADDR_MASK));
|
||||
Print(L"\t%d program headers\n", ehdr.e_phnum);
|
||||
Print(L"\t%d segment headers\n", ehdr.e_shnum);
|
||||
});
|
||||
|
@ -145,8 +145,8 @@ load_elf(fops_fd_t fd, kdesc_t *kd)
|
|||
paddr = (phdrs[i].p_paddr & PADDR_MASK);
|
||||
memsz = phdrs[i].p_memsz;
|
||||
|
||||
DBG_PRT((L"Phdr %d paddr [0x%x-0x%x] offset 0x%x"
|
||||
" filesz 0x%x memsz=0x%x bss_sz=0x%x p_type=0x%x\n",
|
||||
DBG_PRT((L"Phdr %d paddr ["PTR_FMT"-"PTR_FMT"] offset "PTR_FMT""
|
||||
" filesz "PTR_FMT" memsz="PTR_FMT" bss_sz="PTR_FMT" p_type="PTR_FMT"\n",
|
||||
1+i, paddr, paddr+phdrs[i].p_filesz, phdrs[i].p_offset,
|
||||
phdrs[i].p_filesz, memsz,
|
||||
(memsz - phdrs[i].p_filesz), phdrs[i].p_type));
|
||||
|
@ -160,7 +160,7 @@ load_elf(fops_fd_t fd, kdesc_t *kd)
|
|||
}
|
||||
|
||||
if ((UINTN)low_addr & (EFI_PAGE_SIZE - 1)) {
|
||||
ERR_PRT((L"%s : kernel low address 0x%x not page aligned\n",
|
||||
ERR_PRT((L"%s : kernel low address "PTR_FMT" not page aligned\n",
|
||||
LD_NAME, low_addr));
|
||||
goto out;
|
||||
}
|
||||
|
@ -176,16 +176,16 @@ load_elf(fops_fd_t fd, kdesc_t *kd)
|
|||
kd->kentry = (VOID *)(ehdr.e_entry & PADDR_MASK);
|
||||
|
||||
VERB_PRT(3, {
|
||||
Print(L"Lowest PhysAddr: 0x%x\nTotalMemSize:%d bytes (%d pages)\n",
|
||||
Print(L"Lowest PhysAddr: "PTR_FMT"\nTotalMemSize:%d bytes (%d pages)\n",
|
||||
low_addr, total_size, pages);
|
||||
Print(L"Kernel entry @ 0x%x\n", kd->kentry);
|
||||
Print(L"Kernel entry @ "PTR_FMT"\n", kd->kentry);
|
||||
});
|
||||
|
||||
/* now allocate memory for the kernel at the exact requested spot */
|
||||
if (alloc_kmem(low_addr, pages) == -1) {
|
||||
ERR_PRT((L"%s : AllocatePages(%d, 0x%lx) for kernel failed\n",
|
||||
ERR_PRT((L"%s : AllocatePages(%d, "PTR_FMT") for kernel failed\n",
|
||||
LD_NAME, pages, low_addr));
|
||||
ERR_PRT((L"%s : Could not alloc %d pages for the kernel at 0x%lx "
|
||||
ERR_PRT((L"%s : Could not alloc %d pages for the kernel at "PTR_FMT""
|
||||
" and relocation is not not been implemented!\n",
|
||||
LD_NAME, pages, low_addr));
|
||||
goto load_abort;
|
||||
|
@ -206,7 +206,7 @@ load_elf(fops_fd_t fd, kdesc_t *kd)
|
|||
if (phdrs[i].p_type != PT_LOAD)
|
||||
continue;
|
||||
|
||||
VERB_PRT(3, Print(L"poffs: 0x%x (phdrs[%d].p_offset)\n",
|
||||
VERB_PRT(3, Print(L"poffs: "PTR_FMT" (phdrs[%d].p_offset)\n",
|
||||
phdrs[i].p_offset, i));
|
||||
|
||||
filesz = phdrs[i].p_filesz;
|
||||
|
@ -221,9 +221,9 @@ load_elf(fops_fd_t fd, kdesc_t *kd)
|
|||
|
||||
VERB_PRT(4, {
|
||||
Print(L"\nHeader #%d\n", i);
|
||||
Print(L"Offset in file 0x%x\n", phdrs[i].p_offset);
|
||||
Print(L"Physical addr 0x%x\n", low_addr);
|
||||
Print(L"BSS size 0x%x bytes\n", bss_sz);
|
||||
Print(L"Offset in file "PTR_FMT"\n", phdrs[i].p_offset);
|
||||
Print(L"Physical addr "PTR_FMT"\n", low_addr);
|
||||
Print(L"BSS size %d bytes\n", bss_sz);
|
||||
});
|
||||
|
||||
/*
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
#define ELILO_ARCH "IA-32" /* ASCII string */
|
||||
#define PADDR_MASK 0xfffffff
|
||||
|
||||
#define INITRD_START (15*1024*1024)
|
||||
#define DEFAULT_KERNEL_START 0x100000
|
||||
|
||||
/* for now use library versions */
|
||||
#define Memset(a,v,n) SetMem((a),(n),(v))
|
||||
#define Memcpy(a,b,n) CopyMem((a),(b),(n))
|
||||
|
@ -59,6 +62,26 @@
|
|||
*/
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/* Definitions for converting EFI memory map to E820 map for Linux
|
||||
* These definitions are from include/linux/asm-x86/e820.h
|
||||
* The structure ia32_boot_params below is updated to accommodate E820 map
|
||||
* EFI memory map is converted to E820 map in this structure and passed
|
||||
* to Linux. This way the OS does not need to do the conversion.
|
||||
*/
|
||||
|
||||
#define E820_RAM 1
|
||||
#define E820_RESERVED 2
|
||||
#define E820_ACPI 3
|
||||
#define E820_NVS 4
|
||||
#define E820_MAX 128
|
||||
|
||||
struct e820entry {
|
||||
UINT64 addr; /* start of memory segment */
|
||||
UINT64 size; /* size of memory segment */
|
||||
UINT32 type; /* type of memory segment */
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef union ia32_boot_params {
|
||||
UINT8 raw[0x2000];
|
||||
struct {
|
||||
|
@ -155,7 +178,7 @@ typedef union ia32_boot_params {
|
|||
|
||||
/* EFI boot loader signature. */
|
||||
/* 0x1C0 */ UINT8 efi_loader_sig[4]; /* LDR */
|
||||
#define EFI_LOADER_SIG "EFIL"
|
||||
#define EFI_LOADER_SIG_IA32 "EL32"
|
||||
|
||||
/* Address of the EFI system table. */
|
||||
/* 0x1C4 */ UINT32 efi_sys_tbl; /* LDR */
|
||||
|
@ -177,7 +200,9 @@ typedef union ia32_boot_params {
|
|||
/* Available contiguous extended memory in KB. */
|
||||
/* 0x1E0 */ UINT32 alt_mem_k; /* LDR */
|
||||
|
||||
/* 0x1E4 */ UINT8 unused_5[0x0D]; /* unused */
|
||||
/* 0x1E4 */ UINT32 unused_51; /* unused */
|
||||
/* 0x1E8 */ UINT8 e820_nrmap;
|
||||
/* 0x1E9 */ UINT32 unused_52[2]; /* unused */
|
||||
|
||||
/* Size of setup code in sectors (1 sector == 512 bytes). */
|
||||
/* 0x1F1 */ UINT8 setup_sectors; /* BLD */
|
||||
|
@ -258,6 +283,8 @@ typedef union ia32_boot_params {
|
|||
/* 0x226 */ UINT16 unused_7; /* LDR */
|
||||
|
||||
/* 0x228 */ UINT32 cmdline_addr; /* LDR */
|
||||
/* 0x22C */ UINT32 unused_8[41];
|
||||
/* 0x2D0 */ UINT8 e820_map[2560];
|
||||
} s;
|
||||
} boot_params_t;
|
||||
#pragma pack()
|
||||
|
@ -275,11 +302,17 @@ typedef union ia32_boot_params {
|
|||
UINT8 *t = (UINT8 *)(to); \
|
||||
UINT8 *f = (UINT8 *)(from); \
|
||||
UINTN n = cnt; \
|
||||
if (t && f && n) { \
|
||||
while (n--) { \
|
||||
*t++ = *f++; \
|
||||
} \
|
||||
} \
|
||||
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--; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MEMSET(ptr, size, val) { \
|
||||
|
@ -314,6 +347,7 @@ extern UINTN kernel_size;
|
|||
|
||||
extern VOID *initrd_start;
|
||||
extern UINTN initrd_size;
|
||||
extern VOID *kernel_load_address;
|
||||
|
||||
extern dt_addr_t gdt_addr;
|
||||
extern dt_addr_t idt_addr;
|
||||
|
@ -333,19 +367,31 @@ extern INTN ia32_use_legacy_free_boot();
|
|||
static inline void
|
||||
start_kernel(VOID *kentry, boot_params_t *bp)
|
||||
{
|
||||
UINT32 temp;
|
||||
|
||||
/*
|
||||
* Disable interrupts.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
if (bp->s.initrd_start) {
|
||||
MEMCPY(15 * 1024 * 1024, bp->s.initrd_start, bp->s.initrd_size);
|
||||
bp->s.initrd_start = 15 * 1024 * 1024;
|
||||
}
|
||||
/*
|
||||
* Copy boot sector, setup data and command line
|
||||
* to final resting place. We need to copy
|
||||
|
@ -354,6 +400,9 @@ start_kernel(VOID *kentry, boot_params_t *bp)
|
|||
|
||||
MEMCPY(high_base_mem, bp, 0x4000);
|
||||
|
||||
bp = (boot_params_t *)high_base_mem;
|
||||
bp->s.cmdline_addr = high_base_mem + bp->s.cmdline_offset;
|
||||
|
||||
/*
|
||||
* Initialize Linux GDT.
|
||||
*/
|
||||
|
|
316
ia32/system.c
316
ia32/system.c
|
@ -97,7 +97,10 @@ 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;
|
||||
|
@ -131,21 +134,27 @@ sysdeps_initrd_get_addr(kdesc_t *kd, memdesc_t *imem)
|
|||
DBG_PRT((L"initrd_get_addr()\n"));
|
||||
|
||||
if (!kd || !imem) {
|
||||
ERR_PRT((L"kd=0x%x imem=0x%x", kd, imem));
|
||||
ERR_PRT((L"kd=" PTR_FMT " imem=" PTR_FMT, kd, imem));
|
||||
return -1;
|
||||
}
|
||||
|
||||
VERB_PRT(3, Print(L"kstart=0x%x kentry=0x%x kend=0x%x\n",
|
||||
VERB_PRT(3, Print(L"kstart=" PTR_FMT " kentry=" PTR_FMT " kend=" PTR_FMT "\n",
|
||||
kd->kstart, kd->kentry, kd->kend));
|
||||
|
||||
imem->start_addr = kd->kend;
|
||||
|
||||
VERB_PRT(3, Print(L"initrd start_addr=0x%x pgcnt=%d\n",
|
||||
VERB_PRT(3, Print(L"initrd start_addr=" PTR_FMT " pgcnt=%d\n",
|
||||
imem->start_addr, imem->pgcnt));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VOID *
|
||||
sysdeps_checkfix_initrd(VOID *start_addr, memdesc_t *imem)
|
||||
{
|
||||
return start_addr;
|
||||
}
|
||||
|
||||
VOID
|
||||
sysdeps_free_boot_params(boot_params_t *bp)
|
||||
{
|
||||
|
@ -156,6 +165,277 @@ sysdeps_free_boot_params(boot_params_t *bp)
|
|||
free_memmap(&md);
|
||||
}
|
||||
|
||||
static VOID find_bits(unsigned long mask, UINT8 *first, UINT8* len) {
|
||||
unsigned char bit_pos = 0, bit_len = 0;
|
||||
*first =0;
|
||||
*len = 0;
|
||||
if (mask == 0)
|
||||
return;
|
||||
while (!(mask & 0x1)) {
|
||||
mask = mask >> 1;
|
||||
bit_pos++;
|
||||
}
|
||||
while (mask & 0x1) {
|
||||
mask = mask >> 1;
|
||||
bit_len++;
|
||||
}
|
||||
*first = bit_pos;
|
||||
*len = bit_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get video information.
|
||||
*/
|
||||
static INTN get_video_info(boot_params_t * bp) {
|
||||
EFI_GUID GopProtocol = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop_interface;
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Gop_info;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Gop_mode = NULL;
|
||||
EFI_HANDLE *Gop_handle = NULL;
|
||||
EFI_STATUS efi_status;
|
||||
UINTN size = 0;
|
||||
UINTN size1;
|
||||
UINT8 i;
|
||||
|
||||
efi_status = uefi_call_wrapper(
|
||||
BS->LocateHandle,
|
||||
5,
|
||||
ByProtocol,
|
||||
&GopProtocol,
|
||||
NULL,
|
||||
&size,
|
||||
(VOID **)Gop_handle);
|
||||
|
||||
if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL) {
|
||||
Print(L"EFI returned no GoP handle, No Graphics Output Device?\n");
|
||||
Print(L"--Elilo will try to default to console text mode.\n");
|
||||
return -1;
|
||||
}
|
||||
Gop_handle = alloc(size, 0);
|
||||
efi_status = uefi_call_wrapper(
|
||||
BS->LocateHandle,
|
||||
5,
|
||||
ByProtocol,
|
||||
&GopProtocol,
|
||||
NULL,
|
||||
&size,
|
||||
(VOID **)Gop_handle);
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
ERR_PRT((L"LocateHandle GopProtocol failed."));
|
||||
free(Gop_handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=0; i < size/sizeof(EFI_HANDLE); i++) {
|
||||
Gop_handle += i;
|
||||
efi_status = uefi_call_wrapper(
|
||||
BS->HandleProtocol,
|
||||
3,
|
||||
*Gop_handle,
|
||||
&GopProtocol,
|
||||
(VOID **) &Gop_interface);
|
||||
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
continue;
|
||||
}
|
||||
Gop_mode = Gop_interface->Mode;
|
||||
efi_status = uefi_call_wrapper(
|
||||
Gop_interface->QueryMode,
|
||||
4,
|
||||
Gop_interface,
|
||||
Gop_mode->Mode,
|
||||
&size1,
|
||||
&Gop_info);
|
||||
if (!EFI_ERROR(efi_status))
|
||||
break;
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (EFI_ERROR(efi_status) || i > (size/sizeof(EFI_HANDLE))) {
|
||||
ERR_PRT((L"HandleProtocol GopProtocol failed."));
|
||||
free(Gop_handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bp->s.is_vga = 0x70;
|
||||
bp->s.orig_cursor_col = 0;
|
||||
bp->s.orig_cursor_row = 0;
|
||||
bp->s.orig_video_page = 0;
|
||||
bp->s.orig_video_mode = 0;
|
||||
bp->s.orig_video_cols = 0;
|
||||
bp->s.orig_video_rows = 0;
|
||||
bp->s.orig_ega_bx = 0;
|
||||
bp->s.orig_video_points = 0;
|
||||
|
||||
bp->s.lfb_width = Gop_info->HorizontalResolution;
|
||||
bp->s.lfb_height = Gop_info->VerticalResolution;
|
||||
bp->s.lfb_base = Gop_mode->FrameBufferBase;
|
||||
bp->s.lfb_size = Gop_mode->FrameBufferSize;
|
||||
bp->s.lfb_pages = 1;
|
||||
bp->s.vesa_seg = 0;
|
||||
bp->s.vesa_off = 0;
|
||||
if (Gop_info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
|
||||
bp->s.lfb_depth = 32;
|
||||
bp->s.lfb_red_size = 8;
|
||||
bp->s.lfb_red_pos = 0;
|
||||
bp->s.lfb_green_size = 8;
|
||||
bp->s.lfb_green_pos = 8;
|
||||
bp->s.lfb_blue_size = 8;
|
||||
bp->s.lfb_blue_pos = 16;
|
||||
bp->s.lfb_rsvd_size = 8;
|
||||
bp->s.lfb_rsvd_pos = 24;
|
||||
bp->s.lfb_line_len = Gop_info->PixelsPerScanLine * 4;
|
||||
|
||||
} else if (Gop_info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
|
||||
bp->s.lfb_depth = 32;
|
||||
bp->s.lfb_red_size = 8;
|
||||
bp->s.lfb_red_pos = 16;
|
||||
bp->s.lfb_green_size = 8;
|
||||
bp->s.lfb_green_pos = 8;
|
||||
bp->s.lfb_blue_size = 8;
|
||||
bp->s.lfb_blue_pos = 0;
|
||||
bp->s.lfb_rsvd_size = 8;
|
||||
bp->s.lfb_rsvd_pos = 24;
|
||||
bp->s.lfb_line_len = Gop_info->PixelsPerScanLine * 4;
|
||||
} else if (Gop_info->PixelFormat == PixelBitMask) {
|
||||
find_bits(Gop_info->PixelInformation.RedMask,
|
||||
&bp->s.lfb_red_pos, &bp->s.lfb_red_size);
|
||||
find_bits(Gop_info->PixelInformation.GreenMask,
|
||||
&bp->s.lfb_green_pos, &bp->s.lfb_green_size);
|
||||
find_bits(Gop_info->PixelInformation.BlueMask,
|
||||
&bp->s.lfb_blue_pos, &bp->s.lfb_blue_size);
|
||||
find_bits(Gop_info->PixelInformation.ReservedMask,
|
||||
&bp->s.lfb_rsvd_pos, &bp->s.lfb_rsvd_size);
|
||||
bp->s.lfb_depth = bp->s.lfb_red_size + bp->s.lfb_green_size +
|
||||
bp->s.lfb_blue_size + bp->s.lfb_rsvd_size;
|
||||
bp->s.lfb_line_len = (Gop_info->PixelsPerScanLine * bp->s.lfb_depth) / 8;
|
||||
} else {
|
||||
bp->s.lfb_depth = 4;
|
||||
bp->s.lfb_red_size = 0;
|
||||
bp->s.lfb_red_pos = 0;
|
||||
bp->s.lfb_green_size = 0;
|
||||
bp->s.lfb_green_pos = 0;
|
||||
bp->s.lfb_blue_size = 0;
|
||||
bp->s.lfb_blue_pos = 0;
|
||||
bp->s.lfb_rsvd_size = 0;
|
||||
bp->s.lfb_rsvd_pos = 0;
|
||||
bp->s.lfb_line_len = bp->s.lfb_width / 2;
|
||||
}
|
||||
return 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
|
||||
*/
|
||||
|
||||
/* Add a memory region to the e820 map */
|
||||
static void add_memory_region (struct e820entry *e820_map,
|
||||
int *e820_nr_map,
|
||||
UINT64 start,
|
||||
UINT64 size,
|
||||
UINT32 type)
|
||||
{
|
||||
int x = *e820_nr_map;
|
||||
|
||||
if (x == E820_MAX) {
|
||||
Print(L"Too many entries in the memory map!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((x > 0) && e820_map[x-1].addr + e820_map[x-1].size == start
|
||||
&& e820_map[x-1].type == type)
|
||||
e820_map[x-1].size += size;
|
||||
else {
|
||||
e820_map[x].addr = start;
|
||||
e820_map[x].size = size;
|
||||
e820_map[x].type = type;
|
||||
(*e820_nr_map)++;
|
||||
}
|
||||
}
|
||||
|
||||
void fill_e820map(boot_params_t *bp, mmap_desc_t *mdesc)
|
||||
{
|
||||
int nr_map, e820_nr_map = 0, i;
|
||||
UINT64 start, end, size;
|
||||
EFI_MEMORY_DESCRIPTOR *md, *p;
|
||||
struct e820entry *e820_map;
|
||||
|
||||
nr_map = mdesc->map_size/mdesc->desc_size;
|
||||
e820_map = (struct e820entry *)bp->s.e820_map;
|
||||
|
||||
for (i = 0, p = mdesc->md; i < nr_map; i++)
|
||||
{
|
||||
md = p;
|
||||
switch (md->Type) {
|
||||
case EfiACPIReclaimMemory:
|
||||
add_memory_region(e820_map, &e820_nr_map,
|
||||
md->PhysicalStart,
|
||||
md->NumberOfPages << EFI_PAGE_SHIFT,
|
||||
E820_ACPI);
|
||||
break;
|
||||
case EfiRuntimeServicesCode:
|
||||
case EfiRuntimeServicesData:
|
||||
case EfiReservedMemoryType:
|
||||
case EfiMemoryMappedIO:
|
||||
case EfiMemoryMappedIOPortSpace:
|
||||
case EfiUnusableMemory:
|
||||
case EfiPalCode:
|
||||
add_memory_region(e820_map, &e820_nr_map,
|
||||
md->PhysicalStart,
|
||||
md->NumberOfPages << EFI_PAGE_SHIFT,
|
||||
E820_RESERVED);
|
||||
break;
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory:
|
||||
start = md->PhysicalStart;
|
||||
size = md->NumberOfPages << EFI_PAGE_SHIFT;
|
||||
end = start + size;
|
||||
/* Fix up for BIOS that claims RAM in 640K-1MB region */
|
||||
if (start < 0x100000ULL && end > 0xA0000ULL) {
|
||||
if (start < 0xA0000ULL) {
|
||||
/* start < 640K
|
||||
* set memory map from start to 640K
|
||||
*/
|
||||
add_memory_region(e820_map,
|
||||
&e820_nr_map,
|
||||
start,
|
||||
0xA0000ULL-start,
|
||||
E820_RAM);
|
||||
}
|
||||
if (end <= 0x100000ULL)
|
||||
continue;
|
||||
/* end > 1MB
|
||||
* set memory map avoiding 640K to 1MB hole
|
||||
*/
|
||||
start = 0x100000ULL;
|
||||
size = end - start;
|
||||
}
|
||||
add_memory_region(e820_map, &e820_nr_map,
|
||||
start, size, E820_RAM);
|
||||
break;
|
||||
case EfiACPIMemoryNVS:
|
||||
add_memory_region(e820_map, &e820_nr_map,
|
||||
md->PhysicalStart,
|
||||
md->NumberOfPages << EFI_PAGE_SHIFT,
|
||||
E820_NVS);
|
||||
break;
|
||||
default:
|
||||
/* We should not hit this case */
|
||||
add_memory_region(e820_map, &e820_nr_map,
|
||||
md->PhysicalStart,
|
||||
md->NumberOfPages << EFI_PAGE_SHIFT,
|
||||
E820_RESERVED);
|
||||
break;
|
||||
}
|
||||
p = NextMemoryDescriptor(p, mdesc->desc_size);
|
||||
}
|
||||
bp->s.e820_nrmap = e820_nr_map;
|
||||
}
|
||||
|
||||
/*
|
||||
* IA-32 specific boot parameters initialization routine
|
||||
*/
|
||||
|
@ -177,7 +457,7 @@ sysdeps_create_boot_params(
|
|||
DBG_PRT((L"fill_boot_params()\n"));
|
||||
|
||||
if (!bp || !cmdline || !initrd || !cookie) {
|
||||
ERR_PRT((L"bp=0x%x cmdline=0x%x initrd=0x%x cookie=0x%x",
|
||||
ERR_PRT((L"bp=" PTR_FMT " cmdline=" PTR_FMT " initrd=" PTR_FMT " cookie=" PTR_FMT,
|
||||
bp, cmdline, initrd, cookie));
|
||||
|
||||
if (param_start != NULL) {
|
||||
|
@ -197,9 +477,6 @@ sysdeps_create_boot_params(
|
|||
*/
|
||||
if (param_start != NULL) {
|
||||
CopyMem(bp, param_start, 0x2000);
|
||||
free(param_start);
|
||||
param_start = NULL;
|
||||
param_size = 0;
|
||||
}
|
||||
/*
|
||||
* Save off our header revision information.
|
||||
|
@ -213,9 +490,11 @@ sysdeps_create_boot_params(
|
|||
bp->s.unused_2 = 0;
|
||||
ZeroMem(bp->s.unused_3, sizeof bp->s.unused_3);
|
||||
ZeroMem(bp->s.unused_4, sizeof bp->s.unused_4);
|
||||
ZeroMem(bp->s.unused_5, sizeof bp->s.unused_5);
|
||||
ZeroMem(&bp->s.unused_51, sizeof bp->s.unused_51);
|
||||
ZeroMem(bp->s.unused_52, sizeof bp->s.unused_52);
|
||||
bp->s.unused_6 = 0;
|
||||
bp->s.unused_7 = 0;
|
||||
ZeroMem(bp->s.unused_8, sizeof bp->s.unused_8);
|
||||
|
||||
/*
|
||||
* Tell kernel this was loaded by an advanced loader type.
|
||||
|
@ -262,7 +541,7 @@ sysdeps_create_boot_params(
|
|||
* Initial RAMdisk and root device stuff.
|
||||
*/
|
||||
|
||||
DBG_PRT((L"initrd->start_addr=0x%x initrd->pgcnt=%d\n",
|
||||
DBG_PRT((L"initrd->start_addr=" PTR_FMT " initrd->pgcnt=%d\n",
|
||||
initrd->start_addr, initrd->pgcnt));
|
||||
|
||||
/* These RAMdisk flags are not needed, just zero them. */
|
||||
|
@ -310,7 +589,7 @@ sysdeps_create_boot_params(
|
|||
/*
|
||||
* EFI loader signature
|
||||
*/
|
||||
CopyMem(bp->s.efi_loader_sig, EFI_LOADER_SIG, 4);
|
||||
CopyMem(bp->s.efi_loader_sig, EFI_LOADER_SIG_IA32, 4);
|
||||
|
||||
/*
|
||||
* Kernel entry point.
|
||||
|
@ -344,7 +623,7 @@ sysdeps_create_boot_params(
|
|||
#define WAIT_FOR_KEY() \
|
||||
{ \
|
||||
EFI_INPUT_KEY key; \
|
||||
while (ST->ConIn->ReadKeyStroke(ST->ConIn, &key) != EFI_SUCCESS) { \
|
||||
while (uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &key) != EFI_SUCCESS) { \
|
||||
; \
|
||||
} \
|
||||
}
|
||||
|
@ -402,6 +681,7 @@ sysdeps_create_boot_params(
|
|||
CHECK_OFFSET(loader_start, 0x1D8, L"%xh");
|
||||
CHECK_OFFSET(loader_size, 0x1DC, L"%xh");
|
||||
CHECK_OFFSET(alt_mem_k, 0x1E0, L"%xh");
|
||||
CHECK_OFFSET(e820_nrmap, 0x1E8, L"%xh");
|
||||
CHECK_OFFSET(setup_sectors, 0x1F1, L"%xh");
|
||||
CHECK_OFFSET(mount_root_rdonly, 0x1F2, L"%xh");
|
||||
CHECK_OFFSET(sys_size, 0x1F4, L"%xh");
|
||||
|
@ -426,6 +706,7 @@ sysdeps_create_boot_params(
|
|||
CHECK_OFFSET(bootsect_helper, 0x220, L"%xh");
|
||||
CHECK_OFFSET(heap_end_ptr, 0x224, L"%xh");
|
||||
CHECK_OFFSET(cmdline_addr, 0x228, L"%xh");
|
||||
CHECK_OFFSET(e820_map, 0x2D0, L"'%-2560.2560a'");
|
||||
|
||||
if (test) {
|
||||
ERR_PRT((L"Boot sector and/or setup parameter alignment error."));
|
||||
|
@ -440,7 +721,11 @@ sysdeps_create_boot_params(
|
|||
* in the fill routine gets accounted for.
|
||||
*/
|
||||
|
||||
efi_status = ST->ConOut->QueryMode(
|
||||
if (!get_video_info(bp)) goto do_memmap;
|
||||
|
||||
efi_status = uefi_call_wrapper(
|
||||
ST->ConOut->QueryMode,
|
||||
4,
|
||||
ST->ConOut,
|
||||
ST->ConOut->Mode->Mode,
|
||||
&cols,
|
||||
|
@ -488,6 +773,7 @@ sysdeps_create_boot_params(
|
|||
bp->s.vesa_seg = 0;
|
||||
bp->s.vesa_off = 0;
|
||||
|
||||
do_memmap:
|
||||
/*
|
||||
* Get memory map description and cookie for ExitBootServices()
|
||||
*/
|
||||
|
@ -503,6 +789,10 @@ sysdeps_create_boot_params(
|
|||
bp->s.efi_mem_desc_size = mdesc.desc_size;
|
||||
bp->s.efi_mem_desc_ver = mdesc.desc_version;
|
||||
bp->s.efi_sys_tbl = (UINTN)systab;
|
||||
/* Now that we have EFI memory map, convert it to E820 map
|
||||
* and update the bootparam accordingly
|
||||
*/
|
||||
fill_e820map(bp, &mdesc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -23,10 +23,15 @@
|
|||
# to use this program.
|
||||
#
|
||||
|
||||
include ../Make.defaults
|
||||
include ../Make.rules
|
||||
SRCDIR = .
|
||||
|
||||
VPATH = $(SRCDIR)
|
||||
|
||||
include $(SRCDIR)/../Make.defaults
|
||||
include $(SRCDIR)/../Make.rules
|
||||
|
||||
TOPDIR=$(SRCDIR)/..
|
||||
|
||||
TOPDIR=$(CDIR)/..
|
||||
|
||||
FILES=system.o config.o fpswa.o plain_loader.o gzip_loader.o \
|
||||
gzip.o memset.o memcpy.o setjmp.o longjmp.o
|
||||
|
|
|
@ -132,7 +132,7 @@ check_fpswa(EFI_HANDLE image, EFI_HANDLE dev, CHAR16 *fpswa_file)
|
|||
#endif
|
||||
};
|
||||
UINTN j, count = sizeof(fpswa_filenames)/sizeof(CHAR16 *);
|
||||
INTN cookie;
|
||||
UINTN cookie;
|
||||
CHAR16 devname[FILENAME_MAXLEN];
|
||||
|
||||
if (fpswa_file) {
|
||||
|
|
19
ia64/gzip.c
19
ia64/gzip.c
|
@ -161,7 +161,7 @@ gzip_free(void *where)
|
|||
int
|
||||
fill_inbuf(void)
|
||||
{
|
||||
INTN expected, nread;
|
||||
UINTN expected, nread;
|
||||
EFI_STATUS status;
|
||||
|
||||
expected = nread = INBUFSIZE;
|
||||
|
@ -170,7 +170,9 @@ fill_inbuf(void)
|
|||
if (EFI_ERROR(status)) {
|
||||
error("elilo: Read failed");
|
||||
}
|
||||
#ifdef DEBUG_GZIP
|
||||
DBG_PRT((L"%s : read %d bytes of %d bytes\n", LD_NAME, nread, expected));
|
||||
#endif
|
||||
|
||||
insize = nread;
|
||||
inptr = 1;
|
||||
|
@ -309,7 +311,7 @@ analyze_chunks(void)
|
|||
* the relevant header information.
|
||||
*/
|
||||
int
|
||||
first_block (const char *buf, long blocksize)
|
||||
first_block (const unsigned char *buf, long blocksize)
|
||||
{
|
||||
Elf64_Ehdr *elf;
|
||||
Elf64_Phdr *phdrs;
|
||||
|
@ -439,7 +441,7 @@ first_block (const char *buf, long blocksize)
|
|||
if (alloc_kmem((void *)low_addr, pages) == -1) {
|
||||
VOID *new_addr;
|
||||
|
||||
VERB_PRT(1, (L"%s : AllocatePages(%d, 0x%lx) for kernel failed\n", LD_NAME, pages, low_addr));
|
||||
VERB_PRT(1, Print(L"%s : AllocatePages(%d, 0x%lx) for kernel failed\n", LD_NAME, pages, low_addr));
|
||||
|
||||
if (ia64_can_relocate() == 0) {
|
||||
ERR_PRT((L"relocation is disabled, cannot load kernel"));
|
||||
|
@ -464,7 +466,7 @@ first_block (const char *buf, long blocksize)
|
|||
/* unsigned arithmetic */
|
||||
load_offset = (UINTN) (new_addr - ROUNDDOWN((UINTN) low_addr,256*MB));
|
||||
|
||||
VERB_PRT(1, (L"low_addr=0x%lx new_addr=0x%lx offset=0x%lx", low_addr, new_addr, load_offset));
|
||||
VERB_PRT(1, Print(L"low_addr=0x%lx new_addr=0x%lx offset=0x%lx", low_addr, new_addr, load_offset));
|
||||
|
||||
/*
|
||||
* correct various addresses for non-zero load_offset
|
||||
|
@ -526,12 +528,13 @@ flush_window(void)
|
|||
static const CHAR8 helicopter[4] = { '|' , '/' , '-' , '\\' };
|
||||
static UINTN heli_count;
|
||||
struct segment *cp;
|
||||
char *src, *dst;
|
||||
unsigned char *src, *dst;
|
||||
long cnt;
|
||||
|
||||
if (!outcnt) return;
|
||||
|
||||
#ifdef DEBUG_GZIP
|
||||
DBG_PRT((L"%s : flush_window outnct=%d file_offset=%ld\n", LD_NAME, outcnt, file_offset));
|
||||
#endif
|
||||
|
||||
Print(L"%c\b",helicopter[heli_count++%4]);
|
||||
|
||||
|
@ -565,7 +568,7 @@ tail:
|
|||
file_offset += skip;
|
||||
outcnt -= skip;
|
||||
}
|
||||
dst = (char *)cp->addr + (file_offset - cp->offset);
|
||||
dst = (unsigned char *)cp->addr + (file_offset - cp->offset);
|
||||
|
||||
cnt = cp->offset + cp->size - file_offset;
|
||||
|
||||
|
@ -582,7 +585,7 @@ tail:
|
|||
/* See if we are at the end of this chunk */
|
||||
if (file_offset == cp->offset + cp->size) {
|
||||
if (cp->bss_sz) {
|
||||
dst = (char *)cp->addr + cp->size;
|
||||
dst = (unsigned char *)cp->addr + cp->size;
|
||||
Memset(dst, 0, cp->bss_sz);
|
||||
}
|
||||
nextchunk();
|
||||
|
|
|
@ -159,4 +159,4 @@ longjmp:
|
|||
invala // virt. -> phys. regnum mapping may change
|
||||
mov pr=r24,-1
|
||||
br.ret.dptk.few rp
|
||||
.endp __longjmp
|
||||
.endp longjmp
|
||||
|
|
|
@ -288,7 +288,7 @@ load_elf(fops_fd_t fd, kdesc_t *kd)
|
|||
if (alloc_kmem(low_addr, pages) == -1) {
|
||||
VOID *new_addr;
|
||||
|
||||
VERB_PRT(1, (L"%s : AllocatePages(%d, 0x%lx) for kernel failed\n", LD_NAME, pages, low_addr));
|
||||
VERB_PRT(1, Print(L"%s : AllocatePages(%d, 0x%lx) for kernel failed\n", LD_NAME, pages, low_addr));
|
||||
|
||||
if (ia64_can_relocate() == 0) {
|
||||
ERR_PRT((L"relocation is disabled, cannot load kernel"));
|
||||
|
|
|
@ -81,6 +81,7 @@ setjmp:
|
|||
.proc __sigsetjmp
|
||||
__sigsetjmp:
|
||||
//.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
|
||||
.body
|
||||
alloc loc1=ar.pfs,2,2,2,0
|
||||
mov r16=ar.unat
|
||||
;;
|
||||
|
@ -89,6 +90,7 @@ __sigsetjmp:
|
|||
add r3=8,in0
|
||||
;;
|
||||
st8.spill.nta [r2]=sp,16 // r12 (sp)
|
||||
;;
|
||||
st8.spill.nta [r3]=gp,16 // r1 (gp)
|
||||
;;
|
||||
st8.nta [r2]=r16,16 // save caller's unat
|
||||
|
@ -96,13 +98,13 @@ __sigsetjmp:
|
|||
add r8=0xa0,in0
|
||||
;;
|
||||
st8.spill.nta [r2]=r4,16 // r4
|
||||
;;
|
||||
st8.spill.nta [r3]=r5,16 // r5
|
||||
add r9=0xb0,in0
|
||||
;;
|
||||
stf.spill.nta [r8]=f2,32
|
||||
stf.spill.nta [r9]=f3,32
|
||||
mov loc0=rp
|
||||
.body
|
||||
;;
|
||||
stf.spill.nta [r8]=f4,32
|
||||
stf.spill.nta [r9]=f5,32
|
||||
|
@ -139,6 +141,7 @@ __sigsetjmp:
|
|||
stf.spill.nta [r9]=f31
|
||||
|
||||
st8.spill.nta [r2]=r6,16 // r6
|
||||
;;
|
||||
st8.spill.nta [r3]=r7,16 // r7
|
||||
;;
|
||||
mov r23=ar.bsp
|
||||
|
|
|
@ -86,7 +86,7 @@ start_kernel(VOID *kentry, VOID *bp)
|
|||
asm volatile ("mov r28=%1; br.sptk.few %0" :: "b"(kentry),"r"(bp));
|
||||
}
|
||||
|
||||
static inline const UINT64
|
||||
static inline UINT64
|
||||
__ia64_swab64 (UINT64 x)
|
||||
{
|
||||
UINT64 result;
|
||||
|
@ -95,13 +95,13 @@ __ia64_swab64 (UINT64 x)
|
|||
return result;
|
||||
}
|
||||
|
||||
static inline const UINT32
|
||||
static inline UINT32
|
||||
__ia64_swab32 (UINT32 x)
|
||||
{
|
||||
return __ia64_swab64(x) >> 32;
|
||||
}
|
||||
|
||||
static inline const UINT16
|
||||
static inline UINT16
|
||||
__ia64_swab16(UINT16 x)
|
||||
{
|
||||
return __ia64_swab64(x) >> 48;
|
||||
|
|
|
@ -55,7 +55,7 @@ sysdeps_create_boot_params(boot_params_t *bp, CHAR8 *cmdline, memdesc_t *initrd,
|
|||
|
||||
if (get_memmap(&mdesc) == -1) return -1;
|
||||
|
||||
DBG_PRT((L"Got memory map @ 0x%lx (%d bytes)", mdesc.md, mdesc.map_size));
|
||||
DBG_PRT((L"Got memory map @ 0x%lx (%d bytes) with key %d", mdesc.md, mdesc.map_size, mdesc.cookie));
|
||||
|
||||
bp->efi_systab = (UINTN)systab;
|
||||
bp->efi_memmap = (UINTN)mdesc.md;
|
||||
|
@ -140,6 +140,12 @@ sysdeps_initrd_get_addr(kdesc_t *kd, memdesc_t *imem)
|
|||
return 0;
|
||||
}
|
||||
|
||||
VOID *
|
||||
sysdeps_checkfix_initrd(VOID *start_addr, memdesc_t *imem)
|
||||
{
|
||||
return start_addr;
|
||||
}
|
||||
|
||||
/* Flush data cache [addr; addr + len], and sync with icache. */
|
||||
void
|
||||
flush_dcache (CHAR8 *addr, UINT64 len)
|
||||
|
@ -147,7 +153,7 @@ flush_dcache (CHAR8 *addr, UINT64 len)
|
|||
/* Cache line length is at least 32. */
|
||||
UINT64 a = (UINT64)addr & ~0x1f;
|
||||
|
||||
VERB_PRT(3, Print(L"Flush 0x%lx-", a));
|
||||
DBG_PRT((L"Flush 0x%lx-", a));
|
||||
|
||||
/* Flush data. */
|
||||
for (len = (len + 31) & ~0x1f; len > 0; len -= 0x20, a += 0x20)
|
||||
|
@ -155,5 +161,5 @@ flush_dcache (CHAR8 *addr, UINT64 len)
|
|||
/* Sync and serialize. Maybe extra. */
|
||||
asm volatile (";; sync.i;; srlz.i;;");
|
||||
|
||||
VERB_PRT(3, Print(L"0x%lx\n", a));
|
||||
DBG_PRT((L"0x%lx\n", a));
|
||||
}
|
||||
|
|
|
@ -1094,10 +1094,10 @@ static int gunzip(void)
|
|||
error("Input has invalid flags\n");
|
||||
return -1;
|
||||
}
|
||||
(ulg)get_byte(); /* Get timestamp */
|
||||
((ulg)get_byte()) << 8;
|
||||
((ulg)get_byte()) << 16;
|
||||
((ulg)get_byte()) << 24;
|
||||
(void)get_byte(); /* Get timestamp - 4 bytes */
|
||||
(void)get_byte();
|
||||
(void)get_byte();
|
||||
(void)get_byte();
|
||||
|
||||
(void)get_byte(); /* Ignore extra flags for the moment */
|
||||
(void)get_byte(); /* Ignore OS type for the moment */
|
||||
|
|
14
initrd.c
14
initrd.c
|
@ -41,6 +41,10 @@ INTN
|
|||
load_file(CHAR16 *filename, memdesc_t *image)
|
||||
{
|
||||
EFI_STATUS status;
|
||||
/*
|
||||
* Actually using the value from sysdeps_initrd_get_addr()
|
||||
* instead of NULL is no change for ia64!
|
||||
*/
|
||||
VOID *start_addr = image->start_addr;
|
||||
UINTN pgcnt;
|
||||
UINT64 size = 0;
|
||||
|
@ -71,15 +75,19 @@ load_file(CHAR16 *filename, memdesc_t *image)
|
|||
/* round up to get required number of pages (4KB) */
|
||||
image->pgcnt = pgcnt = EFI_SIZE_TO_PAGES(image->size);
|
||||
|
||||
start_addr = alloc_pages(pgcnt, EfiLoaderData, start_addr ? AllocateAddress : AllocateAnyPages, start_addr);
|
||||
start_addr = alloc_pages(pgcnt, EfiLoaderData,
|
||||
start_addr ? AllocateAddress : AllocateAnyPages, start_addr);
|
||||
|
||||
start_addr = sysdeps_checkfix_initrd(start_addr, image);
|
||||
|
||||
if (start_addr == NULL) {
|
||||
ERR_PRT((L"Failed to allocate %d pages for %s image", pgcnt,
|
||||
filename));
|
||||
goto error;
|
||||
}
|
||||
VERB_PRT(2, Print(L"%s image: total_size: %ld bytes base: 0x%lx "
|
||||
VERB_PRT(2, Print(L"%s image: total_size: %d bytes base: " PTR_FMT " "
|
||||
"pages %d\n", filename, image->size,
|
||||
(UINTN)start_addr, pgcnt));
|
||||
start_addr, pgcnt));
|
||||
|
||||
Print(L"Loading file %s...", filename);
|
||||
|
||||
|
|
6
loader.c
6
loader.c
|
@ -38,12 +38,18 @@ loader_ops_t *
|
|||
loader_probe(CHAR16 *kname)
|
||||
{
|
||||
loader_ops_t *ops;
|
||||
UINTN n = 0;
|
||||
|
||||
for (ops= ldops_list; ops; ops = ops->next) {
|
||||
n++;
|
||||
VERB_PRT(3, Print(L"Probing loader: %s\n", ops->ld_name));
|
||||
if (ops->ld_probe(kname) == 0) {
|
||||
return ops;
|
||||
}
|
||||
}
|
||||
if (!n) {
|
||||
ERR_PRT((L"No loaders registered"));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
3 . 1 6 R E L E A S E N O T E S
|
||||
===================================
|
||||
|
||||
QUICK CHANGE SUMMARY
|
||||
====================
|
||||
* Adds native x86x crossbuild functionality
|
||||
build 32bit or 64bit versions from either environment via
|
||||
make ARCH=ia32|x86_64 (the ARCH IS case sensitive).
|
||||
make by itself will default to the native host arch.
|
||||
* Add console reset call during initialization. thanks A. Steinmetz
|
||||
* simplify output of no GOP warning text so it no longer looks like an error.
|
||||
* MAJOR: Fixed Fault crash when EFI memory map changes from under elilo.
|
||||
(from an outside interrupt in this case). When the EFI Memory map
|
||||
changes after elilo has already built boot params to pass to the
|
||||
kernel the EFI call to ExitBootSvcs just prior to boot will fail
|
||||
because elilo has the old map key. This is valid EFI behavior, elilo
|
||||
retries to pick up the new memory map and key but had already freed
|
||||
the start params portion of boot params resulting in a NULL DEREF
|
||||
crash reset once it hands the now bogus boot params to the kernel on
|
||||
the 2nd successful call to exit efi and boot.
|
||||
Thanks to Jerry Hoemann @ HP for reporting this bug.
|
||||
* minor bugfix, fixed -m option broken. thanks Allan-lsk.
|
||||
|
||||
BUILD NOTES
|
||||
====================
|
||||
You will need the following toolchain to build elilo-3.14 from source
|
||||
the elilo build environment is optimized for Debian and Debian based distros.
|
||||
elilo-3.16 was built in the squeeze+(ubuntu 11.x) build environments except
|
||||
for itanium which is unchanged to best support legacy enterprise configs.
|
||||
Toolchain versions for this release were:
|
||||
x86x(32 & 64bit versions)
|
||||
* gnu-efi --> 3.0i-3
|
||||
* gcc ------> 4:4.4.4-1ubuntu2
|
||||
* binutils -> 2.20.51.20100908-0ubuntu2
|
||||
ia64
|
||||
* gnu-efi --> 3.0e-2
|
||||
* gcc ------> 4.3.2-2
|
||||
* binutils -> 2.18.1~cvs20080103-7
|
||||
|
||||
* if you use a debian based build environment you will have no problems
|
||||
and setting it up is simple. you will be able to build elilo in 3 steps:
|
||||
1. apt-get install gnu-efi, gcc, binutils
|
||||
2. apt-get source elilo (or download elilo-3.16 source from SourceForge.)
|
||||
3. extract source tarball and cd to ./$your-elilo-source and type $> make
|
||||
|
||||
|
||||
** If you use the upstream toolchain tarballs(i.e. pre distro) you will need
|
||||
to move some files around for elilo build to work.
|
||||
GNU-EFI (provides the efi 1.10 and uefi 2.x libraries & api)
|
||||
-------
|
||||
gnu-efi libraries are installed to /usr/local/lib by the
|
||||
upstream gnu-efi source package. elilo expects them to be in system location
|
||||
/usr/lib. efi includes may be located in /usr/local/include/efi. elilo
|
||||
expects them to be in system location /usr/include/efi.
|
||||
[ The reason is LSB compliance ].
|
||||
|
||||
BINUTILS (provides the elf conversion utility to produce efi bins)
|
||||
--------
|
||||
binutils provides objcopy which is installed to /usr/local/bin by binutils,
|
||||
elilo source expects it to be in /usr/bin.
|
||||
|
||||
again this LSB compliance is taken care of by the distro's that fix
|
||||
the toolchains to install to the correct compliant system locations
|
||||
instead of the "user optional" location.
|
||||
|
||||
ELILO ON EFI X86_64
|
||||
=====================
|
||||
HARD REQUIREMENTS
|
||||
EFI + x86_64 REQUIRES an efi64 enabled linux kernel i.e. 2.6.21 or newer
|
||||
nothing earlier will work, 2.6.21 was the earliest kernel that efi64
|
||||
support went into. You need to compile the kernel with CONFIG_EFI
|
||||
kernel option ON.
|
||||
x86_64 platforms with UEFI 2.0 firmware deprecate UGA protocol
|
||||
and therefore only the Graphics Output Protocol (GOP) is supported. For
|
||||
such platforms, the kernel must be compiled with EFI_FB option ON. This
|
||||
will enable early boot messages on the console. Elilo for x86_64
|
||||
attempts to query EFI for GOP support and if it fails it defaults to
|
||||
text mode which may or may not show you early console ouput depends on
|
||||
your efi console settings and physical setup. Elilo has no way to know
|
||||
if your console settings are messed up.
|
||||
|
||||
WORKING ELILO.CONF FOR EFI X86_64 EXAMPLE
|
||||
Here is my elilo.conf from my UEFI2.0/x86_64 (with nvidia pcie add on
|
||||
card, i.e. your vga= kernel param may be different) workstation which uses GOP.
|
||||
Here is a partial kernel vga table I was able to find and add here.
|
||||
Colours 640x400 640x480 800x600 1024x768 1152x864 1280x1024 1600x1200
|
||||
-------+--------------------------------------------------------------
|
||||
4 bits | ? ? 0x302 ? ? ? ?
|
||||
8 bits | 0x300 0x301 0x303 0x305 0x161 0x307 0x31C
|
||||
15 bits | ? 0x310 0x313 0x316 0x162 0x319 0x31D
|
||||
16 bits | ? 0x311 0x314 0x317 0x163 0x31A 0x31E
|
||||
decimal | d785 d788 d791
|
||||
24 bits | ? 0x312 0x315 0x318 ? 0x31B 0x31F
|
||||
|
||||
Additionally from ...kernel-source/Documentation/Boot.txt...
|
||||
vga=<mode>
|
||||
<mode> here is either an integer (in C notation, either
|
||||
decimal, octal, or hexadecimal) or one of the strings
|
||||
"normal" (meaning 0xFFFF), "ext" (meaning 0xFFFE) or "ask"
|
||||
(meaning 0xFFFD). This value should be entered into the
|
||||
vid_mode field, as it is used by the kernel before the command
|
||||
line is parsed.
|
||||
|
||||
example below shows me console output, what elilo is doing, and kernel boot.
|
||||
vga=normal with efi console input output directed to graphics card should
|
||||
work as well.
|
||||
|
||||
default=UBUNTU
|
||||
chooser=simple
|
||||
verbose=5
|
||||
delay=30
|
||||
append="root=/dev/sda3 vga=0x31e splash showopts"
|
||||
|
||||
image=/vmlinuz-2.6.32-27-generic
|
||||
label="UBUNTU"
|
||||
description="Ubuntu 2.6.32-27-generic kernel"
|
||||
initrd=/initrd.img-2.6.32-27-generic
|
||||
|
||||
|
12
strops.c
12
strops.c
|
@ -41,11 +41,11 @@ StrnCpy(OUT CHAR16 *dst, IN const CHAR16 *src, IN UINTN size)
|
|||
{
|
||||
CHAR16 *res = dst;
|
||||
|
||||
while (size-- && (*dst++ = *src++) != CHAR_NULL);
|
||||
while (size && size-- && (*dst++ = *src++) != CHAR_NULL);
|
||||
/*
|
||||
* does the null padding
|
||||
*/
|
||||
while (size-- > 0) *dst++ = CHAR_NULL;
|
||||
while (size && size-- > 0) *dst++ = CHAR_NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -55,11 +55,11 @@ StrnXCpy(OUT CHAR8 *dst, IN const CHAR16 *src, IN UINTN size)
|
|||
{
|
||||
CHAR8 *res = dst;
|
||||
|
||||
while (size-- && (*dst++ = (CHAR8)*src++) != '\0');
|
||||
while (size && size-- && (*dst++ = (CHAR8)*src++) != '\0');
|
||||
/*
|
||||
* does the null padding
|
||||
*/
|
||||
while (size-- > 0) *dst++ = '\0';
|
||||
while (size && size-- > 0) *dst++ = '\0';
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -76,11 +76,11 @@ strncpya(OUT CHAR8 *dst, IN const CHAR8 *src, IN UINTN size)
|
|||
{
|
||||
CHAR8 *res = dst;
|
||||
|
||||
while (size-- && (*dst++ = *src++) != '\0');
|
||||
while (size && size-- && (*dst++ = *src++) != '\0');
|
||||
/*
|
||||
* does the null padding
|
||||
*/
|
||||
while (size-- > 0) *dst++ = '\0';
|
||||
while (size && size-- > 0) *dst++ = '\0';
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
|
@ -30,6 +34,8 @@
|
|||
#include "ia64/sysdeps.h"
|
||||
#elif defined CONFIG_ia32
|
||||
#include "ia32/sysdeps.h"
|
||||
#elif defined CONFIG_x86_64
|
||||
#include "x86_64/sysdeps.h"
|
||||
#endif
|
||||
|
||||
#endif /* __ELILO_SYSDEPS_H__ */
|
||||
|
|
|
@ -23,10 +23,15 @@
|
|||
# to use this program.
|
||||
#
|
||||
|
||||
include ../Make.defaults
|
||||
include ../Make.rules
|
||||
SRCDIR = .
|
||||
|
||||
VPATH = $(SRCDIR)
|
||||
|
||||
include $(SRCDIR)/../Make.defaults
|
||||
include $(SRCDIR)/../Make.rules
|
||||
|
||||
TOPDIR=$(SRCDIR)/..
|
||||
|
||||
TOPDIR=$(CDIR)/..
|
||||
|
||||
FILES=eliloalt.o
|
||||
TARGET=eliloalt
|
||||
|
|
|
@ -47,8 +47,10 @@
|
|||
#define ELILOALT_VERSION "0.02"
|
||||
|
||||
#define ELILO_ALT_NAME "EliloAlt"
|
||||
#define EFIVAR_DIR "/proc/efi/vars"
|
||||
#define EFIVAR_DIR "/sys/firmware/efi/vars"
|
||||
#define OFIVAR_DIR "/proc/efi/vars"
|
||||
#define ELILO_ALTVAR EFIVAR_DIR"/"ELILO_ALT_NAME"-00000000-0000-0000-0000-000000000000"
|
||||
#define OLILO_ALTVAR OFIVAR_DIR"/"ELILO_ALT_NAME"-00000000-0000-0000-0000-000000000000"
|
||||
|
||||
#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001
|
||||
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
|
||||
|
@ -80,7 +82,9 @@ typedef struct _efi_variable_t {
|
|||
uint32_t attributes;
|
||||
} __attribute__((packed)) efi_variable_t;
|
||||
|
||||
static char *efivar_dir = EFIVAR_DIR;
|
||||
static char *elilo_alt_name = ELILO_ALT_NAME;
|
||||
static char *elilo_altvar = ELILO_ALTVAR;
|
||||
|
||||
static struct option cmd_options[]={
|
||||
{ "version", 0, 0, 1},
|
||||
|
@ -129,9 +133,15 @@ check_proc_efi(int find_entry)
|
|||
if (getuid() != 0) {
|
||||
fatal_error("This program must be run as root\n");
|
||||
}
|
||||
efi_vars = opendir(EFIVAR_DIR);
|
||||
efi_vars = opendir(efivar_dir);
|
||||
if (efi_vars == NULL) {
|
||||
fatal_error("Cannot access %s\n", EFIVAR_DIR);
|
||||
efivar_dir = OFIVAR_DIR;
|
||||
elilo_altvar = OLILO_ALTVAR;
|
||||
efi_vars = opendir(efivar_dir);
|
||||
}
|
||||
if (efi_vars == NULL) {
|
||||
fatal_error("Can access neither %s nor %s\n",
|
||||
EFIVAR_DIR, efivar_dir);
|
||||
}
|
||||
if (!find_entry) {
|
||||
closedir(efi_vars);
|
||||
|
@ -143,9 +153,10 @@ check_proc_efi(int find_entry)
|
|||
break;
|
||||
}
|
||||
if (entry == NULL) {
|
||||
fatal_error("Cannot find entry in %s\n", EFIVAR_DIR);
|
||||
fatal_error("Cannot find entry in %s\n", efivar_dir);
|
||||
}
|
||||
sprintf(name, "%s/%s", EFIVAR_DIR, entry->d_name);
|
||||
snprintf(name, 1023, "%s/%s", efivar_dir, entry->d_name);
|
||||
name[1023] = 0;
|
||||
closedir(efi_vars);
|
||||
return name;
|
||||
}
|
||||
|
@ -158,7 +169,7 @@ delete_var(void)
|
|||
|
||||
check_proc_efi(0);
|
||||
|
||||
fd = open(ELILO_ALTVAR, O_WRONLY);
|
||||
fd = open(elilo_altvar, O_WRONLY);
|
||||
if (fd == -1) {
|
||||
fatal_error("variable not defined\n");
|
||||
}
|
||||
|
@ -176,7 +187,7 @@ delete_var(void)
|
|||
|
||||
r = write(fd, &var, sizeof(var));
|
||||
if (r != sizeof(var)) {
|
||||
fatal_error("Variable %s defined but invalid content\n", ELILO_ALTVAR);
|
||||
fatal_error("Variable %s defined but invalid content\n", elilo_altvar);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
@ -191,7 +202,7 @@ print_var(void)
|
|||
|
||||
check_proc_efi(0);
|
||||
|
||||
fd = open(ELILO_ALTVAR, O_RDONLY);
|
||||
fd = open(elilo_altvar, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
fatal_error("variable not defined\n");
|
||||
}
|
||||
|
@ -200,7 +211,7 @@ print_var(void)
|
|||
|
||||
r = read(fd, &var, sizeof(var));
|
||||
if (r != sizeof(var)) {
|
||||
fatal_error("Variable %s defined but invalid content\n", ELILO_ALTVAR);
|
||||
fatal_error("Variable %s defined but invalid content\n", elilo_altvar);
|
||||
}
|
||||
printf("EliloAlt=\"");
|
||||
for(i=0; i < var.datasize; i+=1){
|
||||
|
@ -231,7 +242,7 @@ set_var(char *cmdline)
|
|||
|
||||
fd = open(name, O_WRONLY);
|
||||
if (fd == -1) {
|
||||
fatal_error("can't open %s: %s\n", ELILO_ALTVAR, strerror(errno));
|
||||
fatal_error("can't open %s: %s\n", elilo_altvar, strerror(errno));
|
||||
}
|
||||
|
||||
memset(&var, 0, sizeof(var));
|
||||
|
@ -256,7 +267,7 @@ set_var(char *cmdline)
|
|||
|
||||
r = write(fd, &var, sizeof(var));
|
||||
if (r != sizeof(var)) {
|
||||
fatal_error("Variable %s defined but invalid content %d\n", ELILO_ALTVAR, r);
|
||||
fatal_error("Variable %s defined but invalid content %d\n", elilo_altvar, r);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
|
|
40
util.c
40
util.c
|
@ -5,6 +5,11 @@
|
|||
* Copyright (C) 2001 Silicon Graphics, Inc.
|
||||
* Contributed by Brent Casavant <bcasavan@sgi.com>
|
||||
*
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
|
@ -40,7 +45,10 @@
|
|||
static INTN
|
||||
read_keypress(EFI_INPUT_KEY *key)
|
||||
{
|
||||
return systab->ConIn->ReadKeyStroke(systab->ConIn, key);
|
||||
return uefi_call_wrapper(systab->ConIn->ReadKeyStroke,
|
||||
2,
|
||||
systab->ConIn,
|
||||
key);
|
||||
}
|
||||
|
||||
|
||||
|
@ -55,7 +63,10 @@ check_abort(VOID)
|
|||
inline VOID
|
||||
reset_input(VOID)
|
||||
{
|
||||
systab->ConIn->Reset(systab->ConIn, 1);
|
||||
uefi_call_wrapper(systab->ConIn->Reset,
|
||||
2,
|
||||
systab->ConIn,
|
||||
1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -71,9 +82,9 @@ wait_keypress_abort(VOID)
|
|||
Print(L"Hit ENTER to continue or ANY other key to cancel");
|
||||
|
||||
/* cleanup buffer first */
|
||||
while (conin->ReadKeyStroke(conin, &key) == EFI_SUCCESS);
|
||||
while (uefi_call_wrapper(conin->ReadKeyStroke, 2, conin, &key) == EFI_SUCCESS);
|
||||
|
||||
while ((status=conin->ReadKeyStroke(conin, &key)) == EFI_NOT_READY );
|
||||
while ((status=uefi_call_wrapper(conin->ReadKeyStroke,2, conin, &key)) == EFI_NOT_READY );
|
||||
|
||||
if (EFI_ERROR(status)) return ELILO_LOAD_ERROR;
|
||||
|
||||
|
@ -102,13 +113,13 @@ wait_timeout(UINTN timeout)
|
|||
if (timeout == 0) return 0;
|
||||
|
||||
/* Create a timeout timer */
|
||||
status = BS->CreateEvent(EVT_TIMER, 0, NULL, NULL, &timer);
|
||||
status = uefi_call_wrapper(BS->CreateEvent, 5, EVT_TIMER, 0, NULL, NULL, &timer);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L" waitkey CreateEvent failed %r", status));
|
||||
return -1;
|
||||
}
|
||||
/* In 100ns increments */
|
||||
status = BS->SetTimer(timer, TimerPeriodic, TENTH_SEC);
|
||||
status = uefi_call_wrapper(BS->SetTimer, 3, timer, TimerPeriodic, TENTH_SEC);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"waitkey SetTimer failed %r", status));
|
||||
return -1;
|
||||
|
@ -118,25 +129,27 @@ wait_timeout(UINTN timeout)
|
|||
list[1] = systab->ConIn->WaitForKey;
|
||||
|
||||
do {
|
||||
status = BS->WaitForEvent(2, list, &idx);
|
||||
status = uefi_call_wrapper(BS->WaitForEvent, 3, 2, list, &idx);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"waitkey WaitForEvent failed %r", status));
|
||||
return -1;
|
||||
}
|
||||
if (timeout % 10 == 1) Print(L".");
|
||||
|
||||
} while (timeout-- && idx == 0);
|
||||
Print(L"\n");
|
||||
|
||||
/*
|
||||
* SetTimer(timer, TimerCancel, 0) is causing problems on IA-32 and gcc3
|
||||
* I do not know why it dies with EFI12.35. So let's fake a key stroke.
|
||||
*/
|
||||
status = BS->SetTimer(timer, TimerCancel, 0);
|
||||
status = uefi_call_wrapper(BS->SetTimer, 3, timer, TimerCancel, 0);
|
||||
if (EFI_ERROR(status)) {
|
||||
ERR_PRT((L"waitkey SetTimer(TimerCancel) failed %r", status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
BS->CloseEvent(timer);
|
||||
uefi_call_wrapper(BS->CloseEvent, 1, timer);
|
||||
|
||||
return idx ? 1 : 0;
|
||||
}
|
||||
|
@ -237,7 +250,7 @@ split_args(CHAR16 *buffer, CHAR16 *kname, CHAR16 *args)
|
|||
INTN
|
||||
read_file(UINTN fd, UINTN total_size, CHAR8 *buffer)
|
||||
{
|
||||
INTN size, j=0;
|
||||
UINTN size, j=0;
|
||||
EFI_STATUS status;
|
||||
CHAR16 helicopter[4] = { L'|' , L'/' , L'-' , L'\\' };
|
||||
INTN ret = ELILO_LOAD_SUCCESS;
|
||||
|
@ -278,7 +291,7 @@ read_file(UINTN fd, UINTN total_size, CHAR8 *buffer)
|
|||
INTN
|
||||
get_memmap(mmap_desc_t *desc)
|
||||
{
|
||||
#define ELILO_MEMMAP_SIZE_DEFAULT EFI_PAGE_SIZE
|
||||
#define ELILO_MEMMAP_SIZE_DEFAULT (EFI_PAGE_SIZE*2)
|
||||
#define ELILO_MEMMAP_INC (sizeof(EFI_MEMORY_DESCRIPTOR)<<1)
|
||||
|
||||
EFI_STATUS status;
|
||||
|
@ -292,7 +305,8 @@ get_memmap(mmap_desc_t *desc)
|
|||
ERR_PRT((L"failed to allocate memory map buffer"));
|
||||
return -1;
|
||||
}
|
||||
status = (*BS->GetMemoryMap)(&desc->map_size, desc->md, &desc->cookie, &desc->desc_size, &desc->desc_version);
|
||||
status = uefi_call_wrapper(BS->GetMemoryMap, 5, &desc->map_size, desc->md,
|
||||
&desc->cookie, &desc->desc_size, &desc->desc_version);
|
||||
if (status == EFI_SUCCESS) break;
|
||||
|
||||
free(desc->md);
|
||||
|
@ -303,7 +317,7 @@ get_memmap(mmap_desc_t *desc)
|
|||
}
|
||||
desc->map_size += ELILO_MEMMAP_INC;
|
||||
}
|
||||
DBG_PRT((L"final get_memmap map_size=%ld", desc->map_size));
|
||||
DBG_PRT((L"final get_memmap map_size=%d", desc->map_size));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#
|
||||
# Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
# Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
#
|
||||
# This file is part of the ELILO, the EFI Linux boot loader.
|
||||
#
|
||||
# ELILO is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# ELILO is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with ELILO; see the file COPYING. If not, write to the Free
|
||||
# Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
#
|
||||
# Please check out the elilo.txt for complete documentation on how
|
||||
# to use this program.
|
||||
#
|
||||
|
||||
SRCDIR = .
|
||||
|
||||
VPATH = $(SRCDIR)
|
||||
|
||||
include $(SRCDIR)/../Make.defaults
|
||||
include $(SRCDIR)/../Make.rules
|
||||
|
||||
TOPDIR=$(SRCDIR)/..
|
||||
|
||||
|
||||
FILES=system.o config.o bzimage.o plain_loader.o gzip_loader.o gzip.o
|
||||
#FILES=system.o config.o plain_loader.o
|
||||
|
||||
TARGET=sysdeps.o
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
system.o: rmswitch.h
|
||||
|
||||
rmswitch.h: bin_to_h.c rmswitch.S
|
||||
$(CC) -o bin_to_h $(SRCDIR)/bin_to_h.c
|
||||
$(AS) -o rmswitch.o $(SRCDIR)/rmswitch.S
|
||||
$(LD) -Ttext 0x0 -s --oformat binary -o rmswitch rmswitch.o
|
||||
./bin_to_h <rmswitch >rmswitch.h
|
||||
|
||||
$(TARGET): $(FILES)
|
||||
$(LD) $(LD3264) -r -o $@ $(FILES)
|
||||
|
||||
clean:
|
||||
$(RM) -f $(TARGET) $(FILES)
|
||||
$(RM) -f bin_to_h.o bin_to_h
|
||||
$(RM) -f rmswitch.h rmswitch.o rmswitch
|
|
@ -0,0 +1,27 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
unsigned n = 0;
|
||||
int c;
|
||||
|
||||
printf("UINT8 rmswitch_image[] = {\n");
|
||||
|
||||
while ((c = getchar()) != EOF) {
|
||||
printf("0x%02x,%s",
|
||||
c & 0xFF,
|
||||
(++n & 0x07) ? " " : "\n");
|
||||
}
|
||||
|
||||
if (n & 0x07) {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf(
|
||||
"};\n"
|
||||
"UINTN rmswitch_size = sizeof rmswitch_image;\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,352 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Contributed by Mike Johnston <johnston@intel.com>
|
||||
* Contributed by Chris Ahna <christopher.j.ahna@intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* ELILO is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ELILO; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Please check out the elilo.txt for complete documentation on how
|
||||
* to use this program.
|
||||
*/
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
|
||||
#include "elilo.h"
|
||||
#include "loader.h"
|
||||
|
||||
boot_params_t *param_start = NULL;
|
||||
UINTN param_size = 0;
|
||||
|
||||
UINTN kernel_size = 0x800000; /* 8M (default x86_64 bzImage size limit) */
|
||||
|
||||
static VOID *
|
||||
bzImage_alloc()
|
||||
{
|
||||
UINTN pages = EFI_SIZE_TO_PAGES(kernel_size);
|
||||
int reloc_kernel = 0;
|
||||
VOID *kla, *kend = kernel_start + kernel_size;
|
||||
UINT32 kalign, kmask;
|
||||
boot_params_t *ps = param_start;
|
||||
|
||||
/*
|
||||
* Get address for kernel from header, if applicable & available.
|
||||
*/
|
||||
if ((ps->s.hdr_major < 2) ||
|
||||
(ps->s.hdr_major == 2 && ps->s.hdr_minor < 5)) {
|
||||
reloc_kernel = 0;
|
||||
} else {
|
||||
if (ps->s.kernel_start >= DEFAULT_KERNEL_START)
|
||||
kernel_start = (void *)(UINT64)ps->s.kernel_start;
|
||||
reloc_kernel = ps->s.relocatable_kernel;
|
||||
kalign = ps->s.kernel_alignment;
|
||||
kmask = kalign - 1;
|
||||
VERB_PRT(3, Print(L"kernel header (%d.%d) suggests kernel "
|
||||
"start at address "PTR_FMT" (%srelocatable!)\n",
|
||||
ps->s.hdr_major, ps->s.hdr_minor, ps->s.kernel_start,
|
||||
(reloc_kernel ? L"": L"not ")));
|
||||
}
|
||||
|
||||
/*
|
||||
* Best effort for old (< 2.6.20) and non-relocatable kernels
|
||||
*/
|
||||
if (alloc_kmem(kernel_start, pages) == 0) {
|
||||
VERB_PRT(3, Print(L"kernel_start: "PTR_FMT" kernel_size: %d\n",
|
||||
kernel_start, kernel_size));
|
||||
return kernel_start;
|
||||
} else if ( ! reloc_kernel ) {
|
||||
/*
|
||||
* Couldn't get desired address--just load it anywhere and
|
||||
* (try to) move it later. It's the only chance for non-
|
||||
* relocatable kernels, but it breaks occassionally...
|
||||
*/
|
||||
ERR_PRT((L"Kernel header (%d.%d) suggests kernel "
|
||||
"start at address "PTR_FMT" (non relocatable!)\n"
|
||||
"This address is not available, so an attempt"
|
||||
"is made to copy the kernel there later on\n"
|
||||
"BEWARE: this is unsupported and may not work. "
|
||||
"Please update your kernel.\n",
|
||||
ps->s.hdr_major, ps->s.hdr_minor, ps->s.kernel_start));
|
||||
kla = (VOID *)(UINT32_MAX - kernel_size);
|
||||
/* NULL would preserve the "anywhere" semantic, */
|
||||
/* but it would not prevent allocation above 4GB! */
|
||||
|
||||
if (alloc_kmem_anywhere(&kla, pages) != 0) {
|
||||
/* out of luck */
|
||||
return NULL;
|
||||
}
|
||||
VERB_PRT(3, Print(L"kernel_start: "PTR_FMT
|
||||
" kernel_size: %d loading at: "PTR_FMT"\n",
|
||||
kernel_start, kernel_size, kla));
|
||||
return kla;
|
||||
}
|
||||
|
||||
|
||||
/* Is 'ps->s.kernel_alignment' guaranteed to be sane? */
|
||||
if (kalign < EFI_PAGE_SIZE) {
|
||||
kalign = EFI_PAGE_SIZE;
|
||||
kmask = EFI_PAGE_MASK;
|
||||
}
|
||||
DBG_PRT((L"alignment: kernel=0x%x efi_page=0x%x : 0x%x\n",
|
||||
ps->s.kernel_alignment, EFI_PAGE_SIZE, kalign));
|
||||
|
||||
/*
|
||||
* Couldn't get the preferred address, but luckily it's
|
||||
* a relocatable kernel, so ...
|
||||
*
|
||||
* 1. use 'find_kernel_memory()' (like Itanium)
|
||||
* 2. try out the 16 lowest possible aligned addresses (> 0)
|
||||
* 3. get enough memory to align "creatively"
|
||||
* 4. forget alignment (and start praying)...
|
||||
*/
|
||||
|
||||
/* 1. */
|
||||
if ((find_kernel_memory(kernel_start, kend, kalign, &kla) != 0) ||
|
||||
(alloc_kmem(kla, pages) != 0)) {
|
||||
kla = NULL;
|
||||
}
|
||||
|
||||
/* 2. */
|
||||
if ( ! kla && (UINT64)kernel_start < kalign ) {
|
||||
int i;
|
||||
for ( i = 1; i < 16 && !kla; i++ ) {
|
||||
VOID *tmp = (VOID *)((UINT64)kalign * i);
|
||||
if (alloc_kmem(tmp, pages) == 0) {
|
||||
kla = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 3. */
|
||||
if ( ! kla ) {
|
||||
UINTN apages = EFI_SIZE_TO_PAGES(kernel_size + kmask);
|
||||
kla = (VOID *)(UINT32_MAX - kernel_size - kmask);
|
||||
|
||||
if (alloc_kmem_anywhere(&kla, apages) == 0) {
|
||||
kla = (VOID *)(((UINT64)kla + kmask) & ~kmask);
|
||||
} else {
|
||||
kla = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* 4. last resort */
|
||||
if ( ! kla ) {
|
||||
kla = (VOID *)(UINT32_MAX - kernel_size);
|
||||
if (alloc_kmem_anywhere(&kla, pages) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
kernel_start = kla;
|
||||
VERB_PRT(1, Print(L"relocating kernel_start: "PTR_FMT
|
||||
" kernel_size: %d\n", kernel_start, kernel_size));
|
||||
return kla;
|
||||
}
|
||||
|
||||
static INTN
|
||||
bzImage_probe(CHAR16 *kname)
|
||||
{
|
||||
EFI_STATUS efi_status;
|
||||
UINTN size;
|
||||
fops_fd_t fd;
|
||||
UINT8 bootsect[512];
|
||||
|
||||
DBG_PRT((L"probe_bzImage_boot()\n"));
|
||||
|
||||
if (!kname) {
|
||||
ERR_PRT((L"kname == %xh", kname));
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open kernel image.
|
||||
*/
|
||||
DBG_PRT((L"opening %s...\n", kname));
|
||||
|
||||
efi_status = fops_open(kname, &fd);
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
ERR_PRT((L"Could not open %s.", kname));
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Read boot sector.
|
||||
*/
|
||||
|
||||
DBG_PRT((L"\nreading boot sector...\n"));
|
||||
|
||||
size = sizeof bootsect;
|
||||
efi_status = fops_read(fd, bootsect, &size);
|
||||
if (EFI_ERROR(efi_status) || size != sizeof bootsect) {
|
||||
ERR_PRT((L"Could not read boot sector from %s.", kname));
|
||||
fops_close(fd);
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Verify boot sector signature.
|
||||
*/
|
||||
|
||||
if (bootsect[0x1FE] != 0x55 || bootsect[0x1FF] != 0xAA) {
|
||||
ERR_PRT((L"%s is not a bzImage kernel image.\n", kname));
|
||||
fops_close(fd);
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Check for out of range setup data size.
|
||||
* Will almost always be 7, but we will accept 1 to 64.
|
||||
*/
|
||||
|
||||
DBG_PRT((L"bootsect[1F1h] == %d setup sectors\n", bootsect[0x1F1]));
|
||||
|
||||
if (bootsect[0x1F1] < 1 || bootsect[0x1F1] > 64) {
|
||||
ERR_PRT((L"%s is not a valid bzImage kernel image.",
|
||||
kname));
|
||||
fops_close(fd);
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Allocate and read setup data.
|
||||
*/
|
||||
|
||||
DBG_PRT((L"reading setup data...\n"));
|
||||
|
||||
param_size = (bootsect[0x1F1] + 1) * 512;
|
||||
param_start = alloc(param_size, EfiLoaderData);
|
||||
|
||||
DBG_PRT((L"param_size=%d param_start=%x", param_size, param_start));
|
||||
|
||||
if (!param_start) {
|
||||
ERR_PRT((L"Could not allocate %d bytes of setup data.",
|
||||
param_size));
|
||||
fops_close(fd);
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
|
||||
CopyMem(param_start, bootsect, sizeof bootsect);
|
||||
|
||||
size = param_size - 512;
|
||||
efi_status = fops_read(fd, ((UINT8 *)param_start) + 512, &size);
|
||||
|
||||
if (EFI_ERROR(efi_status) || size != param_size - 512) {
|
||||
ERR_PRT((L"Could not read %d bytes of setup data.",
|
||||
param_size - 512));
|
||||
free(param_start);
|
||||
param_start = NULL;
|
||||
param_size = 0;
|
||||
fops_close(fd);
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Check for setup data signature.
|
||||
*/
|
||||
|
||||
{
|
||||
UINT8 *c = ((UINT8 *)param_start)+514;
|
||||
DBG_PRT((L"param_start(c=%x): %c-%c-%c-%c",
|
||||
c, (CHAR16)c[0],(CHAR16) c[1], (CHAR16)c[2], (CHAR16)c[3]));
|
||||
}
|
||||
if (CompareMem(((UINT8 *)param_start) + 514, "HdrS", 4)) {
|
||||
ERR_PRT((L"%s does not have a setup signature.",
|
||||
kname));
|
||||
free(param_start);
|
||||
param_start = NULL;
|
||||
param_size = 0;
|
||||
fops_close(fd);
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Allocate memory for kernel.
|
||||
*/
|
||||
|
||||
kernel_load_address = bzImage_alloc();
|
||||
if ( ! kernel_load_address ) {
|
||||
ERR_PRT((L"Could not allocate memory for kernel."));
|
||||
free(param_start);
|
||||
param_start = NULL;
|
||||
param_size = 0;
|
||||
fops_close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now read the rest of the kernel image into memory.
|
||||
*/
|
||||
|
||||
Print(L"Loading kernel %s... ", kname);
|
||||
|
||||
size = kernel_size;
|
||||
efi_status = fops_read(fd, kernel_load_address, &size);
|
||||
if (EFI_ERROR(efi_status) || size < 0x10000) {
|
||||
ERR_PRT((L"Error reading kernel image (0x%x).", efi_status));
|
||||
free(param_start);
|
||||
param_start = NULL;
|
||||
param_size = 0;
|
||||
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));
|
||||
|
||||
/*
|
||||
* Boot sector, setup data and kernel image loaded.
|
||||
*/
|
||||
|
||||
fops_close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
static INTN
|
||||
bzImage_load(CHAR16 *kname, kdesc_t *kd)
|
||||
{
|
||||
DBG_PRT((L"load_bzImage_boot()\n"));
|
||||
|
||||
if (!kname || !kd) {
|
||||
ERR_PRT((L"kname="PTR_FMT" kd="PTR_FMT"", kname, kd));
|
||||
free(param_start);
|
||||
param_start = NULL;
|
||||
param_size = 0;
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
kd->kstart = kd->kentry = kernel_start;
|
||||
kd->kend = ((UINT8 *)kd->kstart) + kernel_size;
|
||||
|
||||
DBG_PRT((L"kstart="PTR_FMT" kentry="PTR_FMT" kend="PTR_FMT"\n", kd->kstart, kd->kentry, kd->kend));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
loader_ops_t bzimage_loader = {
|
||||
NULL,
|
||||
L"bzImage_loader",
|
||||
&bzImage_probe,
|
||||
&bzImage_load
|
||||
};
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Contributed by Chris Ahna <christopher.j.ahna@intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* ELILO is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ELILO; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Please check out the elilo.txt for complete documentation on how
|
||||
* to use this program.
|
||||
*/
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
|
||||
#include "elilo.h"
|
||||
#include "config.h"
|
||||
#include "private.h"
|
||||
|
||||
typedef struct {
|
||||
UINTN legacy_free_boot;
|
||||
UINTN text_mode;
|
||||
} 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}
|
||||
};
|
||||
|
||||
static config_option_t sysdeps_image_options[]={
|
||||
{OPT_BOOL, OPT_IMAGE_SYS, L"text-mode", NULL, NULL, x86_64_opt_offsetof(text_mode)}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* X86_64 operations that need to be done only once and just before
|
||||
* entering the main loop of the loader
|
||||
* Return:
|
||||
* 0 if sucessful
|
||||
* -1 otherwise (will abort execution)
|
||||
*/
|
||||
INTN
|
||||
sysdeps_preloop_actions(EFI_HANDLE dev, CHAR16 **argv, INTN argc, INTN index, EFI_HANDLE image)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define X86_64_CMDLINE_OPTIONS L""
|
||||
|
||||
CHAR16 *
|
||||
sysdeps_get_cmdline_opts(VOID)
|
||||
{
|
||||
return X86_64_CMDLINE_OPTIONS;
|
||||
}
|
||||
|
||||
INTN
|
||||
sysdeps_getopt(INTN c, INTN optind, CHAR16 *optarg)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
VOID
|
||||
sysdeps_print_cmdline_opts(VOID)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
INTN
|
||||
x86_64_use_legacy_free_boot(VOID)
|
||||
{
|
||||
return x86_64_gconf.legacy_free_boot ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
INTN
|
||||
x86_64_text_mode(VOID)
|
||||
{
|
||||
return (elilo_opt.sys_img_opts &&
|
||||
elilo_opt.sys_img_opts->text_mode == TRUE) ? 1 : 0;
|
||||
}
|
||||
|
||||
INTN
|
||||
sysdeps_register_options(VOID)
|
||||
{
|
||||
INTN ret;
|
||||
|
||||
ret = register_config_options(sysdeps_global_options,
|
||||
sizeof(sysdeps_global_options)/sizeof(config_option_t),
|
||||
OPTIONS_GROUP_GLOBAL);
|
||||
if (ret == -1 ) return ret;
|
||||
|
||||
ret = register_config_options(sysdeps_image_options,
|
||||
sizeof(sysdeps_image_options)/sizeof(config_option_t),
|
||||
OPTIONS_GROUP_IMAGE);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,560 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2002 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
*
|
||||
* Copyright (C) 2001 Silicon Graphics, Inc.
|
||||
* Contributed by Brent Casavant <bcasavan@sgi.com>
|
||||
*
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* ELILO is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ELILO; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Please check out the elilo.txt for complete documentation on how
|
||||
* to use this program.
|
||||
*/
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
|
||||
#include "elf.h"
|
||||
#include "elilo.h"
|
||||
#include "gzip.h"
|
||||
#include "private.h"
|
||||
|
||||
#define memzero(s, n) Memset((VOID *)(s), 0, (n))
|
||||
#define memcpy(a,b,n) Memcpy((VOID *)(a),(b),(n))
|
||||
|
||||
/* size of output buffer */
|
||||
#define WSIZE 0x8000 /* Window size must be at least 32k, */
|
||||
/* and a power of two */
|
||||
/* size of input buffer */
|
||||
#define INBUFSIZE 0x8000
|
||||
|
||||
/*
|
||||
* gzip declarations
|
||||
*/
|
||||
|
||||
#define OF(args) args
|
||||
#define FUNC_STATIC static
|
||||
|
||||
typedef unsigned char uch;
|
||||
typedef unsigned short ush;
|
||||
typedef unsigned long ulg;
|
||||
|
||||
|
||||
typedef struct segment {
|
||||
unsigned long addr; /* start address */
|
||||
unsigned long offset; /* file offset */
|
||||
unsigned long size; /* file size */
|
||||
unsigned long bss_sz; /* BSS size */
|
||||
UINT8 flags; /* indicates whether to load or not */
|
||||
} segment_t;
|
||||
|
||||
#define CHUNK_FL_VALID 0x1
|
||||
#define CHUNK_FL_LOAD 0x2
|
||||
|
||||
#define CHUNK_CAN_LOAD(n) chunks[(n)].flags |= CHUNK_FL_LOAD
|
||||
#define CHUNK_NO_LOAD(n) chunks[(n)].flags &= ~CHUNK_FL_LOAD
|
||||
#define CHUNK_IS_LOAD(n) (chunks[(n)].flags & CHUNK_FL_LOAD)
|
||||
|
||||
#define CHUNK_VALIDATE(n) chunks[(n)].flags |= CHUNK_FL_VALID
|
||||
#define CHUNK_INVALIDATE(n) chunks[(n)].flags = 0
|
||||
#define CHUNK_IS_VALID(n) (chunks[(n)].flags & CHUNK_FL_VALID)
|
||||
|
||||
/*
|
||||
* static parameters to gzip helper functions
|
||||
* we cannot use paramters because API was not
|
||||
* designed that way
|
||||
*/
|
||||
static segment_t *chunks; /* holds the list of segments */
|
||||
static segment_t *cur_chunk;
|
||||
static UINTN nchunks;
|
||||
static UINTN chunk; /* current segment */
|
||||
static UINTN input_fd;
|
||||
static VOID *kernel_entry, *kernel_base, *kernel_end;
|
||||
|
||||
static uch *inbuf; /* input buffer (compressed data) */
|
||||
static uch *window; /* output buffer (uncompressed data) */
|
||||
static unsigned long file_offset; /* position in the file */
|
||||
|
||||
static unsigned insize = 0; /* valid bytes in inbuf */
|
||||
static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
|
||||
static unsigned outcnt = 0; /* bytes in output buffer */
|
||||
|
||||
/* gzip flag byte */
|
||||
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
|
||||
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
|
||||
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
|
||||
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
|
||||
#define COMMENT 0x10 /* bit 4 set: file comment present */
|
||||
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
|
||||
#define RESERVED 0xC0 /* bit 6,7: reserved */
|
||||
|
||||
#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
|
||||
|
||||
/* Diagnostic functions */
|
||||
#ifdef INFLATE_DEBUG
|
||||
# define Assert(cond,msg) {if(!(cond)) error(msg);}
|
||||
int stderr;
|
||||
# define Trace(x) Print(L"line %d:\n", __LINE__);
|
||||
# define Tracev(x) {if (verbose) Print(L"line %d:\n", __LINE__) ;}
|
||||
# define Tracevv(x) {if (verbose>1) Print(L"line %d:\n", __LINE__) ;}
|
||||
# define Tracec(c,x) {if (verbose && (c)) Print(L"line %d:\n", __LINE__) ;}
|
||||
# define Tracecv(c,x) {if (verbose>1 && (c)) Print(L"line %d:\n", __LINE__) ;}
|
||||
#else
|
||||
# define Assert(cond,msg)
|
||||
# define Trace(x)
|
||||
# define Tracev(x)
|
||||
# define Tracevv(x)
|
||||
# define Tracec(c,x)
|
||||
# define Tracecv(c,x)
|
||||
#endif
|
||||
|
||||
static int fill_inbuf(void);
|
||||
static void flush_window(void);
|
||||
static void error(char *m);
|
||||
static long bytes_out;
|
||||
static void error(char *m);
|
||||
static int error_return;
|
||||
|
||||
static void *
|
||||
gzip_malloc(int size)
|
||||
{
|
||||
return (void *)alloc(size, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gzip_free(void *where)
|
||||
{
|
||||
return free(where);
|
||||
}
|
||||
|
||||
#include "inflate.c"
|
||||
|
||||
/*
|
||||
* Fill the input buffer and return the first byte in it. This is called
|
||||
* only when the buffer is empty and at least one byte is really needed.
|
||||
*/
|
||||
int
|
||||
fill_inbuf(void)
|
||||
{
|
||||
UINTN expected, nread;
|
||||
EFI_STATUS status;
|
||||
|
||||
expected = nread = INBUFSIZE;
|
||||
|
||||
status = fops_read(input_fd, inbuf, &nread);
|
||||
if (EFI_ERROR(status)) {
|
||||
error("elilo: Read failed");
|
||||
}
|
||||
#ifdef DEBUG_GZIP
|
||||
DBG_PRT((L"%s : read %d bytes of %d bytes\n", LD_NAME, nread, expected));
|
||||
#endif
|
||||
|
||||
insize = nread;
|
||||
inptr = 1;
|
||||
|
||||
return inbuf[0];
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
|
||||
* (Used for the decompressed data only.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Run a set of bytes through the crc shift register. If s is a NULL
|
||||
* pointer, then initialize the crc shift register contents instead.
|
||||
* Return the current crc in either case.
|
||||
*
|
||||
* Input:
|
||||
* S pointer to bytes to pump through.
|
||||
* N number of bytes in S[].
|
||||
*/
|
||||
unsigned long
|
||||
updcrc(unsigned char *s, unsigned n)
|
||||
{
|
||||
register unsigned long c;
|
||||
/* crc is defined in inflate.c */
|
||||
|
||||
if (!s) {
|
||||
c = 0xffffffffL;
|
||||
} else {
|
||||
c = crc;
|
||||
while (n--) {
|
||||
c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
|
||||
}
|
||||
}
|
||||
crc = c;
|
||||
return c ^ 0xffffffffUL; /* (instead of ~c for 64-bit machines) */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clear input and output buffers
|
||||
*/
|
||||
void
|
||||
clear_bufs(void)
|
||||
{
|
||||
outcnt = 0;
|
||||
inptr = 0;
|
||||
chunk = 0;
|
||||
cur_chunk = NULL;
|
||||
file_offset = 0;
|
||||
}
|
||||
|
||||
|
||||
static INTN
|
||||
is_valid_header(Elf64_Ehdr *ehdr)
|
||||
{
|
||||
UINT16 type, machine;
|
||||
|
||||
type = ehdr->e_type;
|
||||
machine = ehdr->e_machine;
|
||||
|
||||
VERB_PRT(3, Print(L"class=%d type=%d data=%d machine=%d\n",
|
||||
ehdr->e_ident[EI_CLASS],
|
||||
type,
|
||||
ehdr->e_ident[EI_DATA],
|
||||
machine));
|
||||
|
||||
return ehdr->e_ident[EI_MAG0] == 0x7f
|
||||
&& ehdr->e_ident[EI_MAG1] == 'E'
|
||||
&& ehdr->e_ident[EI_MAG2] == 'L'
|
||||
&& ehdr->e_ident[EI_MAG3] == 'F'
|
||||
&& ehdr->e_ident[EI_CLASS] == ELFCLASS64
|
||||
&& type == ET_EXEC /* must be executable */
|
||||
&& machine == EM_X86_64 ? 0 : -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* will invalidate loadble segments which overlap with others
|
||||
*/
|
||||
void
|
||||
check_overlap(int i)
|
||||
{
|
||||
int j;
|
||||
unsigned long iend = chunks[i].addr + chunks[i].size;
|
||||
|
||||
for(j=0; j < nchunks; j++) {
|
||||
if (j ==i) continue;
|
||||
if (chunks[i].addr >= chunks[j].addr && iend < (chunks[j].addr + chunks[j].size)) {
|
||||
DBG_PRT((L"%s : segment %d fully included in segment %d\n", LD_NAME, i, j));
|
||||
CHUNK_INVALIDATE(i); /* nullyify segment */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
analyze_chunks(void)
|
||||
{
|
||||
INTN i;
|
||||
|
||||
for (i=0; i < nchunks; i++) {
|
||||
if (CHUNK_IS_VALID(i) && !CHUNK_IS_LOAD(i))
|
||||
check_overlap(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The decompression code calls this function after decompressing the
|
||||
* first block of the object file. The first block must contain all
|
||||
* the relevant header information.
|
||||
*/
|
||||
int
|
||||
first_block (const unsigned char *buf, long blocksize)
|
||||
{
|
||||
Elf64_Ehdr *elf;
|
||||
Elf64_Phdr *phdrs;
|
||||
UINTN total_size, pages;
|
||||
UINTN low_addr, max_addr;
|
||||
UINTN offs = 0;
|
||||
UINT16 phnum;
|
||||
UINTN paddr, memsz;
|
||||
INTN i;
|
||||
|
||||
elf = (Elf64_Ehdr *)buf;
|
||||
|
||||
if (is_valid_header(elf) == -1)
|
||||
return -1;
|
||||
|
||||
offs = elf->e_phoff;
|
||||
phnum = elf->e_phnum;
|
||||
|
||||
VERB_PRT(3, {
|
||||
Print(L"Entry point 0x%lx\n", elf->e_entry);
|
||||
Print(L"%d program headers\n", phnum);
|
||||
Print(L"%d segment headers\n", elf->e_shnum);
|
||||
});
|
||||
|
||||
if (offs + phnum * sizeof(*phdrs) > (unsigned) blocksize) {
|
||||
ERR_PRT((L"%s : ELF program headers not in first block (%ld)\n", LD_NAME, offs));
|
||||
return -1;
|
||||
}
|
||||
|
||||
kernel_entry = (VOID *)(elf->e_entry & PADDR_MASK);
|
||||
|
||||
phdrs = (Elf64_Phdr *) (buf + offs);
|
||||
low_addr = ~0;
|
||||
max_addr = 0;
|
||||
|
||||
/*
|
||||
* allocate chunk table
|
||||
* Convention: a segment that does not need loading will
|
||||
* have chunk[].addr = 0.
|
||||
*/
|
||||
chunks = (void *)alloc(sizeof(struct segment)*phnum, 0);
|
||||
if (chunks == NULL) {
|
||||
ERR_PRT((L"%s : failed alloc chunks %r\n", LD_NAME));
|
||||
return -1;
|
||||
}
|
||||
nchunks = phnum;
|
||||
/*
|
||||
* find lowest and higest virtual addresses
|
||||
* don't assume FULLY sorted !
|
||||
*/
|
||||
for (i = 0; i < phnum; ++i) {
|
||||
/*
|
||||
* record chunk no matter what because no load may happen
|
||||
* anywhere in archive, not just as the last segment
|
||||
*/
|
||||
paddr = (phdrs[i].p_paddr & PADDR_MASK);
|
||||
memsz = phdrs[i].p_memsz,
|
||||
|
||||
chunks[i].addr = paddr;
|
||||
chunks[i].offset = phdrs[i].p_offset;
|
||||
chunks[i].size = phdrs[i].p_filesz;
|
||||
chunks[i].bss_sz = phdrs[i].p_memsz - phdrs[i].p_filesz;
|
||||
|
||||
CHUNK_VALIDATE(i);
|
||||
|
||||
if (phdrs[i].p_type != PT_LOAD) {
|
||||
CHUNK_NO_LOAD(i); /* mark no load chunk */
|
||||
DBG_PRT((L"%s : skipping segment %ld\n", LD_NAME, i));
|
||||
continue;
|
||||
}
|
||||
|
||||
CHUNK_CAN_LOAD(i); /* mark no load chunk */
|
||||
|
||||
VERB_PRT(3,
|
||||
Print(L"\n%s : segment %ld vaddr [0x%lx-0x%lx] offset %ld filesz %ld "
|
||||
"memsz=%ld bss_sz=%ld\n",
|
||||
LD_NAME, 1+i, chunks[i].addr, chunks[i].addr+phdrs[i].p_filesz,
|
||||
chunks[i].offset, chunks[i].size, memsz, chunks[i].bss_sz));
|
||||
|
||||
if (paddr < low_addr)
|
||||
low_addr = paddr;
|
||||
if (paddr + memsz > max_addr)
|
||||
max_addr = paddr + memsz;
|
||||
}
|
||||
|
||||
if (low_addr & (EFI_PAGE_SIZE - 1)) {
|
||||
ERR_PRT((L"%s : low_addr not page aligned 0x%lx\n", LD_NAME, low_addr));
|
||||
goto error;
|
||||
}
|
||||
analyze_chunks();
|
||||
|
||||
DBG_PRT((L"%s : %d program headers entry=0x%lx\nlowest_addr=0x%lx highest_addr=0x%lx\n",
|
||||
LD_NAME,
|
||||
phnum, kernel_entry, low_addr, max_addr));
|
||||
|
||||
total_size = (UINTN)max_addr - (UINTN)low_addr;
|
||||
pages = EFI_SIZE_TO_PAGES(total_size);
|
||||
|
||||
/*
|
||||
* Record end of kernel for initrd
|
||||
*/
|
||||
kernel_base = (void *)low_addr;
|
||||
kernel_end = (void *)(low_addr + (pages << EFI_PAGE_SHIFT));
|
||||
|
||||
/* allocate memory for the kernel */
|
||||
if (alloc_kmem((void *)low_addr, pages) == -1) {
|
||||
ERR_PRT((L"%s : AllocatePages(%d, 0x%lx) for kernel failed\n",
|
||||
LD_NAME, pages, low_addr));
|
||||
ERR_PRT((L"%s : Could not load kernel at 0x%lx\n", LD_NAME, low_addr));
|
||||
ERR_PRT((L"%s : Bailing\n", LD_NAME));
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
if (chunks)
|
||||
free(chunks);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine which chunk in the Elf file will be coming out of the expand
|
||||
* code next.
|
||||
*/
|
||||
static void
|
||||
nextchunk(void)
|
||||
{
|
||||
int i;
|
||||
segment_t *cp;
|
||||
|
||||
cp = NULL;
|
||||
for(i=0; i < nchunks; i++) {
|
||||
|
||||
if (!CHUNK_IS_VALID(i) || !CHUNK_IS_LOAD(i)) continue;
|
||||
|
||||
if (file_offset > chunks[i].offset) continue;
|
||||
|
||||
if (cp == NULL || chunks[i].offset < cp->offset) cp = &chunks[i];
|
||||
}
|
||||
cur_chunk = cp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write the output window window[0..outcnt-1] holding uncompressed
|
||||
* data and update crc.
|
||||
*/
|
||||
void
|
||||
flush_window(void)
|
||||
{
|
||||
static const CHAR8 helicopter[4] = { '|' , '/' , '-' , '\\' };
|
||||
static UINTN heli_count;
|
||||
struct segment *cp;
|
||||
unsigned char *src, *dst;
|
||||
long cnt;
|
||||
|
||||
if (!outcnt) return;
|
||||
#ifdef DEBUG_GZIP
|
||||
DBG_PRT((L"%s : flush_window outnct=%d file_offset=%ld\n", LD_NAME, outcnt, file_offset));
|
||||
#endif
|
||||
|
||||
Print(L"%c\b",helicopter[heli_count++%4]);
|
||||
|
||||
updcrc(window, outcnt);
|
||||
|
||||
/* first time, we extract the headers */
|
||||
if (!bytes_out) {
|
||||
if (first_block(window, outcnt) < 0)
|
||||
error("invalid exec header");
|
||||
nextchunk();
|
||||
}
|
||||
|
||||
bytes_out += outcnt;
|
||||
src = window;
|
||||
tail:
|
||||
/* check if user wants to abort */
|
||||
if (check_abort() == EFI_SUCCESS) goto load_abort;
|
||||
|
||||
cp = cur_chunk;
|
||||
if (cp == NULL || file_offset + outcnt <= cp->offset) {
|
||||
file_offset += outcnt;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Does this window begin before the current chunk? */
|
||||
if (file_offset < cp->offset) {
|
||||
unsigned long skip = cp->offset - file_offset;
|
||||
|
||||
src += skip;
|
||||
file_offset += skip;
|
||||
outcnt -= skip;
|
||||
}
|
||||
dst = (unsigned char *)cp->addr + (file_offset - cp->offset);
|
||||
cnt = cp->offset + cp->size - file_offset;
|
||||
if (cnt > outcnt)
|
||||
cnt = outcnt;
|
||||
|
||||
Memcpy(dst, src, cnt);
|
||||
|
||||
file_offset += cnt;
|
||||
outcnt -= cnt;
|
||||
src += cnt;
|
||||
|
||||
/* See if we are at the end of this chunk */
|
||||
if (file_offset == cp->offset + cp->size) {
|
||||
if (cp->bss_sz) {
|
||||
dst = (unsigned char *)cp->addr + cp->size;
|
||||
Memset(dst, 0, cp->bss_sz);
|
||||
}
|
||||
nextchunk();
|
||||
/* handle remaining bytes */
|
||||
if (outcnt)
|
||||
goto tail;
|
||||
}
|
||||
return;
|
||||
load_abort:
|
||||
free_kmem();
|
||||
error_return = ELILO_LOAD_ABORTED;
|
||||
}
|
||||
|
||||
static void
|
||||
error(char *x)
|
||||
{
|
||||
ERR_PRT((L"%s : %a", LD_NAME, x));
|
||||
/* will eventually exit with error from gunzip() */
|
||||
}
|
||||
|
||||
INT32
|
||||
decompress_kernel(VOID)
|
||||
{
|
||||
INT32 ret;
|
||||
|
||||
clear_bufs();
|
||||
makecrc();
|
||||
Print(L"Uncompressing Linux... ");
|
||||
ret = gunzip();
|
||||
if (ret == 0)
|
||||
Print(L"done\n");
|
||||
return ret == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
int
|
||||
gunzip_kernel(fops_fd_t fd, kdesc_t *kd)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
error_return = ELILO_LOAD_ERROR;
|
||||
|
||||
window = (void *)alloc(WSIZE, 0);
|
||||
if (window == NULL) {
|
||||
ERR_PRT((L"%s : allocate output window failed\n", LD_NAME));
|
||||
return -1;
|
||||
}
|
||||
|
||||
inbuf = (void *)alloc(INBUFSIZE, 0);
|
||||
if (inbuf == NULL) {
|
||||
ERR_PRT((L"%s : allocate input window failedr\n", LD_NAME));
|
||||
goto error;
|
||||
}
|
||||
input_fd = fd;
|
||||
insize = 0;
|
||||
bytes_out = 0;
|
||||
|
||||
ret = decompress_kernel();
|
||||
error:
|
||||
if (window) free(window);
|
||||
if (inbuf) free(inbuf);
|
||||
|
||||
if (ret == 0) {
|
||||
kd->kentry = kernel_entry;
|
||||
kd->kend = kernel_end;
|
||||
kd->kstart = kernel_base;
|
||||
error_return = ELILO_LOAD_SUCCESS;
|
||||
}
|
||||
return error_return;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2002 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
*
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* ELILO is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ELILO; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Please check out the elilo.txt for complete documentation on how
|
||||
* to use this program.
|
||||
*/
|
||||
|
||||
#ifndef __GZIP_H__
|
||||
#define __GZIP_H__
|
||||
|
||||
|
||||
int gzip_probe(unsigned char *, unsigned long);
|
||||
int gunzip_kernel(fops_fd_t, kdesc_t *);
|
||||
|
||||
#define LD_NAME L"gzip_x86_64"
|
||||
|
||||
#endif /* __GZIP_H__ */
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2002 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* ELILO is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ELILO; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Please check out the elilo.txt for complete documentation on how
|
||||
* to use this program.
|
||||
*/
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
|
||||
#include "elilo.h"
|
||||
#include "loader.h"
|
||||
#include "gzip.h"
|
||||
|
||||
static INTN
|
||||
gzip_probe_format(CHAR16 *kname)
|
||||
{
|
||||
UINT8 buf[4];
|
||||
EFI_STATUS status;
|
||||
INTN ret = -1;
|
||||
UINTN size;
|
||||
fops_fd_t fd;
|
||||
|
||||
status = fops_open(kname, &fd);
|
||||
if (EFI_ERROR(status)) return -1;
|
||||
|
||||
size = sizeof(buf);
|
||||
status = fops_read(fd, buf, &size);
|
||||
|
||||
if (EFI_ERROR(status) || size != sizeof(buf)) goto error;
|
||||
|
||||
ret = gzip_probe(buf, sizeof(buf));
|
||||
error:
|
||||
fops_close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static INTN
|
||||
gzip_load_kernel(CHAR16 *kname, kdesc_t *kd)
|
||||
{
|
||||
EFI_STATUS status;
|
||||
INT32 ret;
|
||||
fops_fd_t fd;
|
||||
|
||||
status = fops_open(kname, &fd);
|
||||
if (EFI_ERROR(status)) return ELILO_LOAD_ERROR;
|
||||
|
||||
ret = gunzip_kernel(fd, kd);
|
||||
|
||||
fops_close(fd);
|
||||
|
||||
return ret; /* could be success, error, or abort */
|
||||
}
|
||||
|
||||
loader_ops_t gzip_loader={
|
||||
NULL,
|
||||
LD_NAME,
|
||||
gzip_probe_format,
|
||||
gzip_load_kernel
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2002 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
*
|
||||
* Copyright (C) 2001 Silicon Graphics, Inc.
|
||||
* Contributed by Brent Casavant <bcasavan@sgi.com>
|
||||
*
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* ELILO is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ELILO; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Please check out the elilo.txt for complete documentation on how
|
||||
* to use this program.
|
||||
*/
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
|
||||
#include "elilo.h"
|
||||
#include "loader.h"
|
||||
#include "elf.h"
|
||||
#include "private.h"
|
||||
|
||||
#define LD_NAME L"plain_elf64"
|
||||
|
||||
static INTN
|
||||
is_valid_header(Elf64_Ehdr *ehdr)
|
||||
{
|
||||
UINT16 type, machine;
|
||||
|
||||
type = ehdr->e_type;
|
||||
machine = ehdr->e_machine;
|
||||
|
||||
DBG_PRT((L"class=%d type=%d data=%d machine=%d\n",
|
||||
ehdr->e_ident[EI_CLASS],
|
||||
type,
|
||||
ehdr->e_ident[EI_DATA],
|
||||
machine));
|
||||
|
||||
return ehdr->e_ident[EI_MAG0] == 0x7f
|
||||
&& ehdr->e_ident[EI_MAG1] == 'E'
|
||||
&& ehdr->e_ident[EI_MAG2] == 'L'
|
||||
&& ehdr->e_ident[EI_MAG3] == 'F'
|
||||
&& ehdr->e_ident[EI_CLASS] == ELFCLASS64
|
||||
&& type == ET_EXEC /* must be executable */
|
||||
&& machine == EM_X86_64? 0 : -1;
|
||||
}
|
||||
|
||||
static INTN
|
||||
plain_probe(CHAR16 *kname)
|
||||
{
|
||||
Elf64_Ehdr ehdr;
|
||||
EFI_STATUS status;
|
||||
INTN ret = -1;
|
||||
fops_fd_t fd;
|
||||
UINTN size = sizeof(ehdr);
|
||||
|
||||
status = fops_open(kname, &fd);
|
||||
if (EFI_ERROR(status))
|
||||
return -1;
|
||||
|
||||
VERB_PRT(3, {
|
||||
Print(L"plain_probe: kname=%s\n", kname);
|
||||
});
|
||||
status = fops_read(fd, &ehdr, &size);
|
||||
if (EFI_ERROR(status) || size != sizeof(ehdr))
|
||||
goto error;
|
||||
|
||||
ret = is_valid_header(&ehdr);
|
||||
error:
|
||||
fops_close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static INTN
|
||||
load_elf(fops_fd_t fd, kdesc_t *kd)
|
||||
{
|
||||
Elf64_Ehdr ehdr;
|
||||
Elf64_Phdr *phdrs;
|
||||
EFI_STATUS status;
|
||||
INTN ret = ELILO_LOAD_ERROR;
|
||||
UINTN i, total_size = 0;
|
||||
UINTN pages, size, bss_sz, osize;
|
||||
VOID *low_addr = (VOID *)~0;
|
||||
VOID *max_addr = (VOID *)0;
|
||||
UINTN paddr, memsz, filesz;
|
||||
UINT16 phnum;
|
||||
|
||||
Print(L"Loading Linux... ");
|
||||
|
||||
size = sizeof(ehdr);
|
||||
|
||||
status = fops_read(fd, &ehdr, &size);
|
||||
if (EFI_ERROR(status) || size < sizeof(ehdr))
|
||||
return ELILO_LOAD_ERROR;
|
||||
|
||||
if (is_valid_header(&ehdr) == -1) {
|
||||
ERR_PRT((L"%s : not a 64-bit ELF image\n", LD_NAME));
|
||||
return ELILO_LOAD_ERROR;
|
||||
}
|
||||
VERB_PRT(3, {
|
||||
Print(L"ELF Header information: \n");
|
||||
Print(L"\tEntry point "PTR_FMT"\n", (ehdr.e_entry & PADDR_MASK));
|
||||
Print(L"\t%d program headers\n", ehdr.e_phnum);
|
||||
Print(L"\t%d segment headers\n", ehdr.e_shnum);
|
||||
});
|
||||
|
||||
phnum = ehdr.e_phnum;
|
||||
|
||||
if (fops_seek(fd, ehdr.e_phoff) < 0) {
|
||||
ERR_PRT((L"%s : seek to %d for phdrs failed", LD_NAME, ehdr.e_phoff));
|
||||
return ELILO_LOAD_ERROR;
|
||||
}
|
||||
size = osize = (phnum * sizeof(Elf64_Phdr));
|
||||
|
||||
DBG_PRT((L"%s : allocate %d bytes for %d pheaders each of size:%d phentsize=%d\n",
|
||||
LD_NAME, size, phnum, sizeof(Elf64_Phdr), ehdr.e_phentsize));
|
||||
|
||||
phdrs = (Elf64_Phdr *)alloc(size, 0);
|
||||
if (phdrs == NULL) {
|
||||
ERR_PRT((L"%s : allocate for phdrs failed", LD_NAME));
|
||||
return ELILO_LOAD_ERROR;
|
||||
}
|
||||
status = fops_read(fd, phdrs, &size);
|
||||
if (EFI_ERROR(status) || size != osize) {
|
||||
ERR_PRT((L"%s : phdr load failed", LD_NAME, status));
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* First pass to figure out total memory footprint
|
||||
*/
|
||||
for (i = 0; i < phnum; i++) {
|
||||
|
||||
paddr = (phdrs[i].p_paddr & PADDR_MASK);
|
||||
memsz = phdrs[i].p_memsz;
|
||||
|
||||
DBG_PRT((L"Phdr %d paddr ["PTR_FMT"-"PTR_FMT"] offset "PTR_FMT""
|
||||
" filesz "PTR_FMT" memsz="PTR_FMT" bss_sz="PTR_FMT" p_type="PTR_FMT"\n",
|
||||
1+i, paddr, paddr+phdrs[i].p_filesz, phdrs[i].p_offset,
|
||||
phdrs[i].p_filesz, memsz,
|
||||
(memsz - phdrs[i].p_filesz), phdrs[i].p_type));
|
||||
|
||||
if (phdrs[i].p_type != PT_LOAD)
|
||||
continue;
|
||||
if (paddr < (UINTN)low_addr)
|
||||
low_addr = (VOID *)paddr;
|
||||
if (paddr + memsz > (UINTN)max_addr)
|
||||
max_addr = (VOID *)paddr + memsz;
|
||||
}
|
||||
|
||||
if ((UINTN)low_addr & (EFI_PAGE_SIZE - 1)) {
|
||||
ERR_PRT((L"%s : kernel low address "PTR_FMT" not page aligned\n",
|
||||
LD_NAME, low_addr));
|
||||
goto out;
|
||||
}
|
||||
/* how many bytes are needed to hold the kernel? */
|
||||
total_size = (UINTN)max_addr - (UINTN)low_addr;
|
||||
|
||||
/* round up to get required number of pages */
|
||||
pages = EFI_SIZE_TO_PAGES(total_size);
|
||||
|
||||
/* keep track of location where kernel starts and ends */
|
||||
kd->kstart = low_addr;
|
||||
kd->kend = (low_addr + (pages << EFI_PAGE_SHIFT));
|
||||
kd->kentry = (VOID *)(ehdr.e_entry & PADDR_MASK);
|
||||
|
||||
VERB_PRT(3, {
|
||||
Print(L"Lowest PhysAddr: "PTR_FMT"\nTotalMemSize:%d bytes (%d pages)\n",
|
||||
low_addr, total_size, pages);
|
||||
Print(L"Kernel entry @ "PTR_FMT"\n", kd->kentry);
|
||||
});
|
||||
|
||||
/* now allocate memory for the kernel at the exact requested spot */
|
||||
if (alloc_kmem(low_addr, pages) == -1) {
|
||||
ERR_PRT((L"%s : AllocatePages(%d, 0x%lx) for kernel failed\n",
|
||||
LD_NAME, pages, low_addr));
|
||||
ERR_PRT((L"%s : Could not alloc %d pages for the kernel at 0x%lx "
|
||||
" and relocation is not not been implemented!\n",
|
||||
LD_NAME, pages, low_addr));
|
||||
goto load_abort;
|
||||
}
|
||||
/* Pure paranoia. Clear the memory first. Just in case... */
|
||||
Memset(low_addr, 0, (pages << EFI_PAGE_SHIFT));
|
||||
|
||||
VERB_PRT(1, Print(L"Press any key to interrupt\n"));
|
||||
|
||||
/*
|
||||
* Walk through the program headers
|
||||
* and actually load data into physical memory
|
||||
*/
|
||||
|
||||
for (i = 0; i < phnum; i++) {
|
||||
/* Check for pure loadable segment; ignore if not loadable */
|
||||
if (phdrs[i].p_type != PT_LOAD)
|
||||
continue;
|
||||
|
||||
VERB_PRT(3, Print(L"poffs: "PTR_FMT" (phdrs[%d].p_offset)\n",
|
||||
phdrs[i].p_offset, i));
|
||||
|
||||
filesz = phdrs[i].p_filesz;
|
||||
low_addr = (VOID *)((UINTN) phdrs[i].p_paddr & PADDR_MASK);
|
||||
|
||||
/* Move to the right position */
|
||||
if (fops_seek(fd, phdrs[i].p_offset) < 0)
|
||||
goto out_kernel;
|
||||
|
||||
/* How many BSS bytes to clear */
|
||||
bss_sz = phdrs[i].p_memsz - filesz;
|
||||
|
||||
VERB_PRT(4, {
|
||||
Print(L"\nHeader #%d\n", i);
|
||||
Print(L"Offset in file "PTR_FMT"\n", phdrs[i].p_offset);
|
||||
Print(L"Physical addr "PTR_FMT"\n", low_addr);
|
||||
Print(L"BSS size %d bytes\n", bss_sz);
|
||||
});
|
||||
|
||||
/*
|
||||
* Read actual segment into memory
|
||||
*/
|
||||
ret = fops_read(fd, low_addr, &filesz);
|
||||
if (ret == ELILO_LOAD_ABORTED) goto load_abort;
|
||||
if (ret == ELILO_LOAD_ERROR) goto out;
|
||||
|
||||
/*
|
||||
* Clear bss section
|
||||
*/
|
||||
if (bss_sz)
|
||||
Memset((VOID *)low_addr+filesz, 0, bss_sz);
|
||||
}
|
||||
|
||||
free(phdrs);
|
||||
return ELILO_LOAD_SUCCESS;
|
||||
|
||||
load_abort:
|
||||
Print(L"..Aborted\n");
|
||||
ret = ELILO_LOAD_ABORTED;
|
||||
out_kernel:
|
||||
/* free kernel memory */
|
||||
free_kmem();
|
||||
out:
|
||||
free(phdrs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static INTN
|
||||
plain_load_kernel(CHAR16 *kname, kdesc_t *kd)
|
||||
{
|
||||
INTN ret;
|
||||
fops_fd_t fd;
|
||||
EFI_STATUS status;
|
||||
|
||||
/*
|
||||
* Moving the open here simplifies the load_elf() error handling
|
||||
*/
|
||||
status = fops_open(kname, &fd);
|
||||
if (EFI_ERROR(status)) return ELILO_LOAD_ERROR;
|
||||
|
||||
Print(L"Loading %s...", kname);
|
||||
|
||||
ret = load_elf(fd, kd);
|
||||
|
||||
fops_close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
loader_ops_t plain_loader={
|
||||
NULL,
|
||||
LD_NAME,
|
||||
plain_probe,
|
||||
plain_load_kernel
|
||||
};
|
||||
|
||||
/*void plain_loader_init()
|
||||
{
|
||||
loader_ops_t plain={
|
||||
NULL,
|
||||
LD_NAME,
|
||||
plain_probe,
|
||||
plain_load_kernel
|
||||
};
|
||||
*plain_loader=*plain;
|
||||
}*/
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
*
|
||||
* Copyright (C) 2006-2009 Intel Corporation
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* ELILO is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ELILO; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Please check out the elilo.txt for complete documentation on how
|
||||
* to use this program.
|
||||
*/
|
||||
|
||||
#ifndef __ELILO_PRIVATE_X86_64_H__
|
||||
#define __ELILO_PRIVATE_X86_64_H__
|
||||
|
||||
#endif /* __ELILO_PRIVATE_X86_64_H__ */
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
#
|
||||
# Switch from protected mode to real mode and jump to setup.S
|
||||
# image located at %cx:0.
|
||||
#
|
||||
# This module must be placed into physical memory at 0:7C00h.
|
||||
# EFI has some real mode thunking code at 2000:0h.
|
||||
#
|
||||
# Processor and non-maskable interrupts should be disabled
|
||||
# before control is passed to this module.
|
||||
#
|
||||
|
||||
.global _start
|
||||
|
||||
.code32
|
||||
.text
|
||||
_start:
|
||||
#
|
||||
# Load identity mapped GDT & real mode IDT.
|
||||
# Add 7C00h to the addresses since this is linked to start
|
||||
# at 0h and it is being placed at 7C00h.
|
||||
#
|
||||
|
||||
lgdt %cs:gdt_48 + 0x7C00
|
||||
lidt %cs:idt_48 + 0x7C00
|
||||
|
||||
#
|
||||
# Turn off PG bit in CR0 and set CR3 to zero.
|
||||
#
|
||||
|
||||
movl %cr0, %eax
|
||||
andl $0x7FFFFFFF, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
xorl %eax, %eax
|
||||
movl %eax, %cr3
|
||||
|
||||
#
|
||||
# Reload CS.
|
||||
# Now we add 7B00h because we need to force the segment
|
||||
# address and selector to be the same.
|
||||
#
|
||||
|
||||
.byte 0xEA
|
||||
.long pm_reload + 0x7B00
|
||||
.word 0x10
|
||||
|
||||
pm_reload:
|
||||
|
||||
.code16
|
||||
|
||||
#
|
||||
# Reload DS, ES, FS, GS & SS.
|
||||
#
|
||||
|
||||
movw $0x18, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
movw %ax, %ss
|
||||
|
||||
#
|
||||
# Switch to real mode. Clear PE bit in CR0.
|
||||
#
|
||||
|
||||
movl %cr0, %eax
|
||||
andl $0xFFFFFFFE, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
#
|
||||
# Reload CS.
|
||||
#
|
||||
|
||||
.byte 0xEA
|
||||
.word rm_reload + 0x7C00
|
||||
.word 0
|
||||
|
||||
rm_reload:
|
||||
|
||||
#
|
||||
# Reload SS & SP.
|
||||
#
|
||||
|
||||
xorw %ax, %ax
|
||||
movw %ax, %ss
|
||||
movw $0x7BFE, %sp
|
||||
|
||||
#
|
||||
# Start running setup.S
|
||||
#
|
||||
|
||||
.byte 0xEA
|
||||
.word 0
|
||||
.word 0x9020
|
||||
|
||||
#
|
||||
# GDT & IDT stuff for switching into real mode.
|
||||
#
|
||||
|
||||
gdt: .word 0, 0, 0, 0 # unused (00h)
|
||||
.word 0, 0, 0, 0 # dummy (08h)
|
||||
.word 0xFFFF, 0x100 # code (10h)
|
||||
.word 0x9A00, 0
|
||||
.word 0xFFFF, 0x180 # data (18h)
|
||||
.word 0x9200, 0
|
||||
|
||||
gdt_48: .word 0x08 * 0x400
|
||||
.long gdt + 0x7C00
|
||||
|
||||
idt_48: .word 0x400
|
||||
.long 0
|
||||
|
||||
#
|
||||
# Be careful not to exceed 1F0h or the the bootsect.S
|
||||
# parameters will be lost!
|
||||
#
|
||||
|
||||
.end
|
|
@ -0,0 +1,465 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Contributed by Mike Johnston <johnston@intel.com>
|
||||
* Contributed by Chris Ahna <christopher.j.ahna@intel.com>
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* ELILO is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ELILO; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Please check out the elilo.txt for complete documentation on how
|
||||
* to use this program.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is used to define all the x86_64-specific data structures
|
||||
* and constant used by the generic ELILO
|
||||
*/
|
||||
#ifndef __ELILO_SYSDEPS_X86_64_H__
|
||||
#define __ELILO_SYSDEPS_X86_64_H__
|
||||
|
||||
#define ELILO_ARCH "x86_64" /* ASCII string */
|
||||
#define PADDR_MASK 0xfffffff
|
||||
|
||||
/* for now use library versions */
|
||||
#define Memset(a,v,n) SetMem((a),(n),(v))
|
||||
#define Memcpy(a,b,n) CopyMem((a),(b),(n))
|
||||
|
||||
/* Put initrd to far away from kernel image to avoid conflict.
|
||||
* May need to adjust this number if it is not big enough.
|
||||
*/
|
||||
#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
|
||||
* following Linux kernel source files:
|
||||
* linux/include/tty.h
|
||||
* linux/arch/i386/kernel/setup.c
|
||||
* linux/arch/i386/boot/bootsect.S
|
||||
* linux/arch/i386/boot/setup.S
|
||||
* linux/arch/i386/boot/video.S
|
||||
*
|
||||
* New fields in this structure for EFI and ELILO are:
|
||||
* efi_loader_sig
|
||||
* efi_st_addr
|
||||
*
|
||||
* A new bit, LDRFLAG_BOOT_PARAM_RELOC, in the loader_flags
|
||||
* field is also defined in this file.
|
||||
*/
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/* Definitions for converting EFI memory map to E820 map for Linux
|
||||
* These definitions are from include/linux/asm-x86_64/e820.h
|
||||
* The structure x86_64_boot_params below is updated to accommodate E820 map
|
||||
* EFI memory map is converted to E820 map in this structure and passed
|
||||
* to Linux. This way the OS does not need to do the conversion.
|
||||
*/
|
||||
#define E820_RAM 1
|
||||
#define E820_RESERVED 2
|
||||
#define E820_ACPI 3
|
||||
#define E820_NVS 4
|
||||
#define E820_EXEC_CODE 5
|
||||
#define E820_MAX 128
|
||||
|
||||
struct e820entry {
|
||||
UINT64 addr; /* start of memory segment */
|
||||
UINT64 size; /* size of memory segment */
|
||||
UINT32 type; /* type of memory segment */
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
typedef union x86_64_boot_params {
|
||||
UINT8 raw[0x2000];
|
||||
struct {
|
||||
/* Cursor position before passing control to kernel. */
|
||||
/* 0x00 */ UINT8 orig_cursor_col; /* LDR */
|
||||
/* 0x01 */ UINT8 orig_cursor_row; /* LDR */
|
||||
|
||||
/* Available contiguous extended memory in KB. */
|
||||
/* 0x02 */ UINT16 ext_mem_k; /* LDR */
|
||||
|
||||
/* Video page, mode and screen width before passing control to kernel. */
|
||||
/* 0x04 */ UINT16 orig_video_page; /* LDR */
|
||||
/* 0x06 */ UINT8 orig_video_mode; /* LDR */
|
||||
/* 0x07 */ UINT8 orig_video_cols; /* LDR */
|
||||
|
||||
/* 0x08 */ UINT16 pad_1; /* unused */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x0A */ UINT16 orig_ega_bx; /* LDR */
|
||||
|
||||
/* 0x0C */ UINT16 pad_2; /* unused */
|
||||
|
||||
/* Screen height before passing control to kernel. */
|
||||
/* 0x0E */ UINT8 orig_video_rows; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x0F */ UINT8 is_vga; /* LDR */
|
||||
/* 0x10 */ UINT16 orig_video_points; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x12 */ UINT16 lfb_width; /* LDR */
|
||||
/* 0x14 */ UINT16 lfb_height; /* LDR */
|
||||
/* 0x16 */ UINT16 lfb_depth; /* LDR */
|
||||
/* 0x18 */ UINT32 lfb_base; /* LDR */
|
||||
/* 0x1C */ UINT32 lfb_size; /* LDR */
|
||||
|
||||
/* Offset of command line (from start of ia32_boot_param struct). */
|
||||
/* The command line magik number must be set for the kernel setup */
|
||||
/* code to use the command line offset. */
|
||||
/* 0x20 */ UINT16 cmdline_magik; /* LDR */
|
||||
#define CMDLINE_MAGIK 0xA33F
|
||||
/* 0x22 */ UINT16 cmdline_offset; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x24 */ UINT16 lfb_line_len; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x26 */ UINT8 lfb_red_size; /* LDR */
|
||||
/* 0x27 */ UINT8 lfb_red_pos; /* LDR */
|
||||
/* 0x28 */ UINT8 lfb_green_size; /* LDR */
|
||||
/* 0x29 */ UINT8 lfb_green_pos; /* LDR */
|
||||
/* 0x2A */ UINT8 lfb_blue_size; /* LDR */
|
||||
/* 0x2B */ UINT8 lfb_blue_pos; /* LDR */
|
||||
/* 0x2C */ UINT8 lfb_rsvd_size; /* LDR */
|
||||
/* 0x2D */ UINT8 lfb_rsvd_pos; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x2E */ UINT16 vesa_seg; /* LDR */
|
||||
/* 0x30 */ UINT16 vesa_off; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x32 */ UINT16 lfb_pages; /* LDR */
|
||||
/* 0x34 */ UINT8 lfb_reserved[0x0C]; /* reserved */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x40 */ UINT16 apm_bios_ver; /* LDR */
|
||||
#define NO_APM_BIOS 0x0000
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x42 */ UINT16 bios_code_seg; /* LDR */
|
||||
/* 0x44 */ UINT32 bios_entry_point; /* LDR */
|
||||
/* 0x48 */ UINT16 bios_code_seg16; /* LDR */
|
||||
/* 0x4A */ UINT16 bios_data_seg; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x4C */ UINT16 apm_bios_flags; /* LDR */
|
||||
#define NO_32BIT_APM_MASK 0xFFFD
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x4E */ UINT32 bios_code_len; /* LDR */
|
||||
/* 0x52 */ UINT16 bios_data_len; /* LDR */
|
||||
|
||||
/* 0x54 */ UINT8 pad_3[0x2C]; /* unused */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x80 */ UINT8 hd0_info[0x10]; /* LDR */
|
||||
/* 0x90 */ UINT8 hd1_info[0x10]; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0xA0 */ UINT16 mca_info_len; /* LDR */
|
||||
/* 0xA2 */ UINT8 mca_info_buf[0x10]; /* LDR */
|
||||
|
||||
/* 0xB2 */ UINT8 pad_4[0x10E]; /* unused */
|
||||
|
||||
/* EFI boot loader signature. */
|
||||
/* 0x1C0 */ UINT8 efi_loader_sig[4]; /* LDR */
|
||||
#define EFI_LOADER_SIG_X64 "EL64"
|
||||
|
||||
/* Address of the EFI system table. */
|
||||
/* 0x1C4 */ UINT32 efi_sys_tbl; /* LDR */
|
||||
|
||||
/* EFI memory descriptor size. */
|
||||
/* 0x1C8 */ UINT32 efi_mem_desc_size; /* LDR */
|
||||
|
||||
/* EFI memory descriptor version. */
|
||||
/* 0x1CC */ UINT32 efi_mem_desc_ver; /* LDR */
|
||||
|
||||
/* Address & size of EFI memory map. */
|
||||
/* 0x1D0 */ UINT32 efi_mem_map; /* LDR */
|
||||
/* 0x1D4 */ UINT32 efi_mem_map_size; /* LDR */
|
||||
|
||||
/* 0x1D8 */ UINT32 efi_sys_tbl_hi; /* LDR */
|
||||
/* 0x1DC */ UINT32 efi_mem_map_hi; /* LDR */
|
||||
|
||||
/* Available contiguous extended memory in KB. */
|
||||
/* 0x1E0 */ UINT32 alt_mem_k; /* LDR */
|
||||
|
||||
/* 0x1E4 */ UINT32 pad_51; /* unused */
|
||||
/* 0x1E8 */ UINT8 e820_nrmap;
|
||||
/* 0x1E9 */ UINT32 pad_52[2]; /* unused */
|
||||
|
||||
/* Size of setup code in sectors (1 sector == 512 bytes). */
|
||||
/* 0x1F1 */ UINT8 setup_sectors; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x1F2 */ UINT16 mount_root_rdonly; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x1F4 */ UINT32 sys_size; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x1F8 */ UINT16 ram_size_DNU; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x1FA */ UINT16 video_mode_flag; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x1FC */ UINT16 orig_root_dev; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x1FE */ UINT16 boot_flag; /* ? */
|
||||
|
||||
/* Jump past setup data (not used in EFI). */
|
||||
/* 0x200 */ UINT16 jump; /* BLD */
|
||||
|
||||
/* Setup data signature. */
|
||||
/* 0x202 */ UINT8 setup_sig[4]; /* BLD */
|
||||
#define SETUP_SIG "HdrS"
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x206 */ UINT8 hdr_minor; /* BLD */
|
||||
/* 0x207 */ UINT8 hdr_major; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x208 */ UINT32 rm_switch; /* LDD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x20C */ UINT16 start_sys_seg; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x20E */ UINT16 kernel_verstr_offset; /* BLD */
|
||||
|
||||
/* Loader type & version. */
|
||||
/* 0x210 */ UINT8 loader_type; /* LDR */
|
||||
#define LDRTYPE_ELILO 0x50 /* 5?h == elilo */
|
||||
/* ?0h == revision */
|
||||
|
||||
/* 0x211 */ UINT8 loader_flags; /* BLD and LDR */
|
||||
#define LDRFLAG_CAN_USE_HEAP 0x80
|
||||
#define LDRFLAG_BOOT_PARAM_RELOC 0x40
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x212 */ UINT16 setup_move_size; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x214 */ UINT32 kernel_start; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x218 */ UINT32 initrd_start; /* LDR */
|
||||
/* 0x21C */ UINT32 initrd_size; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x220 */ UINT32 bootsect_helper_DNU; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x224 */ UINT16 heap_end_ptr; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x226 */ UINT8 ext_loader_ver; /* LDR */
|
||||
/* 0x227 */ UINT8 ext_loader_type; /* LDR */
|
||||
|
||||
/* 0x228 */ UINT32 cmdline_addr; /* LDR */
|
||||
/* 0x22C */ UINT32 initrd_addr_max; /* BLD */
|
||||
/* 0x230 */ UINT32 kernel_alignment; /* BLD */
|
||||
/* 0x234 */ UINT8 relocatable_kernel; /* BLD */
|
||||
/* 0x235 */ UINT8 pad_8[3];
|
||||
/* 0x238 */ UINT32 pad_9[38];
|
||||
/* 0x2D0 */ UINT8 e820_map[2560];
|
||||
} s;
|
||||
} boot_params_t;
|
||||
#pragma pack()
|
||||
|
||||
/*
|
||||
* The stuff below here is for jumping to the kernel.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some macros to copy and set memory after EFI has been
|
||||
* stopped.
|
||||
*/
|
||||
|
||||
#define MEMCPY(to, from, cnt) { \
|
||||
UINT8 *t = (UINT8 *)(to); \
|
||||
UINT8 *f = (UINT8 *)(from); \
|
||||
UINTN n = cnt; \
|
||||
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--; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MEMSET(ptr, size, val) { \
|
||||
UINT8 *p = (UINT8 *)(ptr); \
|
||||
UINTN n = (UINTN)(size); \
|
||||
UINT8 v = (UINT8)(val); \
|
||||
if (p && n) { \
|
||||
while (n--) { \
|
||||
*p++ = v; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* Descriptor table pointer format.
|
||||
*/
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UINT16 limit;
|
||||
UINT64 base;
|
||||
} dt_addr_t;
|
||||
#pragma pack()
|
||||
|
||||
extern UINTN high_base_mem;
|
||||
extern UINTN high_ext_mem;
|
||||
|
||||
extern boot_params_t *param_start;
|
||||
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;
|
||||
|
||||
extern dt_addr_t gdt_addr;
|
||||
extern dt_addr_t idt_addr;
|
||||
|
||||
extern UINT16 init_gdt[];
|
||||
extern UINTN sizeof_init_gdt;
|
||||
|
||||
extern UINT8 rmswitch_image[];
|
||||
extern UINTN rmswitch_size;
|
||||
|
||||
extern INTN x86_64_use_legacy_free_boot();
|
||||
extern INTN x86_64_text_mode();
|
||||
|
||||
/*
|
||||
* How to jump to kernel code
|
||||
*/
|
||||
|
||||
|
||||
static inline void
|
||||
start_kernel(VOID *kentry, boot_params_t *bp)
|
||||
{
|
||||
struct {
|
||||
UINT32 kernel_entry;
|
||||
UINT16 kernel_cs;
|
||||
} jumpvector;
|
||||
VOID *jump_start;
|
||||
|
||||
/*
|
||||
* Disable interrupts.
|
||||
*/
|
||||
asm volatile ( "cli" : : );
|
||||
|
||||
/*
|
||||
* Relocate kernel (if needed).
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy boot sector, setup data and command line
|
||||
* to final resting place. We need to copy
|
||||
* BOOT_PARAM_MEMSIZE bytes.
|
||||
*/
|
||||
|
||||
MEMCPY(high_base_mem, bp, 0x4000);
|
||||
|
||||
bp = (boot_params_t *)high_base_mem;
|
||||
bp->s.cmdline_addr = high_base_mem + bp->s.cmdline_offset;
|
||||
|
||||
/*
|
||||
* Initialize Linux GDT.
|
||||
*/
|
||||
|
||||
MEMSET(gdt_addr.base, gdt_addr.limit, 0);
|
||||
MEMCPY(gdt_addr.base, init_gdt, sizeof_init_gdt);
|
||||
|
||||
// fixme: why x86_64_use_legacy_free_boot() goes to _relocate?
|
||||
#if 0
|
||||
if (! x86_64_use_legacy_free_boot()) {
|
||||
|
||||
/*
|
||||
* Copy our real mode transition code to 0x7C00.
|
||||
*/
|
||||
|
||||
MEMCPY(0x7C00, rmswitch_image, rmswitch_size);
|
||||
|
||||
asm volatile ( "mov $0x7C00, %%rbx" : : );
|
||||
asm volatile ( "jmp *%%rbx" : : );
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Load descriptor table pointers.
|
||||
*/
|
||||
|
||||
asm volatile ( "lidt %0" : : "m" (idt_addr) );
|
||||
asm volatile ( "lgdt %0" : : "m" (gdt_addr) );
|
||||
|
||||
/*
|
||||
* rsi := address of boot sector and setup data
|
||||
*/
|
||||
|
||||
asm volatile ( "mov %0, %%rsi" : : "m" (high_base_mem) );
|
||||
|
||||
/*
|
||||
* Jump to kernel entry point.
|
||||
*
|
||||
* Cast is to tell gcc that we know we're going from
|
||||
* 64-bit ptr to 32-bit integer.
|
||||
*/
|
||||
jumpvector.kernel_entry=(UINT32)((UINT64)kentry);
|
||||
jumpvector.kernel_cs=0x10;
|
||||
jump_start = (VOID *)&jumpvector;
|
||||
//asm volatile ( "mov %0, %%rcx" : : "m" (&jumpvector) );
|
||||
asm volatile ( "mov %0, %%rcx" : : "m" (jump_start) );
|
||||
asm volatile ( "ljmp *(%%rcx)" : :);
|
||||
/* Never come back to here. */
|
||||
}
|
||||
|
||||
typedef struct sys_img_options {
|
||||
UINT8 dummy; /* forces non-zero offset for first field */
|
||||
UINT8 text_mode; /* do not try to initialize Graphics Output Protocol */
|
||||
} sys_img_options_t;
|
||||
|
||||
#endif /* __ELILO_SYSDEPS_X86_64_H__ */
|
|
@ -0,0 +1,976 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2003 Hewlett-Packard Co.
|
||||
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Contributed by Mike Johnston <johnston@intel.com>
|
||||
* Contributed by Chris Ahna <christopher.j.ahna@intel.com>
|
||||
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
|
||||
* Contributed by Bibo Mao <bibo.mao@intel.com>
|
||||
* Contributed by chandramouli narayanan <mouli@linux.intel.com>
|
||||
* Edgar Hucek <hostmaster@ed-soft.at>
|
||||
*
|
||||
* Updated with code to fill bootparam converting EFI memory map to E820
|
||||
* based on a Linux kernel patch provided by Edgar Hucek
|
||||
* - mouli 06/20/2007
|
||||
*
|
||||
* This file is part of the ELILO, the EFI Linux boot loader.
|
||||
*
|
||||
* ELILO is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* ELILO is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ELILO; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Please check out the elilo.txt for complete documentation on how
|
||||
* to use this program.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains all the x86_64 specific code expected by generic loader
|
||||
*/
|
||||
#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;
|
||||
|
||||
/*
|
||||
* Descriptor table base addresses & limits for Linux startup.
|
||||
*/
|
||||
|
||||
dt_addr_t gdt_addr = { 0x800, 0x94000 };
|
||||
dt_addr_t idt_addr = { 0, 0 };
|
||||
|
||||
/*
|
||||
* Initial GDT layout for Linux startup.
|
||||
*/
|
||||
|
||||
UINT16 init_gdt[] = {
|
||||
/* gdt[0]: dummy */
|
||||
0, 0, 0, 0,
|
||||
|
||||
/* gdt[1]: unused */
|
||||
0, 0, 0, 0,
|
||||
|
||||
/* gdt[2]: code */
|
||||
0xFFFF, /* 4Gb - (0x100000*0x1000 = 4Gb) */
|
||||
0x0000, /* base address=0 */
|
||||
0x9A00, /* code read/exec */
|
||||
0x00CF, /* granularity=4096, 386 (+5th nibble of limit) */
|
||||
|
||||
/* gdt[3]: data */
|
||||
0xFFFF, /* 4Gb - (0x100000*0x1000 = 4Gb) */
|
||||
0x0000, /* base address=0 */
|
||||
0x9200, /* data read/write */
|
||||
0x00CF, /* granularity=4096, 386 (+5th nibble of limit) */
|
||||
};
|
||||
|
||||
UINTN sizeof_init_gdt = sizeof init_gdt;
|
||||
|
||||
/*
|
||||
* Highest available base memory address.
|
||||
*
|
||||
* For traditional kernels and loaders this is always at 0x90000.
|
||||
* For updated kernels and loaders this is computed by taking the
|
||||
* highest available base memory address and rounding down to the
|
||||
* nearest 64 kB boundary and then subtracting 64 kB.
|
||||
*
|
||||
* A non-compressed kernel is automatically assumed to be an updated
|
||||
* kernel. A compressed kernel that has bit 6 (0x40) set in the
|
||||
* loader_flags field is also assumed to be an updated kernel.
|
||||
*/
|
||||
|
||||
UINTN high_base_mem = 0x90000;
|
||||
|
||||
/*
|
||||
* Highest available extended memory address.
|
||||
*
|
||||
* This is computed by taking the highest available extended memory
|
||||
* address and rounding down to the nearest EFI_PAGE_SIZE (usually
|
||||
* 4 kB) boundary.
|
||||
* This is only used for backward compatibility.
|
||||
*/
|
||||
|
||||
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 *)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;
|
||||
|
||||
INTN e820_map_overflow = 0;
|
||||
|
||||
INTN
|
||||
sysdeps_init(EFI_HANDLE dev)
|
||||
{
|
||||
DBG_PRT((L"sysdeps_init()\n"));
|
||||
|
||||
/*
|
||||
* Register our loader(s)...
|
||||
*/
|
||||
|
||||
loader_register(&bzimage_loader);
|
||||
loader_register(&plain_loader);
|
||||
loader_register(&gzip_loader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* initrd_get_addr()
|
||||
* Compute a starting address for the initial RAMdisk image.
|
||||
* For now we suggest 'initrd_addr_max' with room for 32MB,
|
||||
* as image->pgcnt is not initialized yet.
|
||||
*/
|
||||
INTN
|
||||
sysdeps_initrd_get_addr(kdesc_t *kd, memdesc_t *imem)
|
||||
{
|
||||
DBG_PRT((L"initrd_get_addr()\n"));
|
||||
|
||||
if (!kd || !imem) {
|
||||
ERR_PRT((L"kd="PTR_FMT" imem="PTR_FMT"", kd, imem));
|
||||
return -1;
|
||||
}
|
||||
|
||||
VERB_PRT(3, Print(L"initrd_addr_max="PTR_FMT" reserve=%d\n",
|
||||
param_start->s.initrd_addr_max, 32*MB));
|
||||
|
||||
imem->start_addr = (VOID *)
|
||||
(((UINT64)param_start->s.initrd_addr_max - 32*MB + 1)
|
||||
& ~EFI_PAGE_MASK);
|
||||
|
||||
VERB_PRT(3, Print(L"initrd start_addr="PTR_FMT" pgcnt=%d\n",
|
||||
imem->start_addr, imem->pgcnt));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* checkfix_initrd()
|
||||
* Check and possibly fix allocation of initrd memory.
|
||||
*/
|
||||
VOID *
|
||||
sysdeps_checkfix_initrd(VOID *start_addr, memdesc_t *imem)
|
||||
{
|
||||
UINTN pgcnt = EFI_SIZE_TO_PAGES(imem->size);
|
||||
UINT64 initrd_addr_max = (UINT64)param_start->s.initrd_addr_max;
|
||||
UINT64 ki_max = initrd_addr_max - imem->size + 1;
|
||||
VOID *ki_max_addr;
|
||||
|
||||
VERB_PRT( 3, Print(L"loadfile: start_addr="PTR_FMT
|
||||
" ki_max_addr="PTR_FMT"\n", start_addr, (VOID *)ki_max));
|
||||
if (ki_max > UINT32_MAX) {
|
||||
ERR_PRT((L"Force kernel specified initrd_addr_max="PTR_FMT
|
||||
" below 4GB\n", (VOID *)initrd_addr_max));
|
||||
ki_max = UINT32_MAX - imem->size + 1;
|
||||
}
|
||||
ki_max_addr = (VOID *)ki_max;
|
||||
|
||||
if ((UINT64)start_addr > ki_max) {
|
||||
VERB_PRT(1, Print(L"initrd start_addr="PTR_FMT" above "
|
||||
"limit="PTR_FMT"\n", start_addr, ki_max_addr));
|
||||
free(start_addr);
|
||||
start_addr = NULL;
|
||||
}
|
||||
/* so either the initial allocation failed or it's been to high! */
|
||||
if (start_addr == NULL) {
|
||||
start_addr = alloc_pages(pgcnt, EfiLoaderData,
|
||||
AllocateMaxAddress, ki_max_addr);
|
||||
}
|
||||
if ((UINT64)start_addr > ki_max) {
|
||||
ERR_PRT((L"Failed to allocate %d pages below %dMB",
|
||||
pgcnt, (param_start->s.initrd_addr_max+1)>>20));
|
||||
free(start_addr);
|
||||
start_addr = NULL;
|
||||
}
|
||||
return start_addr;
|
||||
}
|
||||
|
||||
VOID
|
||||
sysdeps_free_boot_params(boot_params_t *bp)
|
||||
{
|
||||
mmap_desc_t md;
|
||||
|
||||
ZeroMem(&md, sizeof md);
|
||||
md.md = (VOID *)(UINT64)bp->s.efi_mem_map;
|
||||
free_memmap(&md);
|
||||
}
|
||||
|
||||
static VOID find_bits(unsigned long mask, UINT8 *first, UINT8* len) {
|
||||
unsigned char bit_pos = 0, bit_len = 0;
|
||||
*first =0;
|
||||
*len = 0;
|
||||
if (mask == 0)
|
||||
return;
|
||||
while (!(mask & 0x1)) {
|
||||
mask = mask >> 1;
|
||||
bit_pos++;
|
||||
}
|
||||
while (mask & 0x1) {
|
||||
mask = mask >> 1;
|
||||
bit_len++;
|
||||
}
|
||||
*first = bit_pos;
|
||||
*len = bit_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get video information.
|
||||
*/
|
||||
static INTN get_video_info(boot_params_t * bp) {
|
||||
EFI_GUID GopProtocol = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop_interface;
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Gop_info;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Gop_mode = NULL;
|
||||
EFI_HANDLE *Gop_handle = NULL;
|
||||
EFI_STATUS efi_status;
|
||||
UINTN size = 0;
|
||||
UINTN size1;
|
||||
UINT8 i;
|
||||
|
||||
if (x86_64_text_mode() == 1) {
|
||||
Print((L"Skip GOP init, force text-mode.\n"));
|
||||
return -1;
|
||||
}
|
||||
efi_status = uefi_call_wrapper(
|
||||
BS->LocateHandle,
|
||||
5,
|
||||
ByProtocol,
|
||||
&GopProtocol,
|
||||
NULL,
|
||||
&size,
|
||||
(VOID **)Gop_handle);
|
||||
|
||||
if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL) {
|
||||
Print(L"LocateHandle GopProtocol failed.\n");
|
||||
Print(L"--Either no graphics head is installed,\n" \
|
||||
"--efi console is set to serial, or,\n" \
|
||||
"--the EFI firmware version of this machine is\n" \
|
||||
"--older than UEFI 2.0. and does not support GOP");
|
||||
Print(L"you can SAFELY IGNORE this error. elilo will\n" \
|
||||
"default to text-mode.\n Alternatively you can " \
|
||||
"now force text mode by setting config variable\n" \
|
||||
"text_mode=1 for x86 in elilo.conf or via cmdline.\n\n");
|
||||
Print(L"However if this is the last text output you see\n" \
|
||||
"ensure that your kernel console command line\n " \
|
||||
"variable matches up with the actual efi boot menu\n" \
|
||||
"console output settings.\n\n");
|
||||
return -1;
|
||||
}
|
||||
Gop_handle = alloc(size, 0);
|
||||
efi_status = uefi_call_wrapper(
|
||||
BS->LocateHandle,
|
||||
5,
|
||||
ByProtocol,
|
||||
&GopProtocol,
|
||||
NULL,
|
||||
&size,
|
||||
(VOID **)Gop_handle);
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
ERR_PRT((L"LocateHandle GopProtocol failed."));
|
||||
free(Gop_handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=0; i < size/sizeof(EFI_HANDLE); i++) {
|
||||
Gop_handle += i;
|
||||
efi_status = uefi_call_wrapper(
|
||||
BS->HandleProtocol,
|
||||
3,
|
||||
*Gop_handle,
|
||||
&GopProtocol,
|
||||
&Gop_interface);
|
||||
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
continue;
|
||||
}
|
||||
Gop_mode = Gop_interface->Mode;
|
||||
efi_status = uefi_call_wrapper(
|
||||
Gop_interface->QueryMode,
|
||||
4,
|
||||
Gop_interface,
|
||||
Gop_mode->Mode,
|
||||
&size1,
|
||||
&Gop_info);
|
||||
if (!EFI_ERROR(efi_status))
|
||||
break;
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (EFI_ERROR(efi_status) || i > (size/sizeof(EFI_HANDLE))) {
|
||||
ERR_PRT((L"HandleProtocol GopProtocol failed."));
|
||||
free(Gop_handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bp->s.is_vga = 0x70;
|
||||
bp->s.orig_cursor_col = 0;
|
||||
bp->s.orig_cursor_row = 0;
|
||||
bp->s.orig_video_page = 0;
|
||||
bp->s.orig_video_mode = 0;
|
||||
bp->s.orig_video_cols = 0;
|
||||
bp->s.orig_video_rows = 0;
|
||||
bp->s.orig_ega_bx = 0;
|
||||
bp->s.orig_video_points = 0;
|
||||
|
||||
bp->s.lfb_width = Gop_info->HorizontalResolution;
|
||||
bp->s.lfb_height = Gop_info->VerticalResolution;
|
||||
bp->s.lfb_base = Gop_mode->FrameBufferBase;
|
||||
bp->s.lfb_size = Gop_mode->FrameBufferSize;
|
||||
bp->s.lfb_pages = 1;
|
||||
bp->s.vesa_seg = 0;
|
||||
bp->s.vesa_off = 0;
|
||||
if (Gop_info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
|
||||
bp->s.lfb_depth = 32;
|
||||
bp->s.lfb_red_size = 8;
|
||||
bp->s.lfb_red_pos = 0;
|
||||
bp->s.lfb_green_size = 8;
|
||||
bp->s.lfb_green_pos = 8;
|
||||
bp->s.lfb_blue_size = 8;
|
||||
bp->s.lfb_blue_pos = 16;
|
||||
bp->s.lfb_rsvd_size = 8;
|
||||
bp->s.lfb_rsvd_pos = 24;
|
||||
bp->s.lfb_line_len = Gop_info->PixelsPerScanLine * 4;
|
||||
|
||||
} else if (Gop_info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
|
||||
bp->s.lfb_depth = 32;
|
||||
bp->s.lfb_red_size = 8;
|
||||
bp->s.lfb_red_pos = 16;
|
||||
bp->s.lfb_green_size = 8;
|
||||
bp->s.lfb_green_pos = 8;
|
||||
bp->s.lfb_blue_size = 8;
|
||||
bp->s.lfb_blue_pos = 0;
|
||||
bp->s.lfb_rsvd_size = 8;
|
||||
bp->s.lfb_rsvd_pos = 24;
|
||||
bp->s.lfb_line_len = Gop_info->PixelsPerScanLine * 4;
|
||||
} else if (Gop_info->PixelFormat == PixelBitMask) {
|
||||
find_bits(Gop_info->PixelInformation.RedMask,
|
||||
&bp->s.lfb_red_pos, &bp->s.lfb_red_size);
|
||||
find_bits(Gop_info->PixelInformation.GreenMask,
|
||||
&bp->s.lfb_green_pos, &bp->s.lfb_green_size);
|
||||
find_bits(Gop_info->PixelInformation.BlueMask,
|
||||
&bp->s.lfb_blue_pos, &bp->s.lfb_blue_size);
|
||||
find_bits(Gop_info->PixelInformation.ReservedMask,
|
||||
&bp->s.lfb_rsvd_pos, &bp->s.lfb_rsvd_size);
|
||||
bp->s.lfb_depth = bp->s.lfb_red_size + bp->s.lfb_green_size +
|
||||
bp->s.lfb_blue_size + bp->s.lfb_rsvd_size;
|
||||
bp->s.lfb_line_len = (Gop_info->PixelsPerScanLine * bp->s.lfb_depth) / 8;
|
||||
} else {
|
||||
bp->s.lfb_depth = 4;
|
||||
bp->s.lfb_red_size = 0;
|
||||
bp->s.lfb_red_pos = 0;
|
||||
bp->s.lfb_green_size = 0;
|
||||
bp->s.lfb_green_pos = 0;
|
||||
bp->s.lfb_blue_size = 0;
|
||||
bp->s.lfb_blue_pos = 0;
|
||||
bp->s.lfb_rsvd_size = 0;
|
||||
bp->s.lfb_rsvd_pos = 0;
|
||||
bp->s.lfb_line_len = bp->s.lfb_width / 2;
|
||||
}
|
||||
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,
|
||||
unsigned long long start,
|
||||
unsigned long size,
|
||||
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"));
|
||||
|
||||
/* 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].size += size;
|
||||
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)
|
||||
{
|
||||
int nr_map, e820_nr_map = 0, i;
|
||||
UINT64 start, end, size;
|
||||
EFI_MEMORY_DESCRIPTOR *md, *p;
|
||||
struct e820entry *e820_map;
|
||||
|
||||
nr_map = mdesc->map_size/mdesc->desc_size;
|
||||
e820_map = (struct e820entry *)bp->s.e820_map;
|
||||
|
||||
for (i = 0, p = mdesc->md; i < nr_map; i++)
|
||||
{
|
||||
md = p;
|
||||
switch (md->Type) {
|
||||
case EfiACPIReclaimMemory:
|
||||
add_memory_region(e820_map, &e820_nr_map,
|
||||
md->PhysicalStart,
|
||||
md->NumberOfPages << EFI_PAGE_SHIFT,
|
||||
E820_ACPI);
|
||||
break;
|
||||
case EfiRuntimeServicesCode:
|
||||
add_memory_region(e820_map, &e820_nr_map,
|
||||
md->PhysicalStart,
|
||||
md->NumberOfPages << EFI_PAGE_SHIFT,
|
||||
E820_EXEC_CODE);
|
||||
break;
|
||||
case EfiRuntimeServicesData:
|
||||
case EfiReservedMemoryType:
|
||||
case EfiMemoryMappedIO:
|
||||
case EfiMemoryMappedIOPortSpace:
|
||||
case EfiUnusableMemory:
|
||||
case EfiPalCode:
|
||||
add_memory_region(e820_map, &e820_nr_map,
|
||||
md->PhysicalStart,
|
||||
md->NumberOfPages << EFI_PAGE_SHIFT,
|
||||
E820_RESERVED);
|
||||
break;
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiConventionalMemory:
|
||||
start = md->PhysicalStart;
|
||||
size = md->NumberOfPages << EFI_PAGE_SHIFT;
|
||||
end = start + size;
|
||||
/* Fix up for BIOS that claims RAM in 640K-1MB region */
|
||||
if (start < 0x100000ULL && end > 0xA0000ULL) {
|
||||
if (start < 0xA0000ULL) {
|
||||
/* start < 640K
|
||||
* set memory map from start to 640K
|
||||
*/
|
||||
add_memory_region(e820_map,
|
||||
&e820_nr_map,
|
||||
start,
|
||||
0xA0000ULL-start,
|
||||
E820_RAM);
|
||||
}
|
||||
if (end <= 0x100000ULL)
|
||||
continue;
|
||||
/* end > 1MB
|
||||
* set memory map avoiding 640K to 1MB hole
|
||||
*/
|
||||
start = 0x100000ULL;
|
||||
size = end - start;
|
||||
}
|
||||
add_memory_region(e820_map, &e820_nr_map,
|
||||
start, size, E820_RAM);
|
||||
break;
|
||||
case EfiACPIMemoryNVS:
|
||||
add_memory_region(e820_map, &e820_nr_map,
|
||||
md->PhysicalStart,
|
||||
md->NumberOfPages << EFI_PAGE_SHIFT,
|
||||
E820_NVS);
|
||||
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,
|
||||
E820_RESERVED);
|
||||
break;
|
||||
}
|
||||
p = NextMemoryDescriptor(p, mdesc->desc_size);
|
||||
}
|
||||
bp->s.e820_nrmap = e820_nr_map;
|
||||
}
|
||||
|
||||
/*
|
||||
* x86_64 specific boot parameters initialization routine
|
||||
*
|
||||
* Note: debug and verbose messages have already been turned off!
|
||||
*/
|
||||
INTN
|
||||
sysdeps_create_boot_params(
|
||||
boot_params_t *bp,
|
||||
CHAR8 *cmdline,
|
||||
memdesc_t *initrd,
|
||||
memdesc_t *vmcode,
|
||||
UINTN *cookie)
|
||||
{
|
||||
mmap_desc_t mdesc;
|
||||
EFI_STATUS efi_status;
|
||||
UINTN rows, cols;
|
||||
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"));
|
||||
|
||||
if (!bp || !cmdline || !initrd || !cookie) {
|
||||
ERR_PRT((L"bp="PTR_FMT" cmdline="PTR_FMT" initrd="PTR_FMT" cookie="PTR_FMT"",
|
||||
bp, cmdline, initrd, cookie));
|
||||
|
||||
if (param_start != NULL) {
|
||||
free(param_start);
|
||||
param_start = NULL;
|
||||
param_size = 0;
|
||||
}
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy temporary boot sector and setup data storage to
|
||||
* elilo allocated boot parameter storage. We only need
|
||||
* the first two sectors (1K). The rest of the storage
|
||||
* can be used by the command line.
|
||||
*/
|
||||
if (param_start != NULL) {
|
||||
CopyMem(bp, param_start, 0x2000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save off our header revision information.
|
||||
*/
|
||||
hdr_version = (bp->s.hdr_major << 8) | bp->s.hdr_minor;
|
||||
|
||||
/*
|
||||
* Do NOT clear out unknown memory in boot sector image.
|
||||
* This breaks boot protocol >= 2.10 (2.6.31).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tell kernel this was loaded by an advanced loader type.
|
||||
* If this field is zero, the initrd_start and initrd_size
|
||||
* fields are ignored by the kernel.
|
||||
*/
|
||||
|
||||
bp->s.loader_type = LDRTYPE_ELILO;
|
||||
|
||||
/*
|
||||
* Setup command line information.
|
||||
*/
|
||||
|
||||
bp->s.cmdline_magik = CMDLINE_MAGIK;
|
||||
bp->s.cmdline_offset = (UINT8 *)cmdline - (UINT8 *)bp;
|
||||
|
||||
/*
|
||||
* Clear out the cmdline_addr field so the kernel can find
|
||||
* the cmdline.
|
||||
*/
|
||||
bp->s.cmdline_addr = 0x0;
|
||||
|
||||
/*
|
||||
* Setup hard drive parameters.
|
||||
* %%TBD - It should be okay to zero fill the hard drive
|
||||
* info buffers. The kernel should do its own detection.
|
||||
*/
|
||||
|
||||
ZeroMem(bp->s.hd0_info, sizeof bp->s.hd0_info);
|
||||
ZeroMem(bp->s.hd1_info, sizeof bp->s.hd1_info);
|
||||
|
||||
/*
|
||||
* Memory info.
|
||||
*/
|
||||
|
||||
bp->s.alt_mem_k = high_ext_mem / 1024;
|
||||
|
||||
if (bp->s.alt_mem_k <= 65535)
|
||||
bp->s.ext_mem_k = (UINT16)bp->s.alt_mem_k;
|
||||
else
|
||||
bp->s.ext_mem_k = 65535;
|
||||
|
||||
/*
|
||||
* Initial RAMdisk and root device stuff.
|
||||
*/
|
||||
|
||||
DBG_PRT((L"initrd->start_addr="PTR_FMT" initrd->pgcnt=%d\n",
|
||||
initrd->start_addr, initrd->pgcnt));
|
||||
|
||||
/* 'ramdisk_flags' (@0x1F8) is called 'ram_size' in the meantime, */
|
||||
/* see Documentation/x86/boot.txt. */
|
||||
if (initrd->start_addr && initrd->pgcnt) {
|
||||
if ( (UINT64)initrd->start_addr > UINT32_MAX ) {
|
||||
ERR_PRT((L"Start of initrd out of reach (>4GB)."));
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
/* %%TBD - This will probably have to be changed. */
|
||||
bp->s.initrd_start = (UINT32)(UINT64)initrd->start_addr;
|
||||
bp->s.initrd_size = (UINT32)(initrd->size);
|
||||
} else {
|
||||
bp->s.initrd_start = 0;
|
||||
bp->s.initrd_size = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* APM BIOS info.
|
||||
*/
|
||||
bp->s.apm_bios_ver = NO_APM_BIOS;
|
||||
bp->s.bios_code_seg = 0;
|
||||
bp->s.bios_entry_point = 0;
|
||||
bp->s.bios_code_seg16 = 0;
|
||||
bp->s.bios_data_seg = 0;
|
||||
bp->s.apm_bios_flags = 0;
|
||||
bp->s.bios_code_len = 0;
|
||||
bp->s.bios_data_len = 0;
|
||||
|
||||
/*
|
||||
* MCA BIOS info (misnomer).
|
||||
*/
|
||||
bp->s.mca_info_len = 0;
|
||||
ZeroMem(bp->s.mca_info_buf, sizeof bp->s.mca_info_buf);
|
||||
|
||||
/*
|
||||
* EFI loader signature
|
||||
*/
|
||||
CopyMem(bp->s.efi_loader_sig, EFI_LOADER_SIG_X64, 4);
|
||||
|
||||
/*
|
||||
* Kernel entry point.
|
||||
*/
|
||||
if ( (UINT64)kernel_start != (UINT32)(UINT64)kernel_start ) {
|
||||
ERR_PRT((L"Start of kernel (will be) out of reach (>4GB)."));
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
bp->s.kernel_start = (UINT32)(UINT64)kernel_start;
|
||||
|
||||
/*
|
||||
* When changing stuff in the parameter structure compare
|
||||
* the offsets of the fields with the offsets used in the
|
||||
* boot sector and setup source files.
|
||||
* arch/x86_64/boot/bootsect.S
|
||||
* arch/x86_64/boot/setup.S
|
||||
* arch/x86_64/kernel/setup.c
|
||||
* include/asm-x86_64/setup.h (2.5/2.6)
|
||||
*/
|
||||
|
||||
#define CHECK_OFFSET(n, o, f) \
|
||||
{ \
|
||||
UINTN p = (UINT8 *)&bp->s.n - (UINT8 *)bp; \
|
||||
UINTN q = (UINTN)(o); \
|
||||
if (p != q) { \
|
||||
test |= 1; \
|
||||
Print(L"%20a: %3xh %3xh ", #n, p, q); \
|
||||
if (*f) { \
|
||||
Print(f, bp->s.n); \
|
||||
} \
|
||||
Print(L"\n"); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define WAIT_FOR_KEY() \
|
||||
{ \
|
||||
EFI_INPUT_KEY key; \
|
||||
while (uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &key) != EFI_SUCCESS) { \
|
||||
; \
|
||||
} \
|
||||
}
|
||||
{
|
||||
UINTN test = 0;
|
||||
|
||||
CHECK_OFFSET(orig_cursor_col, 0x00, L"%xh");
|
||||
CHECK_OFFSET(orig_cursor_row, 0x01, L"%xh");
|
||||
CHECK_OFFSET(ext_mem_k, 0x02, L"%xh");
|
||||
CHECK_OFFSET(orig_video_page, 0x04, L"%xh");
|
||||
CHECK_OFFSET(orig_video_mode, 0x06, L"%xh");
|
||||
CHECK_OFFSET(orig_video_cols, 0x07, L"%xh");
|
||||
CHECK_OFFSET(orig_ega_bx, 0x0A, L"%xh");
|
||||
CHECK_OFFSET(orig_video_rows, 0x0E, L"%xh");
|
||||
CHECK_OFFSET(is_vga, 0x0F, L"%xh");
|
||||
CHECK_OFFSET(orig_video_points, 0x10, L"%xh");
|
||||
CHECK_OFFSET(lfb_width, 0x12, L"%xh");
|
||||
CHECK_OFFSET(lfb_height, 0x14, L"%xh");
|
||||
CHECK_OFFSET(lfb_depth, 0x16, L"%xh");
|
||||
CHECK_OFFSET(lfb_base, 0x18, L"%xh");
|
||||
CHECK_OFFSET(lfb_size, 0x1C, L"%xh");
|
||||
CHECK_OFFSET(cmdline_magik, 0x20, L"%xh");
|
||||
CHECK_OFFSET(cmdline_offset, 0x22, L"%xh");
|
||||
CHECK_OFFSET(lfb_line_len, 0x24, L"%xh");
|
||||
CHECK_OFFSET(lfb_red_size, 0x26, L"%xh");
|
||||
CHECK_OFFSET(lfb_red_pos, 0x27, L"%xh");
|
||||
CHECK_OFFSET(lfb_green_size, 0x28, L"%xh");
|
||||
CHECK_OFFSET(lfb_green_pos, 0x29, L"%xh");
|
||||
CHECK_OFFSET(lfb_blue_size, 0x2A, L"%xh");
|
||||
CHECK_OFFSET(lfb_blue_pos, 0x2B, L"%xh");
|
||||
CHECK_OFFSET(lfb_rsvd_size, 0x2C, L"%xh");
|
||||
CHECK_OFFSET(lfb_rsvd_pos, 0x2D, L"%xh");
|
||||
CHECK_OFFSET(vesa_seg, 0x2E, L"%xh");
|
||||
CHECK_OFFSET(vesa_off, 0x30, L"%xh");
|
||||
CHECK_OFFSET(lfb_pages, 0x32, L"%xh");
|
||||
CHECK_OFFSET(lfb_reserved, 0x34, L"");
|
||||
CHECK_OFFSET(apm_bios_ver, 0x40, L"%xh");
|
||||
CHECK_OFFSET(bios_code_seg, 0x42, L"%xh");
|
||||
CHECK_OFFSET(bios_entry_point, 0x44, L"%xh");
|
||||
CHECK_OFFSET(bios_code_seg16, 0x48, L"%xh");
|
||||
CHECK_OFFSET(bios_data_seg, 0x4A, L"%xh");
|
||||
CHECK_OFFSET(apm_bios_flags, 0x4C, L"%xh");
|
||||
CHECK_OFFSET(bios_code_len, 0x4E, L"%xh");
|
||||
CHECK_OFFSET(bios_data_len, 0x52, L"%xh");
|
||||
CHECK_OFFSET(hd0_info, 0x80, L"");
|
||||
CHECK_OFFSET(hd1_info, 0x90, L"");
|
||||
CHECK_OFFSET(mca_info_len, 0xA0, L"%xh");
|
||||
CHECK_OFFSET(mca_info_buf, 0xA2, L"");
|
||||
CHECK_OFFSET(efi_loader_sig, 0x1C0, L"'%-4.4a'");
|
||||
CHECK_OFFSET(efi_sys_tbl, 0x1C4, L"%xh");
|
||||
CHECK_OFFSET(efi_mem_desc_size, 0x1C8, L"%xh");
|
||||
CHECK_OFFSET(efi_mem_desc_ver, 0x1CC, L"%xh");
|
||||
CHECK_OFFSET(efi_mem_map, 0x1D0, L"%xh");
|
||||
CHECK_OFFSET(efi_mem_map_size, 0x1D4, L"%xh");
|
||||
CHECK_OFFSET(efi_sys_tbl_hi, 0x1D8, L"%xh");
|
||||
CHECK_OFFSET(efi_mem_map_hi, 0x1DC, L"%xh");
|
||||
CHECK_OFFSET(alt_mem_k, 0x1E0, L"%xh");
|
||||
CHECK_OFFSET(setup_sectors, 0x1F1, L"%xh");
|
||||
CHECK_OFFSET(mount_root_rdonly, 0x1F2, L"%xh");
|
||||
CHECK_OFFSET(sys_size, 0x1F4, L"%xh");
|
||||
CHECK_OFFSET(video_mode_flag, 0x1FA, L"%xh");
|
||||
CHECK_OFFSET(orig_root_dev, 0x1FC, L"%xh");
|
||||
CHECK_OFFSET(boot_flag, 0x1FE, L"%xh");
|
||||
CHECK_OFFSET(jump, 0x200, L"%xh");
|
||||
CHECK_OFFSET(setup_sig, 0x202, L"'%-4.4a'");
|
||||
CHECK_OFFSET(hdr_minor, 0x206, L"%xh");
|
||||
CHECK_OFFSET(hdr_major, 0x207, L"%xh");
|
||||
CHECK_OFFSET(rm_switch, 0x208, L"%xh");
|
||||
CHECK_OFFSET(start_sys_seg, 0x20C, L"%xh");
|
||||
CHECK_OFFSET(kernel_verstr_offset, 0x20E, L"%xh");
|
||||
CHECK_OFFSET(loader_type, 0x210, L"%xh");
|
||||
CHECK_OFFSET(loader_flags, 0x211, L"%xh");
|
||||
CHECK_OFFSET(setup_move_size, 0x212, L"%xh");
|
||||
CHECK_OFFSET(kernel_start, 0x214, L"%xh");
|
||||
CHECK_OFFSET(initrd_start, 0x218, L"%xh");
|
||||
CHECK_OFFSET(initrd_size, 0x21C, L"%xh");
|
||||
CHECK_OFFSET(heap_end_ptr, 0x224, L"%xh");
|
||||
CHECK_OFFSET(cmdline_addr, 0x228, L"%xh");
|
||||
CHECK_OFFSET(e820_map, 0x2D0, L"%xh");
|
||||
|
||||
if (test) {
|
||||
ERR_PRT((L"Boot sector and/or setup parameter alignment error."));
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get video information.
|
||||
* Do this last so that any other cursor positioning done
|
||||
* in the fill routine gets accounted for.
|
||||
*/
|
||||
|
||||
if (!get_video_info(bp)) goto do_memmap;
|
||||
|
||||
/* Do the old text mode */
|
||||
efi_status = uefi_call_wrapper(
|
||||
ST->ConOut->QueryMode,
|
||||
4,
|
||||
ST->ConOut,
|
||||
ST->ConOut->Mode->Mode,
|
||||
&cols,
|
||||
&rows);
|
||||
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
ERR_PRT((L"QueryMode failed. Fake it."));
|
||||
mode = 3;
|
||||
rows = 25;
|
||||
cols = 80;
|
||||
row = 24;
|
||||
col = 0;
|
||||
} else {
|
||||
mode = (UINT8)ST->ConOut->Mode->Mode;
|
||||
col = (UINT8)ST->ConOut->Mode->CursorColumn;
|
||||
row = (UINT8)ST->ConOut->Mode->CursorRow;
|
||||
}
|
||||
|
||||
bp->s.orig_cursor_col = col;
|
||||
bp->s.orig_cursor_row = row;
|
||||
bp->s.orig_video_page = 0;
|
||||
bp->s.orig_video_mode = mode;
|
||||
bp->s.orig_video_cols = (UINT8)cols;
|
||||
bp->s.orig_video_rows = (UINT8)rows;
|
||||
|
||||
bp->s.orig_ega_bx = 0;
|
||||
bp->s.is_vga = 0;
|
||||
bp->s.orig_video_points = 16;
|
||||
|
||||
bp->s.lfb_width = 0;
|
||||
bp->s.lfb_height = 0;
|
||||
bp->s.lfb_depth = 0;
|
||||
bp->s.lfb_base = 0;
|
||||
bp->s.lfb_size = 0;
|
||||
bp->s.lfb_line_len = 0;
|
||||
bp->s.lfb_red_size = 0;
|
||||
bp->s.lfb_red_pos = 0;
|
||||
bp->s.lfb_green_size = 0;
|
||||
bp->s.lfb_green_pos = 0;
|
||||
bp->s.lfb_blue_size = 0;
|
||||
bp->s.lfb_blue_pos = 0;
|
||||
bp->s.lfb_rsvd_size = 0;
|
||||
bp->s.lfb_rsvd_pos = 0;
|
||||
bp->s.lfb_pages = 0;
|
||||
bp->s.vesa_seg = 0;
|
||||
bp->s.vesa_off = 0;
|
||||
|
||||
do_memmap:
|
||||
/*
|
||||
* Get memory map description and cookie for ExitBootServices()
|
||||
*/
|
||||
|
||||
if (get_memmap(&mdesc)) {
|
||||
ERR_PRT((L"Could not get memory map."));
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
*cookie = mdesc.cookie;
|
||||
bp->s.efi_mem_map = (UINT32)(unsigned long)mdesc.md;
|
||||
bp->s.efi_mem_map_size = mdesc.map_size;
|
||||
bp->s.efi_mem_desc_size = mdesc.desc_size;
|
||||
bp->s.efi_mem_desc_ver = mdesc.desc_version;
|
||||
bp->s.efi_sys_tbl = (UINT32)(unsigned long)systab;
|
||||
bp->s.efi_mem_map_hi = (unsigned long)mdesc.md >> 32;
|
||||
bp->s.efi_sys_tbl_hi = (unsigned long)systab >> 32;
|
||||
/* Now that we have EFI memory map, convert it to E820 map
|
||||
* 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;
|
||||
}
|
Loading…
Reference in New Issue