release 3.14
https://sourceforge.net/projects/elilo/files/elilo/elilo-3.14/
This commit is contained in:
parent
e351d8fbea
commit
82f7288853
29 changed files with 659 additions and 235 deletions
166
x86_64/bzimage.c
166
x86_64/bzimage.c
|
@ -36,6 +36,129 @@ UINTN param_size = 0;
|
|||
|
||||
UINTN kernel_size = 0x800000; /* 8M (default x86_64 bzImage size limit) */
|
||||
|
||||
static VOID *
|
||||
bzImage_alloc()
|
||||
{
|
||||
UINTN pages = EFI_SIZE_TO_PAGES(kernel_size);
|
||||
int reloc_kernel = 0;
|
||||
VOID *kla, *kend = kernel_start + kernel_size;
|
||||
UINT32 kalign, kmask;
|
||||
boot_params_t *ps = param_start;
|
||||
|
||||
/*
|
||||
* Get address for kernel from header, if applicable & available.
|
||||
*/
|
||||
if ((ps->s.hdr_major < 2) ||
|
||||
(ps->s.hdr_major == 2 && ps->s.hdr_minor < 5)) {
|
||||
reloc_kernel = 0;
|
||||
} else {
|
||||
if (ps->s.kernel_start >= DEFAULT_KERNEL_START)
|
||||
kernel_start = (void *)(UINT64)ps->s.kernel_start;
|
||||
reloc_kernel = ps->s.relocatable_kernel;
|
||||
kalign = ps->s.kernel_alignment;
|
||||
kmask = kalign - 1;
|
||||
VERB_PRT(3, Print(L"kernel header (%d.%d) suggests kernel "
|
||||
"start at address "PTR_FMT" (%srelocatable!)\n",
|
||||
ps->s.hdr_major, ps->s.hdr_minor, ps->s.kernel_start,
|
||||
(reloc_kernel ? L"": L"not ")));
|
||||
}
|
||||
|
||||
/*
|
||||
* Best effort for old (< 2.6.20) and non-relocatable kernels
|
||||
*/
|
||||
if (alloc_kmem(kernel_start, pages) == 0) {
|
||||
VERB_PRT(3, Print(L"kernel_start: "PTR_FMT" kernel_size: %d\n",
|
||||
kernel_start, kernel_size));
|
||||
return kernel_start;
|
||||
} else if ( ! reloc_kernel ) {
|
||||
/*
|
||||
* Couldn't get desired address--just load it anywhere and
|
||||
* (try to) move it later. It's the only chance for non-
|
||||
* relocatable kernels, but it breaks occassionally...
|
||||
*/
|
||||
ERR_PRT((L"Kernel header (%d.%d) suggests kernel "
|
||||
"start at address "PTR_FMT" (non relocatable!)\n"
|
||||
"This address is not available, so an attempt"
|
||||
"is made to copy the kernel there later on\n"
|
||||
"BEWARE: this is unsupported and may not work. "
|
||||
"Please update your kernel.\n",
|
||||
ps->s.hdr_major, ps->s.hdr_minor, ps->s.kernel_start));
|
||||
kla = (VOID *)(UINT32_MAX - kernel_size);
|
||||
/* NULL would preserve the "anywhere" semantic, */
|
||||
/* but it would not prevent allocation above 4GB! */
|
||||
|
||||
if (alloc_kmem_anywhere(&kla, pages) != 0) {
|
||||
/* out of luck */
|
||||
return NULL;
|
||||
}
|
||||
VERB_PRT(3, Print(L"kernel_start: "PTR_FMT
|
||||
" kernel_size: %d loading at: "PTR_FMT"\n",
|
||||
kernel_start, kernel_size, kla));
|
||||
return kla;
|
||||
}
|
||||
|
||||
|
||||
/* Is 'ps->s.kernel_alignment' guaranteed to be sane? */
|
||||
if (kalign < EFI_PAGE_SIZE) {
|
||||
kalign = EFI_PAGE_SIZE;
|
||||
kmask = EFI_PAGE_MASK;
|
||||
}
|
||||
DBG_PRT((L"alignment: kernel=0x%x efi_page=0x%x : 0x%x\n",
|
||||
ps->s.kernel_alignment, EFI_PAGE_SIZE, kalign));
|
||||
|
||||
/*
|
||||
* Couldn't get the preferred address, but luckily it's
|
||||
* a relocatable kernel, so ...
|
||||
*
|
||||
* 1. use 'find_kernel_memory()' (like Itanium)
|
||||
* 2. try out the 16 lowest possible aligned addresses (> 0)
|
||||
* 3. get enough memory to align "creatively"
|
||||
* 4. forget alignment (and start praying)...
|
||||
*/
|
||||
|
||||
/* 1. */
|
||||
if ((find_kernel_memory(kernel_start, kend, kalign, &kla) != 0) ||
|
||||
(alloc_kmem(kla, pages) != 0)) {
|
||||
kla = NULL;
|
||||
}
|
||||
|
||||
/* 2. */
|
||||
if ( ! kla && (UINT64)kernel_start < kalign ) {
|
||||
int i;
|
||||
for ( i = 1; i < 16 && !kla; i++ ) {
|
||||
VOID *tmp = (VOID *)((UINT64)kalign * i);
|
||||
if (alloc_kmem(tmp, pages) == 0) {
|
||||
kla = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 3. */
|
||||
if ( ! kla ) {
|
||||
UINTN apages = EFI_SIZE_TO_PAGES(kernel_size + kmask);
|
||||
kla = (VOID *)(UINT32_MAX - kernel_size - kmask);
|
||||
|
||||
if (alloc_kmem_anywhere(&kla, apages) == 0) {
|
||||
kla = (VOID *)(((UINT64)kla + kmask) & ~kmask);
|
||||
} else {
|
||||
kla = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* 4. last resort */
|
||||
if ( ! kla ) {
|
||||
kla = (VOID *)(UINT32_MAX - kernel_size);
|
||||
if (alloc_kmem_anywhere(&kla, pages) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
kernel_start = kla;
|
||||
VERB_PRT(1, Print(L"relocating kernel_start: "PTR_FMT
|
||||
" kernel_size: %d\n", kernel_start, kernel_size));
|
||||
return kla;
|
||||
}
|
||||
|
||||
static INTN
|
||||
bzImage_probe(CHAR16 *kname)
|
||||
{
|
||||
|
@ -158,53 +281,34 @@ bzImage_probe(CHAR16 *kname)
|
|||
* Allocate memory for kernel.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get correct address for kernel from header, if applicable & available.
|
||||
*/
|
||||
if ((param_start->s.hdr_major == 2) &&
|
||||
(param_start->s.hdr_minor >= 6) &&
|
||||
(param_start->s.kernel_start >= DEFAULT_KERNEL_START)) {
|
||||
kernel_start = (void *)param_start->s.kernel_start;
|
||||
VERB_PRT(3, Print(L"kernel header suggests kernel start at address "PTR_FMT"\n",
|
||||
kernel_start));
|
||||
kernel_load_address = bzImage_alloc();
|
||||
if ( ! kernel_load_address ) {
|
||||
ERR_PRT((L"Could not allocate memory for kernel."));
|
||||
free(param_start);
|
||||
param_start = NULL;
|
||||
param_size = 0;
|
||||
fops_close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
kernel_load_address = kernel_start;
|
||||
|
||||
if (alloc_kmem(kernel_start, EFI_SIZE_TO_PAGES(kernel_size)) != 0) {
|
||||
/*
|
||||
* Couldn't get desired address--just load it anywhere and move it later.
|
||||
* (Easier than relocating kernel, and also works with non-relocatable kernels.)
|
||||
*/
|
||||
if (alloc_kmem_anywhere(&kernel_load_address, EFI_SIZE_TO_PAGES(kernel_size)) != 0) {
|
||||
ERR_PRT((L"Could not allocate memory for kernel."));
|
||||
free(param_start);
|
||||
param_start = NULL;
|
||||
param_size = 0;
|
||||
fops_close(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
VERB_PRT(3, Print(L"kernel_start: "PTR_FMT" kernel_size: %d loading at: "PTR_FMT"\n",
|
||||
kernel_start, kernel_size, kernel_load_address));
|
||||
|
||||
/*
|
||||
* Now read the rest of the kernel image into memory.
|
||||
*/
|
||||
|
||||
DBG_PRT((L"reading kernel image...\n"));
|
||||
Print(L"Loading kernel %s... ", kname);
|
||||
|
||||
size = kernel_size;
|
||||
efi_status = fops_read(fd, kernel_load_address, &size);
|
||||
if (EFI_ERROR(efi_status) || size < 0x10000) {
|
||||
ERR_PRT((L"Error reading kernel image %s.", kname));
|
||||
ERR_PRT((L"Error reading kernel image (0x%x).", efi_status));
|
||||
free(param_start);
|
||||
param_start = NULL;
|
||||
param_size = 0;
|
||||
fops_close(fd);
|
||||
free_kmem();
|
||||
return -1;
|
||||
} else {
|
||||
Print(L" done\n");
|
||||
}
|
||||
|
||||
DBG_PRT((L"kernel image read: %d bytes, %d Kbytes\n", size, size / 1024));
|
||||
|
|
|
@ -33,15 +33,23 @@
|
|||
|
||||
typedef struct {
|
||||
UINTN legacy_free_boot;
|
||||
UINTN text_mode;
|
||||
} x86_64_global_config_t;
|
||||
|
||||
|
||||
#define x86_64_opt_offsetof(option) (&((sys_img_options_t *)(0x0))->option)
|
||||
|
||||
static x86_64_global_config_t x86_64_gconf;
|
||||
|
||||
static config_option_t sysdeps_global_options[]={
|
||||
{OPT_BOOL, OPT_GLOBAL, L"legacy-free", NULL, NULL, &x86_64_gconf.legacy_free_boot}
|
||||
};
|
||||
|
||||
static config_option_t sysdeps_image_options[]={
|
||||
{OPT_BOOL, OPT_IMAGE_SYS, L"text-mode", NULL, NULL, x86_64_opt_offsetof(text_mode)}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* X86_64 operations that need to be done only once and just before
|
||||
* entering the main loop of the loader
|
||||
|
@ -81,6 +89,14 @@ x86_64_use_legacy_free_boot(VOID)
|
|||
return x86_64_gconf.legacy_free_boot ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
INTN
|
||||
x86_64_text_mode(VOID)
|
||||
{
|
||||
return (elilo_opt.sys_img_opts &&
|
||||
elilo_opt.sys_img_opts->text_mode == TRUE) ? 1 : 0;
|
||||
}
|
||||
|
||||
INTN
|
||||
sysdeps_register_options(VOID)
|
||||
{
|
||||
|
@ -89,14 +105,11 @@ sysdeps_register_options(VOID)
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -107,12 +107,12 @@ typedef union x86_64_boot_params {
|
|||
/* 0x06 */ UINT8 orig_video_mode; /* LDR */
|
||||
/* 0x07 */ UINT8 orig_video_cols; /* LDR */
|
||||
|
||||
/* 0x08 */ UINT16 unused_1; /* unused */
|
||||
/* 0x08 */ UINT16 pad_1; /* unused */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x0A */ UINT16 orig_ega_bx; /* LDR */
|
||||
|
||||
/* 0x0C */ UINT16 unused_2; /* unused */
|
||||
/* 0x0C */ UINT16 pad_2; /* unused */
|
||||
|
||||
/* Screen height before passing control to kernel. */
|
||||
/* 0x0E */ UINT8 orig_video_rows; /* LDR */
|
||||
|
@ -174,7 +174,7 @@ typedef union x86_64_boot_params {
|
|||
/* 0x4E */ UINT32 bios_code_len; /* LDR */
|
||||
/* 0x52 */ UINT16 bios_data_len; /* LDR */
|
||||
|
||||
/* 0x54 */ UINT8 unused_3[0x2C]; /* unused */
|
||||
/* 0x54 */ UINT8 pad_3[0x2C]; /* unused */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x80 */ UINT8 hd0_info[0x10]; /* LDR */
|
||||
|
@ -184,7 +184,7 @@ typedef union x86_64_boot_params {
|
|||
/* 0xA0 */ UINT16 mca_info_len; /* LDR */
|
||||
/* 0xA2 */ UINT8 mca_info_buf[0x10]; /* LDR */
|
||||
|
||||
/* 0xB2 */ UINT8 unused_4[0x10E]; /* unused */
|
||||
/* 0xB2 */ UINT8 pad_4[0x10E]; /* unused */
|
||||
|
||||
/* EFI boot loader signature. */
|
||||
/* 0x1C0 */ UINT8 efi_loader_sig[4]; /* LDR */
|
||||
|
@ -209,9 +209,9 @@ typedef union x86_64_boot_params {
|
|||
/* Available contiguous extended memory in KB. */
|
||||
/* 0x1E0 */ UINT32 alt_mem_k; /* LDR */
|
||||
|
||||
/* 0x1E4 */ UINT32 unused_51; /* unused */
|
||||
/* 0x1E4 */ UINT32 pad_51; /* unused */
|
||||
/* 0x1E8 */ UINT8 e820_nrmap;
|
||||
/* 0x1E9 */ UINT32 unused_52[2]; /* unused */
|
||||
/* 0x1E9 */ UINT32 pad_52[2]; /* unused */
|
||||
|
||||
/* Size of setup code in sectors (1 sector == 512 bytes). */
|
||||
/* 0x1F1 */ UINT8 setup_sectors; /* BLD */
|
||||
|
@ -220,15 +220,10 @@ typedef union x86_64_boot_params {
|
|||
/* 0x1F2 */ UINT16 mount_root_rdonly; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x1F4 */ UINT16 sys_size; /* BLD */
|
||||
/* 0x1F4 */ UINT32 sys_size; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x1F6 */ UINT16 swap_dev; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x1F8 */ UINT16 ramdisk_flags; /* BLD */
|
||||
#define RAMDISK_PROMPT 0x8000
|
||||
#define RAMDISK_LOAD 0x4000
|
||||
/* 0x1F8 */ UINT16 ram_size_DNU; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x1FA */ UINT16 video_mode_flag; /* BLD */
|
||||
|
@ -236,12 +231,8 @@ typedef union x86_64_boot_params {
|
|||
/* %%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
|
||||
/* 0x1FE */ UINT16 boot_flag; /* ? */
|
||||
|
||||
/* Jump past setup data (not used in EFI). */
|
||||
/* 0x200 */ UINT16 jump; /* BLD */
|
||||
|
@ -283,16 +274,21 @@ typedef union x86_64_boot_params {
|
|||
/* 0x21C */ UINT32 initrd_size; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x220 */ UINT32 bootsect_helper; /* BLD */
|
||||
/* 0x220 */ UINT32 bootsect_helper_DNU; /* BLD */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x224 */ UINT16 heap_end_ptr; /* LDR */
|
||||
|
||||
/* %%TBD */
|
||||
/* 0x226 */ UINT16 unused_7; /* LDR */
|
||||
/* 0x226 */ UINT8 ext_loader_ver; /* LDR */
|
||||
/* 0x227 */ UINT8 ext_loader_type; /* LDR */
|
||||
|
||||
/* 0x228 */ UINT32 cmdline_addr; /* LDR */
|
||||
/* 0x22C */ UINT32 unused_8[41];
|
||||
/* 0x22C */ UINT32 initrd_addr_max; /* BLD */
|
||||
/* 0x230 */ UINT32 kernel_alignment; /* BLD */
|
||||
/* 0x234 */ UINT8 relocatable_kernel; /* BLD */
|
||||
/* 0x235 */ UINT8 pad_8[3];
|
||||
/* 0x238 */ UINT32 pad_9[38];
|
||||
/* 0x2D0 */ UINT8 e820_map[2560];
|
||||
} s;
|
||||
} boot_params_t;
|
||||
|
@ -368,6 +364,7 @@ extern UINT8 rmswitch_image[];
|
|||
extern UINTN rmswitch_size;
|
||||
|
||||
extern INTN x86_64_use_legacy_free_boot();
|
||||
extern INTN x86_64_text_mode();
|
||||
|
||||
/*
|
||||
* How to jump to kernel code
|
||||
|
@ -382,7 +379,6 @@ start_kernel(VOID *kentry, boot_params_t *bp)
|
|||
UINT16 kernel_cs;
|
||||
} jumpvector;
|
||||
VOID *jump_start;
|
||||
uint64_t temp;
|
||||
|
||||
/*
|
||||
* Disable interrupts.
|
||||
|
@ -390,22 +386,16 @@ start_kernel(VOID *kentry, boot_params_t *bp)
|
|||
asm volatile ( "cli" : : );
|
||||
|
||||
/*
|
||||
* Relocate kernel (if needed), and initrd (if present).
|
||||
* Copy kernel first, in case kernel was loaded overlapping where we're
|
||||
* planning to copy the initrd. This assumes that the initrd didn't
|
||||
* get loaded overlapping where we're planning to copy the kernel, but
|
||||
* that's pretty unlikely since we couldn't alloc that space for the
|
||||
* kernel (or the kernel would already be there).
|
||||
* Relocate kernel (if needed).
|
||||
* This assumes that the initrd didn't get loaded overlapping where
|
||||
* we're planning to copy the kernel, but that's pretty unlikely
|
||||
* since we couldn't alloc that space for the kernel (or the kernel
|
||||
* would already be there).
|
||||
*/
|
||||
if (kernel_start != kernel_load_address) {
|
||||
MEMCPY(kernel_start, kernel_load_address, kernel_size);
|
||||
}
|
||||
|
||||
if (bp->s.initrd_start) {
|
||||
temp = bp->s.initrd_start;
|
||||
MEMCPY(INITRD_START, temp , bp->s.initrd_size);
|
||||
bp->s.initrd_start = INITRD_START;
|
||||
}
|
||||
/*
|
||||
* Copy boot sector, setup data and command line
|
||||
* to final resting place. We need to copy
|
||||
|
@ -468,7 +458,8 @@ start_kernel(VOID *kentry, boot_params_t *bp)
|
|||
}
|
||||
|
||||
typedef struct sys_img_options {
|
||||
UINT8 nothing_yet;
|
||||
UINT8 dummy; /* forces non-zero offset for first field */
|
||||
UINT8 text_mode; /* do not try to initialize Graphics Output Protocol */
|
||||
} sys_img_options_t;
|
||||
|
||||
#endif /* __ELILO_SYSDEPS_X86_64_H__ */
|
||||
|
|
261
x86_64/system.c
261
x86_64/system.c
|
@ -38,11 +38,19 @@
|
|||
*/
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "elilo.h"
|
||||
#include "loader.h"
|
||||
#include "rmswitch.h"
|
||||
|
||||
#define DEBUG_CREATE_BOOT_PARAMS 0
|
||||
#if DEBUG_CREATE_BOOT_PARAMS
|
||||
#define DPR(a) do { if (elilo_opt.debug) { Print a; } } while ( 0 )
|
||||
#else
|
||||
#define DPR(a)
|
||||
#endif
|
||||
|
||||
extern loader_ops_t bzimage_loader, plain_loader, gzip_loader;
|
||||
|
||||
/*
|
||||
|
@ -105,14 +113,16 @@ UINTN high_base_mem = 0x90000;
|
|||
UINTN high_ext_mem = 32 * 1024 * 1024;
|
||||
|
||||
/* This starting address will hold true for all of the loader types for now */
|
||||
VOID *kernel_start = (void *)DEFAULT_KERNEL_START;
|
||||
VOID *kernel_start = (VOID *)DEFAULT_KERNEL_START;
|
||||
|
||||
/* The kernel may load elsewhere if EFI firmware reserves kernel_start */
|
||||
VOID *kernel_load_address = DEFAULT_KERNEL_START;
|
||||
VOID *kernel_load_address = (VOID *)DEFAULT_KERNEL_START;
|
||||
|
||||
VOID *initrd_start = NULL;
|
||||
UINTN initrd_size = 0;
|
||||
|
||||
INTN e820_map_overflow = 0;
|
||||
|
||||
INTN
|
||||
sysdeps_init(EFI_HANDLE dev)
|
||||
{
|
||||
|
@ -131,10 +141,8 @@ sysdeps_init(EFI_HANDLE dev)
|
|||
/*
|
||||
* 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.
|
||||
* For now we suggest 'initrd_addr_max' with room for 32MB,
|
||||
* as image->pgcnt is not initialized yet.
|
||||
*/
|
||||
INTN
|
||||
sysdeps_initrd_get_addr(kdesc_t *kd, memdesc_t *imem)
|
||||
|
@ -146,10 +154,12 @@ sysdeps_initrd_get_addr(kdesc_t *kd, memdesc_t *imem)
|
|||
return -1;
|
||||
}
|
||||
|
||||
VERB_PRT(3, Print(L"kstart="PTR_FMT" kentry="PTR_FMT" kend="PTR_FMT"\n",
|
||||
kd->kstart, kd->kentry, kd->kend));
|
||||
VERB_PRT(3, Print(L"initrd_addr_max="PTR_FMT" reserve=%d\n",
|
||||
param_start->s.initrd_addr_max, 32*MB));
|
||||
|
||||
imem->start_addr = kd->kend;
|
||||
imem->start_addr = (VOID *)
|
||||
(((UINT64)param_start->s.initrd_addr_max - 32*MB + 1)
|
||||
& ~EFI_PAGE_MASK);
|
||||
|
||||
VERB_PRT(3, Print(L"initrd start_addr="PTR_FMT" pgcnt=%d\n",
|
||||
imem->start_addr, imem->pgcnt));
|
||||
|
@ -157,6 +167,48 @@ sysdeps_initrd_get_addr(kdesc_t *kd, memdesc_t *imem)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* checkfix_initrd()
|
||||
* Check and possibly fix allocation of initrd memory.
|
||||
*/
|
||||
VOID *
|
||||
sysdeps_checkfix_initrd(VOID *start_addr, memdesc_t *imem)
|
||||
{
|
||||
UINTN pgcnt = EFI_SIZE_TO_PAGES(imem->size);
|
||||
UINT64 initrd_addr_max = (UINT64)param_start->s.initrd_addr_max;
|
||||
UINT64 ki_max = initrd_addr_max - imem->size + 1;
|
||||
VOID *ki_max_addr;
|
||||
|
||||
VERB_PRT( 3, Print(L"loadfile: start_addr="PTR_FMT
|
||||
" ki_max_addr="PTR_FMT"\n", start_addr, (VOID *)ki_max));
|
||||
if (ki_max > UINT32_MAX) {
|
||||
ERR_PRT((L"Force kernel specified initrd_addr_max="PTR_FMT
|
||||
" below 4GB\n", (VOID *)initrd_addr_max));
|
||||
ki_max = UINT32_MAX - imem->size + 1;
|
||||
}
|
||||
ki_max_addr = (VOID *)ki_max;
|
||||
|
||||
if ((UINT64)start_addr > ki_max) {
|
||||
VERB_PRT(1, Print(L"initrd start_addr="PTR_FMT" above "
|
||||
"limit="PTR_FMT"\n", start_addr, ki_max_addr));
|
||||
free(start_addr);
|
||||
start_addr = NULL;
|
||||
}
|
||||
/* so either the initial allocation failed or it's been to high! */
|
||||
if (start_addr == NULL) {
|
||||
start_addr = alloc_pages(pgcnt, EfiLoaderData,
|
||||
AllocateMaxAddress, ki_max_addr);
|
||||
}
|
||||
if ((UINT64)start_addr > ki_max) {
|
||||
ERR_PRT((L"Failed to allocate %d pages below %dMB",
|
||||
pgcnt, (param_start->s.initrd_addr_max+1)>>20));
|
||||
free(start_addr);
|
||||
start_addr = NULL;
|
||||
}
|
||||
return start_addr;
|
||||
}
|
||||
|
||||
VOID
|
||||
sysdeps_free_boot_params(boot_params_t *bp)
|
||||
{
|
||||
|
@ -199,6 +251,10 @@ static INTN get_video_info(boot_params_t * bp) {
|
|||
UINTN size1;
|
||||
UINT8 i;
|
||||
|
||||
if (x86_64_text_mode() == 1) {
|
||||
Print((L"Skip GOP init, force text-mode.\n"));
|
||||
return -1;
|
||||
}
|
||||
efi_status = uefi_call_wrapper(
|
||||
BS->LocateHandle,
|
||||
5,
|
||||
|
@ -209,7 +265,19 @@ static INTN get_video_info(boot_params_t * bp) {
|
|||
(VOID **)Gop_handle);
|
||||
|
||||
if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL) {
|
||||
ERR_PRT((L"LocateHandle GopProtocol failed."));
|
||||
Print(L"LocateHandle GopProtocol failed.\n");
|
||||
Print(L"--Either no graphics head is installed,\n" \
|
||||
"--efi console is set to serial, or,\n" \
|
||||
"--the EFI firmware version of this machine is\n" \
|
||||
"--older than UEFI 2.0. and does not support GOP");
|
||||
Print(L"you can SAFELY IGNORE this error. elilo will\n" \
|
||||
"default to text-mode.\n Alternatively you can " \
|
||||
"now force text mode by setting config variable\n" \
|
||||
"text_mode=1 for x86 in elilo.conf or via cmdline.\n\n");
|
||||
Print(L"However if this is the last text output you see\n" \
|
||||
"ensure that your kernel console command line\n " \
|
||||
"variable matches up with the actual efi boot menu\n" \
|
||||
"console output settings.\n\n");
|
||||
return -1;
|
||||
}
|
||||
Gop_handle = alloc(size, 0);
|
||||
|
@ -326,10 +394,56 @@ static INTN get_video_info(boot_params_t * bp) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
CHAR16 *
|
||||
StrStr(IN const CHAR16 *h, IN const CHAR16 *n)
|
||||
{
|
||||
const CHAR16 *t = h;
|
||||
CHAR16 *res;
|
||||
int len = 0, i;
|
||||
|
||||
len = StrLen((CHAR16 *)n);
|
||||
while(*t != CHAR_NULL) {
|
||||
res = StrChr( t, n[0]);
|
||||
if (!res) return res;
|
||||
for( i = 1; i < len && res[i] != CHAR_NULL && res[i] == n[i]; i++);
|
||||
if ( i == len ) return res;
|
||||
t = res + 1;
|
||||
if (t > h + CMDLINE_MAXLEN) return (CHAR16 *)0;
|
||||
}
|
||||
|
||||
return (CHAR16 *)0;
|
||||
}
|
||||
|
||||
CHAR8 *
|
||||
StrStr8(IN const CHAR8 *h, IN const CHAR8 *n)
|
||||
{
|
||||
const CHAR8 *t = h;
|
||||
CHAR8 *res;
|
||||
int len = 0, i;
|
||||
|
||||
len = strlena((CHAR8 *)n);
|
||||
while(*t != 0) {
|
||||
res = strchra( t, n[0]);
|
||||
if (!res) return res;
|
||||
for( i = 1; i < len && res[i] != 0 && res[i] == n[i]; i++);
|
||||
if ( i == len ) return res;
|
||||
t = res + 1;
|
||||
if (t > (h + CMDLINE_MAXLEN)) return (CHAR8 *)0;
|
||||
}
|
||||
|
||||
return (CHAR8 *)0;
|
||||
}
|
||||
|
||||
/* Convert EFI memory map to E820 map for the operating system
|
||||
* This code is based on a Linux kernel patch submitted by Edgar Hucek
|
||||
*/
|
||||
|
||||
#if DEBUG_CREATE_BOOT_PARAMS
|
||||
static int e820_max = 6;
|
||||
#else
|
||||
static int e820_max = E820_MAX;
|
||||
#endif
|
||||
|
||||
/* Add a memory region to the e820 map */
|
||||
static void add_memory_region (struct e820entry *e820_map,
|
||||
int *e820_nr_map,
|
||||
|
@ -338,21 +452,56 @@ static void add_memory_region (struct e820entry *e820_map,
|
|||
unsigned int type)
|
||||
{
|
||||
int x = *e820_nr_map;
|
||||
static unsigned long long estart = 0ULL;
|
||||
static unsigned long esize = 0L;
|
||||
static unsigned int etype = -1;
|
||||
static int merge = 0;
|
||||
|
||||
if (x == E820_MAX) {
|
||||
Print(L"Too many entries in the memory map!\n");
|
||||
if (x == 0)
|
||||
DPR((L"AMR: %3s %4s %16s/%12s/%s\n",
|
||||
L"idx", L" ", L"start", L"size", L"type"));
|
||||
|
||||
/* merge adjacent regions of same type */
|
||||
if ((x > 0) && e820_map[x-1].addr + e820_map[x-1].size == start
|
||||
&& e820_map[x-1].type == type) {
|
||||
e820_map[x-1].size += size;
|
||||
estart = e820_map[x-1].addr;
|
||||
esize = e820_map[x-1].size;
|
||||
etype = e820_map[x-1].type;
|
||||
merge++;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((x > 0) && e820_map[x-1].addr + e820_map[x-1].size == start
|
||||
&& e820_map[x-1].type == type)
|
||||
e820_map[x-1].size += size;
|
||||
else {
|
||||
/* fill up to E820_MAX */
|
||||
if ( x < e820_max ) {
|
||||
e820_map[x].addr = start;
|
||||
e820_map[x].size = size;
|
||||
e820_map[x].type = type;
|
||||
(*e820_nr_map)++;
|
||||
if (merge) DPR((L"AMR: %3d ==> %016llx/%012lx/%d (%d)\n",
|
||||
x-1, estart, esize, etype, merge));
|
||||
merge=0;
|
||||
DPR((L"AMR: %3d add %016llx/%012lx/%d\n",
|
||||
x, start, size, type));
|
||||
return;
|
||||
}
|
||||
/* different type means another region didn't fit */
|
||||
/* or same type, but there's a hole */
|
||||
if (etype != type || (estart + esize) != start) {
|
||||
if (merge) DPR((L"AMR: %3d ===> %016llx/%012lx/%d (%d)\n",
|
||||
e820_map_overflow, estart, esize, etype, merge));
|
||||
merge = 0;
|
||||
estart = start;
|
||||
esize = size;
|
||||
etype = type;
|
||||
e820_map_overflow++;
|
||||
DPR((L"AMR: %3d OVER %016llx/%012lx/%d\n",
|
||||
e820_map_overflow, start, size, type));
|
||||
return;
|
||||
}
|
||||
/* same type and no hole, merge it */
|
||||
estart += esize;
|
||||
esize += size;
|
||||
merge++;
|
||||
}
|
||||
|
||||
void fill_e820map(boot_params_t *bp, mmap_desc_t *mdesc)
|
||||
|
@ -431,6 +580,7 @@ void fill_e820map(boot_params_t *bp, mmap_desc_t *mdesc)
|
|||
break;
|
||||
default:
|
||||
/* We should not hit this case */
|
||||
DBG_PRT((L"hit default!?"));
|
||||
add_memory_region(e820_map, &e820_nr_map,
|
||||
md->PhysicalStart,
|
||||
md->NumberOfPages << EFI_PAGE_SHIFT,
|
||||
|
@ -444,6 +594,8 @@ void fill_e820map(boot_params_t *bp, mmap_desc_t *mdesc)
|
|||
|
||||
/*
|
||||
* x86_64 specific boot parameters initialization routine
|
||||
*
|
||||
* Note: debug and verbose messages have already been turned off!
|
||||
*/
|
||||
INTN
|
||||
sysdeps_create_boot_params(
|
||||
|
@ -459,6 +611,12 @@ sysdeps_create_boot_params(
|
|||
UINT8 row, col;
|
||||
UINT8 mode;
|
||||
UINT16 hdr_version;
|
||||
UINT8 e820_map_overflow_warned = 0;
|
||||
|
||||
#if DEBUG_CREATE_BOOT_PARAMS
|
||||
elilo_opt.debug=1;
|
||||
elilo_opt.verbose=5;
|
||||
#endif
|
||||
|
||||
DBG_PRT((L"fill_boot_params()\n"));
|
||||
|
||||
|
@ -493,17 +651,9 @@ sysdeps_create_boot_params(
|
|||
hdr_version = (bp->s.hdr_major << 8) | bp->s.hdr_minor;
|
||||
|
||||
/*
|
||||
* Clear out unused memory in boot sector image.
|
||||
* Do NOT clear out unknown memory in boot sector image.
|
||||
* This breaks boot protocol >= 2.10 (2.6.31).
|
||||
*/
|
||||
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.
|
||||
|
@ -553,19 +703,19 @@ sysdeps_create_boot_params(
|
|||
DBG_PRT((L"initrd->start_addr="PTR_FMT" initrd->pgcnt=%d\n",
|
||||
initrd->start_addr, initrd->pgcnt));
|
||||
|
||||
/* These RAMdisk flags are not needed, just zero them. */
|
||||
bp->s.ramdisk_flags = 0;
|
||||
/* These RAMdisk flags are not needed, just zero them. NOT!*/
|
||||
/* 'ramdisk_flags' (@0x1F8) is called 'ram_size' in the meantime, */
|
||||
/* see Documentation/x86/boot.txt. */
|
||||
|
||||
if (initrd->start_addr && initrd->pgcnt) {
|
||||
if ( (UINT64)initrd->start_addr > UINT32_MAX ) {
|
||||
ERR_PRT((L"Start of initrd out of reach (>4GB)."));
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
/* %%TBD - This will probably have to be changed. */
|
||||
bp->s.initrd_start = (UINT32)(UINT64)initrd->start_addr;
|
||||
bp->s.initrd_size = (UINT32)(initrd->size);
|
||||
/*
|
||||
* 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;
|
||||
|
@ -589,11 +739,6 @@ sysdeps_create_boot_params(
|
|||
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
|
||||
*/
|
||||
|
@ -602,6 +747,11 @@ sysdeps_create_boot_params(
|
|||
/*
|
||||
* Kernel entry point.
|
||||
*/
|
||||
if ( (UINT64)kernel_start != (UINT32)(UINT64)kernel_start ) {
|
||||
ERR_PRT((L"Start of kernel (will be) out of reach (>4GB)."));
|
||||
free_kmem();
|
||||
return -1;
|
||||
}
|
||||
bp->s.kernel_start = (UINT32)(UINT64)kernel_start;
|
||||
|
||||
/*
|
||||
|
@ -692,11 +842,9 @@ sysdeps_create_boot_params(
|
|||
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(boot_flag, 0x1FE, L"%xh");
|
||||
CHECK_OFFSET(jump, 0x200, L"%xh");
|
||||
CHECK_OFFSET(setup_sig, 0x202, L"'%-4.4a'");
|
||||
CHECK_OFFSET(hdr_minor, 0x206, L"%xh");
|
||||
|
@ -710,9 +858,9 @@ sysdeps_create_boot_params(
|
|||
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");
|
||||
CHECK_OFFSET(e820_map, 0x2D0, L"%xh");
|
||||
|
||||
if (test) {
|
||||
ERR_PRT((L"Boot sector and/or setup parameter alignment error."));
|
||||
|
@ -802,6 +950,31 @@ do_memmap:
|
|||
* and update the bootparam accordingly
|
||||
*/
|
||||
fill_e820map(bp, &mdesc);
|
||||
|
||||
#if DEBUG_CREATE_BOOT_PARAMS
|
||||
if ( e820_map_overflow == 0 )
|
||||
e820_map_overflow = -1; /* force second get_memmap()! */
|
||||
#endif
|
||||
if (e820_map_overflow && !e820_map_overflow_warned) {
|
||||
CHAR8 *aem = (CHAR8 *)"add_efi_memmap";
|
||||
e820_map_overflow_warned++;
|
||||
|
||||
#if DEBUG_CREATE_BOOT_PARAMS
|
||||
elilo_opt.debug=0;
|
||||
elilo_opt.verbose=0;
|
||||
#endif
|
||||
if (e820_map_overflow == -1 || StrStr8(cmdline, aem)) {
|
||||
/* Print(L"...mapping again, silently!\n"); */
|
||||
goto do_memmap;
|
||||
}
|
||||
|
||||
Print(L"\nCAUTION: EFI memory map has %d more entr%a"
|
||||
" than E820 map supports.\n"
|
||||
"To access all memory, '%a' may be necessary.\n\n",
|
||||
e820_map_overflow, (e820_map_overflow==1)?"y":"ies",
|
||||
aem);
|
||||
goto do_memmap;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue