Stephane Eranian 2007-07-20 09:30:47 -04:00 committed by Vincent Batts
parent 64cdcfed2c
commit 97b2a7df25
40 changed files with 139707 additions and 92 deletions

View file

@ -1,3 +1,77 @@
2007-07-19 Jason Fleischli <jason.fleischli@hp.com>
* 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>

View file

@ -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,7 +55,7 @@ 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
@ -67,7 +68,7 @@ CPPFLAGS = -DCONFIG_$(ARCH)
OPTIMFLAGS = -O2
DEBUGFLAGS = -Wall
CFLAGS = $(OPTIMFLAGS) -fpic -fshort-wchar $(DEBUGFLAGS)
CFLAGS = $(OPTIMFLAGS) -fpic -fshort-wchar $(DEBUGFLAGS)
LDFLAGS = -nostdlib -znocombreloc
INSTALL = install
@ -105,6 +106,12 @@ AR = $(prefix)ar
RANLIB = $(prefix)ranlib
OBJCOPY = $(prefix)objcopy
# Use Modified binutils that supports x86_64 using UEFI ABI
ifeq ($(ARCH), x86_64)
CFLAGS += -DEFI_FUNCTION_WRAPPER
OBJCOPY = /usr/bin/objcopy
endif
ifeq ($(ARCH),ia64)
GCC_VERSION=$(shell $(CROSS_COMPILE)$(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')

View file

@ -32,4 +32,7 @@
%.o: %.c
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
# a rule for .S
%.o: %.S
$(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@

View file

@ -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.
#
@ -58,6 +60,10 @@ 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 \

15
README
View file

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

View file

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

19
alloc.c
View file

@ -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,7 +103,7 @@ 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));
return NULL;
@ -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 */
@ -155,7 +158,7 @@ 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 @ 0x%lx\n", addr));
return;
found:
DBG_PRT((L"free: %s @0x%lx size=%ld\n",
@ -163,9 +166,9 @@ found:
addr, p->size));
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)
@ -195,9 +198,9 @@ free_all(VOID)
DBG_PRT((L"free_all %a @ 0x%lx\n", used_allocs->type == ALLOC_POOL ? "pool" : "pages", used_allocs->addr));
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;

View file

@ -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.
*
@ -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));
}

View file

@ -83,7 +83,7 @@ create_boot_params(CHAR16 *args, memdesc_t *initrd, memdesc_t *vmcode, UINTN *co
/* 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

View file

@ -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.
*
@ -136,7 +140,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;
@ -274,7 +279,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
@ -354,7 +359,7 @@ restart:
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;
}

View file

@ -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.
*
@ -45,8 +49,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)
@ -249,7 +253,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 +300,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;
}
}
@ -465,7 +470,7 @@ restart:
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;
}

View file

@ -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
@ -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");
}

135421
cscope.out Normal file

File diff suppressed because it is too large Load diff

View file

@ -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) 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.
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:
----------
No new options.
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:
-----------------------
None yet.
IV/ Booting from the local system
-----------------------------
@ -447,6 +455,29 @@ 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
-------
@ -457,6 +488,9 @@ 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>
Chandramouli Narayanan <mouli@linux.intel.com>
X/ Bug reports
-----------
@ -468,6 +502,10 @@ X/ Bug reports
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/

1
elf.h
View file

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

BIN
elilo-x86_64.efi Normal file

Binary file not shown.

22
elilo.c
View file

@ -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,7 +46,7 @@
#include "loader.h"
#include "config.h" /* for config_init() */
#define ELILO_VERSION L"3.4"
#define ELILO_VERSION L"3.7"
#define ELILO_SHARED_CMDLINE_OPTS L"pPMC:aDhd:i:vVc:E"
elilo_config_t elilo_opt;
@ -244,7 +249,7 @@ do_launch:
if ((bp=create_boot_params(cmdline, &imem, &mmem, &cookie)) == 0) goto error;
/* terminate bootservices */
status = BS->ExitBootServices(image, cookie);
status = uefi_call_wrapper(BS->ExitBootServices, 2, image, cookie);
if (EFI_ERROR(status)) goto bad_exit;
start_kernel(kd.kentry, bp);
@ -307,7 +312,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 +370,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 +400,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 +444,18 @@ 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);
/* 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));
/*
* verify EDD3.0 status. Users may have to reboot
*/

View file

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

View file

