Stephane Eranian 2009-10-26 09:42:58 -04:00 committed by Vincent Batts
parent 4e87874a03
commit e351d8fbea
26 changed files with 511 additions and 113 deletions

View file

@ -1,3 +1,25 @@
2009-10-22 signed off by Jason Fleischli <jason.fleischli@hp.com>
* elilo 3.12 release commit
* Added additional #defines for debug levels to reduce the output
* Added Mac console patch rework from Julien Blache @ debian
this fixes the invisible console output from elilo on Macs
* Moved static ELILO_VERSION variable from elilo.c to elilo.h
so that elilo will print its version string and arch on startup.
* Fixed bug 2825044 ExitBootServices error handling, correctly deal
with changed memory map key if memory map changes from under elilo.
* Added memory map key to map debug output.
* Fixed bug 2874380 netbooting just flat broken. fixed ia64, x86_64
ia32, fixed handling of server side support of tfpt options (get file size)
elilo now attempts to get file size before attempting read of file
to set the buffers up correctly and deal with tftp servers that dont
support options extensions a little better.
* netboot, fixed bad blocksize handling
* netboot, fixed filename length for elilo-x86_64.conf type on tftp
server.
* increased bzimage kernel max length sizes to 4mb on i386 and 8mb on
x86_64... this is a legacy design hold over from original design and
needs to be re-written to do dynamic size memory management based on
the size of the actual vmlinuz image, as ia64/gzip does.
2008-04-02 signed off by Jason Fleischli <jason.fleischli@hp.com>
* elilo 3.10 release commit
* Bumped version string to 3.10

View file

@ -63,7 +63,7 @@ CDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
TOPDIR =
ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
INCDIR = -I. -I$(TOPDIR) -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol
INCDIR = -I. -I$(TOPDIR) -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol -I$(TOPDIR)/efi110
CPPFLAGS = -DCONFIG_$(ARCH)
OPTIMFLAGS = -O2

View file

@ -67,7 +67,7 @@ endif
FILES = elilo.o getopt.o strops.o loader.o \
fileops.o util.o vars.o alloc.o chooser.o \
config.o initrd.o alternate.o bootparams.o \
gunzip.o fs/fs.o \
gunzip.o console.o fs/fs.o \
choosers/choosers.o \
devschemes/devschemes.o \
$(ARCH)/sysdeps.o \

15
alloc.c
View file

