summaryrefslogtreecommitdiffstats
path: root/sys/boot/common/load_elf.c
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2011-04-03 22:31:51 +0000
committermarcel <marcel@FreeBSD.org>2011-04-03 22:31:51 +0000
commite253ede76350c4b63552fb9fa2ab251200bba4d6 (patch)
treeeca323dd0978bd6b21c62e82ce8932b641bfb4e0 /sys/boot/common/load_elf.c
parent37c0565836f4c33ee4fcf4b66d577ca704ea5375 (diff)
downloadFreeBSD-src-e253ede76350c4b63552fb9fa2ab251200bba4d6.zip
FreeBSD-src-e253ede76350c4b63552fb9fa2ab251200bba4d6.tar.gz
Add 2 new archsw interfaces:
1. arch_loadaddr - used by platform code to adjust the address at which the object gets loaded. Implement PC98 using this new interface instead of using conditional compilation. For ELF objects the ELF header is passed as the data pointer. For raw files it's the filename. Note that ELF objects are first considered as raw files. 2. arch_loadseg - used by platform code to keep track of actual segments, so that (instruction) caches can be flushed or translations can be created. Both the ELF header as well as the program header are passed to allow platform code to treat the kernel proper differently from any additional modules and to have all the relevant details of the loaded segment (e.g. protection).
Diffstat (limited to 'sys/boot/common/load_elf.c')
-rw-r--r--sys/boot/common/load_elf.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c
index f0880b1..ee6389f 100644
--- a/sys/boot/common/load_elf.c
+++ b/sys/boot/common/load_elf.c
@@ -97,7 +97,6 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
struct elf_file ef;
Elf_Ehdr *ehdr;
int err;
- u_int pad;
ssize_t bytes_read;
fp = NULL;
@@ -157,12 +156,6 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
/* Looks OK, got ahead */
ef.kernel = 0;
- /* Page-align the load address */
- pad = (u_int)dest & PAGE_MASK;
- if (pad != 0) {
- pad = PAGE_SIZE - pad;
- dest += pad;
- }
} else if (ehdr->e_type == ET_EXEC) {
/* Looks like a kernel */
if (kfp != NULL) {
@@ -173,7 +166,7 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
/*
* Calculate destination address based on kernel entrypoint
*/
- dest = ehdr->e_entry;
+ dest = (ehdr->e_entry & ~PAGE_MASK);
if (dest == 0) {
printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n");
err = EPERM;
@@ -186,6 +179,11 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
goto oerr;
}
+ if (archsw.arch_loadaddr != NULL)
+ dest = archsw.arch_loadaddr(LOAD_ELF, ehdr, dest);
+ else
+ dest = roundup(dest, PAGE_SIZE);
+
/*
* Ok, we think we should handle this.
*/
@@ -202,7 +200,7 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
#ifdef ELF_VERBOSE
if (ef.kernel)
- printf("%s entry at 0x%jx\n", filename, (uintmax_t)dest);
+ printf("%s entry at 0x%jx\n", filename, (uintmax_t)ehdr->e_entry);
#else
printf("%s ", filename);
#endif
@@ -362,6 +360,9 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
printf("\n");
#endif
+ if (archsw.arch_loadseg != NULL)
+ archsw.arch_loadseg(ehdr, phdr + i, off);
+
if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off))
firstaddr = phdr[i].p_vaddr + off;
if (lastaddr == 0 || lastaddr < (phdr[i].p_vaddr + off + phdr[i].p_memsz))
OpenPOWER on IntegriCloud