diff options
Diffstat (limited to 'sys/boot/common')
-rw-r--r-- | sys/boot/common/bootstrap.h | 2 | ||||
-rw-r--r-- | sys/boot/common/load_elf.c | 23 | ||||
-rw-r--r-- | sys/boot/common/module.c | 36 |
3 files changed, 17 insertions, 44 deletions
diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h index 78b3895..516b8a5 100644 --- a/sys/boot/common/bootstrap.h +++ b/sys/boot/common/bootstrap.h @@ -237,8 +237,6 @@ void file_discard(struct preloaded_file *fp); void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p); int file_addmodule(struct preloaded_file *fp, char *modname, int version, struct kernel_module **newmp); -/* Load from a buffer in memory. */ -struct preloaded_file *mem_load_raw(char *type, char *name, const void *p, size_t len); /* MI module loaders */ #ifdef __elfN diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c index e1e6de7..d712b3d 100644 --- a/sys/boot/common/load_elf.c +++ b/sys/boot/common/load_elf.c @@ -290,14 +290,25 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) } else off = 0; #elif defined(__arm__) - if (off & 0xf0000000u) { - off = -(off & 0xf0000000u); - ehdr->e_entry += off; + /* + * The elf headers in some kernels specify virtual addresses in all + * header fields. More recently, the e_entry and p_paddr fields are the + * proper physical addresses. Even when the p_paddr fields are correct, + * the MI code below uses the p_vaddr fields with an offset added for + * loading (doing so is arguably wrong). To make loading work, we need + * an offset that represents the difference between physical and virtual + * addressing. ARM kernels are always linked at 0xC0000000. Depending + * on the headers, the offset value passed in may be physical or virtual + * (because it typically comes from e_entry), but we always replace + * whatever is passed in with the va<->pa offset. On the other hand, we + * only adjust the entry point if it's a virtual address to begin with. + */ + off = -0xc0000000u; + if ((ehdr->e_entry & 0xc0000000u) == 0xc000000u) + ehdr->e_entry += off; #ifdef ELF_VERBOSE - printf("Converted entry 0x%08x\n", ehdr->e_entry); + printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", ehdr->e_entry, off); #endif - } else - off = 0; #else off = 0; /* other archs use direct mapped kernels */ #endif diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c index 3b74ab7..5808587 100644 --- a/sys/boot/common/module.c +++ b/sys/boot/common/module.c @@ -422,42 +422,6 @@ file_loadraw(char *type, char *name) } /* - * Load a chunk of data as if it had been read from a file. - */ -struct preloaded_file * -mem_load_raw(char *type, char *name, const void *p, size_t len) -{ - struct preloaded_file *fp; - - /* We can't load first */ - if ((file_findfile(NULL, NULL)) == NULL) { - command_errmsg = "can't load file before kernel"; - return(NULL); - } - - if (archsw.arch_loadaddr != NULL) - loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr); - archsw.arch_copyin(p, loadaddr, len); - - /* Looks OK so far; create & populate control structure */ - fp = file_alloc(); - fp->f_name = strdup(name); - fp->f_type = strdup(type); - fp->f_args = NULL; - fp->f_metadata = NULL; - fp->f_loader = -1; - fp->f_addr = loadaddr; - fp->f_size = len; - - /* recognise space consumption */ - loadaddr += len; - - /* Add to the list of loaded files */ - file_insert_tail(fp); - return fp; -} - -/* * Load the module (name), pass it (argc),(argv), add container file * to the list of loaded files. * If module is already loaded just assign new argc/argv. |