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