@ -109,9 +109,9 @@ alloc(UINTN size, EFI_MEMORY_TYPE type)
return NULL;
}
alloc_add(tmp, size, ALLOC_POOL);
#ifdef DEBUG_MEM
DBG_PRT((L"alloc: allocated %d bytes @[" PTR_FMT "-" PTR_FMT "]\n", size, tmp, tmp+size));
#endif
return tmp;
}
@ -161,10 +161,11 @@ free(VOID *addr)
VERB_PRT(1, Print(L"allocator: invalid free @ " PTR_FMT "\n", addr));
return;
found:
#ifdef DEBUG_MEM
DBG_PRT((L"free: %s @" PTR_FMT " size=%d\n",
p->type == ALLOC_POOL ? L"Pool": L"Page",
addr, p->size));
#endif
if (p->type == ALLOC_POOL)
uefi_call_wrapper(BS->FreePool, 1, addr);
else
@ -194,9 +195,9 @@ free_all(VOID)
alloc_entry_t *tmp;
while(used_allocs) {
#ifdef DEBUG_MEM
DBG_PRT((L"free_all %a @ " PTR_FMT "\n", used_allocs->type == ALLOC_POOL ? "pool" : "pages", used_allocs->addr));
#endif
if (used_allocs->type == ALLOC_POOL)
uefi_call_wrapper(BS->FreePool, 1, used_allocs->addr);
else
@ -239,13 +240,17 @@ alloc_kmem(VOID *start_addr, UINTN pgcnt)
VOID
free_kmem(VOID)
{
#ifdef DEBUG_MEM
DBG_PRT((L"free_kmem before (" PTR_FMT ", %d)\n", kmem_addr, kmem_pgcnt));
#endif
if (kmem_addr && kmem_pgcnt != 0) {
free(kmem_addr);
kmem_addr = NULL;
kmem_pgcnt = 0;
}
#ifdef DEBUG_MEM
DBG_PRT((L"free_kmem after (" PTR_FMT ", %d)\n", kmem_addr, kmem_pgcnt));
#endif
}
VOID

View file

@ -32,6 +32,7 @@
#include "elilo.h"
#include "vars.h"
#include "console.h"
/* static is ugly but does the job here! */
static CHAR16 **alt_argv;
@ -288,6 +289,7 @@ restart:
}
if (elilo_opt.prompt) {
console_textmode();
ret = select_kernel(buffer, sizeof(buffer));
if (ret == -1) return -1;
argc = argify(buffer,sizeof(buffer), argv);
@ -355,7 +357,7 @@ restart:
if (elilo_opt.prompt == 0) {
/* minimal printing */
Print(L"ELILO\n");
Print(L"ELILO v%s for EFI/%a\n", ELILO_VERSION, ELILO_ARCH);
ret = wait_timeout(elilo_opt.delay);
if (ret != 0) {
elilo_opt.prompt = 1;

View file

@ -31,6 +31,7 @@
#include <efilib.h>
#include "elilo.h"
#include "console.h"
#define MAX_LABELS 64
#define MSGBUFLEN 4096
@ -394,6 +395,7 @@ restart:
Memset(&elilo_opt.img_opt, 0, sizeof(elilo_opt.img_opt));
if (elilo_opt.prompt) {
console_textmode();
ret = select_kernel(label, sizeof(label));
if (ret == -1) return -1;
argc = argify(PromptBuf,sizeof(PromptBuf), argv);
@ -466,7 +468,7 @@ restart:
if (elilo_opt.prompt == 0) {
/* minimal printing */
Print(L"ELILO\n");
Print(L"ELILO v%s for EFI/%a\n", ELILO_VERSION, ELILO_ARCH);
ret = wait_timeout(elilo_opt.delay);
if (ret != 0) {
elilo_opt.prompt = 1;

View file

@ -255,7 +255,16 @@ next(VOID)
back = 0;
return ch;
}
return getc();
/*
* config files served from pxe/tftpboot windows servers can contain
* extraneous '\r' characters, often the first char in the file, and
* we need to simply skip over those and continue on
*/
ch = getc();
if(ch == '\r')
ch = getc();
return ch;
}
/*
@ -310,13 +319,13 @@ get_token_core(CHAR16 *str, UINTN maxlen, BOOLEAN rhs)
CHAR16 *here;
for (;;) {
while ((ch = next()), ch == ' ' || ch == '\t' || ch == '\n') if (ch == '\n') line_num++;
while ((ch = next()), ch == ' ' || ch == '\t' || ch == '\n') if (ch == '\n' ) line_num++;
if (ch == CHAR_EOF) return TOK_EOF;
/* skip comment line */
if (ch != '#') break;
/* skip comment line */
while ((ch = next()), ch != '\n') if (ch == CHAR_EOF) return TOK_EOF;
line_num++;
}
@ -762,7 +771,10 @@ config_parse(VOID)
if (tok == TOK_EOF) break;
if (tok == TOK_ERR) return -1;
if (tok == TOK_ERR) {
Print(L"Bad Token from elilo config file, parser read: %s\n elilo exiting\n", str);
return -1;
}
if ( (p = find_option(current_options, str)) == NULL) {
config_error(L"Unkown option %s", str);

71
console.c Normal file
View file

@ -0,0 +1,71 @@
/*
* console.c - Console screen handling functions
*
* Copyright (C) 2006 Christoph Pfisterer
*
* This file is part of the ELILO, the EFI Linux boot loader.
*
* ELILO is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* ELILO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ELILO; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Please check out the elilo.txt for complete documentation on how
* to use this program.
*/
#include <efi.h>
#include <efilib.h>
#include "elilo.h"
#include <efiConsoleControl.h>
static EFI_GUID console_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
static BOOLEAN console_inited = FALSE;
static EFI_CONSOLE_CONTROL_PROTOCOL *console_control;
/*
* Initialize console functions
*/
static VOID console_init(VOID)
{
EFI_STATUS status;
if (!console_inited) {
console_inited = TRUE;
status = LibLocateProtocol(&console_guid, (VOID **) &console_control);
if (EFI_ERROR(status))
console_control = NULL;
}
}
/*
* Switch the console to text mode
*/
VOID console_textmode(VOID)
{
EFI_CONSOLE_CONTROL_SCREEN_MODE console_mode;
console_init();
if (console_control != NULL) {
uefi_call_wrapper(console_control->GetMode, 4, console_control, &console_mode, NULL, NULL);
if (console_mode == EfiConsoleControlScreenGraphics)
uefi_call_wrapper(console_control->SetMode, 2, console_control, EfiConsoleControlScreenText);
}
}

32
console.h Normal file
View file

@ -0,0 +1,32 @@
/*
* console.h - Console screen handling functions
*
* Copyright (C) 2006 Christoph Pfisterer
*
* This file is part of the ELILO, the EFI Linux boot loader.
*
* ELILO is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* ELILO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ELILO; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Please check out the elilo.txt for complete documentation on how
* to use this program.
*/
#ifndef __ELILO_CONSOLE_H__
#define __ELILO_CONSOLE_H__
extern VOID console_textmode(VOID);
#endif /* __ELILO_CONSOLE_H__ */

View file

@ -3,8 +3,11 @@ How to netboot using ELILO
Copyright (C) 2002-2003 Hewlett-Packard Co.
Contributed by Stephane Eranian <eranian@hpl.hp.com>
Updated by Jason Fleischli <jason.fleischli@hp.com>
Last updated: 03/08/11
Last updated: 10/19/2009
x86_64 and uefi support was added @ elilo version 3.8 and linux kernel >= 2.6.24
EFI has full support for the PXE and DHCP protocol. As such
it is relatively easy to boot a machine from the network using EFI.
@ -126,7 +129,7 @@ only on two very common cases:
This filename is an opportunity to specify a machine specific configuration file.
2) AA[BB[CC]][-ia32|ia64].conf
2) AA[BB[CC]][-ia32|ia64|x86_64].conf
As of version 3.5, elilo will also look for IPv4 class A,B,C
subnet-specific versions of the config file. This is useful when you
want to have a common config file for all machines connected to a
@ -140,14 +143,14 @@ only on two very common cases:
config files first (So for example, on an Itanium system,
"0A0000-ia64.conf" will be tried before "0A0000.conf")
3) elilo-ia32.config or elilo-ia64.conf
3) elilo-ia32.conf, elilo-x86_64.conf, or elilo-ia64.conf
Depending on the machine (client side) architecture elilo will try the IA-32 or
IA-64 file.
Depending on the machine (client side) architecture elilo will try the matching
architecture specific filename.
This filename is an opportunity to specify a architecture specific configuration file.
This distinction between the architectures is useful when the same TFTP server services
the two types of clients : IA32- and IA-64 machines.
the three types of clients : ia32, x86_64, and ia64 machines.
4) elilo.conf
@ -244,7 +247,7 @@ only on two very common cases:
- use the name provide by the PXE server Layer 1 or
- elilo-ia64.conf/elilo-ia32.conf or
- elilo-ia64.conf/elilo-ia32.conf/elilo-x86_64 or
- elilo.conf
@ -390,7 +393,7 @@ only on two very common cases:
In the case of a DHCP boot, this type of customization makes sense only for
the shared configuration file, elilo-ia64.conf/elilo-ia32.conf or elilo.conf.
the shared configuration file, elilo-ia64.conf/elilo-ia32.conf/elilo-x86_64 or elilo.conf.
The configuration file based on the IP address (such as C0A80205.conf in this
case) would provide another way of customizing parameters for a specific
client (IP address). The same thing holds if the name of the config file

