1/** 2 * \file 3 * \brief Multiboot utility functions. 4 */ 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 <kernel.h> 16#include <stdio.h> 17#include <string.h> 18#include <inttypes.h> 19#include <paging_kernel_arch.h> 20#include <elf/elf.h> 21#include <kernel_multiboot.h> 22#include <barrelfish_kpi/arm_core_data.h> 23#include <startup_arch.h> 24 25/* The BSP kernel allocates its coreboot data in its BSS, all other cores will 26 * overwrite this pointer with that passed to them at boot time. */ 27struct arm_core_data *core_data; 28 29/** 30 * \brief Return multiboot module by trailing pathname. 31 * 32 * Returns a pointer to the multiboot module which has a trailing 33 * pathname of 'pathname' or NULL if there is none. 34 * 35 * \param pathname Trailing pathname of module to look for. 36 * 37 * \return Pointer to multiboot module or NULL if none found. 38 */ 39struct multiboot_modinfo *multiboot_find_module(const char *pathname) 40{ 41 struct multiboot_info *mb = 42 (struct multiboot_info *)core_data->multiboot_header; 43 struct multiboot_modinfo *mod = (struct multiboot_modinfo *) 44 local_phys_to_mem(mb->mods_addr); 45 46 for(size_t i = 0; i < mb->mods_count; i++) { 47 const char *modname = MBADDR_ASSTRING(mod[i].string), *endstr; 48 49 // Strip off trailing whitespace 50 if(strchr(modname, ' ')) { 51 endstr = strchr(modname, ' '); 52 } else { 53 endstr = modname + strlen(modname); 54 } 55 56 if(!strncmp(endstr - strlen(pathname), pathname, strlen(pathname))) { 57 return &mod[i]; 58 } 59 } 60 61 return NULL; 62} 63 64/** 65 * \brief Return end address of multiboot image 66 * 67 * This function is used to compute a safe location to place the boot kernel. 68 */ 69uintptr_t multiboot_end_addr(struct multiboot_info *mi) 70{ 71 lpaddr_t end = (lpaddr_t)mi + sizeof(struct multiboot_info); 72 73#define CHECK(pa) { lpaddr_t tmp = pa; if (tmp > end) { end = tmp; } } 74#define CHECK_STR(pstr) CHECK(pstr + strlen((char *)(uintptr_t)pstr) + 1) 75 76 if (mi->flags & MULTIBOOT_INFO_FLAG_HAS_CMDLINE) { 77 CHECK_STR(mi->cmdline) 78 } 79 80 if (mi->flags & MULTIBOOT_INFO_FLAG_HAS_MODS) { 81 struct multiboot_modinfo *mod = (void *)(uintptr_t)mi->mods_addr; 82 83 for(int i = 0; i < mi->mods_count; i++) { 84 CHECK(mod[i].mod_end) 85 CHECK_STR(mod[i].string) 86 } 87 } 88 89 if (mi->flags & MULTIBOOT_INFO_FLAG_HAS_ELF_SYMS) { 90 CHECK(mi->syms.elf.addr + mi->syms.elf.num * mi->syms.elf.size) 91 /* FIXME: does this include mi_elfshdr_shndx?? */ 92 } 93 94 if (mi->flags & MULTIBOOT_INFO_FLAG_HAS_MMAP) { 95 CHECK(mi->mmap_addr + mi->mmap_length) 96 } 97 98 if (mi->flags & MULTIBOOT_INFO_FLAG_HAS_DRIVES) { 99 CHECK(mi->drives_addr + mi->drives_length) 100 } 101 102 if (mi->flags & MULTIBOOT_INFO_FLAG_HAS_LOADERNAME) { 103 CHECK_STR(mi->boot_loader_name) 104 } 105 106 /* TODO: config table, APM table, VBE */ 107 108#undef CHECK 109#undef CHECK_STR 110 111 return end; 112} 113