2 * \file bootstrap/server/src/startup.c
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"
49 #if defined (ARCH_x86) || defined(ARCH_amd64)
50 #include "ARCH-x86/serial.h"
53 #if defined (ARCH_ppc32)
54 #include <l4/drivers/of_if.h>
55 #include <l4/drivers/of_dev.h>
60 static l4util_mb_info_t *mb_info;
61 /* management of allocated memory regions */
62 static Region_list regions;
63 static Region __regs[MAX_REGION];
65 /* management of conventional memory regions */
66 static Region_list ram;
67 static Region __ram[8];
69 #if defined(ARCH_x86) || defined(ARCH_amd64)
70 static l4util_mb_vbe_mode_t __mb_vbe;
71 static l4util_mb_vbe_ctrl_t __mb_ctrl;
74 l4_kip_kernel_uart_info kip_kernel_uart_info;
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");
180 const char *get_cmdline(l4util_mb_info_t *mbi)
182 if (mbi && mbi->flags & L4UTIL_MB_CMDLINE)
183 return L4_CHAR_PTR(mbi->cmdline);
185 if (*builtin_cmdline)
186 return builtin_cmdline;
192 * Get the API version from the KIP.
195 unsigned long get_api_version(void *kip)
197 return ((unsigned long *)kip)[1];
202 check_arg_str(char *cmdline, const char *arg)
205 while ((s = strstr(s, arg)))
215 * Scan the command line for the given argument.
217 * The cmdline string may either be including the calling program
218 * (.../bootstrap -arg1 -arg2) or without (-arg1 -arg2) in the realmode
219 * case, there, we do not have a leading space
221 * return pointer after argument, NULL if not found
224 check_arg(l4util_mb_info_t *mbi, const char *arg)
226 const char *c = get_cmdline(mbi);
228 return check_arg_str((char *)c, arg);
235 * Calculate the maximum memory limit in MB.
237 * The limit is the highes physical address where conventional RAM is allowed.
239 * If available the '-maxmem=xx' command line option is used.
240 * If not then the memory is limited to 3 GB IA32 and unlimited on other
245 get_memory_limit(l4util_mb_info_t *mbi)
247 unsigned long arch_limit = ~0UL;
248 #if defined(ARCH_x86)
249 /* Limit memory, we cannot really handle more right now. In fact, the
250 * problem is roottask. It maps as many superpages/pages as it gets.
251 * After that, the remaining pages are mapped using l4sigma0_map_anypage()
252 * with a receive window of L4_WHOLE_ADDRESS_SPACE. In response Sigma0
253 * could deliver pages beyond the 3GB user space limit. */
254 arch_limit = 3024UL << 20;
257 /* maxmem= parameter? */
258 if (char *c = check_arg(mbi, "-maxmem="))
260 unsigned long l = strtoul(c + 8, NULL, 10) << 20;
269 parse_memvalue(const char *s, unsigned long *val, char **ep)
272 *val = strtoul(s, ep, 0);
278 case 'G': *val <<= 10;
279 case 'M': *val <<= 10;
280 case 'k': case 'K': *val <<= 10; (*ep)++;
287 * Parse a memory layout string: size@offset
288 * E.g.: 256M@0x40000000, or 128M@128M
291 parse_mem_layout(const char *s, unsigned long *sz, unsigned long *offset)
295 if (parse_memvalue(s, sz, &ep))
304 if (parse_memvalue(ep + 1, offset, &ep))
311 dump_ram_map(bool show_total = false)
314 unsigned long long sum = 0;
315 for (Region *i = ram.begin(); i < ram.end(); ++i)
317 printf(" RAM: %016llx - %016llx: %lldkB\n",
318 i->begin(), i->end(), (i->end() - i->begin() + 1) >> 10);
319 sum += i->end() - i->begin() + 1;
322 printf(" Total RAM: %lldMB\n", sum >> 20);
326 setup_memory_map(l4util_mb_info_t *mbi)
328 bool parsed_mem_option = false;
329 const char *s = get_cmdline(mbi);
333 while ((s = check_arg_str((char *)s, "-mem=")))
336 unsigned long sz, offset = 0;
337 if (!parse_mem_layout(s, &sz, &offset))
339 parsed_mem_option = true;
340 ram.add(Region::n(offset, offset + sz, ".ram", Region::Ram));
345 if (!parsed_mem_option)
346 // No -mem option given, use the one given by the platform
347 Platform_base::platform->setup_memory_map(mbi, &ram, ®ions);
352 static void do_the_memset(unsigned long s, unsigned val, unsigned long len)
354 printf("Presetting memory %16lx - %16lx to '%x'\n",
355 s, s + len - 1, val);
356 memset((void *)s, val, len);
359 static void fill_mem(unsigned fill_value)
362 for (Region const *r = ram.begin(); r != ram.end(); ++r)
364 unsigned long long b = r->begin();
365 // The regions list must be sorted!
366 for (Region const *reg = regions.begin(); reg != regions.end(); ++reg)
368 // completely before ram?
369 if (reg->end() < r->begin())
371 // completely after ram?
372 if (reg->begin() > r->end())
375 if (reg->begin() <= r->begin())
377 else if (b > reg->begin()) // some overlapping
379 if (reg->end() + 1 > b)
384 do_the_memset(b, fill_value, reg->begin() - 1 - b + 1);
390 do_the_memset(b, fill_value, r->end() - b + 1);
396 * Move modules to another address.
398 * Source and destination regions may overlap.
401 move_modules(l4util_mb_info_t *mbi, unsigned long modaddr)
403 long offset = modaddr - (L4_MB_MOD_PTR(mbi->mods_addr))[0].mod_start;
405 unsigned dir = offset > 0 ? -1 : 1;
409 printf(" => Images in place\n");
413 printf(" Moving %d modules to %lx with offset %lx\n",
414 mbi->mods_count, modaddr, offset);
416 i = dir == 1 ? 1 : mbi->mods_count;
417 i_end = dir == 1 ? mbi->mods_count + 1 : 0;
418 for (; i != i_end ; i += dir)
420 unsigned long start = (L4_MB_MOD_PTR(mbi->mods_addr))[i-1].mod_start;
421 unsigned long end = (L4_MB_MOD_PTR(mbi->mods_addr))[i-1].mod_end;
428 c[0] = *(unsigned char*)(start + 0);
429 c[1] = *(unsigned char*)(start + 1);
430 c[2] = *(unsigned char*)(start + 2);
431 c[3] = *(unsigned char*)(start + 3);
433 c[0] = c[0] < 32 ? '.' : c[0];
434 c[1] = c[1] < 32 ? '.' : c[1];
435 c[2] = c[2] < 32 ? '.' : c[2];
436 c[3] = c[3] < 32 ? '.' : c[3];
437 printf(" moving module %02d { %lx, %lx } (%s) -> { %lx - %lx }\n",
438 i, start, end, c, start + offset, end + offset);
440 for (int a = 0; a < 0x100; a += 4)
441 printf("%08lx%s", *(unsigned long *)(start + a), (a % 32 == 28) ? "\n" : " ");
444 printf(" moving module %02d { %lx-%lx } -> { %lx-%lx }\n",
445 i, start, end, start + offset, end + offset);
448 Region *overlap = regions.find(Region(start + offset, end + offset));
451 printf("ERROR: module target [%lx-%lx) overlaps\n", start + offset,
454 panic("can not move module");
456 if (!ram.contains(Region(start + offset, end + offset)))
457 panic("Panic: Would move outside of RAM");
458 memmove((void *)(start+offset), (void *)start, end-start);
459 (L4_MB_MOD_PTR(mbi->mods_addr))[i-1].mod_start += offset;
460 (L4_MB_MOD_PTR(mbi->mods_addr))[i-1].mod_end += offset;
466 * Add the bootstrap binary itself to the allocated memory regions.
471 extern int _start; /* begin of image -- defined in crt0.S */
472 extern int _end; /* end of image -- defined by bootstrap.ld */
474 regions.add(Region::n((unsigned long)&_start, (unsigned long)&_end,
475 ".bootstrap", Region::Boot));
480 * Add the memory containing the boot modules to the allocated regions.
483 add_boot_modules_region(l4util_mb_info_t *mbi)
486 Region::n((L4_MB_MOD_PTR(mbi->mods_addr))[0].mod_start,
487 (L4_MB_MOD_PTR(mbi->mods_addr))[mbi->mods_count-1].mod_end,
488 ".Modules Memory", Region::Root));
493 * Add all sections of the given ELF binary to the allocated regions.
494 * Actually does not load the ELF binary (see load_elf_module()).
497 add_elf_regions(l4util_mb_info_t *mbi, l4_umword_t module,
500 exec_task_t exec_task;
503 const char *error_msg;
504 l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t*)mbi->mods_addr;
506 assert(module < mbi->mods_count);
508 exec_task.begin = 0xffffffff;
510 exec_task.type = type;
512 exec_task.mod_start = L4_VOID_PTR(mb_mod[module].mod_start);
513 exec_task.mod = mb_mod + module;
515 printf(" Scanning %s\n", L4_CHAR_PTR(mb_mod[module].cmdline));
517 r = exec_load_elf(l4_exec_add_region, &exec_task,
524 printf("\n%p: ", exec_task.mod_start);
525 for (i = 0; i < 16; ++i)
527 printf("%02x", *(unsigned char *)exec_task.mod_start);
532 for (i = 0; i < 16; ++i)
534 unsigned char c = *(unsigned char *)exec_task.mod_start;
535 printf("%c", c < 32 ? '.' : c);
538 panic("\n\nThis is an invalid binary, fix it (%s).", error_msg);
544 * Load the given ELF binary into memory and free the source
548 load_elf_module(l4util_mb_mod_t *mb_mod)
550 exec_task_t exec_task;
553 const char *error_msg;
555 exec_task.begin = 0xffffffff;
558 exec_task.mod_start = L4_VOID_PTR(mb_mod->mod_start);
559 exec_task.mod = mb_mod;
561 r = exec_load_elf(l4_exec_read_exec, &exec_task,
565 /* clear the image for debugging and security reasons */
566 memset(L4_VOID_PTR(mb_mod->mod_start), 0,
567 mb_mod->mod_end - mb_mod->mod_start);
571 printf(" => can't load module (%s)\n", error_msg);
574 Region m = Region::n(mb_mod->mod_start, mb_mod->mod_end);
575 Region *x = regions.find(m);
578 if (x->begin() == m.begin())
580 unsigned long b = l4_round_page(m.end()+1);
593 * Simple linear memory allocator.
595 * Allocate size bytes startting from *ptr and set *ptr to *ptr + size.
598 lin_alloc(l4_size_t size, char **ptr)
601 *ptr += (size + 3) & ~3;;
607 * Duplicate the given command line.
609 * This function is use for relocating the multi-boot info.
610 * The new location is *ptr and *ptr is incemented by the size of the
611 * string (basically like lin_alloc() does).
613 * This function also implements the mechanism to replace the command line
614 * of a module from the bootstrap comand line.
617 char *dup_cmdline(l4util_mb_info_t *mbi, unsigned mod_nr, char **ptr,
624 char* name_end = strchr(orig, ' ');
625 if (name_end && *name_end)
631 char const *new_args = get_arg_module(mbi, orig, &size);
633 if (new_args && size)
634 printf(" new args for %d = \"%.*s\"\n", mod_nr, size, new_args);
640 *ptr+= strlen(*ptr)+1;
645 strncpy(*ptr, new_args, size);
655 print_e820_map(l4util_mb_info_t *mbi)
658 printf(" Bootloader MMAP%s\n", mbi->flags & L4UTIL_MB_MEM_MAP
659 ? ":" : " not available.");
662 if (mbi->flags & L4UTIL_MB_MEM_MAP)
664 l4util_mb_addr_range_t *mmap;
665 l4util_mb_for_each_mmap_entry(mmap, mbi)
667 const char *types[] = { "unknown", "RAM", "reserved", "ACPI",
668 "ACPI NVS", "unusable" };
669 const char *type_str = (mmap->type < (sizeof(types) / sizeof(types[0])))
670 ? types[mmap->type] : types[0];
672 printf(" [%9llx, %9llx) %s (%d)\n",
673 (unsigned long long) mmap->addr,
674 (unsigned long long) mmap->addr + (unsigned long long) mmap->size,
675 type_str, (unsigned) mmap->type);
681 * Relocate and compact the multi-boot infomation (MBI).
683 * This function relocates the MBI into the first 4MB of physical memory.
684 * Substructures such as module information, the VESA information, and
685 * the command lines of the modules are also relocated.
686 * During relocation of command lines they may be substituted according
687 * to '-arg=' options from the bootstrap command line.
689 * The memory map is discared and not relocated, because everything after
690 * bootstrap has to use the KIP memory desriptors.
694 relocate_mbi(l4util_mb_info_t *src_mbi, unsigned long* start,
697 l4util_mb_info_t *dst_mbi;
700 print_e820_map(src_mbi);
702 static char mbi_store[16 << 10] __attribute__((aligned(L4_PAGESIZE)));
704 x = (l4_addr_t)&mbi_store;
706 void *mbi_start = (void*)x;
711 dst_mbi = (l4util_mb_info_t*)lin_alloc(sizeof(l4util_mb_info_t), &p);
713 /* copy (extended) multiboot info structure */
714 memcpy(dst_mbi, src_mbi, sizeof(l4util_mb_info_t));
716 dst_mbi->flags &= ~(L4UTIL_MB_CMDLINE | L4UTIL_MB_MEM_MAP | L4UTIL_MB_MEMORY);
718 /* copy extended VIDEO information, if available */
719 if (dst_mbi->flags & L4UTIL_MB_VIDEO_INFO)
721 if (src_mbi->vbe_mode_info)
723 l4util_mb_vbe_mode_t *m
724 = (l4util_mb_vbe_mode_t*)lin_alloc(sizeof(l4util_mb_vbe_mode_t),
727 memcpy(m, L4_VOID_PTR(src_mbi->vbe_mode_info),
728 sizeof(l4util_mb_vbe_mode_t));
729 dst_mbi->vbe_mode_info = (l4_addr_t)m;
732 /* copy VBE controller info structure */
733 if (src_mbi->vbe_ctrl_info)
735 l4util_mb_vbe_ctrl_t *m
736 = (l4util_mb_vbe_ctrl_t*)lin_alloc(sizeof(l4util_mb_vbe_ctrl_t),
738 memcpy(m, L4_VOID_PTR(src_mbi->vbe_ctrl_info),
739 sizeof(l4util_mb_vbe_ctrl_t));
740 dst_mbi->vbe_ctrl_info = (l4_addr_t)m;
744 /* copy module descriptions */
745 l4util_mb_mod_t *mods = (l4util_mb_mod_t*)lin_alloc(sizeof(l4util_mb_mod_t)*
746 src_mbi->mods_count, &p);
747 memcpy(mods, L4_VOID_PTR(dst_mbi->mods_addr),
748 dst_mbi->mods_count * sizeof (l4util_mb_mod_t));
749 dst_mbi->mods_addr = (l4_addr_t)mods;
751 /* copy command lines of modules */
752 for (unsigned i = 0; i < dst_mbi->mods_count; i++)
754 char *n = dup_cmdline(src_mbi, i, &p, (char const *)(mods[i].cmdline));
756 mods[i].cmdline = (l4_addr_t) n;
760 printf(" Relocated mbi to [%p-%p]\n", mbi_start, (void*)(*end));
761 regions.add(Region::n((unsigned long)mbi_start,
762 ((unsigned long)*end) + 0xfe,
763 ".Multiboot info", Region::Root),
764 true /* we overlap with the Bootstrap binary, we are in BSS*/);
772 #include "uncompress.h"
775 //#define DO_CHECK_MD5
779 static void check_md5(const char *name, u_int8_t *start, unsigned size,
783 unsigned char digest[MD5_DIGEST_LENGTH];
784 char s[MD5_DIGEST_STRING_LENGTH];
785 static const char hex[] = "0123456789abcdef";
788 printf(" Checking checksum of %s\n", name);
791 MD5Update(&md5ctx, start, size);
792 MD5Final(digest, &md5ctx);
794 for (j = 0; j < MD5_DIGEST_LENGTH; j++)
796 s[j + j] = hex[digest[j] >> 4];
797 s[j + j + 1] = hex[digest[j] & 0x0f];
801 if (strcmp(s, md5sum))
802 panic("md5sum mismatch");
805 static inline void check_md5(const char *, u_int8_t *, unsigned, const char *)
813 l4_uint32_t size_uncompressed;
815 l4_uint32_t md5sum_compr;
816 l4_uint32_t md5sum_uncompr;
819 extern mod_info _module_info_start[];
820 extern mod_info _module_info_end[];
822 extern l4util_mb_mod_t _modules_mbi_start[];
823 extern l4util_mb_mod_t _modules_mbi_end[];
826 * Create the basic multi-boot structure in IMAGE_MODE
829 construct_mbi(l4util_mb_info_t *mbi)
832 l4util_mb_mod_t *mods = _modules_mbi_start;
837 mbi->mods_count = _module_info_end - _module_info_start;
838 mbi->flags |= L4UTIL_MB_MODS;
839 mbi->mods_addr = (l4_addr_t)mods;
841 assert(mbi->mods_count >= 2);
843 for (i = 0; i < mbi->mods_count; ++i)
844 check_md5(L4_CHAR_PTR(_module_info_start[i].name),
845 (u_int8_t *)_module_info_start[i].start,
846 _module_info_start[i].size,
847 L4_CHAR_PTR(_module_info_start[i].md5sum_compr));
850 printf("Compressed modules:\n");
851 for (i = 0; i < mbi->mods_count; i++)
853 printf(" mod%02u: %08x-%08x: %s\n",
854 i, _module_info_start[i].start,
855 _module_info_start[i].start + _module_info_start[i].size,
856 L4_CHAR_PTR(_module_info_start[i].name));
859 destbuf = l4_round_page(mods[mbi->mods_count - 1].mod_end);
860 if (destbuf < _mod_addr)
863 // advance to last module end
864 for (i = 0; i < mbi->mods_count; i++)
865 destbuf += l4_round_page(_module_info_start[i].size_uncompressed);
867 // check for overlaps and adjust mod_addr accordingly
868 unsigned long d = destbuf;
869 for (i = mbi->mods_count; i > 0; --i)
871 d -= l4_round_page(_module_info_start[i - 1].size_uncompressed);
872 if (d <= _module_info_start[i-1].start + _module_info_start[i-1].size)
874 l4_addr_t x = (_module_info_start[i-1].start + _module_info_start[i-1].size + 0xfff) & ~0xfff;
875 l4_addr_t delta = x - d;
879 printf(" Adjusting modaddr to %lx {%d}\n", _mod_addr, i-1);
884 printf("Uncompressing modules (modaddr = %lx):\n", _mod_addr);
887 for (i = mbi->mods_count; i > 0; --i)
890 destbuf -= l4_round_page(_module_info_start[i - 1].size_uncompressed);
893 (l4_addr_t)decompress(L4_CONST_CHAR_PTR(_module_info_start[i - 1].name),
894 L4_VOID_PTR(_module_info_start[i - 1].start),
896 _module_info_start[i - 1].size,
897 _module_info_start[i - 1].size_uncompressed);
899 l4_addr_t image = _module_info_start[i - 1].start;
901 mods[i - 1].mod_start = image;
902 mods[i - 1].mod_end = image + _module_info_start[i - 1].size_uncompressed;
903 printf(" mod%02u: %08x-%08x: %s\n",
904 i - 1, mods[i - 1].mod_start, mods[i - 1].mod_end,
905 L4_CHAR_PTR(_module_info_start[i - 1].name));
907 panic("Panic: Failure decompressing image\n");
908 if (!ram.contains(Region(mods[i - 1].mod_start,
909 mods[i - 1].mod_end)))
910 panic("Panic: Module does not fit into RAM");
914 for (i = 0; i < mbi->mods_count; ++i)
915 check_md5(L4_CHAR_PTR(_module_info_start[i].name),
916 (u_int8_t *)mods[i].mod_start,
917 _module_info_start[i].size_uncompressed,
918 L4_CHAR_PTR(_module_info_start[i].md5sum_uncompr));
920 #endif /* IMAGE_MODE */
924 init_pc_serial(l4util_mb_info_t *mbi)
926 #if defined(ARCH_x86) || defined(ARCH_amd64)
931 if ((s = check_arg(mbi, "-comport")))
933 char const *a = s + 9;
934 if (!strncmp(a, "pci:", 4))
940 comport = strtoul(a, 0, 0);
943 if (check_arg(mbi, "-serial"))
947 extern unsigned long search_pci_serial_devs(int port_idx, bool scan_only);
948 if (unsigned long port = search_pci_serial_devs(comport, true))
953 printf("PCI IO port = %x\n", comport);
959 com_cons_init(comport);
969 // check that our is_precious_ram function can work ok
970 #error For ARM, IMAGE_MODE must always be enabled
973 /* Occupied RAM at the point we are scannig it */
975 is_precious_ram(unsigned long addr)
977 extern int _start, _end;
978 unsigned i, c = _module_info_end - _module_info_start;
980 if ((unsigned long)&_start <= addr && addr <= (unsigned long)&_end)
983 if ((unsigned long)_module_info_start <= addr
984 && addr <= (unsigned long)_module_info_end)
987 if ((unsigned long)_modules_mbi_start <= addr
988 && addr <= (unsigned long)_modules_mbi_end)
991 for (i = 0; i < c; ++i)
992 if (_module_info_start[i].start <= addr
993 && _module_info_start[i].start + _module_info_start[i].size_uncompressed <= addr)
1000 scan_ram_size(unsigned long base_addr, unsigned long max_scan_size_mb)
1002 // scan the RAM to find out the RAM size, note that at this point we have
1003 // two regions in RAM that we cannot touch, &_start - &_end and the
1006 unsigned long offset;
1007 const unsigned long increment = 1 << 20; // must be multiple of (1 << 20)
1009 printf(" Scanning up to %ld MB RAM\n", max_scan_size_mb);
1011 // initialize memory points
1012 for (offset = increment; offset < (max_scan_size_mb << 20); offset += offset)
1013 if (!is_precious_ram(base_addr + offset))
1014 *(unsigned long *)(base_addr + offset) = 0;
1016 // write something at offset 0, does it appear elsewhere?
1017 *(unsigned long *)base_addr = 0x12345678;
1018 asm volatile("" : : : "memory");
1019 for (offset = increment; offset < (max_scan_size_mb << 20); offset += offset)
1020 if (*(unsigned long *)(base_addr + offset) == 0x12345678)
1021 return offset >> 20;
1023 return max_scan_size_mb;
1028 * \brief Startup, started from crt0.S
1032 startup(l4util_mb_info_t *mbi, l4_umword_t flag,
1033 void *realmode_si, ptab64_mem_info_t *ptab64_info);
1035 startup(l4util_mb_info_t *mbi, l4_umword_t flag,
1036 void *realmode_si, ptab64_mem_info_t *ptab64_info)
1039 boot_info_t boot_info;
1040 l4util_mb_mod_t *mb_mod;
1042 /* fire up serial port if specificed on the command line */
1043 init_pc_serial(mbi);
1045 if (!Platform_base::platform)
1047 // will we ever see this?
1048 printf("No platform found, hangup.");
1053 puts("\nL4 Bootstrapper");
1054 puts(" Build: #" BUILD_NR " " BUILD_DATE
1066 regions.init(__regs, sizeof(__regs)/sizeof(__regs[0]), "regions");
1067 ram.init(__ram, sizeof(__ram)/sizeof(__ram[0]), "RAM",
1068 get_memory_limit(mbi));
1071 // add the page-table on which we're running in 64bit mode
1072 regions.add(Region::n(ptab64_info->addr, ptab64_info->addr + ptab64_info->size,
1073 ".bootstrap-ptab64", Region::Boot));
1078 #if defined(ARCH_x86) || defined(ARCH_amd64)
1080 #ifdef REALMODE_LOADING
1081 /* create synthetic multi boot info */
1082 mbi = init_loader_mbi(realmode_si);
1086 assert(flag == L4UTIL_MB_VALID); /* we need to be multiboot-booted */
1089 #elif defined(ARCH_arm)
1090 l4util_mb_info_t my_mbi;
1091 memset(&my_mbi, 0, sizeof(my_mbi));
1097 #elif defined(ARCH_ppc32)
1101 l4util_mb_info_t my_mbi;
1102 L4_drivers::Of_if of_if;
1104 printf(" Detecting ram size ...\n");
1105 unsigned long ram_size = of_if.detect_ramsize();
1106 printf(" Total memory size is %luMB\n", ram_size / (1024 * 1024));
1108 /* setup mbi and detect OF devices */
1109 memset(&my_mbi, 0, sizeof(my_mbi));
1111 unsigned long drives_addr, drives_length;
1113 if (of_if.detect_devices(&drives_addr, &drives_length))
1115 mbi->flags |= L4UTIL_MB_DRIVE_INFO;
1116 mbi->drives_addr = drives_addr;
1117 mbi->drives_length = drives_length;
1119 ram.add(Region::n(0x0, ram_size, ".ram", Region::Ram));
1122 #error Unknown arch!
1125 setup_memory_map(mbi);
1127 /* basically add the bootstrap binary to the allocated regions */
1130 /* check command line */
1131 if (check_arg(mbi, "-no-sigma0"))
1134 if (check_arg(mbi, "-no-roottask"))
1137 if (const char *s = check_arg(mbi, "-modaddr"))
1138 _mod_addr = strtoul(s + 9, 0, 0);
1144 /* move vbe and ctrl structures to a known location, it might be in the
1145 * way when moving modules around */
1146 #if defined(ARCH_x86) || defined(ARCH_amd64)
1147 if (mbi->flags & L4UTIL_MB_VIDEO_INFO)
1149 if (mbi->vbe_mode_info)
1151 memcpy(&__mb_vbe, L4_VOID_PTR(mbi->vbe_mode_info),
1152 sizeof(l4util_mb_vbe_mode_t));
1153 mbi->vbe_mode_info = (l4_addr_t)&__mb_vbe;
1156 if (mbi->vbe_ctrl_info)
1158 memcpy(&__mb_ctrl, L4_VOID_PTR(mbi->vbe_ctrl_info),
1159 sizeof(l4util_mb_vbe_ctrl_t));
1160 mbi->vbe_ctrl_info = (l4_addr_t)&__mb_ctrl;
1166 move_modules(mbi, _mod_addr);
1168 /* We need at least two boot modules */
1169 assert(mbi->flags & L4UTIL_MB_MODS);
1170 /* We have at least the L4 kernel and the first user task */
1171 assert(mbi->mods_count >= 2);
1172 assert(mbi->mods_count <= MODS_MAX);
1174 /* we're just a GRUB-booted kernel! */
1175 add_boot_modules_region(mbi);
1177 if (const char *s = get_cmdline(mbi))
1179 /* patch modules with content given at command line */
1180 while ((s = check_arg_str((char *)s, "-patch=")))
1181 patch_module(&s, mbi);
1185 add_elf_regions(mbi, kernel_module, Region::Kernel);
1188 add_elf_regions(mbi, sigma0_module, Region::Sigma0);
1191 add_elf_regions(mbi, roottask_module, Region::Root);
1194 /* copy Multiboot data structures, we still need to a safe place
1195 * before playing with memory we don't own and starting L4 */
1196 mb_info = relocate_mbi(mbi, &boot_info.mbi_low, &boot_info.mbi_high);
1198 panic("could not copy multiboot info to memory below 4MB");
1200 mb_mod = (l4util_mb_mod_t*)mb_info->mods_addr;
1202 /* --- Shouldn't touch original Multiboot parameters after here. -- */
1204 /* setup kernel PART ONE */
1205 printf(" Loading ");
1206 print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
1210 boot_info.kernel_start = load_elf_module(mb_mod + kernel_module);
1215 printf(" Loading ");
1216 print_module_name(L4_CONST_CHAR_PTR(mb_mod[sigma0_module].cmdline),
1220 boot_info.sigma0_start = load_elf_module(mb_mod + sigma0_module);
1221 boot_info.sigma0_stack = (l4_addr_t)sigma0_init_stack
1222 + sizeof(sigma0_init_stack);
1225 /* setup roottask */
1229 printf(" Loading ");
1230 print_module_name(L4_CONST_CHAR_PTR(mb_mod[roottask_module].cmdline),
1234 boot_info.roottask_start = load_elf_module(mb_mod + roottask_module);
1235 boot_info.roottask_stack = (l4_addr_t)roottask_init_stack
1236 + sizeof(roottask_init_stack);
1239 /* setup kernel PART TWO (special kernel initialization) */
1242 #if defined(ARCH_x86) || defined(ARCH_amd64) || defined(ARCH_ppc32)
1243 /* setup multi boot info structure for kernel */
1244 l4util_mb_info_t kernel_mbi;
1245 kernel_mbi = *mb_info;
1246 kernel_mbi.flags = L4UTIL_MB_MEMORY;
1247 if (mb_mod[kernel_module].cmdline)
1249 kernel_mbi.cmdline = mb_mod[kernel_module].cmdline;
1250 kernel_mbi.flags |= L4UTIL_MB_CMDLINE;
1257 if (char *c = check_arg(mbi, "-presetmem="))
1259 unsigned fill_value = strtoul(c + 11, NULL, 0);
1260 fill_mem(fill_value);
1263 /* setup the L4 kernel info page before booting the L4 microkernel:
1264 * patch ourselves into the booter task addresses */
1265 unsigned long api_version = get_api_version(l4i);
1266 unsigned major = api_version >> 24;
1267 printf(" API Version: (%x) %s\n", major, (major & 0x80)?"experimental":"");
1270 case 0x02: // Version 2 API
1271 case 0x03: // Version X.0 and X.1
1272 case 0x87: // Fiasco
1273 init_kip_v2(l4i, &boot_info, mb_info, &ram, ®ions);
1274 //init_kip_kuart_info(l4i, &kip_kernel_uart_info);
1278 init_kip_v4(l4i, &boot_info, mb_info, &ram, ®ions);
1281 panic("cannot boot a kernel with unknown api version %lx\n", api_version);
1285 printf(" Starting kernel ");
1286 print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
1288 printf(" at "l4_addr_fmt"\n", boot_info.kernel_start);
1290 #if defined(ARCH_x86)
1292 ("pushl $exit ; jmp *%3"
1294 : "a" (L4UTIL_MB_VALID),
1297 "r" (boot_info.kernel_start));
1299 #elif defined(ARCH_amd64)
1302 ("push $exit; jmp *%2"
1304 : "S" (L4UTIL_MB_VALID), "D" (&kernel_mbi), "r" (boot_info.kernel_start));
1306 #elif defined(ARCH_arm)
1307 typedef void (*startup_func)(void);
1308 startup_func f = (startup_func)boot_info.kernel_start;
1311 #elif defined(ARCH_ppc32)
1313 init_kip_v2_arch((l4_kernel_info_t*)l4i);
1314 printf("CPU at %lu Khz/Bus at %lu Hz\n",
1315 ((l4_kernel_info_t*)l4i)->frequency_cpu,
1316 ((l4_kernel_info_t*)l4i)->frequency_bus);
1317 typedef void (*startup_func)(l4util_mb_info_t *, unsigned long);
1318 startup_func f = (startup_func)boot_info.kernel_start;
1319 of_if.boot_finish();
1320 f(&kernel_mbi, of_if.get_prom());
1323 #error "How to enter the kernel?"
1331 l4_exec_read_exec(void * handle,
1332 l4_addr_t file_ofs, l4_size_t file_size,
1333 l4_addr_t mem_addr, l4_addr_t /*v_addr*/,
1335 exec_sectype_t section_type)
1337 exec_task_t *exec_task = (exec_task_t*)handle;
1341 if (! (section_type & EXEC_SECTYPE_ALLOC))
1344 if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
1347 if (mem_addr < exec_task->begin)
1348 exec_task->begin = mem_addr;
1349 if (mem_addr + mem_size > exec_task->end)
1350 exec_task->end = mem_addr + mem_size;
1353 printf(" [%p-%p]\n", (void *) mem_addr, (void *) (mem_addr + mem_size));
1356 if (!ram.contains(Region::n(mem_addr, mem_addr + mem_size)))
1358 printf("To be loaded binary region is out of memory region.\n");
1359 printf(" Binary region: %lx - %lx\n", mem_addr, mem_addr + mem_size);
1361 panic("Binary outside memory");
1364 memcpy((void *) mem_addr,
1365 (char*)(exec_task->mod_start) + file_ofs, file_size);
1366 if (file_size < mem_size)
1367 memset((void *) (mem_addr + file_size), 0, mem_size - file_size);
1370 Region *f = regions.find(mem_addr);
1373 printf("could not find %lx\n", mem_addr);
1375 panic("Oops: region for module not found\n");
1378 f->name(exec_task->mod->cmdline
1379 ? L4_CONST_CHAR_PTR(exec_task->mod->cmdline)
1385 l4_exec_add_region(void * handle,
1386 l4_addr_t /*file_ofs*/, l4_size_t /*file_size*/,
1387 l4_addr_t mem_addr, l4_addr_t v_addr,
1389 exec_sectype_t section_type)
1391 exec_task_t *exec_task = (exec_task_t*)handle;
1396 if (! (section_type & EXEC_SECTYPE_ALLOC))
1399 if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
1402 regions.add(Region::n(mem_addr, mem_addr + mem_size,
1403 exec_task->mod->cmdline
1404 ? L4_CONST_CHAR_PTR(exec_task->mod->cmdline)
1405 : ".[Unknown]", Region::Type(exec_task->type),
1406 mem_addr == v_addr ? 1 : 0));