3 * \brief Support for the x86 platform
6 * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
10 * (c) 2008-2009 Author(s)
11 * economic rights: Technische Universität Dresden (Germany)
13 * This file is part of TUD:OS and distributed under the terms of the
14 * GNU General Public License 2.
15 * Please see the COPYING-GPL-2 file for details.
19 #include "x86_pc-base.h"
29 enum { Verbose_mbi = 1 };
33 #ifdef REALMODE_LOADING
34 struct Platform_x86_1 : Platform_x86
36 char const *realmode_pointer;
38 void setup_memory_map()
40 Region_list *ram = mem_manager->ram;
41 Region_list *regions = mem_manager->regions;
43 unsigned long m = *(l4_uint32_t*)(realmode_pointer + 0x1e0);
44 printf("Detected memory size: %ldKB\n", m);
45 ram->add(Region::n(0, 0x9fc00, ".ram", Region::Ram));
46 ram->add(Region::n(0x100000, (m + 1024) << 10, ".ram", Region::Ram));
47 regions->add(Region::n(0, 0x1000, ".BIOS", Region::Arch, 0));
50 // Fix EBDA in conventional memory
51 unsigned long p = *(l4_uint16_t *)0x40e << 4;
55 unsigned long e = p + 1024;
56 Region *r = ram->find(Region(p, e - 1));
60 ram->add(Region::n(e, r->end(), ".ram", Region::Ram), true);
66 char const *cmdline() const
69 l4_uint32_t p = *(l4_uint32_t*)(realmode_pointer + 0x228);
73 return (char const *)p;
77 #else // REALMODE_LOADING
79 struct Platform_x86_1 : Platform_x86
81 l4util_mb_info_t *mbi;
83 void setup_memory_map()
85 Region_list *ram = mem_manager->ram;
86 Region_list *regions = mem_manager->regions;
89 // add the page-table on which we're running in 64bit mode
90 regions->add(Region::n(ptab64_info->addr, ptab64_info->addr + ptab64_info->size,
91 ".bootstrap-ptab64", Region::Boot));
93 if (!(mbi->flags & L4UTIL_MB_MEM_MAP))
95 assert(mbi->flags & L4UTIL_MB_MEMORY);
96 ram->add(Region::n(0, (mbi->mem_lower + 1024) << 10, ".ram",
98 ram->add(Region::n(0x100000, (mbi->mem_upper + 1024) << 10, ".ram",
103 l4util_mb_addr_range_t *mmap;
104 l4util_mb_for_each_mmap_entry(mmap, mbi)
106 unsigned long long start = (unsigned long long)mmap->addr;
107 unsigned long long end = (unsigned long long)mmap->addr + mmap->size;
112 ram->add(Region::n(start, end, ".ram", Region::Ram));
117 regions->add(Region::n(start, end, ".BIOS", Region::Arch, mmap->type));
120 regions->add(Region::n(start, end, ".BIOS", Region::No_mem));
128 regions->add(Region::n(0, 0x1000, ".BIOS", Region::Arch, 0));
133 // Fix EBDA in conventional memory
134 unsigned long p = *(l4_uint16_t *)0x40e << 4;
138 unsigned long e = p + 1024;
139 Region *r = ram->find(Region(p, e - 1));
142 if (e - 1 < r->end())
143 ram->add(Region::n(e, r->end(), ".ram", Region::Ram), true);
150 #endif // !REALMODE_LOADING
155 class Platform_x86_loader_mbi :
156 public Platform_x86_1,
157 public Boot_modules_image_mode
160 Boot_modules *modules() { return this; }
164 Platform_x86_loader_mbi _x86_pc_platform;
168 class Platform_x86_multiboot : public Platform_x86_1, public Boot_modules
171 Boot_modules *modules() { return this; }
173 Module module(unsigned index, bool) const
176 l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t*)(unsigned long)mbi->mods_addr;
178 m.start = (char const *)(l4_addr_t)mb_mod[index].mod_start;
179 m.end = (char const *)(l4_addr_t)mb_mod[index].mod_end;
180 m.cmdline = (char const *)(l4_addr_t)mb_mod[index].cmdline;
184 unsigned num_modules() const { return mbi->mods_count; }
188 Region_list *regions = mem_manager->regions;
190 regions->add(Region::n((unsigned long)mbi,
191 (unsigned long)mbi + sizeof(*mbi),
192 ".mbi", Region::Boot));
194 if (mbi->flags & L4UTIL_MB_CMDLINE)
195 regions->add(Region::n((unsigned long)mbi->cmdline,
196 (unsigned long)mbi->cmdline
197 + strlen((char const *)(l4_addr_t)mbi->cmdline) + 1,
198 ".mbi", Region::Boot));
200 l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t*)(unsigned long)mbi->mods_addr;
201 regions->add(Region::n((unsigned long)mb_mod,
202 (unsigned long)&mb_mod[mbi->mods_count],
203 ".mbi", Region::Boot));
205 if (mbi->flags & L4UTIL_MB_VIDEO_INFO)
207 if (mbi->vbe_mode_info)
208 regions->add(Region::start_size(mbi->vbe_mode_info,
209 sizeof(l4util_mb_vbe_mode_t),
210 ".mbi", Region::Boot));
211 if (mbi->vbe_ctrl_info)
212 regions->add(Region::start_size(mbi->vbe_ctrl_info,
213 sizeof(l4util_mb_vbe_ctrl_t),
214 ".mbi", Region::Boot));
218 for (unsigned i = 0; i < mbi->mods_count; ++i)
219 regions->add(Region::n(mb_mod[i].cmdline,
220 (unsigned long)mb_mod[i].cmdline
221 + strlen((char const *)(l4_addr_t)mb_mod[i].cmdline) + 1,
222 ".mbi", Region::Boot));
224 for (unsigned i = 0; i < mbi->mods_count; ++i)
225 regions->add(mod_region(i, mb_mod[i].mod_start,
226 mb_mod[i].mod_end - mb_mod[i].mod_start));
229 void move_module(unsigned index, void *dest,
232 l4util_mb_mod_t *mod = (l4util_mb_mod_t*)(unsigned long)mbi->mods_addr + index;
233 unsigned long size = mod->mod_end - mod->mod_start;
234 _move_module(index, dest, (char const *)(l4_addr_t)mod->mod_start,
235 size, overlap_check);
237 assert ((l4_addr_t)dest < 0xfffffff0);
238 assert ((l4_addr_t)dest < 0xfffffff0 - size);
239 mod->mod_start = (l4_addr_t)dest;
240 mod->mod_end = (l4_addr_t)dest + size;
243 l4util_mb_info_t *construct_mbi(unsigned long mod_addr)
245 // calculate the size needed to cover the full MBI, including command lines
246 unsigned long total_size = sizeof(l4util_mb_info_t);
248 // consider the global command line
249 if (mbi->flags & L4UTIL_MB_CMDLINE)
250 total_size += round_wordsize(strlen((char const *)(l4_addr_t)mbi->cmdline) + 1);
253 if (mbi->flags & L4UTIL_MB_VIDEO_INFO)
255 if (mbi->vbe_mode_info)
256 total_size += sizeof(l4util_mb_vbe_mode_t);
258 if (mbi->vbe_ctrl_info)
259 total_size += sizeof(l4util_mb_vbe_ctrl_t);
263 total_size += sizeof(l4util_mb_mod_t) * mbi->mods_count;
265 // scan through all modules and add the command line
266 l4util_mb_mod_t *mods = (l4util_mb_mod_t*)(unsigned long)mbi->mods_addr;
267 for (l4util_mb_mod_t *m = mods; m != mods + mbi->mods_count; ++m)
269 total_size += round_wordsize(strlen((char const *)(l4_addr_t)m->cmdline) + 1);
272 printf(" need %ld bytes to copy MBI\n", total_size);
274 // try to find a free region for the MBI
275 char *_mb = (char *)mem_manager->find_free_ram(total_size);
277 panic("fatal: could not allocate memory for multi-boot info\n");
279 // mark the region as reserved
280 mem_manager->regions->add(Region::start_size((l4_addr_t)_mb, total_size, ".mbi_rt",
283 printf(" reserved %ld bytes at %p\n", total_size, _mb);
285 // copy the whole MBI
286 l4util_mb_info_t *dst = (l4util_mb_info_t *)_mb;
289 l4util_mb_mod_t *dst_mods = (l4util_mb_mod_t *)(dst + 1);
290 dst->mods_addr = (l4_addr_t)dst_mods;
291 _mb = (char *)(dst_mods + mbi->mods_count);
293 if (mbi->flags & L4UTIL_MB_VIDEO_INFO)
295 if (mbi->vbe_mode_info)
297 l4util_mb_vbe_mode_t *d = (l4util_mb_vbe_mode_t *)_mb;
298 *d = *((l4util_mb_vbe_mode_t *)(l4_addr_t)mbi->vbe_mode_info);
299 dst->vbe_mode_info = (l4_addr_t)d;
300 _mb = (char *)(d + 1);
303 if (mbi->vbe_ctrl_info)
305 l4util_mb_vbe_ctrl_t *d = (l4util_mb_vbe_ctrl_t *)_mb;
306 *d = *((l4util_mb_vbe_ctrl_t *)(l4_addr_t)mbi->vbe_ctrl_info);
307 dst->vbe_ctrl_info = (l4_addr_t)d;
308 _mb = (char *)(d + 1);
314 strcpy(_mb, (char const *)(l4_addr_t)mbi->cmdline);
315 dst->cmdline = (l4_addr_t)_mb;
316 _mb += round_wordsize(strlen(_mb) + 1);
319 for (unsigned i = 0; i < mbi->mods_count; ++i)
321 dst_mods[i] = mods[i];
322 if (char const *c = (char const *)(l4_addr_t)(mods[i].cmdline))
324 unsigned l = strlen(c) + 1;
325 dst_mods[i].cmdline = (l4_addr_t)_mb;
327 _mb += round_wordsize(l);
333 // remove the old MBI from the reserved memory
334 for (Region *r = mem_manager->regions->begin();
335 r != mem_manager->regions->end();)
337 if (strcmp(r->name(), ".mbi"))
340 r = mem_manager->regions->remove(r);
343 move_modules(mod_addr);
348 Platform_x86_multiboot _x86_pc_platform;
350 #endif // !IMAGE_MODE
354 void __main(l4util_mb_info_t *mbi, unsigned long p2, char const *realmode_si,
355 ptab64_mem_info_t const *ptab64_info);
357 void __main(l4util_mb_info_t *mbi, unsigned long p2, char const *realmode_si,
358 ptab64_mem_info_t const *ptab64_info)
361 Platform_base::platform = &_x86_pc_platform;
362 _x86_pc_platform.init();
364 // remember this info to reserve the memory in setup_memory_map later
365 _x86_pc_platform.ptab64_info = ptab64_info;
370 #if defined(REALMODE_LOADING)
371 /* create synthetic multi boot info, if loaded from realmode */
374 _x86_pc_platform.realmode_pointer = realmode_si;
375 cmdline = _x86_pc_platform.cmdline();
377 // cmdline = _mbi_cmdline;
380 assert(p2 == L4UTIL_MB_VALID); /* we need to be multiboot-booted */
381 _x86_pc_platform.mbi = mbi;
382 cmdline = (char const *)(l4_addr_t)mbi->cmdline;
384 _x86_pc_platform.setup_uart(cmdline);