Changeset View
Changeset View
Standalone View
Standalone View
sys/boot/common/load_elf.c
Show First 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
#if defined(__i386__) && __ELF_WORD_SIZE == 64 | #if defined(__i386__) && __ELF_WORD_SIZE == 64 | ||||
#undef ELF_TARG_CLASS | #undef ELF_TARG_CLASS | ||||
#undef ELF_TARG_MACH | #undef ELF_TARG_MACH | ||||
#define ELF_TARG_CLASS ELFCLASS64 | #define ELF_TARG_CLASS ELFCLASS64 | ||||
#define ELF_TARG_MACH EM_X86_64 | #define ELF_TARG_MACH EM_X86_64 | ||||
#endif | #endif | ||||
#if defined(__aarch64__) | |||||
#define KERN_ALIGN (2 * 1024 * 1024) | |||||
#endif | |||||
typedef struct elf_file { | typedef struct elf_file { | ||||
Elf_Phdr *ph; | Elf_Phdr *ph; | ||||
Elf_Ehdr *ehdr; | Elf_Ehdr *ehdr; | ||||
Elf_Sym *symtab; | Elf_Sym *symtab; | ||||
Elf_Hashelt *hashtab; | Elf_Hashelt *hashtab; | ||||
Elf_Hashelt nbuckets; | Elf_Hashelt nbuckets; | ||||
Elf_Hashelt nchains; | Elf_Hashelt nchains; | ||||
Elf_Hashelt *buckets; | Elf_Hashelt *buckets; | ||||
▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | #endif | ||||
/* | /* | ||||
* Calculate destination address based on kernel entrypoint. | * Calculate destination address based on kernel entrypoint. | ||||
* | * | ||||
* For ARM, the destination address is independent of any values in the | * For ARM, the destination address is independent of any values in the | ||||
* elf header (an ARM kernel can be loaded at any 2MB boundary), so we | * elf header (an ARM kernel can be loaded at any 2MB boundary), so we | ||||
* leave dest set to the value calculated by archsw.arch_loadaddr() and | * leave dest set to the value calculated by archsw.arch_loadaddr() and | ||||
* passed in to this function. | * passed in to this function. | ||||
*/ | */ | ||||
#ifndef __arm__ | #if !defined(__arm__) && !defined(__aarch64__) | ||||
if (ehdr->e_type == ET_EXEC) | if (ehdr->e_type == ET_EXEC) | ||||
dest = (ehdr->e_entry & ~PAGE_MASK); | dest = (ehdr->e_entry & ~PAGE_MASK); | ||||
#endif | #endif | ||||
if ((ehdr->e_entry & ~PAGE_MASK) == 0) { | if ((ehdr->e_entry & ~PAGE_MASK) == 0) { | ||||
printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n"); | printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n"); | ||||
err = EPERM; | err = EPERM; | ||||
goto oerr; | goto oerr; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | #elif defined(__arm__) && !defined(EFI) | ||||
* adjusting the location relative to the first virtual address. | * adjusting the location relative to the first virtual address. | ||||
* Because of this there is no need to adjust the offset or entry | * Because of this there is no need to adjust the offset or entry | ||||
* point address as these will both be handled by the efi code. | * point address as these will both be handled by the efi code. | ||||
*/ | */ | ||||
off -= ehdr->e_entry & ~PAGE_MASK; | off -= ehdr->e_entry & ~PAGE_MASK; | ||||
ehdr->e_entry += off; | ehdr->e_entry += off; | ||||
#ifdef ELF_VERBOSE | #ifdef ELF_VERBOSE | ||||
printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", ehdr->e_entry, off); | printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", ehdr->e_entry, off); | ||||
#endif | |||||
#elif defined(__aarch64__) && !defined(EFI) | |||||
andrew: Is this needed in the EFI case? It's been working until now without it. | |||||
Not Done Inline ActionsAlmost certainly not. I'll qualify it with "&& !defined(EFI)". skibo: Almost certainly not. I'll qualify it with "&& !defined(EFI)". | |||||
/* | |||||
* The elf headers in arm kernels specify virtual addresses in all | |||||
* header fields, even the ones that should be physical addresses. | |||||
* We assume the entry point is in the first 2MB, and masking the lower | |||||
* bits will leave us with the virtual address the kernel was linked | |||||
* at. We subtract that from the load offset, making 'off' into the | |||||
* value which, when added to a virtual address in an elf header, | |||||
* translates it to a physical address. We do the va->pa conversion on | |||||
* the entry point address in the header now, so that later we can | |||||
* launch the kernel by just jumping to that address. | |||||
*/ | |||||
off -= ehdr->e_entry & ~(KERN_ALIGN - 1); | |||||
ehdr->e_entry += off; | |||||
#ifdef ELF_VERBOSE | |||||
printf("ehdr->e_entry %p, va<->pa off 0x%llx\n", ehdr->e_entry, off); | |||||
#endif | #endif | ||||
#else | #else | ||||
off = 0; /* other archs use direct mapped kernels */ | off = 0; /* other archs use direct mapped kernels */ | ||||
#endif | #endif | ||||
} | } | ||||
ef->off = off; | ef->off = off; | ||||
if (ef->kernel) | if (ef->kernel) | ||||
▲ Show 20 Lines • Show All 654 Lines • Show Last 20 Lines |
Is this needed in the EFI case? It's been working until now without it.