@ -144,7 +144,7 @@ read_bytes(EFI_BLOCK_IO *blkio, UINT32 mediaid, UINTN offset, VOID *addr, UINTN
DBG_PRT((L"readblock(%x, %d, %d, %d, %x)", 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,
@ -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;

View file

@ -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, 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);
}

View file

@ -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.
*
@ -262,7 +266,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);
@ -337,7 +341,7 @@ retry:
*/
prev_netbufsize = f->netbuf_size;
status = nfs->pxe->Mtftp(nfs->pxe, EFI_PXE_BASE_CODE_TFTP_READ_FILE, f->netbuf, FALSE,
status = uefi_call_wrapper(nfs->pxe->Mtftp, 10, nfs->pxe, EFI_PXE_BASE_CODE_TFTP_READ_FILE, f->netbuf, FALSE,
&(f->netbuf_size),
blocksize > 0 ? &blocksize : NULL,
&nfs->srv_ip,
@ -627,7 +631,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 +684,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 +731,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 +742,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 +771,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 +784,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);
}

View file

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

View file

@ -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.
*
@ -167,6 +171,8 @@ netfs_setdefaults(VOID *intf, config_file_t *config, CHAR16 *kname, UINTN maxlen
# define CONFIG_ARCH_EXTENSION L"-ia64.conf\0"
# elif defined (CONFIG_ia32)
# define CONFIG_ARCH_EXTENSION L"-ia64.conf\0"
# elif defined (CONFIG_x86_64)
# define CONFIG_ARCH_EXTENSION L"-x86_64.conf\0"
# else
# error "You need to specfy your default arch config file"
# endif

View file

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

34
util.c
View file

@ -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,7 +129,7 @@ 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;
@ -130,13 +141,13 @@ wait_timeout(UINTN timeout)
* 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;
}
@ -278,7 +289,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 +303,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);

52
x86_64/Makefile Normal file
View file

@ -0,0 +1,52 @@
#
# 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.
#
include ../Make.defaults
include ../Make.rules
TOPDIR=$(CDIR)/..
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 bin_to_h.c
$(AS) -o rmswitch.o rmswitch.S
$(LD) -Ttext 0x0 -s --oformat binary -o rmswitch rmswitch.o
./bin_to_h <rmswitch >rmswitch.h
$(TARGET): $(FILES)
$(LD) -r -o $@ $(FILES)
clean:
$(RM) -f $(TARGET) $(FILES)
$(RM) -f bin_to_h.o bin_to_h
$(RM) -f rmswitch.h rmswitch.o rmswitch

27
x86_64/bin_to_h.c Normal file
View file

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

224
x86_64/bzimage.c Normal file
View file

@ -0,0 +1,224 @@
/*
* 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 = 0x400000; /* 4M (largest x86 bzImage kernel image) */
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.
*/
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));
}
/*
* Now read the rest of the kernel image into memory.
*/
DBG_PRT((L"reading kernel image...\n"));
size = kernel_size;
efi_status = fops_read(fd, kernel_start, &size);
if (EFI_ERROR(efi_status) || size < 0x10000) {
ERR_PRT((L"Error reading kernel image %s.", kname));
free(param_start);
param_start = NULL;
param_size = 0;
fops_close(fd);
free_kmem();
return -1;
}
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=0x%x kd=0x%x", 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=0x%x kentry=0x%x kend=0x%x\n", kd->kstart, kd->kentry, kd->kend));
return 0;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
loader_ops_t bzimage_loader = {
NULL,
L"bzImage_loader",
&bzImage_probe,
&bzImage_load
};

102
x86_64/config.c Normal file
View file

@ -0,0 +1,102 @@
/*
* 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;
} x86_64_global_config_t;
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}
};
/*
* 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
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 0
/* no per image options yet */
if (ret == -1 ) return ret;
ret = register_config_options(sysdeps_image_options,
sizeof(sysdeps_image_options)/sizeof(config_option_t),
OPTIONS_GROUP_IMAGE);
#endif
return ret;
}

557
x86_64/gzip.c Normal file
View file

@ -0,0 +1,557 @@
/*
* 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)
{
INTN expected, nread;
EFI_STATUS status;
expected = nread = INBUFSIZE;
status = fops_read(input_fd, inbuf, &nread);
if (EFI_ERROR(status)) {
error("elilo: Read failed");
}
DBG_PRT((L"%s : read %d bytes of %d bytes\n", LD_NAME, nread, expected));
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 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;
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));
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 = (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 = (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;
}

40
x86_64/gzip.h Normal file
View file

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

83
x86_64/gzip_loader.c Normal file
View file

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

1205
x86_64/inflate.c Normal file

File diff suppressed because it is too large Load diff

302
x86_64/plain_loader.c Normal file
View file

@ -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 0x%x\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 [0x%x-0x%x] offset 0x%x"
" filesz 0x%x memsz=0x%x bss_sz=0x%x p_type=0x%x\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 0x%x 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: 0x%x\nTotalMemSize:%d bytes (%d pages)\n",
low_addr, total_size, pages);
Print(L"Kernel entry @ 0x%x\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: 0x%x (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 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);
});
/*
* 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;
}*/

35
x86_64/private.h Normal file
View file

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

