diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h index bf3f9622b6ba..d8b45514cfdc 100644 --- a/sys/boot/common/bootstrap.h +++ b/sys/boot/common/bootstrap.h @@ -296,6 +296,24 @@ struct arch_switch /* Perform ISA byte port I/O (only for systems with ISA) */ int (*arch_isainb)(int port); void (*arch_isaoutb)(int port, int value); + + /* + * Interface to adjust the load address according to the "object" + * being loaded. + */ + uint64_t (*arch_loadaddr)(u_int type, void *data, uint64_t addr); +#define LOAD_ELF 1 /* data points to the ELF header. */ +#define LOAD_RAW 2 /* data points to the file name. */ + + /* + * Interface to inform MD code about a loaded (ELF) segment. This + * can be used to flush caches and/or set up translations. + */ +#ifdef __elfN + void (*arch_loadseg)(Elf_Ehdr *eh, Elf_Phdr *ph, uint64_t delta); +#else + void (*arch_loadseg)(void *eh, void *ph, uint64_t delta); +#endif }; extern struct arch_switch archsw; diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c index f0880b1eaa3c..ee6389fec1ff 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)) diff --git a/sys/boot/common/load_elf_obj.c b/sys/boot/common/load_elf_obj.c index 6f3b3493aa3d..dcd71efff386 100644 --- a/sys/boot/common/load_elf_obj.c +++ b/sys/boot/common/load_elf_obj.c @@ -144,8 +144,10 @@ __elfN(obj_loadfile)(char *filename, u_int64_t dest, goto oerr; } - /* Page-align the load address */ - dest = roundup(dest, PAGE_SIZE); + if (archsw.arch_loadaddr != NULL) + dest = archsw.arch_loadaddr(LOAD_ELF, hdr, dest); + else + dest = roundup(dest, PAGE_SIZE); /* * Ok, we think we should handle this. diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c index 063fcdfb7dcb..728992d040d0 100644 --- a/sys/boot/common/module.c +++ b/sys/boot/common/module.c @@ -275,6 +275,9 @@ file_load(char *filename, vm_offset_t dest, struct preloaded_file **result) int error; int i; + if (archsw.arch_loadaddr != NULL) + dest = archsw.arch_loadaddr(LOAD_RAW, filename, dest); + error = EFTYPE; for (i = 0, fp = NULL; file_formats[i] && fp == NULL; i++) { error = (file_formats[i]->l_load)(filename, loadaddr, &fp); @@ -352,9 +355,6 @@ file_loadraw(char *type, char *name) char *cp; int fd, got; vm_offset_t laddr; -#ifdef PC98 - struct stat st; -#endif /* We can't load first */ if ((file_findfile(NULL, NULL)) == NULL) { @@ -369,20 +369,15 @@ file_loadraw(char *type, char *name) return(CMD_ERROR); } name = cp; - + if ((fd = open(name, O_RDONLY)) < 0) { sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno)); free(name); return(CMD_ERROR); } -#ifdef PC98 - /* We cannot use 15M-16M area on pc98. */ - if (loadaddr < 0x1000000 && - fstat(fd, &st) == 0 && - (st.st_size == -1 || loadaddr + st.st_size > 0xf00000)) - loadaddr = 0x1000000; -#endif + if (archsw.arch_loadaddr != NULL) + loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr); laddr = loadaddr; for (;;) { @@ -489,14 +484,6 @@ mod_loadkld(const char *kldname, int argc, char *argv[]) ; do { -#ifdef PC98 - /* We cannot use 15M-16M area on pc98. */ - struct stat st; - if (loadaddr < 0x1000000 && - stat(filename, &st) == 0 && - (st.st_size == -1 || loadaddr + st.st_size > 0xf00000)) - loadaddr = 0x1000000; -#endif err = file_load(filename, loadaddr, &fp); if (err) break; diff --git a/sys/boot/pc98/loader/main.c b/sys/boot/pc98/loader/main.c index da14d0bcf8ff..391c5e9bc86c 100644 --- a/sys/boot/pc98/loader/main.c +++ b/sys/boot/pc98/loader/main.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include "bootstrap.h" @@ -77,6 +78,21 @@ extern char end[]; static void *heap_top; static void *heap_bottom; +static uint64_t +pc98_loadaddr(u_int type, void *data, uint64_t addr) +{ + struct stat st; + + if (type == LOAD_ELF) + return (roundup(addr, PAGE_SIZE)); + + /* We cannot use 15M-16M area on pc98. */ + if (type == LOAD_RAW && addr < 0x1000000 && stat(data, &st) == 0 && + (st.st_size == -1 || addr + st.st_size > 0xf00000)) + addr = 0x1000000; + return (addr); +} + int main(void) { @@ -160,6 +176,7 @@ main(void) archsw.arch_readin = i386_readin; archsw.arch_isainb = isa_inb; archsw.arch_isaoutb = isa_outb; + archsw.arch_loadaddr = pc98_loadaddr; /* * March through the device switch probing for things.