1// Simple boot-loader. 2// 3// This code is only intended for use on M5 where it is started via 4// molly_boot.S which runs on Core 0. 5 6/* 7 * Copyright (c) 2007-2010,2015, ETH Zurich. 8 * Copyright (c) 2015, Hewlett Packard Enterprise Development LP. 9 * All rights reserved. 10 * 11 * This file is distributed under the terms in the attached LICENSE file. 12 * If you do not find this file, copies can be found by writing to: 13 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 14 */ 15 16#include <stdio.h> 17#include <stdint.h> 18#include <stddef.h> 19#include <string.h> 20#include <barrelfish_kpi/types.h> 21#include <errors/errno.h> 22#include <elf/elf.h> 23#include <multiboot.h> 24 25#define BASE_PAGE_SIZE 0x1000 26#define ALIGNMENT 0x10000 27 28/// Round up n to the next multiple of size 29#define ROUND_UP(n, size) ((((n) + (size) - 1)) & (~((size) - 1))) 30 31 32static lpaddr_t phys_alloc_start; 33 34static errval_t linear_alloc(void *s, genvaddr_t base, size_t size, uint32_t flags, 35 void **ret) 36{ 37 // round to base page size 38 uint32_t npages = (size + BASE_PAGE_SIZE - 1) / BASE_PAGE_SIZE; 39 40 /* *ret = (void *)(uintptr_t)base; */ 41 *ret = (void *)phys_alloc_start; 42 43 phys_alloc_start += npages * BASE_PAGE_SIZE; 44 return SYS_ERR_OK; 45} 46 47genvaddr_t kernel_entry; 48 49// Prototypes for functions from molly_boot.S: 50void aarch64_to_kernel_transition(genvaddr_t entry_addr, void* mbi_ptr); 51 52 53// Prototypes for functions from arm_gem5_kernel.c: 54extern struct multiboot_info *molly_get_mbi(void); 55 56// Prototypes for symbols declared via linker script: 57extern void *_start_img; 58extern void *_end_img; 59 60void aarch64_init(void); 61 62void aarch64_init(void) 63{ 64 errval_t err; 65 66 //uint32_t kernel_blob_size = (uint32_t)(&kernel_blob_end - &kernel_blob_start); 67 68 69 struct multiboot_info *mbi = molly_get_mbi(); 70 71 // align kernel start to 16KB 72 phys_alloc_start = ROUND_UP((uint64_t) &_end_img, ALIGNMENT); //+ 73 // BASE_PAGE_SIZE); 74 lpaddr_t kernel_start = phys_alloc_start; 75 76 // Load the kernel out from the boot image: 77 struct multiboot_modinfo *mbi_mods; 78 mbi_mods = (struct multiboot_modinfo*)(uint64_t)(mbi->mods_addr); 79 void *kernel = (void*)(uint64_t)(mbi_mods[0].mod_start); 80 uint32_t kernel_bytes = mbi_mods[0].mod_end - mbi_mods[0].mod_start; 81 82 err = elf64_load(EM_AARCH64, linear_alloc, NULL, (uint64_t)kernel, 83 kernel_bytes, &kernel_entry, NULL, NULL, NULL); 84 if (err_is_fail(err)) { 85 return; 86 } 87 88 // Relocate kernel image 89 struct Elf64_Ehdr *cpu_head = (struct Elf64_Ehdr *)kernel; 90 struct Elf64_Shdr *rela, *symtab, *symhead = 91 (struct Elf64_Shdr *)(kernel + (uintptr_t)cpu_head->e_shoff); 92 genvaddr_t elfbase = elf_virtual_base64(cpu_head); 93 rela = elf64_find_section_header_type(symhead, cpu_head->e_shnum, SHT_RELA); 94 symtab = elf64_find_section_header_type(symhead, cpu_head->e_shnum, SHT_DYNSYM); 95 elf64_relocate(kernel_start, elfbase, 96 (struct Elf64_Rela *)(uintptr_t)(kernel + rela->sh_offset), 97 rela->sh_size, 98 (struct Elf64_Sym *)(uintptr_t)(kernel + symtab->sh_offset), 99 symtab->sh_size, 100 elfbase, (void *)kernel_start); 101 kernel_entry = kernel_entry - elfbase + kernel_start; 102 103 //initialize arm_core_data elf info for relocated header 104 mbi->syms.elf.num = cpu_head->e_shnum; 105 mbi->syms.elf.size = cpu_head->e_shentsize; 106 mbi->syms.elf.addr = (uint64_t)kernel+ cpu_head->e_shoff; 107 mbi->syms.elf.shndx = cpu_head->e_shstrndx; 108 109 aarch64_to_kernel_transition((uintptr_t)kernel_entry, mbi ); 110 111 112} 113