~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/openbios/arch/x86/multiboot.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Support for Multiboot */
 
2
 
 
3
#include "config.h"
 
4
#include "asm/io.h"
 
5
#include "libopenbios/sys_info.h"
 
6
#include "multiboot.h"
 
7
 
 
8
#ifdef CONFIG_DEBUG_BOOT
 
9
#define debug printk
 
10
#else
 
11
#define debug(x...)
 
12
#endif
 
13
 
 
14
struct mbheader {
 
15
    unsigned int magic, flags, checksum;
 
16
};
 
17
 
 
18
static const struct mbheader multiboot_header
 
19
        __attribute__((section (".hdr"))) =
 
20
{
 
21
    MULTIBOOT_HEADER_MAGIC,
 
22
    MULTIBOOT_HEADER_FLAGS,
 
23
    -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
 
24
};
 
25
 
 
26
/* Multiboot information structure, provided by loader to us */
 
27
 
 
28
struct multiboot_mmap {
 
29
        unsigned entry_size;
 
30
        unsigned base_lo, base_hi;
 
31
        unsigned size_lo, size_hi;
 
32
        unsigned type;
 
33
};
 
34
 
 
35
#define MULTIBOOT_MEM_VALID       0x01
 
36
#define MULTIBOOT_BOOT_DEV_VALID  0x02
 
37
#define MULTIBOOT_CMDLINE_VALID   0x04
 
38
#define MULTIBOOT_MODS_VALID      0x08
 
39
#define MULTIBOOT_AOUT_SYMS_VALID 0x10
 
40
#define MULTIBOOT_ELF_SYMS_VALID  0x20
 
41
#define MULTIBOOT_MMAP_VALID      0x40
 
42
 
 
43
void collect_multiboot_info(struct sys_info *info);
 
44
void collect_multiboot_info(struct sys_info *info)
 
45
{
 
46
    struct multiboot_info *mbinfo;
 
47
    struct multiboot_mmap *mbmem;
 
48
    unsigned mbcount, mbaddr;
 
49
    int i;
 
50
    struct memrange *mmap;
 
51
    int mmap_count;
 
52
    module_t *mod;
 
53
 
 
54
    if (info->boot_type != 0x2BADB002)
 
55
        return;
 
56
 
 
57
    debug("Using Multiboot information at %#lx\n", info->boot_data);
 
58
 
 
59
    mbinfo = phys_to_virt(info->boot_data);
 
60
 
 
61
    if (mbinfo->mods_count != 1) {
 
62
            printk("multiboot: no dictionary\n");
 
63
            return;
 
64
    }
 
65
 
 
66
    mod = (module_t *) mbinfo->mods_addr;
 
67
    info->dict_start=(unsigned long *)mod->mod_start;
 
68
    info->dict_end=(unsigned long *)mod->mod_end;
 
69
    debug("multiboot: dictionary at %p-%p\n",
 
70
                    info->dict_start, info->dict_end);
 
71
 
 
72
    if (mbinfo->flags & MULTIBOOT_MMAP_VALID) {
 
73
        /* convert mmap records */
 
74
        mbmem = phys_to_virt(mbinfo->mmap_addr);
 
75
        mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4);
 
76
        mmap = malloc(mbcount * sizeof(struct memrange));
 
77
        mmap_count = 0;
 
78
        mbaddr = mbinfo->mmap_addr;
 
79
        for (i = 0; i < mbcount; i++) {
 
80
            mbmem = phys_to_virt(mbaddr);
 
81
            debug("%08x%08x %08x%08x (%d)\n",
 
82
                    mbmem->base_hi,
 
83
                    mbmem->base_lo,
 
84
                    mbmem->size_hi,
 
85
                    mbmem->size_lo,
 
86
                    mbmem->type);
 
87
            if (mbmem->type == 1) { /* Only normal RAM */
 
88
                mmap[mmap_count].base = mbmem->base_lo
 
89
                    + (((unsigned long long) mbmem->base_hi) << 32);
 
90
                mmap[mmap_count].size = mbmem->size_lo
 
91
                    + (((unsigned long long) mbmem->size_hi) << 32);
 
92
                mmap_count++;
 
93
            }
 
94
            mbaddr += mbmem->entry_size + 4;
 
95
            if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length)
 
96
                break;
 
97
        }
 
98
        /* simple sanity check - there should be at least 2 RAM segments
 
99
         * (base 640k and extended) */
 
100
        if (mmap_count >= 2)
 
101
            goto got_it;
 
102
 
 
103
        printk("Multiboot mmap is broken\n");
 
104
        free(mmap);
 
105
        /* fall back to mem_lower/mem_upper */
 
106
    }
 
107
 
 
108
    if (mbinfo->flags & MULTIBOOT_MEM_VALID) {
 
109
        /* use mem_lower and mem_upper */
 
110
        mmap_count = 2;
 
111
        mmap = malloc(2 * sizeof(*mmap));
 
112
        mmap[0].base = 0;
 
113
        mmap[0].size = mbinfo->mem_lower << 10;
 
114
        mmap[1].base = 1 << 20; /* 1MB */
 
115
        mmap[1].size = mbinfo->mem_upper << 10;
 
116
        goto got_it;
 
117
    }
 
118
 
 
119
    printk("Can't get memory information from Multiboot\n");
 
120
    return;
 
121
 
 
122
got_it:
 
123
    info->memrange = mmap;
 
124
    info->n_memranges = mmap_count;
 
125
 
 
126
    return;
 
127
}