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