118
x86_64/rmswitch.S Normal file
View file

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

451
x86_64/sysdeps.h Normal file
View file

@ -0,0 +1,451 @@
/*
* 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)
/*
* 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 unused_1; /* unused */
/* %%TBD */
/* 0x0A */ UINT16 orig_ega_bx; /* LDR */
/* 0x0C */ UINT16 unused_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 unused_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 unused_4[0x106]; /* unused */
/* Address of the EFI system table. */
/* 0x1B8 */ UINT64 efi_sys_tbl; /* LDR */
/* EFI boot loader signature. */
/* 0x1C0 */ UINT8 efi_loader_sig[4]; /* LDR */
#define EFI_LOADER_SIG "EFIL"
/* EFI memory descriptor size. */
/* 0x1C4 */ UINT32 efi_mem_desc_size; /* LDR */
/* EFI memory descriptor version. */
/* 0x1C8 */ UINT32 efi_mem_desc_ver; /* LDR */
/* Address & size of EFI memory map. */
/* 0x1CC */ UINT32 efi_mem_map_size; /* LDR */
/* 0x1D0 */ UINT64 efi_mem_map; /* LDR */
/* Address & size of loader. */
/* 0x1D8 */ UINT32 loader_start; /* LDR */
/* 0x1DC */ UINT32 loader_size; /* LDR */
/* Available contiguous extended memory in KB. */
/* 0x1E0 */ UINT32 alt_mem_k; /* LDR */
/* 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 */
/* %%TBD */
/* 0x1F2 */ UINT16 mount_root_rdonly; /* BLD */
/* %%TBD */
/* 0x1F4 */ UINT16 sys_size; /* BLD */
/* %%TBD */
/* 0x1F6 */ UINT16 swap_dev; /* BLD */
/* %%TBD */
/* 0x1F8 */ UINT16 ramdisk_flags; /* BLD */
#define RAMDISK_PROMPT 0x8000
#define RAMDISK_LOAD 0x4000
/* %%TBD */
/* 0x1FA */ UINT16 video_mode_flag; /* BLD */
/* %%TBD */
/* 0x1FC */ UINT16 orig_root_dev; /* BLD */
/* 0x1FE */ UINT8 unused_6; /* unused */
/* %%TBD */
/* 0x1FF */ UINT8 aux_dev_info; /* LDR */
#define NO_MOUSE 0x00
#define FOUND_MOUSE 0xAA
/* 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; /* BLD */
/* %%TBD */
/* 0x224 */ UINT16 heap_end_ptr; /* LDR */
/* %%TBD */
/* 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()
/*
* 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) { \
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 *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();
/*
* 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;
UINTN njump;
VOID *jump_start;
/*
* Disable interrupts.
*/
asm volatile ( "cli" : : );
/*
* Relocate initrd, if present.
*/
if (bp->s.initrd_start) {
MEMCPY(INITRD_START, bp->s.initrd_start, bp->s.initrd_size);
bp->s.initrd_start = INITRD_START;
}
/*
* Copy boot sector, setup data and command line
* to final resting place. We need to copy
* BOOT_PARAM_MEMSIZE bytes.
*/
MEMCPY(high_base_mem, bp, 0x4000);
/*
* 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.
*/
jumpvector.kernel_entry=kentry;
jumpvector.kernel_cs=0x10;
njump = &jumpvector;
jump_start = (VOID *)&jumpvector;
//asm volatile ( "mov %0, %%rcx" : : "m" (&jumpvector) );
asm volatile ( "mov %0, %%rcx" : : "m" (jump_start) );
//asm volatile ( "mov %0, %%rcx" : : "m" (njump) );
asm volatile ( "ljmp *(%%rcx)" : :);
/* Never come back to here. */
}
typedef struct sys_img_options {
UINT8 nothing_yet;
} sys_img_options_t;
#endif /* __ELILO_SYSDEPS_X86_64_H__ */

772
x86_64/system.c Normal file
View file