122
efi110/efiConsoleControl.h Normal file
View file

@ -0,0 +1,122 @@
/*++
Copyright (c) 2004, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
ConsoleControl.h
Abstract:
Abstraction of a Text mode or UGA screen
--*/
#ifndef __CONSOLE_CONTROL_H__
#define __CONSOLE_CONTROL_H__
#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \
{ 0xf42f7782, 0x12e, 0x4c12, { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } }
/* typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL; */
struct _EFI_CONSOLE_CONTROL_PROTOCOL;
typedef enum {
EfiConsoleControlScreenText,
EfiConsoleControlScreenGraphics,
EfiConsoleControlScreenMaxValue
} EFI_CONSOLE_CONTROL_SCREEN_MODE;
typedef
EFI_STATUS
(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) (
IN struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
OUT BOOLEAN *UgaExists, OPTIONAL
OUT BOOLEAN *StdInLocked OPTIONAL
)
/*++
Routine Description:
Return the current video mode information. Also returns info about existence
of UGA Draw devices in system, and if the Std In device is locked. All the
arguments are optional and only returned if a non NULL pointer is passed in.
Arguments:
This - Protocol instance pointer.
Mode - Are we in text of grahics mode.
UgaExists - TRUE if UGA Spliter has found a UGA device
StdInLocked - TRUE if StdIn device is keyboard locked
Returns:
EFI_SUCCESS - Mode information returned.
--*/
;
typedef
EFI_STATUS
(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) (
IN struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
OUT EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
)
/*++
Routine Description:
Set the current mode to either text or graphics. Graphics is
for Quiet Boot.
Arguments:
This - Protocol instance pointer.
Mode - Mode to set the
Returns:
EFI_SUCCESS - Mode information returned.
--*/
;
typedef
EFI_STATUS
(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN) (
IN struct _EFI_CONSOLE_CONTROL_PROTOCOL *This,
IN CHAR16 *Password
)
/*++
Routine Description:
Lock Std In devices until Password is typed.
Arguments:
This - Protocol instance pointer.
Password - Password needed to unlock screen. NULL means unlock keyboard
Returns:
EFI_SUCCESS - Mode information returned.
EFI_DEVICE_ERROR - Std In not locked
--*/
;
typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL {
EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode;
EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode;
EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn;
} EFI_CONSOLE_CONTROL_PROTOCOL;
extern EFI_GUID gEfiConsoleControlProtocolGuid;
#endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

41
elilo.c
View file

