2 * \file bootstrap/server/src/startup.cc
3 * \brief Main functions
6 * \author Torsten Frenzel <frenzel@os.inf.tu-dresden.de>,
7 * Frank Mehnert <fm3@os.inf.tu-dresden.de>,
8 * Adam Lackorzynski <adam@os.inf.tu-dresden.de>
9 * Alexander Warg <aw11@os.inf.tu-dresden.de>
10 * Sebastian Sumpf <sumpf@os.inf.tu-dresden.de>
14 * (c) 2005-2009 Author(s)
15 * economic rights: Technische Universität Dresden (Germany)
17 * This file is part of TUD:OS and distributed under the terms of the
18 * GNU General Public License 2.
19 * Please see the COPYING-GPL-2 file for details.
33 #include <l4/sys/compiler.h>
34 #include <l4/util/mb_info.h>
35 #include <l4/util/l4_macros.h>
47 #include "loader_mbi.h"
50 #if defined (ARCH_ppc32)
51 #include <l4/drivers/of_if.h>
52 #include <l4/drivers/of_dev.h>
57 enum { Verbose_load = 0 };
59 static l4util_mb_info_t *mb_info;
60 /* management of allocated memory regions */
61 static Region_list regions;
62 static Region __regs[300];
64 /* management of conventional memory regions */
65 static Region_list ram;
66 static Region __ram[16];
68 #if defined(ARCH_x86) || defined(ARCH_amd64)
69 static l4util_mb_vbe_mode_t __mb_vbe;
70 static l4util_mb_vbe_ctrl_t __mb_ctrl;
73 L4_kernel_options::Uart kuart;
74 unsigned int kuart_flags;
77 * IMAGE_MODE means that all boot modules are linked together to one
81 static l4_addr_t _mod_addr = RAM_BASE + MODADDR;
83 static l4_addr_t _mod_addr;
86 static const char *builtin_cmdline = CMDLINE;
88 /* modules to load by bootstrap */
89 static int sigma0 = 1; /* we need sigma0 */
90 static int roottask = 1; /* we need a roottask */
98 /* we define a small stack for sigma0 and roottask here -- it is used by L4
99 * for parameter passing. however, sigma0 and roottask must switch to its
100 * own private stack as soon as it has initialized itself because this memory
101 * region is later recycled in init.c */
102 static char roottask_init_stack[64]; /* XXX hardcoded */
103 static char sigma0_init_stack[64]; /* XXX hardcoded */
106 static exec_handler_func_t l4_exec_read_exec;
107 static exec_handler_func_t l4_exec_add_region;
112 dump_mbi(l4util_mb_info_t *mbi)
114 printf("%p-%p\n", (void*)(mbi->mem_lower << 10), (void*)(mbi->mem_upper << 10));
115 printf("MBI: [%p-%p]\n", mbi, mbi + 1);
116 printf("MODINFO: [%p-%p]\n", (char*)mbi->mods_addr,
117 (l4util_mb_mod_t*)(mbi->mods_addr) + mbi->mods_count);
119 printf("VBEINFO: [%p-%p]\n", (char*)mbi->vbe_ctrl_info,
120 (l4util_mb_vbe_ctrl_t*)(mbi->vbe_ctrl_info) + 1);
121 printf("VBEMODE: [%p-%p]\n", (char*)mbi->vbe_mode_info,
122 (l4util_mb_vbe_mode_t*)(mbi->vbe_mode_info) + 1);
124 l4util_mb_mod_t *m = (l4util_mb_mod_t*)(mbi->mods_addr);
125 l4util_mb_mod_t *me = m + mbi->mods_count;
128 printf(" MOD: [%p-%p]\n", (void*)m->mod_start, (void*)m->mod_end);
129 printf(" CMD: [%p-%p]\n", (char*)m->cmdline,
130 (char*)m->cmdline + strlen((char*)m->cmdline));
137 * Scan the memory regions with type == Region::Kernel for a
138 * kernel interface page (KIP).
140 * After loading the kernel we scan for the magic number at page boundaries.
145 unsigned char *p, *end;
148 printf(" find kernel info page...\n");
149 for (Region const *m = regions.begin(); m != regions.end(); ++m)
151 if (m->type() != Region::Kernel)
154 if (sizeof(unsigned long) < 8
155 && m->end() >= (1ULL << 32))
156 end = (unsigned char *)(~0UL - 0x1000);
158 end = (unsigned char *) (unsigned long)m->end();
160 for (p = (unsigned char *) (unsigned long)(m->begin() & 0xfffff000);
164 l4_umword_t magic = L4_KERNEL_INFO_MAGIC;
165 if (memcmp(p, &magic, 4) == 0)
168 printf(" found kernel info page at %p\n", p);
175 panic("could not find kernel info page, maybe your kernel is too old");
181 L4_kernel_options::Options *find_kopts(void *kip)
183 unsigned long a = (unsigned long)kip + sizeof(l4_kernel_info_t);
185 // kernel-option directly follow the KIP page
186 a = (a + 4096 - 1) & ~0xfff;
188 L4_kernel_options::Options *ko = (L4_kernel_options::Options *)a;
190 if (ko->magic != L4_kernel_options::Magic)
191 panic("Could not find kernel options page");
196 const char *get_cmdline(l4util_mb_info_t *mbi)
198 if (mbi && mbi->flags & L4UTIL_MB_CMDLINE)
199 return L4_CHAR_PTR(mbi->cmdline);
201 if (*builtin_cmdline)
202 return builtin_cmdline;
208 * Get the API version from the KIP.
211 unsigned long get_api_version(void *kip)
213 return ((unsigned long *)kip)[1];
218 check_arg_str(char *cmdline, const char *arg)
221 while ((s = strstr(s, arg)))
231 * Scan the command line for the given argument.
233 * The cmdline string may either be including the calling program
234 * (.../bootstrap -arg1 -arg2) or without (-arg1 -arg2) in the realmode
235 * case, there, we do not have a leading space
237 * return pointer after argument, NULL if not found
240 check_arg(l4util_mb_info_t *mbi, const char *arg)
242 const char *c = get_cmdline(mbi);
244 return check_arg_str((char *)c, arg);
251 * Calculate the maximum memory limit in MB.
253 * The limit is the highest physical address where conventional RAM is allowed.
254 * The memory is limited to 3 GB IA32 and unlimited on other systems.
258 get_memory_max_address()
260 #if defined(ARCH_x86)
261 /* Limit memory, we cannot really handle more right now. In fact, the
262 * problem is roottask. It maps as many superpages/pages as it gets.
263 * After that, the remaining pages are mapped using l4sigma0_map_anypage()
264 * with a receive window of L4_WHOLE_ADDRESS_SPACE. In response Sigma0
265 * could deliver pages beyond the 3GB user space limit. */
273 * If available the '-maxmem=xx' command line option is used.
277 get_memory_max_size(l4util_mb_info_t *mbi)
279 /* maxmem= parameter? */
280 if (char *c = check_arg(mbi, "-maxmem="))
281 return strtoul(c + 8, NULL, 10) << 20;
287 parse_memvalue(const char *s, unsigned long *val, char **ep)
290 *val = strtoul(s, ep, 0);
296 case 'G': *val <<= 10;
297 case 'M': *val <<= 10;
298 case 'k': case 'K': *val <<= 10; (*ep)++;
305 * Parse a memory layout string: size@offset
306 * E.g.: 256M@0x40000000, or 128M@128M
309 parse_mem_layout(const char *s, unsigned long *sz, unsigned long *offset)
313 if (parse_memvalue(s, sz, &ep))
322 if (parse_memvalue(ep + 1, offset, &ep))
329 dump_ram_map(bool show_total = false)
332 unsigned long long sum = 0;
333 for (Region *i = ram.begin(); i < ram.end(); ++i)
335 printf(" RAM: %016llx - %016llx: %lldkB\n",
336 i->begin(), i->end(), i->size() >> 10);
340 printf(" Total RAM: %lldMB\n", sum >> 20);
344 setup_memory_map(l4util_mb_info_t *mbi)
346 bool parsed_mem_option = false;
347 const char *s = get_cmdline(mbi);
351 while ((s = check_arg_str((char *)s, "-mem=")))
354 unsigned long sz, offset = 0;
355 if (!parse_mem_layout(s, &sz, &offset))
357 parsed_mem_option = true;
358 ram.add(Region::n(offset, offset + sz, ".ram", Region::Ram));
363 if (!parsed_mem_option)
364 // No -mem option given, use the one given by the platform
365 Platform_base::platform->setup_memory_map(mbi, &ram, ®ions);
370 static void do_the_memset(unsigned long s, unsigned val, unsigned long len)
372 printf("Presetting memory %16lx - %16lx to '%x'\n",
373 s, s + len - 1, val);
374 memset((void *)s, val, len);
377 static void fill_mem(unsigned fill_value)
380 for (Region const *r = ram.begin(); r != ram.end(); ++r)
382 unsigned long long b = r->begin();
383 // The regions list must be sorted!
384 for (Region const *reg = regions.begin(); reg != regions.end(); ++reg)
386 // completely before ram?
387 if (reg->end() < r->begin())
389 // completely after ram?
390 if (reg->begin() > r->end())
393 if (reg->begin() <= r->begin())
395 else if (b > reg->begin()) // some overlapping
397 if (reg->end() + 1 > b)
402 do_the_memset(b, fill_value, reg->begin() - 1 - b + 1);
408 do_the_memset(b, fill_value, r->end() - b + 1);
413 move_module(l4util_mb_info_t *mbi, int i, Region *from, Region *to,
416 unsigned long start = from->begin();
417 unsigned long size = from->end() - start + 1;
422 c[0] = *(unsigned char*)(start + 0);
423 c[1] = *(unsigned char*)(start + 1);
424 c[2] = *(unsigned char*)(start + 2);
425 c[3] = *(unsigned char*)(start + 3);
427 c[0] = c[0] < 32 ? '.' : c[0];
428 c[1] = c[1] < 32 ? '.' : c[1];
429 c[2] = c[2] < 32 ? '.' : c[2];
430 c[3] = c[3] < 32 ? '.' : c[3];
431 printf(" moving module %02d { %lx, %llx } (%s) -> { %llx - %llx } [%ld]\n",
432 i, start, from->end(), c, to->begin(), to->end(), size);
434 for (int a = 0; a < 0x100; a += 4)
435 printf("%08lx%s", *(unsigned long *)(start + a), (a % 32 == 28) ? "\n" : " ");
439 printf(" moving module %02d { %lx-%llx } -> { %llx-%llx } [%ld]\n",
440 i, start, from->end(), to->begin(), to->end(), size);
442 if (!ram.contains(*to))
443 panic("Panic: Would move outside of RAM");
447 Region *overlap = regions.find(*to);
450 printf("ERROR: module target [%llx-%llx) overlaps\n",
451 to->begin(), to->end());
454 panic("cannot move module");
457 memmove((void *)to->begin(), (void *)start, size);
458 unsigned long x = to->end() + 1;
459 memset((char *)x, 0, l4_round_page(x) - x);
461 (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_start = to->begin();
462 (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_end = to->end() + 1;
463 from->begin(to->begin());
464 from->end(to->end());
468 unsigned long mbi_mod_start(l4util_mb_info_t *mbi, int i)
469 { return (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_start; }
472 unsigned long mbi_mod_end(l4util_mb_info_t *mbi, int i)
473 { return (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_end; }
476 unsigned long mbi_mod_size(l4util_mb_info_t *mbi, int i)
477 { return mbi_mod_end(mbi, i) - mbi_mod_start(mbi, i); }
480 * Move modules to another address.
482 * Source and destination regions may overlap.
485 move_modules(l4util_mb_info_t *mbi, unsigned long modaddr)
487 printf(" Moving up to %d modules behind %lx\n", mbi->mods_count, modaddr);
489 Region *ramr = ram.find(Region(modaddr, modaddr));
490 Region module_area(modaddr, ramr->end(), "ram for modules");
492 unsigned long firstmodulestart = ~0UL, lastmoduleend = 0;
493 for (unsigned i = 0; i < mbi->mods_count; ++i)
495 if (lastmoduleend < mbi_mod_end(mbi, i))
496 lastmoduleend = mbi_mod_end(mbi, i);
497 if (firstmodulestart > mbi_mod_start(mbi, i))
498 firstmodulestart = mbi_mod_start(mbi, i);
500 lastmoduleend = l4_round_page(lastmoduleend);
501 if (firstmodulestart < modaddr)
503 Region s(lastmoduleend, ramr->end());
504 unsigned long sz = modaddr - firstmodulestart;
505 lastmoduleend = regions.find_free(s, sz, L4_PAGESHIFT) + sz;
508 for (unsigned i = 0; i < mbi->mods_count; ++i)
510 unsigned long start = mbi_mod_start(mbi, i);
511 unsigned long end = mbi_mod_end(mbi, i);
512 unsigned long size = mbi_mod_size(mbi, i);
517 Region from(start, end - 1);
518 Region *this_module = regions.find(from);
519 assert(this_module->begin() == from.begin()
520 && this_module->end() == from.end());
524 if (start < lastmoduleend)
526 Region to(lastmoduleend, lastmoduleend + (end - start) - 1);
527 if (module_area.contains(to))
529 move_module(mbi, i, this_module, &to, true);
530 lastmoduleend = l4_round_page(this_module->end());
536 if (start >= modaddr)
539 unsigned long long to = regions.find_free(module_area, size, L4_PAGESHIFT);
542 Region m_to = Region(to, to + size - 1);
543 move_module(mbi, i, this_module, &m_to, true);
546 // now everything is behind modaddr -> pull close to modaddr now
547 // this is optional but avoids holes and gives more consecutive memory
550 printf(" Compactifying\n");
553 unsigned long lastend = modaddr;
554 for (Region *i = regions.begin(); i < regions.end(); ++i)
556 if (i->begin() < modaddr)
561 for (; mi < mbi->mods_count; ++mi)
562 if (i->begin() == mbi_mod_start(mbi, mi))
565 if (mi < 3 || mbi->mods_count == mi)
568 unsigned long start = mbi_mod_start(mbi, mi);
569 unsigned long end = mbi_mod_end(mbi, mi);
573 Region to(lastend, end - 1 - (start - lastend));
574 move_module(mbi, mi, i, &to, false);
577 lastend = l4_round_page(end);
583 * Add the bootstrap binary itself to the allocated memory regions.
588 extern int _start; /* begin of image -- defined in crt0.S */
589 extern int _end; /* end of image -- defined by bootstrap.ld */
591 regions.add(Region::n((unsigned long)&_start, (unsigned long)&_end,
592 ".bootstrap", Region::Boot));
597 * Add the memory containing the boot modules to the allocated regions.
600 add_boot_modules_region(l4util_mb_info_t *mbi)
602 for (unsigned int i = 0; i < mbi->mods_count; ++i)
603 regions.add(Region(mbi_mod_start(mbi, i), mbi_mod_end(mbi, i) - 1,
604 ".Module", Region::Root));
609 * Add all sections of the given ELF binary to the allocated regions.
610 * Actually does not load the ELF binary (see load_elf_module()).
613 add_elf_regions(l4util_mb_info_t *mbi, l4_umword_t module,
616 exec_task_t exec_task;
619 const char *error_msg;
620 l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t*)(unsigned long)mbi->mods_addr;
622 assert(module < mbi->mods_count);
624 exec_task.begin = 0xffffffff;
626 exec_task.type = type;
628 exec_task.mod_start = L4_VOID_PTR(mb_mod[module].mod_start);
629 exec_task.mod = mb_mod + module;
631 printf(" Scanning %s\n", L4_CHAR_PTR(mb_mod[module].cmdline));
633 r = exec_load_elf(l4_exec_add_region, &exec_task,
640 printf("\n%p: ", exec_task.mod_start);
641 for (int i = 0; i < 4; ++i)
643 printf("%08lx ", *((unsigned long *)exec_task.mod_start + i));
646 for (int i = 0; i < 16; ++i)
648 unsigned char c = *(unsigned char *)((char *)exec_task.mod_start + i);
649 printf("%c", c < 32 ? '.' : c);
652 panic("\n\nThis is an invalid binary, fix it (%s).", error_msg);
658 * Load the given ELF binary into memory and free the source
662 load_elf_module(l4util_mb_mod_t *mb_mod)
664 exec_task_t exec_task;
667 const char *error_msg;
669 exec_task.begin = 0xffffffff;
672 exec_task.mod_start = L4_VOID_PTR(mb_mod->mod_start);
673 exec_task.mod = mb_mod;
675 r = exec_load_elf(l4_exec_read_exec, &exec_task,
679 /* clear the image for debugging and security reasons */
680 memset(L4_VOID_PTR(mb_mod->mod_start), 0,
681 mb_mod->mod_end - mb_mod->mod_start);
685 printf(" => can't load module (%s)\n", error_msg);
688 Region m = Region::n(mb_mod->mod_start, mb_mod->mod_end);
689 Region *x = regions.find(m);
692 if (x->begin() == m.begin())
694 unsigned long b = l4_round_page(m.end()+1);
707 * Simple linear memory allocator.
709 * Allocate size bytes starting from *ptr and set *ptr to *ptr + size.
712 lin_alloc(l4_size_t size, char **ptr)
715 *ptr += (size + 3) & ~3;;
721 * Duplicate the given command line.
723 * This function is used for relocating the multi-boot info.
724 * The new location is *ptr and *ptr is incremented by the size of the
725 * string (basically like lin_alloc() does).
727 * This function also implements the mechanism to replace the command line
728 * of a module from the bootstrap command line.
731 char *dup_cmdline(l4util_mb_info_t *mbi, unsigned mod_nr, char **ptr,
738 char* name_end = strchr(orig, ' ');
739 if (name_end && *name_end)
745 char const *new_args = get_arg_module(mbi, orig, &size);
747 if (new_args && size)
748 printf(" new args for %d = \"%.*s\"\n", mod_nr, size, new_args);
754 *ptr+= strlen(*ptr)+1;
759 strncpy(*ptr, new_args, size);
769 print_e820_map(l4util_mb_info_t *mbi)
772 printf(" Bootloader MMAP%s\n", mbi->flags & L4UTIL_MB_MEM_MAP
773 ? ":" : " not available.");
776 if (mbi->flags & L4UTIL_MB_MEM_MAP)
778 l4util_mb_addr_range_t *mmap;
779 l4util_mb_for_each_mmap_entry(mmap, mbi)
781 const char *types[] = { "unknown", "RAM", "reserved", "ACPI",
782 "ACPI NVS", "unusable" };
783 const char *type_str = (mmap->type < (sizeof(types) / sizeof(types[0])))
784 ? types[mmap->type] : types[0];
786 printf(" [%9llx, %9llx) %s (%d)\n",
787 (unsigned long long) mmap->addr,
788 (unsigned long long) mmap->addr + (unsigned long long) mmap->size,
789 type_str, (unsigned) mmap->type);
795 * Relocate and compact the multi-boot infomation (MBI).
797 * This function relocates the MBI into the first 4MB of physical memory.
798 * Substructures such as module information, the VESA information, and
799 * the command lines of the modules are also relocated.
800 * During relocation of command lines they may be substituted according
801 * to '-arg=' options from the bootstrap command line.
803 * The memory map is discarded and not relocated, because everything after
804 * bootstrap has to use the KIP memory descriptors.
808 relocate_mbi(l4util_mb_info_t *src_mbi, unsigned long* start,
811 l4util_mb_info_t *dst_mbi;
814 print_e820_map(src_mbi);
816 static char mbi_store[16 << 10] __attribute__((aligned(L4_PAGESIZE)));
818 x = (l4_addr_t)&mbi_store;
820 void *mbi_start = (void*)x;
825 dst_mbi = (l4util_mb_info_t*)lin_alloc(sizeof(l4util_mb_info_t), &p);
827 /* copy (extended) multiboot info structure */
828 memcpy(dst_mbi, src_mbi, sizeof(l4util_mb_info_t));
830 dst_mbi->flags &= ~(L4UTIL_MB_CMDLINE | L4UTIL_MB_MEM_MAP | L4UTIL_MB_MEMORY);
832 /* copy extended VIDEO information, if available */
833 if (dst_mbi->flags & L4UTIL_MB_VIDEO_INFO)
835 if (src_mbi->vbe_mode_info)
837 l4util_mb_vbe_mode_t *m
838 = (l4util_mb_vbe_mode_t*)lin_alloc(sizeof(l4util_mb_vbe_mode_t),
841 memcpy(m, L4_VOID_PTR(src_mbi->vbe_mode_info),
842 sizeof(l4util_mb_vbe_mode_t));
843 dst_mbi->vbe_mode_info = (l4_addr_t)m;
846 /* copy VBE controller info structure */
847 if (src_mbi->vbe_ctrl_info)
849 l4util_mb_vbe_ctrl_t *m
850 = (l4util_mb_vbe_ctrl_t*)lin_alloc(sizeof(l4util_mb_vbe_ctrl_t),
852 memcpy(m, L4_VOID_PTR(src_mbi->vbe_ctrl_info),
853 sizeof(l4util_mb_vbe_ctrl_t));
854 dst_mbi->vbe_ctrl_info = (l4_addr_t)m;
858 /* copy module descriptions */
859 l4util_mb_mod_t *mods = (l4util_mb_mod_t*)lin_alloc(sizeof(l4util_mb_mod_t)*
860 src_mbi->mods_count, &p);
861 memcpy(mods, L4_VOID_PTR(dst_mbi->mods_addr),
862 dst_mbi->mods_count * sizeof (l4util_mb_mod_t));
863 dst_mbi->mods_addr = (l4_addr_t)mods;
865 /* copy command lines of modules */
866 for (unsigned i = 0; i < dst_mbi->mods_count; i++)
868 char *n = dup_cmdline(src_mbi, i, &p, (char const *)(unsigned long)mods[i].cmdline);
870 mods[i].cmdline = (l4_addr_t) n;
874 printf(" Relocated mbi to [%p-%p]\n", mbi_start, (void *)(*end));
875 regions.add(Region::n((unsigned long)mbi_start,
876 ((unsigned long)*end) + 0xfe,
877 ".Multiboot info", Region::Root),
878 true /* we overlap with the Bootstrap binary, we are in BSS*/);
886 #include "uncompress.h"
889 //#define DO_CHECK_MD5
893 static void check_md5(const char *name, u_int8_t *start, unsigned size,
897 unsigned char digest[MD5_DIGEST_LENGTH];
898 char s[MD5_DIGEST_STRING_LENGTH];
899 static const char hex[] = "0123456789abcdef";
902 printf(" Checking checksum of %s\n", name);
905 MD5Update(&md5ctx, start, size);
906 MD5Final(digest, &md5ctx);
908 for (j = 0; j < MD5_DIGEST_LENGTH; j++)
910 s[j + j] = hex[digest[j] >> 4];
911 s[j + j + 1] = hex[digest[j] & 0x0f];
915 if (strcmp(s, md5sum))
916 panic("md5sum mismatch");
919 static inline void check_md5(const char *, u_int8_t *, unsigned, const char *)
927 l4_uint32_t size_uncompressed;
929 l4_uint32_t md5sum_compr;
930 l4_uint32_t md5sum_uncompr;
933 extern mod_info _module_info_start[];
934 extern mod_info _module_info_end[];
936 extern l4util_mb_mod_t _modules_mbi_start[];
937 extern l4util_mb_mod_t _modules_mbi_end[];
938 extern char _mbi_cmdline[];
941 * Create the basic multi-boot structure in IMAGE_MODE
944 construct_mbi(l4util_mb_info_t *mbi)
947 l4util_mb_mod_t *mods = _modules_mbi_start;
952 mbi->mods_count = _module_info_end - _module_info_start;
953 mbi->flags |= L4UTIL_MB_MODS;
954 mbi->mods_addr = (l4_addr_t)mods;
956 assert(mbi->mods_count >= 2);
958 for (i = 0; i < mbi->mods_count; ++i)
959 check_md5(L4_CHAR_PTR(_module_info_start[i].name),
960 (u_int8_t *)_module_info_start[i].start,
961 _module_info_start[i].size,
962 L4_CHAR_PTR(_module_info_start[i].md5sum_compr));
965 printf("Compressed modules:\n");
966 for (i = 0; i < mbi->mods_count; i++)
968 printf(" mod%02u: %08x-%08x: %s\n",
969 i, _module_info_start[i].start,
970 _module_info_start[i].start + _module_info_start[i].size,
971 L4_CHAR_PTR(_module_info_start[i].name));
974 destbuf = l4_round_page(mods[mbi->mods_count - 1].mod_end);
975 if (destbuf < _mod_addr)
978 // advance to last module end
979 for (i = 0; i < mbi->mods_count; i++)
980 destbuf += l4_round_page(_module_info_start[i].size_uncompressed);
982 // check for overlaps and adjust mod_addr accordingly
983 unsigned long d = destbuf;
984 for (i = mbi->mods_count; i > 0; --i)
986 d -= l4_round_page(_module_info_start[i - 1].size_uncompressed);
987 if (d <= _module_info_start[i-1].start + _module_info_start[i-1].size)
989 l4_addr_t x = (_module_info_start[i-1].start + _module_info_start[i-1].size + 0xfff) & ~0xfff;
990 l4_addr_t delta = x - d;
994 printf(" Adjusting modaddr to %lx {%d}\n", _mod_addr, i-1);
999 printf("Uncompressing modules (modaddr = %lx):\n", _mod_addr);
1002 for (i = mbi->mods_count; i > 0; --i)
1005 destbuf -= l4_round_page(_module_info_start[i - 1].size_uncompressed);
1008 (l4_addr_t)decompress(L4_CONST_CHAR_PTR(_module_info_start[i - 1].name),
1009 L4_VOID_PTR(_module_info_start[i - 1].start),
1011 _module_info_start[i - 1].size,
1012 _module_info_start[i - 1].size_uncompressed);
1014 l4_addr_t image = _module_info_start[i - 1].start;
1016 mods[i - 1].mod_start = image;
1017 mods[i - 1].mod_end = image + _module_info_start[i - 1].size_uncompressed;
1018 printf(" mod%02u: %08x-%08x: %s\n",
1019 i - 1, mods[i - 1].mod_start, mods[i - 1].mod_end,
1020 L4_CHAR_PTR(_module_info_start[i - 1].name));
1022 panic("Panic: Failure decompressing image\n");
1023 if (!ram.contains(Region(mods[i - 1].mod_start,
1024 mods[i - 1].mod_end)))
1025 panic("Panic: Module does not fit into RAM");
1029 for (i = 0; i < mbi->mods_count; ++i)
1030 check_md5(L4_CHAR_PTR(_module_info_start[i].name),
1031 (u_int8_t *)mods[i].mod_start,
1032 _module_info_start[i].size_uncompressed,
1033 L4_CHAR_PTR(_module_info_start[i].md5sum_uncompr));
1035 #endif /* IMAGE_MODE */
1038 /* Occupied RAM at the point we are scanning it */
1040 is_precious_ram(unsigned long addr)
1042 extern int _start, _end;
1044 if ((unsigned long)&_start <= addr && addr <= (unsigned long)&_end)
1048 unsigned i, c = _module_info_end - _module_info_start;
1049 if ((unsigned long)_module_info_start <= addr
1050 && addr <= (unsigned long)_module_info_end)
1053 if ((unsigned long)_modules_mbi_start <= addr
1054 && addr <= (unsigned long)_modules_mbi_end)
1057 for (i = 0; i < c; ++i)
1058 if (_module_info_start[i].start <= addr
1059 && addr < _module_info_start[i].start + _module_info_start[i].size_uncompressed)
1067 scan_ram_size(unsigned long base_addr, unsigned long max_scan_size_mb)
1069 // scan the RAM to find out the RAM size, note that at this point we have
1070 // two regions in RAM that we cannot touch, &_start - &_end and the
1073 unsigned long offset;
1074 const unsigned long increment = 1 << 20; // must be multiple of (1 << 20)
1076 printf(" Scanning up to %ld MB RAM\n", max_scan_size_mb);
1078 // initialize memory points
1079 for (offset = increment; offset < (max_scan_size_mb << 20); offset += offset)
1080 if (!is_precious_ram(base_addr + offset))
1081 *(unsigned long *)(base_addr + offset) = 0;
1083 // write something at offset 0, does it appear elsewhere?
1084 *(unsigned long *)base_addr = 0x12345678;
1085 asm volatile("" : : : "memory");
1086 for (offset = increment; offset < (max_scan_size_mb << 20); offset += offset)
1087 if (*(unsigned long *)(base_addr + offset) == 0x12345678)
1088 return offset >> 20;
1090 return max_scan_size_mb;
1094 * \brief Startup, started from crt0.S
1098 startup(l4util_mb_info_t *mbi, l4_umword_t flag,
1099 void *realmode_si, ptab64_mem_info_t *ptab64_info);
1101 startup(l4util_mb_info_t *mbi, l4_umword_t flag,
1102 void *realmode_si, ptab64_mem_info_t *ptab64_info)
1105 boot_info_t boot_info;
1106 l4util_mb_mod_t *mb_mod;
1108 if (!Platform_base::platform)
1110 // will we ever see this?
1111 printf("No platform found, hangup.");
1117 loader_mbi_add_cmdline(_mbi_cmdline);
1121 if (check_arg(mbi, "-wait"))
1123 puts("\nL4 Bootstrapper is waiting for key input to continue...");
1124 if (getchar() == -1)
1125 puts(" ...no key input available.");
1127 puts(" ...going on.");
1130 puts("\nL4 Bootstrapper");
1131 puts(" Build: #" BUILD_NR " " BUILD_DATE
1143 regions.init(__regs, sizeof(__regs) / sizeof(__regs[0]), "regions");
1144 ram.init(__ram, sizeof(__ram) / sizeof(__ram[0]), "RAM",
1145 get_memory_max_size(mbi), get_memory_max_address());
1148 // add the page-table on which we're running in 64bit mode
1149 regions.add(Region::n(ptab64_info->addr, ptab64_info->addr + ptab64_info->size,
1150 ".bootstrap-ptab64", Region::Boot));
1155 #if defined(ARCH_x86) || defined(ARCH_amd64)
1157 #ifdef REALMODE_LOADING
1158 /* create synthetic multi boot info */
1159 mbi = init_loader_mbi_x86_realmode(realmode_si);
1163 assert(flag == L4UTIL_MB_VALID); /* we need to be multiboot-booted */
1166 #elif defined(ARCH_arm)
1172 #elif defined(ARCH_ppc32)
1178 L4_drivers::Of_if of_if;
1180 printf(" Detecting ram size ...\n");
1181 unsigned long ram_size = of_if.detect_ramsize();
1182 printf(" Total memory size is %luMB\n", ram_size / (1024 * 1024));
1184 /* detect OF devices */
1185 unsigned long drives_addr, drives_length;
1187 if (of_if.detect_devices(&drives_addr, &drives_length))
1189 mbi->flags |= L4UTIL_MB_DRIVE_INFO;
1190 mbi->drives_addr = drives_addr;
1191 mbi->drives_length = drives_length;
1193 ram.add(Region::n(0x0, ram_size, ".ram", Region::Ram));
1195 #elif defined(ARCH_sparc)
1201 #error Unknown arch!
1204 setup_memory_map(mbi);
1206 /* basically add the bootstrap binary to the allocated regions */
1209 /* check command line */
1210 if (check_arg(mbi, "-no-sigma0"))
1213 if (check_arg(mbi, "-no-roottask"))
1216 if (const char *s = check_arg(mbi, "-modaddr"))
1217 _mod_addr = RAM_BASE + strtoul(s + 9, 0, 0);
1219 _mod_addr = l4_round_page(_mod_addr);
1225 /* move vbe and ctrl structures to a known location, it might be in the
1226 * way when moving modules around */
1227 #if defined(ARCH_x86) || defined(ARCH_amd64)
1228 if (mbi->flags & L4UTIL_MB_VIDEO_INFO)
1230 if (mbi->vbe_mode_info)
1232 memcpy(&__mb_vbe, L4_VOID_PTR(mbi->vbe_mode_info),
1233 sizeof(l4util_mb_vbe_mode_t));
1234 mbi->vbe_mode_info = (l4_addr_t)&__mb_vbe;
1237 if (mbi->vbe_ctrl_info)
1239 memcpy(&__mb_ctrl, L4_VOID_PTR(mbi->vbe_ctrl_info),
1240 sizeof(l4util_mb_vbe_ctrl_t));
1241 mbi->vbe_ctrl_info = (l4_addr_t)&__mb_ctrl;
1246 /* We need at least two boot modules */
1247 assert(mbi->flags & L4UTIL_MB_MODS);
1248 /* We have at least the L4 kernel and the first user task */
1249 assert(mbi->mods_count >= 2);
1250 assert(mbi->mods_count <= MODS_MAX);
1252 /* we're just a GRUB-booted kernel! */
1253 add_boot_modules_region(mbi);
1256 move_modules(mbi, _mod_addr);
1258 if (const char *s = get_cmdline(mbi))
1260 /* patch modules with content given at command line */
1261 while ((s = check_arg_str((char *)s, "-patch=")))
1262 patch_module(&s, mbi);
1266 add_elf_regions(mbi, kernel_module, Region::Kernel);
1269 add_elf_regions(mbi, sigma0_module, Region::Sigma0);
1272 add_elf_regions(mbi, roottask_module, Region::Root);
1275 /* copy Multiboot data structures, we still need to a safe place
1276 * before playing with memory we don't own and starting L4 */
1277 mb_info = relocate_mbi(mbi, &boot_info.mbi_low, &boot_info.mbi_high);
1279 panic("could not copy multiboot info to memory below 4MB");
1281 mb_mod = (l4util_mb_mod_t *)(unsigned long)mb_info->mods_addr;
1283 /* --- Shouldn't touch original Multiboot parameters after here. -- */
1285 /* setup kernel PART ONE */
1286 printf(" Loading ");
1287 print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
1291 boot_info.kernel_start = load_elf_module(mb_mod + kernel_module);
1296 printf(" Loading ");
1297 print_module_name(L4_CONST_CHAR_PTR(mb_mod[sigma0_module].cmdline),
1301 boot_info.sigma0_start = load_elf_module(mb_mod + sigma0_module);
1302 boot_info.sigma0_stack = (l4_addr_t)sigma0_init_stack
1303 + sizeof(sigma0_init_stack);
1306 /* setup roottask */
1310 printf(" Loading ");
1311 print_module_name(L4_CONST_CHAR_PTR(mb_mod[roottask_module].cmdline),
1315 boot_info.roottask_start = load_elf_module(mb_mod + roottask_module);
1316 boot_info.roottask_stack = (l4_addr_t)roottask_init_stack
1317 + sizeof(roottask_init_stack);
1320 /* setup kernel PART TWO (special kernel initialization) */
1323 #if defined(ARCH_x86) || defined(ARCH_amd64) || defined(ARCH_ppc32)
1324 /* setup multi boot info structure for kernel */
1325 l4util_mb_info_t kernel_mbi;
1326 kernel_mbi = *mb_info;
1327 kernel_mbi.flags = L4UTIL_MB_MEMORY;
1328 if (mb_mod[kernel_module].cmdline)
1330 kernel_mbi.cmdline = mb_mod[kernel_module].cmdline;
1331 kernel_mbi.flags |= L4UTIL_MB_CMDLINE;
1338 if (char *c = check_arg(mbi, "-presetmem="))
1340 unsigned fill_value = strtoul(c + 11, NULL, 0);
1341 fill_mem(fill_value);
1344 L4_kernel_options::Options *lko = find_kopts(l4i);
1345 kcmdline_parse(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline), lko);
1347 lko->flags |= kuart_flags;
1350 /* setup the L4 kernel info page before booting the L4 microkernel:
1351 * patch ourselves into the booter task addresses */
1352 unsigned long api_version = get_api_version(l4i);
1353 unsigned major = api_version >> 24;
1354 printf(" API Version: (%x) %s\n", major, (major & 0x80)?"experimental":"");
1357 case 0x02: // Version 2 API
1358 case 0x03: // Version X.0 and X.1
1359 case 0x87: // Fiasco
1360 init_kip_v2(l4i, &boot_info, mb_info, &ram, ®ions);
1364 init_kip_v4(l4i, &boot_info, mb_info, &ram, ®ions);
1367 panic("cannot boot a kernel with unknown api version %lx\n", api_version);
1371 printf(" Starting kernel ");
1372 print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
1374 printf(" at "l4_addr_fmt"\n", boot_info.kernel_start);
1376 #if defined(ARCH_x86)
1378 ("pushl $exit ; jmp *%3"
1380 : "a" (L4UTIL_MB_VALID),
1383 "r" (boot_info.kernel_start));
1385 #elif defined(ARCH_amd64)
1388 ("push $exit; jmp *%2"
1390 : "S" (L4UTIL_MB_VALID), "D" (&kernel_mbi), "r" (boot_info.kernel_start));
1392 #elif defined(ARCH_arm)
1393 typedef void (*startup_func)(void);
1394 startup_func f = (startup_func)boot_info.kernel_start;
1397 #elif defined(ARCH_ppc32)
1399 init_kip_v2_arch((l4_kernel_info_t*)l4i);
1400 printf("CPU at %lu Khz/Bus at %lu Hz\n",
1401 ((l4_kernel_info_t*)l4i)->frequency_cpu,
1402 ((l4_kernel_info_t*)l4i)->frequency_bus);
1403 typedef void (*startup_func)(l4util_mb_info_t *, unsigned long);
1404 startup_func f = (startup_func)boot_info.kernel_start;
1405 of_if.boot_finish();
1406 f(&kernel_mbi, of_if.get_prom());
1408 #elif defined(ARCH_sparc)
1410 printf("ENTER THE KERNEL!\n");
1411 asm volatile("or %%g0,%0,%%g2\n\t"
1412 "jmpl %%g2,%%g0\n\t"
1413 "nop\n\t" : : "r"(boot_info.kernel_start));
1417 #error "How to enter the kernel?"
1425 l4_exec_read_exec(void * handle,
1426 l4_addr_t file_ofs, l4_size_t file_size,
1427 l4_addr_t mem_addr, l4_addr_t /*v_addr*/,
1429 exec_sectype_t section_type)
1431 exec_task_t *exec_task = (exec_task_t*)handle;
1435 if (! (section_type & EXEC_SECTYPE_ALLOC))
1438 if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
1441 if (mem_addr < exec_task->begin)
1442 exec_task->begin = mem_addr;
1443 if (mem_addr + mem_size > exec_task->end)
1444 exec_task->end = mem_addr + mem_size;
1447 printf(" [%p-%p]\n", (void *) mem_addr, (void *) (mem_addr + mem_size));
1449 if (!ram.contains(Region::n(mem_addr, mem_addr + mem_size)))
1451 printf("To be loaded binary region is out of memory region.\n");
1452 printf(" Binary region: %lx - %lx\n", mem_addr, mem_addr + mem_size);
1454 panic("Binary outside memory");
1457 memcpy((void *) mem_addr,
1458 (char*)(exec_task->mod_start) + file_ofs, file_size);
1459 if (file_size < mem_size)
1460 memset((void *) (mem_addr + file_size), 0, mem_size - file_size);
1463 Region *f = regions.find(mem_addr);
1466 printf("could not find %lx\n", mem_addr);
1468 panic("Oops: region for module not found\n");
1471 f->name(exec_task->mod->cmdline
1472 ? L4_CONST_CHAR_PTR(exec_task->mod->cmdline)
1478 l4_exec_add_region(void * handle,
1479 l4_addr_t /*file_ofs*/, l4_size_t /*file_size*/,
1480 l4_addr_t mem_addr, l4_addr_t v_addr,
1482 exec_sectype_t section_type)
1484 exec_task_t *exec_task = (exec_task_t*)handle;
1489 if (! (section_type & EXEC_SECTYPE_ALLOC))
1492 if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
1495 regions.add(Region::n(mem_addr, mem_addr + mem_size,
1496 exec_task->mod->cmdline
1497 ? L4_CONST_CHAR_PTR(exec_task->mod->cmdline)
1498 : ".[Unknown]", Region::Type(exec_task->type),
1499 mem_addr == v_addr ? 1 : 0));