|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.