@ -46,7 +46,6 @@
#include "loader.h"
#include "config.h" /* for config_init() */
#define ELILO_VERSION L"3.10"
#define ELILO_SHARED_CMDLINE_OPTS L"pPMC:aDhd:i:vVc:E"
elilo_config_t elilo_opt;
@ -215,7 +214,7 @@ main_loop(EFI_HANDLE dev, CHAR16 **argv, INTN argc, INTN index, EFI_HANDLE image
EFI_STATUS status = EFI_SUCCESS;
kdesc_t kd;
memdesc_t imem, mmem;
INTN r;
INTN r, retries=0;
/*
* First place where we potentially do system dependent
@ -246,7 +245,15 @@ do_launch:
VERB_PRT(3, Print(L"final cmdline(%d): %s\n", r, cmdline));
/* Give user time to see the output before launch */
if (elilo_opt.debug || elilo_opt.verbose) r = wait_timeout(300);
if (elilo_opt.debug || elilo_opt.verbose) {
r = wait_timeout(150);
/* have to turn off all console output(except error output) now before final get_mmemap()
* call or it can cause the efi map key to change and the ExitBootSvc call to fail,
* forcing debug and verbose options off is the surest way to enforce this.
*/
elilo_opt.debug=0;
elilo_opt.verbose=0;
}
/* free resources associated with file accesses (before ExitBootServices) */
close_devices();
@ -254,9 +261,32 @@ do_launch:
/* No console output permitted after create_boot_params()! */
if ((bp=create_boot_params(cmdline, &imem, &mmem, &cookie)) == 0) goto error;
/* terminate bootservices */
/* terminate bootservices
* efi ExitBootSvcs spec: *note, get_memmap is called by create_boot_params()
* An EFI OS loader must ensure that it has the system's current memory map at the time
* it calls ExitBootServices(). This is done by passing in the current memory map's
* MapKey value as returned by GetMemoryMap(). Care must be taken to ensure that the
* memory map does not change between these two calls. It is suggested that
* GetMemoryMap()be called immediately before calling ExitBootServices(). */
retry:
status = uefi_call_wrapper(BS->ExitBootServices, 2, image, cookie);
if (EFI_ERROR(status)) goto bad_exit;
if (EFI_ERROR(status))
{
ERR_PRT((L"\nExitBootSvcs: failed, memory map has changed.\n"));
if (retries < 2)
{
ERR_PRT((L"Main_Loop: Retrying,... have to rebuild boot params"));
retries++;
free_boot_params(bp);
if ((bp=create_boot_params(cmdline, &imem, &mmem, &cookie)) == 0) goto error;
goto retry;
} else {
ERR_PRT((L"\nMain_Loop: tried ExitBootSvcs 3 times... retries exceeded.... giving up\n"));
goto bad_exit;
}
}
start_kernel(kd.kentry, bp);
/* NOT REACHED */
@ -270,6 +300,7 @@ bad_exit:
error:
free_kmem();
if (imem.start_addr) free(imem.start_addr);
if (mmem.start_addr) free(mmem.start_addr);
if (bp) free_boot_params(bp);
exit_error:
return ELILO_LOAD_ERROR;

View file

@ -29,6 +29,8 @@
#ifndef __ELILO_H__
#define __ELILO_H__
#define ELILO_VERSION L"3.12"
#include <efi.h>
#ifdef CONFIG_ia32

View file

@ -26,6 +26,10 @@
#ifndef __ELILO_DEBUG__
#define __ELILO_DEBUG__
//#define DEBUG_MEM
//#define DEBUG_GZIP
//#define DEBUG_BZ
#define ELILO_DEBUG 1
#define ERR_PRT(a) do { Print(L"%a(line %d):", __FILE__, __LINE__); Print a; Print(L"\n"); } while (0);

View file

@ -1,6 +1,7 @@
/*
* Copyright (C) 2001-2003 Hewlett-Packard Co.
* Copyright (C) 2001-2009 Hewlett-Packard Co.
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
* Contributed by Jason Fleischli <jason.fleischli@hp.com>
* Copyright (C) 2006-2009 Intel Corporation
* Contributed by Fenghua Yu <fenghua.yu@intel.com>
* Contributed by Bibo Mao <bibo.mao@intel.com>
@ -38,6 +39,13 @@
#define NETFS_DEFAULT_BUFSIZE 16*MB
#define NETFS_DEFAULT_BUFSIZE_INC 8*MB
#define NETFS_DEFAULT_BLOCKSIZE 1024 /* setting to zero is supposed to default the underlying */
/* pxe implementation to largest blocksize supported,... */
/* in reality on original older efi implementations its */
/* never set causing the pxe transfer to timeout. */
/* the spec defines the minimum supported blocksize default */
/* to be 512 bytes... a bit extreme, 1024 should work for */
/* everything */
#define NETFS_DEFAULT_SERVER_TYPE EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP
#define NETFS_FD_MAX 2
@ -221,7 +229,7 @@ netfs_extract_ip(netfs_priv_state_t *nfs)
if (pxe->Mode->RouteTableEntries>0)
Memcpy(&nfs->gw_ip, &pxe->Mode->RouteTable[0].GwAddr, sizeof(EFI_IP_ADDRESS));
VERB_PRT(1, Print(L"PXE PxeDiscoverValid: %s\n", pxe->Mode->PxeDiscoverValid? L"Yes (PXE-aware DHCPD)" : L"No (Regular DHCPD)"));
VERB_PRT(1, Print(L"PXE PxeDiscoverValid: %s\n", pxe->Mode->PxeDiscoverValid? L"Yes (PXE-aware DHCPD)\n" : L"No (Regular DHCPD)\n"));
#if 0
status = BS->HandleProtocol(dev, &PxeCallbackProtocol, (VOID **)&netfs_callback);
status = LibInstallProtocolInterfaces(&dev, &PxeCallbackProtocol, &netfs_callback, NULL);
@ -279,7 +287,9 @@ netfs_open(netfs_interface_t *this, CHAR16 *name, UINTN *fd)
netfs_fd_t *f;
EFI_STATUS status;
CHAR8 ascii_name[FILENAME_MAXLEN];
UINTN blocksize = 0, prev_netbufsize;
UINTN blocksize = NETFS_DEFAULT_BLOCKSIZE;
UINTN prev_netbufsize, retries = 0;
BOOLEAN server_provided_filesize = FALSE;
if (this == NULL || name == NULL || fd == NULL) return EFI_INVALID_PARAMETER;
@ -305,6 +315,7 @@ netfs_open(netfs_interface_t *this, CHAR16 *name, UINTN *fd)
return EFI_SUCCESS;
}
f->netbuf_maxsize = NETFS_DEFAULT_BUFSIZE;
f->netbuf_size = 0;
if (f->netbuf == NULL && netbuf_alloc(f) == -1) {
netfs_fd_free(nfs, f);
@ -315,58 +326,108 @@ netfs_open(netfs_interface_t *this, CHAR16 *name, UINTN *fd)
U2ascii(name, ascii_name, FILENAME_MAXLEN);
VERB_PRT(2, Print(L"downloading %a from %d.%d.%d.%d...", ascii_name,
VERB_PRT(2, Print(L"downloading %a from %d.%d.%d.%d...\n", ascii_name,
nfs->srv_ip.v4.Addr[0],
nfs->srv_ip.v4.Addr[1],
nfs->srv_ip.v4.Addr[2],
nfs->srv_ip.v4.Addr[3]));
retry:
f->netbuf_size = f->netbuf_maxsize;
if (retries == 2) {
netfs_fd_free(nfs, f);
VERB_PRT(2, Print(L"Failed: %r\n", status));
return status;
}
DBG_PRT((L"\nbefore netbuf:" PTR_FMT " netbuf_size=%d\n", f->netbuf, f->netbuf_size));
/*
* For EFI versions older than 14.61:
* it seems like there is an EFI bug (or undocumented behavior) when the buffer size
* is too small AND the blocksize parameter is NULL, i.e., used the largest possible.
* In this case, Mtftp() never returns EFI_BUFFER_TOO_SMALL but EFI_TIMEOUT instead.
* This is true for 1.02 and also 1.10 it seems. Here we set it to the minimal value (512).
*
* Also it seems like on a READ_FILE which returns EFI_BUFFER_TOO_SMALL, the buffersize
* is NOT updated to reflect the required size for the next attempt.
*
* For EFI versions 14.61 and higher:
* In case the buffer is too small AND the TFTP server reports the file size (see RFC 2349),
* the f->netbuf_size will report the exact size for the buffer.
/*
* netboot bugfix SF tracker 2874380
* EFI 1.10 spec
* For read operations, the return data will be placed in the buffer specified by BufferPtr. If
* BufferSize is too small to contain the entire downloaded file, then
* EFI_BUFFER_TOO_SMALL will be returned and BufferSize will be set to zero or the size of
* the requested file (the size of the requested file is only returned if the TFTP server supports TFTP
* options). If BufferSize is large enough for the read operation, then BufferSize will be set to
* the size of the downloaded file, and EFI_SUCCESS will be returned. Applications using the
* PxeBc.Mtftp() services should use the get-file-size operations to determine the size of the
* downloaded file prior to using the read-file operationsespecially when downloading large
* (greater than 64 MB) filesinstead of making two calls to the read-file operation. Following this
* recommendation will save time if the file is larger than expected and the TFTP server does not
* support TFTP option extensions. Without TFTP option extension support, the client has to
* download the entire file, counting and discarding the received packets, to determine the file size.
* ...
* For TFTP get file size operations, the size of the requested file or directory is returned in
* BufferSize, and EFI_SUCCESS will be returned. If the TFTP server does not support options,
* the file will be downloaded into a bit bucket and the length of the downloaded file will be returned.
*/
status = uefi_call_wrapper(nfs->pxe->Mtftp, 10,
nfs->pxe,
EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
f->netbuf,
FALSE,
&(f->netbuf_size), // PXE writes size of file from server here
&blocksize,
&nfs->srv_ip,
ascii_name,
NULL,
FALSE);
/*
* If options are not supported by this tftp server, according to the spec the file will be
* downloaded into a bit bucket, the size calculated by efi fw and returned in the status
* field of this call. YUK!!... in this case we will default to currently allocated max
* if thats still not big enough it will be caught and increased following the read file attempt
* then retried.
* XXX need to research how this is handled or changed in the latest UEFI spec.
*/
if (status != EFI_SUCCESS) {
f->netbuf_size = f->netbuf_maxsize;
VERB_PRT(2, Print(L"setting default buffer size of %d for %a, no filesize recd from tftp server\n",
f->netbuf_size, ascii_name));
}
if (status == EFI_SUCCESS) {
server_provided_filesize = TRUE;
VERB_PRT(2, Print(L"received file size of %d for %a from tftp server.\n",
f->netbuf_size, ascii_name));
}
if (f->netbuf_size > f->netbuf_maxsize) { // we need a bigger buffer
VERB_PRT(2, Print(L"allocated buffer too small, attempting to increase\n"));
f->netbuf_maxsize += f->netbuf_size;
free(f->netbuf);
f->netbuf = NULL;
if (netbuf_alloc(f) == -1) return EFI_OUT_OF_RESOURCES;
}
/* paranoid catch any corner case missed */
if (f->netbuf_size == 0) f->netbuf_size = f->netbuf_maxsize;
DBG_PRT((L"\nbefore read: netbuf:" PTR_FMT " netbuf_size=%d blocksize=%d\n",
f->netbuf,
f->netbuf_size,
blocksize));
prev_netbufsize = f->netbuf_size;
status = 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,
ascii_name,
NULL,
FALSE);
/* now try and download this file from the tftp server */
status = uefi_call_wrapper(nfs->pxe->Mtftp, 10,
nfs->pxe,
EFI_PXE_BASE_CODE_TFTP_READ_FILE,
f->netbuf,
FALSE,
&(f->netbuf_size),
&blocksize,
&nfs->srv_ip,
ascii_name,
NULL,
FALSE);
DBG_PRT((L"after Mftp=%r netbuf:" PTR_FMT " netbuf_size=%d blocksize=%d\n",
DBG_PRT((L"after: status=%r netbuf:" PTR_FMT " netbuf_size=%d blocksize=%d\n",
status,
f->netbuf,
f->netbuf_size,
blocksize));
if (status == EFI_TIMEOUT && blocksize == 0) {
/*
* XXX: if blocksize is not adjusted we could loop forever here
*/
//blocksize = 512;
status = EFI_BUFFER_TOO_SMALL;
}
/*
* check if we need to increase our buffer size
*/
if (status == EFI_BUFFER_TOO_SMALL) {
DBG_PRT((L"buffer too small, need netbuf_size=%d", f->netbuf_size));
if ((status == EFI_TIMEOUT || status == EFI_BUFFER_TOO_SMALL) && !server_provided_filesize) {
Print(L"buffer too small, need netbuf_size=%d\n", f->netbuf_size);
/*
* if the TFTP server supports TFTP options, then we should
* get the required size. So we test to see if the size
@ -378,16 +439,22 @@ retry:
} else {
/* we got an answer from the TFTP server, let's try it */
f->netbuf_maxsize = f->netbuf_size;
server_provided_filesize = TRUE;
}
free(f->netbuf);
f->netbuf = NULL; /* will force reallocation */
if (netbuf_alloc(f) == 0) goto retry;
if (netbuf_alloc(f) == 0) {
retries++;
goto retry;
}
/* fall through in case of error */
} else if (status == EFI_TIMEOUT) { //if just a simple timeout, buffers are good just retry
VERB_PRT(2, Print(L"TFTP returned EFI_TIMEOUT ERROR... %d retries left.\n", (2 - retries)));
retries++;
goto retry;
}
if (status == EFI_SUCCESS) {
/* start at the beginning of the file */
f->netbuf_pos = 0;

View file

@ -169,10 +169,13 @@ netfs_setdefaults(VOID *intf, config_file_t *config, CHAR16 *kname, UINTN maxlen
# if defined(CONFIG_ia64)
# define CONFIG_ARCH_EXTENSION L"-ia64.conf\0"
# define EXTENSION_LENGTH 11
# elif defined (CONFIG_ia32)
# define CONFIG_ARCH_EXTENSION L"-ia64.conf\0"
# define CONFIG_ARCH_EXTENSION L"-ia32.conf\0"
# define EXTENSION_LENGTH 11
# elif defined (CONFIG_x86_64)
# define CONFIG_ARCH_EXTENSION L"-x86_64.conf\0"
# define EXTENSION_LENGTH 13
# else
# error "You need to specfy your default arch config file"
# endif
@ -187,19 +190,19 @@ netfs_setdefaults(VOID *intf, config_file_t *config, CHAR16 *kname, UINTN maxlen
StrnCpy(config[0].fname+8, CONFIG_EXTENSION, 6);
StrnCpy(config[1].fname, str, maxlen-1);
StrnCpy(config[1].fname+6, CONFIG_ARCH_EXTENSION, 11);
StrnCpy(config[1].fname+6, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH);
StrnCpy(config[2].fname, str, maxlen-1);
StrnCpy(config[2].fname+6, CONFIG_EXTENSION, 6);
StrnCpy(config[3].fname, str, maxlen-1);
StrnCpy(config[3].fname+4, CONFIG_ARCH_EXTENSION, 11);
StrnCpy(config[3].fname+4, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH);
StrnCpy(config[4].fname, str, maxlen-1);
StrnCpy(config[4].fname+4, CONFIG_EXTENSION, 6);
StrnCpy(config[5].fname, str, maxlen-1);
StrnCpy(config[5].fname+2, CONFIG_ARCH_EXTENSION, 11);
StrnCpy(config[5].fname+2, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH);
StrnCpy(config[6].fname, str, maxlen-1);
StrnCpy(config[6].fname+2, CONFIG_EXTENSION, 6);

View file

@ -34,7 +34,7 @@
boot_params_t *param_start = NULL;
UINTN param_size = 0;
UINTN kernel_size = 0x200000; /* 2M (largest x86 bzImage kernel image) */
UINTN kernel_size = 0x400000; /* 4M (default x86 bzImage size limit) */
static INTN
bzImage_probe(CHAR16 *kname)

View file

@ -162,7 +162,9 @@ fill_inbuf(void)
if (EFI_ERROR(status)) {
error("elilo: Read failed");
}
#ifdef DEBUG_GZIP
DBG_PRT((L"%s : read %d bytes of %d bytes\n", LD_NAME, nread, expected));
#endif
insize = nread;
inptr = 1;
@ -434,8 +436,9 @@ flush_window(void)
long cnt;
if (!outcnt) return;
#ifdef DEBUG_GZIP
DBG_PRT((L"%s : flush_window outnct=%d file_offset=%d\n", LD_NAME, outcnt, file_offset));
#endif
Print(L"%c\b",helicopter[heli_count++%4]);

View file

@ -170,7 +170,9 @@ fill_inbuf(void)
if (EFI_ERROR(status)) {
error("elilo: Read failed");
}
#ifdef DEBUG_GZIP
DBG_PRT((L"%s : read %d bytes of %d bytes\n", LD_NAME, nread, expected));
#endif
insize = nread;
inptr = 1;
@ -530,8 +532,9 @@ flush_window(void)
long cnt;
if (!outcnt) return;
#ifdef DEBUG_GZIP
DBG_PRT((L"%s : flush_window outnct=%d file_offset=%ld\n", LD_NAME, outcnt, file_offset));
#endif
Print(L"%c\b",helicopter[heli_count++%4]);

View file

@ -55,7 +55,7 @@ sysdeps_create_boot_params(boot_params_t *bp, CHAR8 *cmdline, memdesc_t *initrd,
if (get_memmap(&mdesc) == -1) return -1;
DBG_PRT((L"Got memory map @ 0x%lx (%d bytes)", mdesc.md, mdesc.map_size));
DBG_PRT((L"Got memory map @ 0x%lx (%d bytes) with key %d", mdesc.md, mdesc.map_size, mdesc.cookie));
bp->efi_systab = (UINTN)systab;
bp->efi_memmap = (UINTN)mdesc.md;
@ -147,7 +147,7 @@ flush_dcache (CHAR8 *addr, UINT64 len)
/* Cache line length is at least 32. */
UINT64 a = (UINT64)addr & ~0x1f;
VERB_PRT(3, Print(L"Flush 0x%lx-", a));
DBG_PRT((L"Flush 0x%lx-", a));
/* Flush data. */
for (len = (len + 31) & ~0x1f; len > 0; len -= 0x20, a += 0x20)
@ -155,5 +155,5 @@ flush_dcache (CHAR8 *addr, UINT64 len)
/* Sync and serialize. Maybe extra. */
asm volatile (";; sync.i;; srlz.i;;");
VERB_PRT(3, Print(L"0x%lx\n", a));
DBG_PRT((L"0x%lx\n", a));
}

View file

@ -1,17 +1,24 @@
3 . 1 0 R E L E A S E N O T E S
3 . 1 2 R E L E A S E N O T E S
===================================
QUICK SUMMARY
====================
* FIXES MAC CONSOLE ISSUE
* FIXES NETBOOT BROKEN
* FIXES EXITBOOTSERVICES FAILURE
* TEMP FIX INCREASE BZIMAGE LIMITS
BUILD NOTES
====================
You will need the following toolchain to build elilo-3.10 from source
You will need the following toolchain to build elilo-3.12 from source
the elilo build environment is optimized for Debian and Debian based distros.
1. gnu-efi3.0d or greater, elilo-3.10 binaries were built with gnu-efi3.0e-2
shipping in Lenny
2. gcc-4.1.1 or greater, elilo-3.10 binaries were built with:
1. gnu-efi3.0d or greater, (you will want gnu-efi3.0i or > for cross build env
setups) elilo-3.12 binaries were built with gnu-efi3.0e-2
2. gcc-4.1.1 or greater, elilo-3.12 binaries were built with:
x86 -> 4.2.3-1ubuntu6
x86_64 -> 4.2.3-1ubuntu6
ia64 -> 4.3.2-1.1
3. binutils-2.17.50.0.14 or greater, elilo-3.10 binaries were built with:
3. binutils-2.17.50.0.14 or greater, elilo-3.12 binaries were built with:
x86 -> 2.18.1-cvs20080103-0ubuntu1
x86_64 -> 2.18.1~cvs20080103-0ubuntu1
ia64 -> 2.18.1~cvs20080103-7
@ -19,8 +26,8 @@ BUILD NOTES
* if you use a debian based (lenny)build environment you will have no problems
and setting it up is simple. you will be able to build elilo in 3 steps:
1. apt-get install gnu-efi, gcc, binutils
2. apt-get source elilo (or download elilo-3.10.tar.gz from SourceForge.)
3. cd ./elilo-3.10 and type make
2. apt-get source elilo (or download elilo-3.12.tar.gz from SourceForge.)
3. cd ./elilo-3.12 and type make
** If you use the upstream tarballs for the toolchain you will need to move
some files around.
@ -40,7 +47,7 @@ BUILD NOTES
ELILO ON EFI X86_64
=====================
HARD REQUIREMENTS
Elilo/x86_64 requires efi64 enabled linux kernel i.e. 2.6.21 or newer
EFI + x86_64 requires efi64 enabled linux kernel i.e. 2.6.21 or newer
nothing earlier will work, 2.6.21 was the earliest kernel that efi64
support went into. You need to compile the kernel with CONFIG_EFI
kernel option ON.
@ -50,13 +57,12 @@ HARD REQUIREMENTS
will enable early boot messages on the console. Elilo for x86_64
attempts to query EFI for GOP support and if it fails it defaults to
text mode which may or may not show you early console ouput depends on
your efi and physical setup. If efi default console ouput is set to
serial and you dont have anything attached to the serial port then youre
not going to see messages from elilo, duh.
your efi and physical setup.
WORKING ELILO.CONF FOR EFI X86_64 EXAMPLE
Here is my elilo.conf from my UEFI2.0/x86_64 workstation which uses GOP.
shows me console output, what elilo is doing, and kernel boot.
Here is my elilo.conf from my UEFI2.0/x86_64 (with nvidia pcie add on
card, i.e. your vga= kernel param may be different) workstation which uses GOP.
...shows me console output, what elilo is doing, and kernel boot.
default=UBUNTU
chooser=simple
@ -70,24 +76,29 @@ WORKING ELILO.CONF FOR EFI X86_64 EXAMPLE
initrd=/initrd.img-2.6.24-23-generic
CHANGES FROM 3.8 TO 3.10
CHANGES FROM 3.10 TO 3.12
========================
Patch contributions from David Lombard @ Intel and Stuart Hayes @ Dell
thank you.
Patch contributions from Julen Blache @ Debian
thank you. ** ADDS MAC IA32 NATIVE BOOT SUPPORT (i.e. consplitter fix)
* added PTR_FMT 32bit & 64bit pointer translation for correct output
* elilo hang bugfix x86_64 non-standard kernels with non-traditional start
address elilo will pull the start address from the kernel elf header for 2.6
or newer kernels, map memory and use that start address, else use standard
1MB default start address. And handle case of overlapping kernels
and initrds in memory.
* ported kernel start adress and memory overlap handling to ia32
* eliminated all possible compiler warnings except those actually
caused by gnu-efi that cant be fixed here.
* Debug output improvement, added pauses with visual feedback when
user sets debug or verbose options.
* bugfix added missing find_bits function definition back into ia32
subtree
* bugfix loader_probe now correctly errors out if no loaders
registered.
* Added additional #defines for debug levels to reduce the output noise
* Added Mac console patch rework from Julien Blache @ debian
this fixes the invisible console output from elilo on Macs
* Moved static ELILO_VERSION variable from elilo.c to elilo.h
so that elilo will print its version string and arch on startup.
* Fixed bug 2825044 ExitBootServices error handling, correctly deal
with changed memory map key if memory map changes from under elilo.
* Added memory map key to map debug output.
* Fixed bug 2874380 netbooting just flat broken. fixed ia64, x86_64
ia32, fixed handling of server side support of tfpt options (get file size)
elilo now attempts to get file size before attempting read of file
to set the buffers up correctly and deal with tftp servers that dont
support options extensions a little better.
* netboot, fixed bad blocksize handling
* netboot, fixed filename length for elilo-x86_64.conf type on tftp
server.
* increased bzimage kernel max length sizes to 4mb on i386 and 8mb on
x86_64... this is a legacy design hold over from original design and
needs to be re-written to do dynamic size memory management based on
the size of the actual vmlinuz image, as ia64/gzip does.

View file

@ -34,7 +34,7 @@
boot_params_t *param_start = NULL;
UINTN param_size = 0;
UINTN kernel_size = 0x400000; /* 4M (largest x86 bzImage kernel image) */
UINTN kernel_size = 0x800000; /* 8M (default x86_64 bzImage size limit) */
static INTN
bzImage_probe(CHAR16 *kname)

View file

@ -165,7 +165,9 @@ fill_inbuf(void)
if (EFI_ERROR(status)) {
error("elilo: Read failed");
}
#ifdef DEBUG_GZIP
DBG_PRT((L"%s : read %d bytes of %d bytes\n", LD_NAME, nread, expected));
#endif
insize = nread;
inptr = 1;
@ -437,8 +439,9 @@ flush_window(void)
long cnt;
if (!outcnt) return;
#ifdef DEBUG_GZIP
DBG_PRT((L"%s : flush_window outnct=%d file_offset=%ld\n", LD_NAME, outcnt, file_offset));
#endif
Print(L"%c\b",helicopter[heli_count++%4]);