summaryrefslogtreecommitdiffstats
path: root/sys/boot/common
diff options
context:
space:
mode:
Diffstat (limited to 'sys/boot/common')
-rw-r--r--sys/boot/common/bootstrap.h2
-rw-r--r--sys/boot/common/load_elf.c23
-rw-r--r--sys/boot/common/module.c36
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.
OpenPOWER on IntegriCloud