Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:12.3
elilo
elilo-x86-64-initrd.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File elilo-x86-64-initrd.diff of Package elilo
--- 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);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor