1/* 2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <autoconf.h> 8#include <elfloader/gen_config.h> 9 10#include <drivers.h> 11#include <drivers/uart.h> 12#include <printf.h> 13#include <types.h> 14#include <abort.h> 15#include <strops.h> 16#include <cpuid.h> 17 18#include <binaries/efi/efi.h> 19#include <elfloader.h> 20 21/* 0xd00dfeed in big endian */ 22#define DTB_MAGIC (0xedfe0dd0) 23 24/* Maximum alignment we need to preserve when relocating (64K) */ 25#define MAX_ALIGN_BITS (14) 26 27ALIGN(BIT(PAGE_BITS)) VISIBLE 28char core_stack_alloc[CONFIG_MAX_NUM_NODES][BIT(PAGE_BITS)]; 29 30struct image_info kernel_info; 31struct image_info user_info; 32void *dtb; 33uint32_t dtb_size; 34 35extern void finish_relocation(int offset, void *_dynamic, unsigned int total_offset); 36void continue_boot(int was_relocated); 37 38/* 39 * Make sure the ELF loader is below the kernel's first virtual address 40 * so that when we enable the MMU we can keep executing. 41 */ 42extern char _DYNAMIC[]; 43void relocate_below_kernel(void) 44{ 45 /* 46 * These are the ELF loader's physical addresses, 47 * since we are either running with MMU off or 48 * identity-mapped. 49 */ 50 uintptr_t UNUSED start = (uintptr_t)_text; 51 uintptr_t end = (uintptr_t)_end; 52 53 if (end <= kernel_info.virt_region_start) { 54 /* 55 * If the ELF loader is already below the kernel, 56 * skip relocation. 57 */ 58 continue_boot(0); 59 return; 60 } 61 62#ifdef CONFIG_IMAGE_EFI 63 /* 64 * Note: we make the (potentially incorrect) assumption 65 * that there is enough physical RAM below the kernel's first vaddr 66 * to fit the ELF loader. 67 * FIXME: do we need to make sure we don't accidentally wipe out the DTB too? 68 */ 69 uintptr_t size = end - start; 70 71 /* 72 * we ROUND_UP size in this calculation so that all aligned things 73 * (interrupt vectors, stack, etc.) end up in similarly aligned locations. 74 * The strictes alignment requirement we have is the 64K-aligned AArch32 75 * page tables, so we use that to calculate the new base of the elfloader. 76 */ 77 uintptr_t new_base = kernel_info.virt_region_start - (ROUND_UP(size, MAX_ALIGN_BITS)); 78 uint32_t offset = start - new_base; 79 printf("relocating from %p-%p to %p-%p... size=0x%x (padded size = 0x%x)\n", start, end, new_base, new_base + size, 80 size, ROUND_UP(size, MAX_ALIGN_BITS)); 81 82 memmove((void *)new_base, (void *)start, size); 83 84 /* call into assembly to do the finishing touches */ 85 finish_relocation(offset, _DYNAMIC, new_base); 86#else 87 printf("The ELF loader does not support relocating itself. You probably need to move the kernel window higher, or the load address lower.\n"); 88 abort(); 89#endif 90} 91 92/* 93 * Entry point. 94 * 95 * Unpack images, setup the MMU, jump to the kernel. 96 */ 97void main(UNUSED void *arg) 98{ 99 int num_apps; 100 101 void *bootloader_dtb = NULL; 102 103 initialise_devices(); 104 105#ifdef CONFIG_IMAGE_UIMAGE 106 if (arg) { 107 uint32_t magic = *(uint32_t *)arg; 108 /* 109 * This might happen on ancient bootloaders which 110 * still think Linux wants atags instead of a 111 * device tree. 112 */ 113 if (magic != DTB_MAGIC) { 114 printf("Bootloader did not supply a valid device tree!\n"); 115 arg = NULL; 116 } 117 } 118 bootloader_dtb = arg; 119#else 120 bootloader_dtb = NULL; 121#endif 122 123#ifdef CONFIG_IMAGE_EFI 124 if (efi_exit_boot_services() != EFI_SUCCESS) { 125 printf("Unable to exit UEFI boot services!\n"); 126 abort(); 127 } 128 129 bootloader_dtb = efi_get_fdt(); 130#endif 131 132 /* Print welcome message. */ 133 platform_init(); 134 printf("\nELF-loader started on "); 135 print_cpuid(); 136 137 printf(" paddr=[%p..%p]\n", _text, _end - 1); 138 139 /* 140 * U-Boot will either pass us a DTB, or (if we're being booted via bootelf) 141 * pass '0' in argc. 142 */ 143 if (bootloader_dtb) { 144 printf(" dtb=%p\n", dtb); 145 } else { 146 printf("No DTB passed in from boot loader.\n"); 147 } 148 149 /* Unpack ELF images into memory. */ 150 load_images(&kernel_info, &user_info, 1, &num_apps, bootloader_dtb, &dtb, &dtb_size); 151 if (num_apps != 1) { 152 printf("No user images loaded!\n"); 153 abort(); 154 } 155 156 /* 157 * We don't really know where we've been loaded. 158 * It's possible that EFI loaded us in a place 159 * that will become part of the 'kernel window' 160 * once we switch to the boot page tables. 161 * Make sure this is not the case. 162 */ 163 relocate_below_kernel(); 164 printf("Relocation failed, aborting.\n"); 165 abort(); 166} 167 168void continue_boot(int was_relocated) 169{ 170 if (was_relocated) { 171 printf("ELF loader relocated, continuing boot...\n"); 172 } 173 174 /* 175 * If we were relocated, we need to re-initialise the 176 * driver model so all its pointers are set up properly. 177 */ 178 if (was_relocated) { 179 initialise_devices(); 180 } 181 182#if (defined(CONFIG_ARCH_ARM_V7A) || defined(CONFIG_ARCH_ARM_V8A)) && !defined(CONFIG_ARM_HYPERVISOR_SUPPORT) 183 if (is_hyp_mode()) { 184 extern void leave_hyp(void); 185 leave_hyp(); 186 } 187#endif 188 /* Setup MMU. */ 189 if (is_hyp_mode()) { 190#ifdef CONFIG_ARCH_AARCH64 191 extern void disable_caches_hyp(); 192 disable_caches_hyp(); 193#endif 194 init_hyp_boot_vspace(&kernel_info); 195 } else { 196 /* If we are not in HYP mode, we enable the SV MMU and paging 197 * just in case the kernel does not support hyp mode. */ 198 init_boot_vspace(&kernel_info); 199 } 200 201#if CONFIG_MAX_NUM_NODES > 1 202 smp_boot(); 203#endif /* CONFIG_MAX_NUM_NODES */ 204 205 if (is_hyp_mode()) { 206 printf("Enabling hypervisor MMU and paging\n"); 207 arm_enable_hyp_mmu(); 208 } else { 209 printf("Enabling MMU and paging\n"); 210 arm_enable_mmu(); 211 } 212 213 /* Enter kernel. */ 214 if ((uintptr_t)uart_get_mmio() < kernel_info.virt_region_start) { 215 printf("Jumping to kernel-image entry point...\n\n"); 216 } else { 217 /* Our serial port is no longer accessible */ 218 } 219 220 ((init_arm_kernel_t)kernel_info.virt_entry)(user_info.phys_region_start, 221 user_info.phys_region_end, user_info.phys_virt_offset, 222 user_info.virt_entry, (paddr_t)dtb, dtb_size); 223 224 /* We should never get here. */ 225 printf("Kernel returned back to the elf-loader.\n"); 226 abort(); 227} 228