forked from pool/elilo
229 lines
6.9 KiB
Diff
229 lines
6.9 KiB
Diff
|
---
|
||
|
elilo.h | 5 ++++
|
||
|
ia32/system.c | 6 +++++
|
||
|
ia64/system.c | 6 +++++
|
||
|
initrd.c | 12 +++++++++-
|
||
|
x86_64/sysdeps.h | 20 ++++++------------
|
||
|
x86_64/system.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++-------
|
||
|
6 files changed, 88 insertions(+), 22 deletions(-)
|
||
|
|
||
|
--- a/elilo.h
|
||
|
+++ b/elilo.h
|
||
|
@@ -54,6 +54,10 @@
|
||
|
#define ROUNDUP(x,a) (((x) + (a) - 1) & ~((a) - 1))
|
||
|
#define ROUNDDOWN(x,a) ((x) & ~((a) - 1))
|
||
|
|
||
|
+#ifndef UINT32_MAX
|
||
|
+#define UINT32_MAX ((UINT32)-1)
|
||
|
+#endif
|
||
|
+
|
||
|
/*
|
||
|
* Elilo Boot modes
|
||
|
*/
|
||
|
@@ -212,6 +216,7 @@ extern CHAR16 *sysdeps_get_cmdline_opts(
|
||
|
extern INTN sysdeps_getopt(INTN, INTN, CHAR16 *);
|
||
|
extern VOID sysdeps_print_cmdline_opts(VOID);
|
||
|
extern INTN sysdeps_register_options(VOID);
|
||
|
+extern VOID *sysdeps_checkfix_initrd(VOID *, memdesc_t *);
|
||
|
|
||
|
#define CHAR_SLASH L'/'
|
||
|
#define CHAR_BACKSLASH L'\\'
|
||
|
--- a/ia32/system.c
|
||
|
+++ b/ia32/system.c
|
||
|
@@ -149,6 +149,12 @@ sysdeps_initrd_get_addr(kdesc_t *kd, mem
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+VOID *
|
||
|
+sysdeps_checkfix_initrd(VOID *start_addr, memdesc_t *imem)
|
||
|
+{
|
||
|
+ return start_addr;
|
||
|
+}
|
||
|
+
|
||
|
VOID
|
||
|
sysdeps_free_boot_params(boot_params_t *bp)
|
||
|
{
|
||
|
--- a/ia64/system.c
|
||
|
+++ b/ia64/system.c
|
||
|
@@ -140,6 +140,12 @@ sysdeps_initrd_get_addr(kdesc_t *kd, mem
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+VOID *
|
||
|
+sysdeps_checkfix_initrd(VOID *start_addr, memdesc_t *imem)
|
||
|
+{
|
||
|
+ return start_addr;
|
||
|
+}
|
||
|
+
|
||
|
/* Flush data cache [addr; addr + len], and sync with icache. */
|
||
|
void
|
||
|
flush_dcache (CHAR8 *addr, UINT64 len)
|
||
|
--- a/initrd.c
|
||
|
+++ b/initrd.c
|
||
|
@@ -41,7 +41,11 @@ INTN
|
||
|
load_file(CHAR16 *filename, memdesc_t *image)
|
||
|
{
|
||
|
EFI_STATUS status;
|
||
|
- VOID *start_addr = NULL;
|
||
|
+ /*
|
||
|
+ * Actually using the value from sysdeps_initrd_get_addr()
|
||
|
+ * instead of NULL is no change for ia64!
|
||
|
+ */
|
||
|
+ VOID *start_addr = image->start_addr;
|
||
|
UINTN pgcnt;
|
||
|
UINT64 size = 0;
|
||
|
fops_fd_t fd;
|
||
|
@@ -71,7 +75,11 @@ load_file(CHAR16 *filename, memdesc_t *i
|
||
|
/* round up to get required number of pages (4KB) */
|
||
|
image->pgcnt = pgcnt = EFI_SIZE_TO_PAGES(image->size);
|
||
|
|
||
|
- start_addr = alloc_pages(pgcnt, EfiLoaderData, start_addr ? AllocateAddress : AllocateAnyPages, 0 );
|
||
|
+ start_addr = alloc_pages(pgcnt, EfiLoaderData,
|
||
|
+ start_addr ? AllocateAddress : AllocateAnyPages, start_addr);
|
||
|
+
|
||
|
+ start_addr = sysdeps_checkfix_initrd(start_addr, image);
|
||
|
+
|
||
|
if (start_addr == NULL) {
|
||
|
ERR_PRT((L"Failed to allocate %d pages for %s image", pgcnt,
|
||
|
filename));
|
||
|
--- a/x86_64/sysdeps.h
|
||
|
+++ b/x86_64/sysdeps.h
|
||
|
@@ -284,7 +284,8 @@ typedef union x86_64_boot_params {
|
||
|
/* 0x227 */ UINT8 ext_loader_type; /* LDR */
|
||
|
|
||
|
/* 0x228 */ UINT32 cmdline_addr; /* LDR */
|
||
|
-/* 0x22C */ UINT32 pad_8[41];
|
||
|
+/* 0x22C */ UINT32 initrd_addr_max; /* BLD */
|
||
|
+/* 0x230 */ UINT32 pad_8[40];
|
||
|
/* 0x2D0 */ UINT8 e820_map[2560];
|
||
|
} s;
|
||
|
} boot_params_t;
|
||
|
@@ -374,7 +375,6 @@ start_kernel(VOID *kentry, boot_params_t
|
||
|
UINT16 kernel_cs;
|
||
|
} jumpvector;
|
||
|
VOID *jump_start;
|
||
|
- uint64_t temp;
|
||
|
|
||
|
/*
|
||
|
* Disable interrupts.
|
||
|
@@ -382,22 +382,16 @@ start_kernel(VOID *kentry, boot_params_t
|
||
|
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
|
||
|
--- a/x86_64/system.c
|
||
|
+++ b/x86_64/system.c
|
||
|
@@ -131,10 +131,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 +144,12 @@ sysdeps_initrd_get_addr(kdesc_t *kd, mem
|
||
|
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 +157,48 @@ sysdeps_initrd_get_addr(kdesc_t *kd, mem
|
||
|
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)
|
||
|
{
|
||
|
@@ -550,6 +592,11 @@ sysdeps_create_boot_params(
|
||
|
/* 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);
|