root / hw / multiboot.c @ 3d53f5c3
History | View | Annotate | Download (11.6 kB)
1 | 52001445 | Adam Lackorzynski | /*
|
---|---|---|---|
2 | 52001445 | Adam Lackorzynski | * QEMU PC System Emulator
|
3 | 52001445 | Adam Lackorzynski | *
|
4 | 52001445 | Adam Lackorzynski | * Copyright (c) 2003-2004 Fabrice Bellard
|
5 | 52001445 | Adam Lackorzynski | *
|
6 | 52001445 | Adam Lackorzynski | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 52001445 | Adam Lackorzynski | * of this software and associated documentation files (the "Software"), to deal
|
8 | 52001445 | Adam Lackorzynski | * in the Software without restriction, including without limitation the rights
|
9 | 52001445 | Adam Lackorzynski | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 52001445 | Adam Lackorzynski | * copies of the Software, and to permit persons to whom the Software is
|
11 | 52001445 | Adam Lackorzynski | * furnished to do so, subject to the following conditions:
|
12 | 52001445 | Adam Lackorzynski | *
|
13 | 52001445 | Adam Lackorzynski | * The above copyright notice and this permission notice shall be included in
|
14 | 52001445 | Adam Lackorzynski | * all copies or substantial portions of the Software.
|
15 | 52001445 | Adam Lackorzynski | *
|
16 | 52001445 | Adam Lackorzynski | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 52001445 | Adam Lackorzynski | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 52001445 | Adam Lackorzynski | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 52001445 | Adam Lackorzynski | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 52001445 | Adam Lackorzynski | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 52001445 | Adam Lackorzynski | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 52001445 | Adam Lackorzynski | * THE SOFTWARE.
|
23 | 52001445 | Adam Lackorzynski | */
|
24 | 52001445 | Adam Lackorzynski | |
25 | 52001445 | Adam Lackorzynski | #include "hw.h" |
26 | 52001445 | Adam Lackorzynski | #include "fw_cfg.h" |
27 | 52001445 | Adam Lackorzynski | #include "multiboot.h" |
28 | 52001445 | Adam Lackorzynski | #include "loader.h" |
29 | 52001445 | Adam Lackorzynski | #include "elf.h" |
30 | 52001445 | Adam Lackorzynski | #include "sysemu.h" |
31 | 52001445 | Adam Lackorzynski | |
32 | 52001445 | Adam Lackorzynski | /* Show multiboot debug output */
|
33 | 52001445 | Adam Lackorzynski | //#define DEBUG_MULTIBOOT
|
34 | 52001445 | Adam Lackorzynski | |
35 | 52001445 | Adam Lackorzynski | #ifdef DEBUG_MULTIBOOT
|
36 | 52001445 | Adam Lackorzynski | #define mb_debug(a...) fprintf(stderr, ## a) |
37 | 52001445 | Adam Lackorzynski | #else
|
38 | 52001445 | Adam Lackorzynski | #define mb_debug(a...)
|
39 | 52001445 | Adam Lackorzynski | #endif
|
40 | 52001445 | Adam Lackorzynski | |
41 | 52001445 | Adam Lackorzynski | #define MULTIBOOT_STRUCT_ADDR 0x9000 |
42 | 52001445 | Adam Lackorzynski | |
43 | 52001445 | Adam Lackorzynski | #if MULTIBOOT_STRUCT_ADDR > 0xf0000 |
44 | 52001445 | Adam Lackorzynski | #error multiboot struct needs to fit in 16 bit real mode |
45 | 52001445 | Adam Lackorzynski | #endif
|
46 | 52001445 | Adam Lackorzynski | |
47 | 52001445 | Adam Lackorzynski | enum {
|
48 | 52001445 | Adam Lackorzynski | /* Multiboot info */
|
49 | 52001445 | Adam Lackorzynski | MBI_FLAGS = 0,
|
50 | 52001445 | Adam Lackorzynski | MBI_MEM_LOWER = 4,
|
51 | 52001445 | Adam Lackorzynski | MBI_MEM_UPPER = 8,
|
52 | 52001445 | Adam Lackorzynski | MBI_BOOT_DEVICE = 12,
|
53 | 52001445 | Adam Lackorzynski | MBI_CMDLINE = 16,
|
54 | 52001445 | Adam Lackorzynski | MBI_MODS_COUNT = 20,
|
55 | 52001445 | Adam Lackorzynski | MBI_MODS_ADDR = 24,
|
56 | 52001445 | Adam Lackorzynski | MBI_MMAP_ADDR = 48,
|
57 | 52001445 | Adam Lackorzynski | |
58 | 52001445 | Adam Lackorzynski | MBI_SIZE = 88,
|
59 | 52001445 | Adam Lackorzynski | |
60 | 52001445 | Adam Lackorzynski | /* Multiboot modules */
|
61 | 52001445 | Adam Lackorzynski | MB_MOD_START = 0,
|
62 | 52001445 | Adam Lackorzynski | MB_MOD_END = 4,
|
63 | 52001445 | Adam Lackorzynski | MB_MOD_CMDLINE = 8,
|
64 | 52001445 | Adam Lackorzynski | |
65 | 52001445 | Adam Lackorzynski | MB_MOD_SIZE = 16,
|
66 | 52001445 | Adam Lackorzynski | |
67 | 52001445 | Adam Lackorzynski | /* Region offsets */
|
68 | 52001445 | Adam Lackorzynski | ADDR_E820_MAP = MULTIBOOT_STRUCT_ADDR + 0,
|
69 | 52001445 | Adam Lackorzynski | ADDR_MBI = ADDR_E820_MAP + 0x500,
|
70 | 52001445 | Adam Lackorzynski | |
71 | 52001445 | Adam Lackorzynski | /* Multiboot flags */
|
72 | 52001445 | Adam Lackorzynski | MULTIBOOT_FLAGS_MEMORY = 1 << 0, |
73 | 52001445 | Adam Lackorzynski | MULTIBOOT_FLAGS_BOOT_DEVICE = 1 << 1, |
74 | 52001445 | Adam Lackorzynski | MULTIBOOT_FLAGS_CMDLINE = 1 << 2, |
75 | 52001445 | Adam Lackorzynski | MULTIBOOT_FLAGS_MODULES = 1 << 3, |
76 | 52001445 | Adam Lackorzynski | MULTIBOOT_FLAGS_MMAP = 1 << 6, |
77 | 52001445 | Adam Lackorzynski | }; |
78 | 52001445 | Adam Lackorzynski | |
79 | 52001445 | Adam Lackorzynski | typedef struct { |
80 | 52001445 | Adam Lackorzynski | /* buffer holding kernel, cmdlines and mb_infos */
|
81 | 52001445 | Adam Lackorzynski | void *mb_buf;
|
82 | 52001445 | Adam Lackorzynski | /* address in target */
|
83 | 52001445 | Adam Lackorzynski | target_phys_addr_t mb_buf_phys; |
84 | 52001445 | Adam Lackorzynski | /* size of mb_buf in bytes */
|
85 | 52001445 | Adam Lackorzynski | unsigned mb_buf_size;
|
86 | 52001445 | Adam Lackorzynski | /* offset of mb-info's in bytes */
|
87 | 52001445 | Adam Lackorzynski | target_phys_addr_t offset_mbinfo; |
88 | 52001445 | Adam Lackorzynski | /* offset in buffer for cmdlines in bytes */
|
89 | 52001445 | Adam Lackorzynski | target_phys_addr_t offset_cmdlines; |
90 | 52001445 | Adam Lackorzynski | /* offset of modules in bytes */
|
91 | 52001445 | Adam Lackorzynski | target_phys_addr_t offset_mods; |
92 | 52001445 | Adam Lackorzynski | /* available slots for mb modules infos */
|
93 | 52001445 | Adam Lackorzynski | int mb_mods_avail;
|
94 | 52001445 | Adam Lackorzynski | /* currently used slots of mb modules */
|
95 | 52001445 | Adam Lackorzynski | int mb_mods_count;
|
96 | 52001445 | Adam Lackorzynski | } MultibootState; |
97 | 52001445 | Adam Lackorzynski | |
98 | 52001445 | Adam Lackorzynski | static uint32_t mb_add_cmdline(MultibootState *s, const char *cmdline) |
99 | 52001445 | Adam Lackorzynski | { |
100 | 52001445 | Adam Lackorzynski | int len = strlen(cmdline) + 1; |
101 | 52001445 | Adam Lackorzynski | target_phys_addr_t p = s->offset_cmdlines; |
102 | 52001445 | Adam Lackorzynski | |
103 | 52001445 | Adam Lackorzynski | pstrcpy((char *)s->mb_buf + p, len, cmdline);
|
104 | 52001445 | Adam Lackorzynski | s->offset_cmdlines += len; |
105 | 52001445 | Adam Lackorzynski | return s->mb_buf_phys + p;
|
106 | 52001445 | Adam Lackorzynski | } |
107 | 52001445 | Adam Lackorzynski | |
108 | 52001445 | Adam Lackorzynski | static void mb_add_mod(MultibootState *s, |
109 | 52001445 | Adam Lackorzynski | target_phys_addr_t start, target_phys_addr_t end, |
110 | 52001445 | Adam Lackorzynski | target_phys_addr_t cmdline_phys) |
111 | 52001445 | Adam Lackorzynski | { |
112 | 52001445 | Adam Lackorzynski | char *p;
|
113 | 52001445 | Adam Lackorzynski | assert(s->mb_mods_count < s->mb_mods_avail); |
114 | 52001445 | Adam Lackorzynski | |
115 | 52001445 | Adam Lackorzynski | p = (char *)s->mb_buf + s->offset_mbinfo + MB_MOD_SIZE * s->mb_mods_count;
|
116 | 52001445 | Adam Lackorzynski | |
117 | 52001445 | Adam Lackorzynski | stl_p(p + MB_MOD_START, start); |
118 | 52001445 | Adam Lackorzynski | stl_p(p + MB_MOD_END, end); |
119 | 52001445 | Adam Lackorzynski | stl_p(p + MB_MOD_CMDLINE, cmdline_phys); |
120 | 52001445 | Adam Lackorzynski | |
121 | 52001445 | Adam Lackorzynski | mb_debug("mod%02d: %08x - %08x\n", s->mb_mods_count, start, end);
|
122 | 52001445 | Adam Lackorzynski | |
123 | 52001445 | Adam Lackorzynski | s->mb_mods_count++; |
124 | 52001445 | Adam Lackorzynski | } |
125 | 52001445 | Adam Lackorzynski | |
126 | 52001445 | Adam Lackorzynski | int load_multiboot(void *fw_cfg, |
127 | 52001445 | Adam Lackorzynski | FILE *f, |
128 | 52001445 | Adam Lackorzynski | const char *kernel_filename, |
129 | 52001445 | Adam Lackorzynski | const char *initrd_filename, |
130 | 52001445 | Adam Lackorzynski | const char *kernel_cmdline, |
131 | 52001445 | Adam Lackorzynski | int kernel_file_size,
|
132 | 52001445 | Adam Lackorzynski | uint8_t *header) |
133 | 52001445 | Adam Lackorzynski | { |
134 | 52001445 | Adam Lackorzynski | int i, is_multiboot = 0; |
135 | 52001445 | Adam Lackorzynski | uint32_t flags = 0;
|
136 | 52001445 | Adam Lackorzynski | uint32_t mh_entry_addr; |
137 | 52001445 | Adam Lackorzynski | uint32_t mh_load_addr; |
138 | 52001445 | Adam Lackorzynski | uint32_t mb_kernel_size; |
139 | 52001445 | Adam Lackorzynski | MultibootState mbs; |
140 | 52001445 | Adam Lackorzynski | uint8_t bootinfo[MBI_SIZE]; |
141 | 52001445 | Adam Lackorzynski | uint8_t *mb_bootinfo_data; |
142 | 52001445 | Adam Lackorzynski | |
143 | 52001445 | Adam Lackorzynski | /* Ok, let's see if it is a multiboot image.
|
144 | 52001445 | Adam Lackorzynski | The header is 12x32bit long, so the latest entry may be 8192 - 48. */
|
145 | 52001445 | Adam Lackorzynski | for (i = 0; i < (8192 - 48); i += 4) { |
146 | 52001445 | Adam Lackorzynski | if (ldl_p(header+i) == 0x1BADB002) { |
147 | 52001445 | Adam Lackorzynski | uint32_t checksum = ldl_p(header+i+8);
|
148 | 52001445 | Adam Lackorzynski | flags = ldl_p(header+i+4);
|
149 | 52001445 | Adam Lackorzynski | checksum += flags; |
150 | 52001445 | Adam Lackorzynski | checksum += (uint32_t)0x1BADB002;
|
151 | 52001445 | Adam Lackorzynski | if (!checksum) {
|
152 | 52001445 | Adam Lackorzynski | is_multiboot = 1;
|
153 | 52001445 | Adam Lackorzynski | break;
|
154 | 52001445 | Adam Lackorzynski | } |
155 | 52001445 | Adam Lackorzynski | } |
156 | 52001445 | Adam Lackorzynski | } |
157 | 52001445 | Adam Lackorzynski | |
158 | 52001445 | Adam Lackorzynski | if (!is_multiboot)
|
159 | 52001445 | Adam Lackorzynski | return 0; /* no multiboot */ |
160 | 52001445 | Adam Lackorzynski | |
161 | 52001445 | Adam Lackorzynski | mb_debug("qemu: I believe we found a multiboot image!\n");
|
162 | 52001445 | Adam Lackorzynski | memset(bootinfo, 0, sizeof(bootinfo)); |
163 | 52001445 | Adam Lackorzynski | memset(&mbs, 0, sizeof(mbs)); |
164 | 52001445 | Adam Lackorzynski | |
165 | 52001445 | Adam Lackorzynski | if (flags & 0x00000004) { /* MULTIBOOT_HEADER_HAS_VBE */ |
166 | 52001445 | Adam Lackorzynski | fprintf(stderr, "qemu: multiboot knows VBE. we don't.\n");
|
167 | 52001445 | Adam Lackorzynski | } |
168 | 52001445 | Adam Lackorzynski | if (!(flags & 0x00010000)) { /* MULTIBOOT_HEADER_HAS_ADDR */ |
169 | 52001445 | Adam Lackorzynski | uint64_t elf_entry; |
170 | 52001445 | Adam Lackorzynski | uint64_t elf_low, elf_high; |
171 | 52001445 | Adam Lackorzynski | int kernel_size;
|
172 | 52001445 | Adam Lackorzynski | fclose(f); |
173 | 409dbce5 | Aurelien Jarno | kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry, |
174 | 409dbce5 | Aurelien Jarno | &elf_low, &elf_high, 0, ELF_MACHINE, 0); |
175 | 52001445 | Adam Lackorzynski | if (kernel_size < 0) { |
176 | 52001445 | Adam Lackorzynski | fprintf(stderr, "Error while loading elf kernel\n");
|
177 | 52001445 | Adam Lackorzynski | exit(1);
|
178 | 52001445 | Adam Lackorzynski | } |
179 | 52001445 | Adam Lackorzynski | mh_load_addr = elf_low; |
180 | 52001445 | Adam Lackorzynski | mb_kernel_size = elf_high - elf_low; |
181 | 52001445 | Adam Lackorzynski | mh_entry_addr = elf_entry; |
182 | 52001445 | Adam Lackorzynski | |
183 | 52001445 | Adam Lackorzynski | mbs.mb_buf = qemu_malloc(mb_kernel_size); |
184 | 52001445 | Adam Lackorzynski | if (rom_copy(mbs.mb_buf, mh_load_addr, mb_kernel_size) != mb_kernel_size) {
|
185 | 52001445 | Adam Lackorzynski | fprintf(stderr, "Error while fetching elf kernel from rom\n");
|
186 | 52001445 | Adam Lackorzynski | exit(1);
|
187 | 52001445 | Adam Lackorzynski | } |
188 | 52001445 | Adam Lackorzynski | |
189 | 52001445 | Adam Lackorzynski | mb_debug("qemu: loading multiboot-elf kernel (%#x bytes) with entry %#zx\n",
|
190 | 52001445 | Adam Lackorzynski | mb_kernel_size, (size_t)mh_entry_addr); |
191 | 52001445 | Adam Lackorzynski | } else {
|
192 | 52001445 | Adam Lackorzynski | /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_ADDR. */
|
193 | 52001445 | Adam Lackorzynski | uint32_t mh_header_addr = ldl_p(header+i+12);
|
194 | 52001445 | Adam Lackorzynski | mh_load_addr = ldl_p(header+i+16);
|
195 | 52001445 | Adam Lackorzynski | uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr); |
196 | 52001445 | Adam Lackorzynski | |
197 | 52001445 | Adam Lackorzynski | mh_entry_addr = ldl_p(header+i+28);
|
198 | 52001445 | Adam Lackorzynski | mb_kernel_size = kernel_file_size - mb_kernel_text_offset; |
199 | 52001445 | Adam Lackorzynski | |
200 | 52001445 | Adam Lackorzynski | /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE.
|
201 | 52001445 | Adam Lackorzynski | uint32_t mh_mode_type = ldl_p(header+i+32);
|
202 | 52001445 | Adam Lackorzynski | uint32_t mh_width = ldl_p(header+i+36);
|
203 | 52001445 | Adam Lackorzynski | uint32_t mh_height = ldl_p(header+i+40);
|
204 | 52001445 | Adam Lackorzynski | uint32_t mh_depth = ldl_p(header+i+44); */
|
205 | 52001445 | Adam Lackorzynski | |
206 | 52001445 | Adam Lackorzynski | mb_debug("multiboot: mh_header_addr = %#x\n", mh_header_addr);
|
207 | 52001445 | Adam Lackorzynski | mb_debug("multiboot: mh_load_addr = %#x\n", mh_load_addr);
|
208 | 52001445 | Adam Lackorzynski | mb_debug("multiboot: mh_load_end_addr = %#x\n", ldl_p(header+i+20)); |
209 | 52001445 | Adam Lackorzynski | mb_debug("multiboot: mh_bss_end_addr = %#x\n", ldl_p(header+i+24)); |
210 | 52001445 | Adam Lackorzynski | mb_debug("qemu: loading multiboot kernel (%#x bytes) at %#x\n",
|
211 | 52001445 | Adam Lackorzynski | mb_kernel_size, mh_load_addr); |
212 | 52001445 | Adam Lackorzynski | |
213 | 52001445 | Adam Lackorzynski | mbs.mb_buf = qemu_malloc(mb_kernel_size); |
214 | 52001445 | Adam Lackorzynski | fseek(f, mb_kernel_text_offset, SEEK_SET); |
215 | 52001445 | Adam Lackorzynski | if (fread(mbs.mb_buf, 1, mb_kernel_size, f) != mb_kernel_size) { |
216 | 52001445 | Adam Lackorzynski | fprintf(stderr, "fread() failed\n");
|
217 | 52001445 | Adam Lackorzynski | exit(1);
|
218 | 52001445 | Adam Lackorzynski | } |
219 | 52001445 | Adam Lackorzynski | fclose(f); |
220 | 52001445 | Adam Lackorzynski | } |
221 | 52001445 | Adam Lackorzynski | |
222 | 52001445 | Adam Lackorzynski | mbs.mb_buf_phys = mh_load_addr; |
223 | 52001445 | Adam Lackorzynski | |
224 | 52001445 | Adam Lackorzynski | mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_kernel_size); |
225 | 52001445 | Adam Lackorzynski | mbs.offset_mbinfo = mbs.mb_buf_size; |
226 | 52001445 | Adam Lackorzynski | |
227 | 52001445 | Adam Lackorzynski | /* Calculate space for cmdlines and mb_mods */
|
228 | 52001445 | Adam Lackorzynski | mbs.mb_buf_size += strlen(kernel_filename) + 1;
|
229 | 52001445 | Adam Lackorzynski | mbs.mb_buf_size += strlen(kernel_cmdline) + 1;
|
230 | 52001445 | Adam Lackorzynski | if (initrd_filename) {
|
231 | 52001445 | Adam Lackorzynski | const char *r = initrd_filename; |
232 | 52001445 | Adam Lackorzynski | mbs.mb_buf_size += strlen(r) + 1;
|
233 | 52001445 | Adam Lackorzynski | mbs.mb_mods_avail = 1;
|
234 | 52001445 | Adam Lackorzynski | while ((r = strchr(r, ','))) { |
235 | 52001445 | Adam Lackorzynski | mbs.mb_mods_avail++; |
236 | 52001445 | Adam Lackorzynski | r++; |
237 | 52001445 | Adam Lackorzynski | } |
238 | 52001445 | Adam Lackorzynski | mbs.mb_buf_size += MB_MOD_SIZE * mbs.mb_mods_avail; |
239 | 52001445 | Adam Lackorzynski | } |
240 | 52001445 | Adam Lackorzynski | |
241 | 52001445 | Adam Lackorzynski | mbs.mb_buf_size = TARGET_PAGE_ALIGN(mbs.mb_buf_size); |
242 | 52001445 | Adam Lackorzynski | |
243 | 52001445 | Adam Lackorzynski | /* enlarge mb_buf to hold cmdlines and mb-info structs */
|
244 | 52001445 | Adam Lackorzynski | mbs.mb_buf = qemu_realloc(mbs.mb_buf, mbs.mb_buf_size); |
245 | 52001445 | Adam Lackorzynski | mbs.offset_cmdlines = mbs.offset_mbinfo + mbs.mb_mods_avail * MB_MOD_SIZE; |
246 | 52001445 | Adam Lackorzynski | |
247 | 52001445 | Adam Lackorzynski | if (initrd_filename) {
|
248 | 52001445 | Adam Lackorzynski | char *next_initrd;
|
249 | 52001445 | Adam Lackorzynski | |
250 | 52001445 | Adam Lackorzynski | mbs.offset_mods = mbs.mb_buf_size; |
251 | 52001445 | Adam Lackorzynski | |
252 | 52001445 | Adam Lackorzynski | do {
|
253 | 52001445 | Adam Lackorzynski | char *next_space;
|
254 | 52001445 | Adam Lackorzynski | uint32_t mb_mod_length; |
255 | 52001445 | Adam Lackorzynski | uint32_t offs = mbs.mb_buf_size; |
256 | 52001445 | Adam Lackorzynski | |
257 | 52001445 | Adam Lackorzynski | next_initrd = strchr(initrd_filename, ',');
|
258 | 52001445 | Adam Lackorzynski | if (next_initrd)
|
259 | 52001445 | Adam Lackorzynski | *next_initrd = '\0';
|
260 | 52001445 | Adam Lackorzynski | /* if a space comes after the module filename, treat everything
|
261 | 52001445 | Adam Lackorzynski | after that as parameters */
|
262 | 52001445 | Adam Lackorzynski | target_phys_addr_t c = mb_add_cmdline(&mbs, initrd_filename); |
263 | 52001445 | Adam Lackorzynski | if ((next_space = strchr(initrd_filename, ' '))) |
264 | 52001445 | Adam Lackorzynski | *next_space = '\0';
|
265 | 52001445 | Adam Lackorzynski | mb_debug("multiboot loading module: %s\n", initrd_filename);
|
266 | 52001445 | Adam Lackorzynski | mb_mod_length = get_image_size(initrd_filename); |
267 | 52001445 | Adam Lackorzynski | if (mb_mod_length < 0) { |
268 | 52001445 | Adam Lackorzynski | fprintf(stderr, "failed to get %s image size\n", initrd_filename);
|
269 | 52001445 | Adam Lackorzynski | exit(1);
|
270 | 52001445 | Adam Lackorzynski | } |
271 | 52001445 | Adam Lackorzynski | |
272 | 52001445 | Adam Lackorzynski | mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_mod_length + mbs.mb_buf_size); |
273 | 52001445 | Adam Lackorzynski | mbs.mb_buf = qemu_realloc(mbs.mb_buf, mbs.mb_buf_size); |
274 | 52001445 | Adam Lackorzynski | |
275 | 52001445 | Adam Lackorzynski | load_image(initrd_filename, (unsigned char *)mbs.mb_buf + offs); |
276 | 52001445 | Adam Lackorzynski | mb_add_mod(&mbs, mbs.mb_buf_phys + offs, |
277 | 52001445 | Adam Lackorzynski | mbs.mb_buf_phys + offs + mb_mod_length, c); |
278 | 52001445 | Adam Lackorzynski | |
279 | 52001445 | Adam Lackorzynski | mb_debug("mod_start: %p\nmod_end: %p\n cmdline: %#x\n",
|
280 | 52001445 | Adam Lackorzynski | (char *)mbs.mb_buf + offs,
|
281 | 52001445 | Adam Lackorzynski | (char *)mbs.mb_buf + offs + mb_mod_length, c);
|
282 | 52001445 | Adam Lackorzynski | initrd_filename = next_initrd+1;
|
283 | 52001445 | Adam Lackorzynski | } while (next_initrd);
|
284 | 52001445 | Adam Lackorzynski | } |
285 | 52001445 | Adam Lackorzynski | |
286 | 52001445 | Adam Lackorzynski | /* Commandline support */
|
287 | 52001445 | Adam Lackorzynski | char kcmdline[strlen(kernel_filename) + strlen(kernel_cmdline) + 2]; |
288 | 52001445 | Adam Lackorzynski | snprintf(kcmdline, sizeof(kcmdline), "%s %s", |
289 | 52001445 | Adam Lackorzynski | kernel_filename, kernel_cmdline); |
290 | 52001445 | Adam Lackorzynski | stl_p(bootinfo + MBI_CMDLINE, mb_add_cmdline(&mbs, kcmdline)); |
291 | 52001445 | Adam Lackorzynski | |
292 | 52001445 | Adam Lackorzynski | stl_p(bootinfo + MBI_MODS_ADDR, mbs.mb_buf_phys + mbs.offset_mbinfo); |
293 | 52001445 | Adam Lackorzynski | stl_p(bootinfo + MBI_MODS_COUNT, mbs.mb_mods_count); /* mods_count */
|
294 | 52001445 | Adam Lackorzynski | |
295 | 52001445 | Adam Lackorzynski | /* the kernel is where we want it to be now */
|
296 | 52001445 | Adam Lackorzynski | stl_p(bootinfo + MBI_FLAGS, MULTIBOOT_FLAGS_MEMORY |
297 | 52001445 | Adam Lackorzynski | | MULTIBOOT_FLAGS_BOOT_DEVICE |
298 | 52001445 | Adam Lackorzynski | | MULTIBOOT_FLAGS_CMDLINE |
299 | 52001445 | Adam Lackorzynski | | MULTIBOOT_FLAGS_MODULES |
300 | 52001445 | Adam Lackorzynski | | MULTIBOOT_FLAGS_MMAP); |
301 | 52001445 | Adam Lackorzynski | stl_p(bootinfo + MBI_MEM_LOWER, 640);
|
302 | 52001445 | Adam Lackorzynski | stl_p(bootinfo + MBI_MEM_UPPER, ram_size / 1024);
|
303 | 52001445 | Adam Lackorzynski | stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8001ffff); /* XXX: use the -boot switch? */ |
304 | 52001445 | Adam Lackorzynski | stl_p(bootinfo + MBI_MMAP_ADDR, ADDR_E820_MAP); |
305 | 52001445 | Adam Lackorzynski | |
306 | 52001445 | Adam Lackorzynski | mb_debug("multiboot: mh_entry_addr = %#x\n", mh_entry_addr);
|
307 | 52001445 | Adam Lackorzynski | mb_debug(" mb_buf_phys = %x\n", mbs.mb_buf_phys);
|
308 | 52001445 | Adam Lackorzynski | mb_debug(" mod_start = %x\n", mbs.mb_buf_phys + mbs.offset_mods);
|
309 | 52001445 | Adam Lackorzynski | mb_debug(" mb_mods_count = %d\n", mbs.mb_mods_count);
|
310 | 52001445 | Adam Lackorzynski | |
311 | 52001445 | Adam Lackorzynski | /* save bootinfo off the stack */
|
312 | 52001445 | Adam Lackorzynski | mb_bootinfo_data = qemu_malloc(sizeof(bootinfo));
|
313 | 52001445 | Adam Lackorzynski | memcpy(mb_bootinfo_data, bootinfo, sizeof(bootinfo));
|
314 | 52001445 | Adam Lackorzynski | |
315 | 52001445 | Adam Lackorzynski | /* Pass variables to option rom */
|
316 | 52001445 | Adam Lackorzynski | fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ENTRY, mh_entry_addr); |
317 | 52001445 | Adam Lackorzynski | fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, mh_load_addr); |
318 | 52001445 | Adam Lackorzynski | fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, mbs.mb_buf_size); |
319 | 52001445 | Adam Lackorzynski | fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, |
320 | 52001445 | Adam Lackorzynski | mbs.mb_buf, mbs.mb_buf_size); |
321 | 52001445 | Adam Lackorzynski | |
322 | 52001445 | Adam Lackorzynski | fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, ADDR_MBI); |
323 | 52001445 | Adam Lackorzynski | fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, sizeof(bootinfo));
|
324 | 52001445 | Adam Lackorzynski | fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, mb_bootinfo_data, |
325 | 52001445 | Adam Lackorzynski | sizeof(bootinfo));
|
326 | 52001445 | Adam Lackorzynski | |
327 | 52001445 | Adam Lackorzynski | option_rom[nb_option_roms] = "multiboot.bin";
|
328 | 52001445 | Adam Lackorzynski | nb_option_roms++; |
329 | 52001445 | Adam Lackorzynski | |
330 | 52001445 | Adam Lackorzynski | return 1; /* yes, we are multiboot */ |
331 | 52001445 | Adam Lackorzynski | } |