1/*
2 * Copyright (c) 2016, Hewlett Packard Enterprise Development LP.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
8 */
9
10#include <stddef.h>
11#include <stdint.h>
12#include <stdio.h>
13#include <string.h>
14
15#include <multiboot2.h>
16
17#include <arch/armv8/kernel_multiboot2.h>
18
19
20struct multiboot_header_tag *
21multiboot2_find_header(struct multiboot_header_tag *mb, const size_t size, const multiboot_uint16_t type) {
22    size_t processed = 0;
23
24    while(processed < size) {
25        /* encountered the end tag */
26        if (mb->type == MULTIBOOT_TAG_TYPE_END) {
27            return NULL;
28        } else if (mb->type == type) {
29            return mb;
30        }
31
32        processed += mb->size;
33        mb = ((void*)mb) + mb->size;
34    }
35
36    return NULL;
37}
38
39struct multiboot_tag_string *
40multiboot2_find_cmdline(struct multiboot_header_tag *mb, const size_t size)
41{
42    return (struct multiboot_tag_string*)multiboot2_find_header(mb, size, MULTIBOOT_TAG_TYPE_CMDLINE);
43}
44
45struct multiboot_tag_module_64 *multiboot2_find_module_64(
46        struct multiboot_header_tag *multiboot, const size_t size, const char* pathname) {
47    size_t len = strlen(pathname);
48    size_t position = 0;
49    multiboot = multiboot2_find_header(multiboot, size, MULTIBOOT_TAG_TYPE_MODULE_64);
50    while (multiboot) {
51        struct multiboot_tag_module_64 *module_64 = (struct multiboot_tag_module_64 *) multiboot;
52        // Strip off trailing whitespace
53        char *modname = module_64->cmdline;
54        char *endstr;
55        if(strchr(modname, ' ')) {
56            endstr = strchr(modname, ' ');
57        } else {
58            endstr = modname + strlen(modname);
59        }
60
61        if(!strncmp(endstr - len, pathname, len)) {
62            return module_64;
63        }
64        multiboot = ((void *) multiboot) + multiboot->size;
65        position += multiboot->size;
66        multiboot = multiboot2_find_header(multiboot, size - position, MULTIBOOT_TAG_TYPE_MODULE_64);
67    }
68    return NULL;
69}
70