@ -0,0 +1,772 @@
/*
* 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 "elilo.h"
#include "loader.h"
#include "rmswitch.h"
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 *)0x100000; /* 1M */
VOID *initrd_start = NULL;
UINTN initrd_size = 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, this image is placed immediately after the end of
* the kernel memory. Inside the start_kernel() code, the
* RAMdisk image will be relocated to the top of available
* extended memory.
*/
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=0x%x imem=0x%x", kd, imem));
return -1;
}
VERB_PRT(3, Print(L"kstart=0x%x kentry=0x%x kend=0x%x\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",
imem->start_addr, imem->pgcnt));
return 0;
}
VOID
sysdeps_free_boot_params(boot_params_t *bp)
{
mmap_desc_t md;
ZeroMem(&md, sizeof md);
md.md = (VOID *)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;
EFI_HANDLE *Gop_handle;
EFI_STATUS efi_status;
UINTN size, 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) {
ERR_PRT((L"LocateHandle GopProtocol failed."));
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 = 0x24;
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
*/
void fill_e820map(boot_params_t *bp, mmap_desc_t *mdesc)
{
int nr_map, 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;
bp->s.e820_nrmap = nr_map;
for (i = 0, p = mdesc->md; i < nr_map; i++)
{
md = p;
switch (md->Type) {
case EfiACPIReclaimMemory:
e820_map->addr = md->PhysicalStart;
e820_map->size = md->NumberOfPages << EFI_PAGE_SHIFT;
e820_map->type = E820_ACPI;
break;
case EfiRuntimeServicesCode:
e820_map->addr = md->PhysicalStart;
e820_map->size = md->NumberOfPages << EFI_PAGE_SHIFT;
e820_map->type = E820_EXEC_CODE;
break;
case EfiRuntimeServicesData:
case EfiReservedMemoryType:
case EfiMemoryMappedIO:
case EfiMemoryMappedIOPortSpace:
case EfiUnusableMemory:
case EfiPalCode:
e820_map->addr = md->PhysicalStart;
e820_map->size = md->NumberOfPages << EFI_PAGE_SHIFT;
e820_map->type = 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
*/
e820_map->addr = start;
e820_map->size = 0xA0000ULL-start;
e820_map->type = E820_RAM;
e820_map++;
}
if (end <= 0x100000ULL)
continue;
/* end > 1MB
* set memory map avoiding 640K to 1MB hole
*/
start = 0x100000ULL;
size = end - start;
}
e820_map->addr = start;
e820_map->size = size;
e820_map->type = E820_RAM;
break;
case EfiACPIMemoryNVS:
e820_map->addr = md->PhysicalStart;
e820_map->size = md->NumberOfPages << EFI_PAGE_SHIFT;
e820_map->type = E820_NVS;
break;
default:
/* We should not hit this case */
e820_map->addr = md->PhysicalStart;
size = md->NumberOfPages << EFI_PAGE_SHIFT;
e820_map->type = E820_RESERVED;
break;
}
e820_map++;
p = NextMemoryDescriptor(p, mdesc->desc_size);
}
}
/*
* x86_64 specific boot parameters initialization routine
*/
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;
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",
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);
free(param_start);
param_start = NULL;
param_size = 0;
}
/*
* Save off our header revision information.
*/
hdr_version = (bp->s.hdr_major << 8) | bp->s.hdr_minor;
/*
* Clear out unused memory in boot sector image.
*/
bp->s.unused_1 = 0;
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_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.
* 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=0x%x initrd->pgcnt=%d\n",
initrd->start_addr, initrd->pgcnt));
/* These RAMdisk flags are not needed, just zero them. */
bp->s.ramdisk_flags = 0;
if (initrd->start_addr && initrd->pgcnt) {
/* %%TBD - This will probably have to be changed. */
bp->s.initrd_start = (UINT32)initrd->start_addr;
bp->s.initrd_size = (UINT32)(initrd->size);
/*
* This is the RAMdisk root device for RedHat 2.2.x
* kernels (major 0x01, minor 0x00).
*/
bp->s.orig_root_dev = 0x0100;
} 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);
/*
* Pointing device presence. The kernel will detect this.
*/
bp->s.aux_dev_info = NO_MOUSE;
/*
* EFI loader signature
*/
CopyMem(bp->s.efi_loader_sig, EFI_LOADER_SIG, 4);
/*
* Kernel entry point.
*/
bp->s.kernel_start = (UINT32)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_sys_tbl, 0x1B8, L"%xh");
CHECK_OFFSET(efi_loader_sig, 0x1C0, L"'%-4.4a'");
CHECK_OFFSET(efi_mem_desc_size, 0x1C4, L"%xh");
CHECK_OFFSET(efi_mem_desc_ver, 0x1C8, L"%xh");
CHECK_OFFSET(efi_mem_map_size, 0x1CC, L"%xh");
CHECK_OFFSET(efi_mem_map, 0x1D0, L"%xh");
CHECK_OFFSET(loader_start, 0x1D8, L"%xh");
CHECK_OFFSET(loader_size, 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(swap_dev, 0x1F6, L"%xh");
CHECK_OFFSET(ramdisk_flags, 0x1F8, L"%xh");
CHECK_OFFSET(video_mode_flag, 0x1FA, L"%xh");
CHECK_OFFSET(orig_root_dev, 0x1FC, L"%xh");
CHECK_OFFSET(aux_dev_info, 0x1FF, 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(bootsect_helper, 0x220, L"%xh");
CHECK_OFFSET(heap_end_ptr, 0x224, L"%xh");
CHECK_OFFSET(cmdline_addr, 0x228, 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 = (UINTN)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 = (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;
}