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 ? mbi->mods_count : 1;
409 printf(" => Images in place\n");
413 printf(" move modules to %lx with offset %lx\n", modaddr, offset);
415 for (i = dir; i != mbi->mods_count - dir ; offset > 0 ? i-- : i++)
417 unsigned long start = (L4_MB_MOD_PTR(mbi->mods_addr))[i-1].mod_start;
418 unsigned long end = (L4_MB_MOD_PTR(mbi->mods_addr))[i-1].mod_end;
425 c[0] = *(unsigned char*)(start + 0);
426 c[1] = *(unsigned char*)(start + 1);
427 c[2] = *(unsigned char*)(start + 2);
428 c[3] = *(unsigned char*)(start + 3);
430 c[0] = c[0] < 32 ? '.' : c[0];
431 c[1] = c[1] < 32 ? '.' : c[1];
432 c[2] = c[2] < 32 ? '.' : c[2];
433 c[3] = c[3] < 32 ? '.' : c[3];
434 printf(" move module %02d { %lx, %lx } (%s) -> { %lx - %lx }\n",
435 i, start, end, c, start + offset, end + offset);
437 for (int a = 0; a < 0x100; a += 4)
438 printf("%08lx%s", *(unsigned long *)(start + a), (a % 32 == 28) ? "\n" : " ");
441 printf(" move module %02d { %lx-%lx } -> { %lx-%lx }\n",
442 i, start, end, start + offset, end + offset);
445 Region *overlap = regions.find(Region(start + offset, end + offset));
448 printf("ERROR: module target [%lx-%lx) overlaps\n", start + offset,
451 panic("can not move module");
453 if (!ram.contains(Region(start + offset, end + offset)))
454 panic("Panic: Would move outside of RAM");
455 memmove((void *)(start+offset), (void *)start, end-start);
456 (L4_MB_MOD_PTR(mbi->mods_addr))[i-1].mod_start += offset;
457 (L4_MB_MOD_PTR(mbi->mods_addr))[i-1].mod_end += offset;
463 * Add the bootstrap binary itself to the allocated memory regions.
468 extern int _start; /* begin of image -- defined in crt0.S */
469 extern int _end; /* end of image -- defined by bootstrap.ld */
471 regions.add(Region::n((unsigned long)&_start, (unsigned long)&_end,
472 ".bootstrap", Region::Boot));
477 * Add the memory containing the boot modules to the allocated regions.
480 add_boot_modules_region(l4util_mb_info_t *mbi)
483 Region::n((L4_MB_MOD_PTR(mbi->mods_addr))[0].mod_start,
484 (L4_MB_MOD_PTR(mbi->mods_addr))[mbi->mods_count-1].mod_end,
485 ".Modules Memory", Region::Root));
490 * Add all sections of the given ELF binary to the allocated regions.
491 * Actually does not load the ELF binary (see load_elf_module()).
494 add_elf_regions(l4util_mb_info_t *mbi, l4_umword_t module,
497 exec_task_t exec_task;
500 const char *error_msg;
501 l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t*)mbi->mods_addr;
503 assert(module < mbi->mods_count);
505 exec_task.begin = 0xffffffff;
507 exec_task.type = type;
509 exec_task.mod_start = L4_VOID_PTR(mb_mod[module].mod_start);
510 exec_task.mod = mb_mod + module;
512 printf(" Scanning %s\n", L4_CHAR_PTR(mb_mod[module].cmdline));
514 r = exec_load_elf(l4_exec_add_region, &exec_task,
521 printf("\n%p: ", exec_task.mod_start);
522 for (i = 0; i < 16; ++i)
524 printf("%02x", *(unsigned char *)exec_task.mod_start);
529 for (i = 0; i < 16; ++i)
531 unsigned char c = *(unsigned char *)exec_task.mod_start;
532 printf("%c", c < 32 ? '.' : c);
535 panic("\n\nThis is an invalid binary, fix it.");
541 * Load the given ELF binary into memory and free the source
545 load_elf_module(l4util_mb_mod_t *mb_mod)
547 exec_task_t exec_task;
550 const char *error_msg;
552 exec_task.begin = 0xffffffff;
555 exec_task.mod_start = L4_VOID_PTR(mb_mod->mod_start);
556 exec_task.mod = mb_mod;
558 r = exec_load_elf(l4_exec_read_exec, &exec_task,
562 /* clear the image for debugging and security reasons */
563 memset(L4_VOID_PTR(mb_mod->mod_start), 0,
564 mb_mod->mod_end - mb_mod->mod_start);
568 printf(" => can't load module (%s)\n", error_msg);
571 Region m = Region::n(mb_mod->mod_start, mb_mod->mod_end);
572 Region *x = regions.find(m);
575 if (x->begin() == m.begin())
577 unsigned long b = l4_round_page(m.end()+1);
590 * Simple linear memory allocator.
592 * Allocate size bytes startting from *ptr and set *ptr to *ptr + size.
595 lin_alloc(l4_size_t size, char **ptr)
598 *ptr += (size + 3) & ~3;;
604 * Duplicate the given command line.
606 * This function is use for relocating the multi-boot info.
607 * The new location is *ptr and *ptr is incemented by the size of the
608 * string (basically like lin_alloc() does).
610 * This function also implements the mechanism to replace the command line
611 * of a module from the bootstrap comand line.
614 char *dup_cmdline(l4util_mb_info_t *mbi, unsigned mod_nr, char **ptr,
621 char* name_end = strchr(orig, ' ');
622 if (name_end && *name_end)
628 char const *new_args = get_arg_module(mbi, orig, &size);
630 if (new_args && size)
631 printf(" new args for %d = \"%.*s\"\n", mod_nr, size, new_args);
637 *ptr+= strlen(*ptr)+1;
642 strncpy(*ptr, new_args, size);
652 print_e820_map(l4util_mb_info_t *mbi)
655 printf(" Bootloader MMAP%s\n", mbi->flags & L4UTIL_MB_MEM_MAP
656 ? ":" : " not available.");
659 if (mbi->flags & L4UTIL_MB_MEM_MAP)
661 l4util_mb_addr_range_t *mmap;
662 l4util_mb_for_each_mmap_entry(mmap, mbi)
664 const char *types[] = { "unknown", "RAM", "reserved", "ACPI",
665 "ACPI NVS", "unusable" };
666 const char *type_str = (mmap->type < (sizeof(types) / sizeof(types[0])))
667 ? types[mmap->type] : types[0];
669 printf(" [%9llx, %9llx) %s (%d)\n",
670 (unsigned long long) mmap->addr,
671 (unsigned long long) mmap->addr + (unsigned long long) mmap->size,
672 type_str, (unsigned) mmap->type);
678 * Relocate and compact the multi-boot infomation (MBI).
680 * This function relocates the MBI into the first 4MB of physical memory.
681 * Substructures such as module information, the VESA information, and
682 * the command lines of the modules are also relocated.
683 * During relocation of command lines they may be substituted according
684 * to '-arg=' options from the bootstrap command line.
686 * The memory map is discared and not relocated, because everything after
687 * bootstrap has to use the KIP memory desriptors.
691 relocate_mbi(l4util_mb_info_t *src_mbi, unsigned long* start,
694 l4util_mb_info_t *dst_mbi;
697 print_e820_map(src_mbi);
699 static char mbi_store[16 << 10] __attribute__((aligned(L4_PAGESIZE)));
701 x = (l4_addr_t)&mbi_store;
703 void *mbi_start = (void*)x;
708 dst_mbi = (l4util_mb_info_t*)lin_alloc(sizeof(l4util_mb_info_t), &p);
710 /* copy (extended) multiboot info structure */
711 memcpy(dst_mbi, src_mbi, sizeof(l4util_mb_info_t));
713 dst_mbi->flags &= ~(L4UTIL_MB_CMDLINE | L4UTIL_MB_MEM_MAP | L4UTIL_MB_MEMORY);
715 /* copy extended VIDEO information, if available */
716 if (dst_mbi->flags & L4UTIL_MB_VIDEO_INFO)
718 if (src_mbi->vbe_mode_info)
720 l4util_mb_vbe_mode_t *m
721 = (l4util_mb_vbe_mode_t*)lin_alloc(sizeof(l4util_mb_vbe_mode_t),
724 memcpy(m, L4_VOID_PTR(src_mbi->vbe_mode_info),
725 sizeof(l4util_mb_vbe_mode_t));
726 dst_mbi->vbe_mode_info = (l4_addr_t)m;
729 /* copy VBE controller info structure */
730 if (src_mbi->vbe_ctrl_info)
732 l4util_mb_vbe_ctrl_t *m
733 = (l4util_mb_vbe_ctrl_t*)lin_alloc(sizeof(l4util_mb_vbe_ctrl_t),
735 memcpy(m, L4_VOID_PTR(src_mbi->vbe_ctrl_info),
736 sizeof(l4util_mb_vbe_ctrl_t));
737 dst_mbi->vbe_ctrl_info = (l4_addr_t)m;
741 /* copy module descriptions */
742 l4util_mb_mod_t *mods = (l4util_mb_mod_t*)lin_alloc(sizeof(l4util_mb_mod_t)*
743 src_mbi->mods_count, &p);
744 memcpy(mods, L4_VOID_PTR(dst_mbi->mods_addr),
745 dst_mbi->mods_count * sizeof (l4util_mb_mod_t));
746 dst_mbi->mods_addr = (l4_addr_t)mods;
748 /* copy command lines of modules */
749 for (unsigned i = 0; i < dst_mbi->mods_count; i++)
751 char *n = dup_cmdline(src_mbi, i, &p, (char const *)(mods[i].cmdline));
753 mods[i].cmdline = (l4_addr_t) n;
757 printf(" Relocated mbi to [%p-%p]\n", mbi_start, (void*)(*end));
758 regions.add(Region::n((unsigned long)mbi_start,
759 ((unsigned long)*end) + 0xfe,
760 ".Multiboot info", Region::Root),
761 true /* we overlap with the Bootstrap binary, we are in BSS*/);
769 #include "uncompress.h"
772 //#define DO_CHECK_MD5
776 static void check_md5(const char *name, u_int8_t *start, unsigned size,
780 unsigned char digest[MD5_DIGEST_LENGTH];
781 char s[MD5_DIGEST_STRING_LENGTH];
782 static const char hex[] = "0123456789abcdef";
785 printf(" Checking checksum of %s\n", name);
788 MD5Update(&md5ctx, start, size);
789 MD5Final(digest, &md5ctx);
791 for (j = 0; j < MD5_DIGEST_LENGTH; j++)
793 s[j + j] = hex[digest[j] >> 4];
794 s[j + j + 1] = hex[digest[j] & 0x0f];
798 if (strcmp(s, md5sum))
799 panic("md5sum mismatch");
802 static inline void check_md5(const char *, u_int8_t *, unsigned, const char *)
810 l4_uint32_t size_uncompressed;
812 l4_uint32_t md5sum_compr;
813 l4_uint32_t md5sum_uncompr;
816 extern mod_info _module_info_start[];
817 extern mod_info _module_info_end[];
819 extern l4util_mb_mod_t _modules_mbi_start[];
820 extern l4util_mb_mod_t _modules_mbi_end[];
823 * Create the basic multi-boot structure in IMAGE_MODE
826 construct_mbi(l4util_mb_info_t *mbi)
829 l4util_mb_mod_t *mods = _modules_mbi_start;
834 mbi->mods_count = _module_info_end - _module_info_start;
835 mbi->flags |= L4UTIL_MB_MODS;
836 mbi->mods_addr = (l4_addr_t)mods;
838 assert(mbi->mods_count >= 2);
840 for (i = 0; i < mbi->mods_count; ++i)
841 check_md5(L4_CHAR_PTR(_module_info_start[i].name),
842 (u_int8_t *)_module_info_start[i].start,
843 _module_info_start[i].size,
844 L4_CHAR_PTR(_module_info_start[i].md5sum_compr));
847 printf("Compressed modules:\n");
848 for (i = 0; i < mbi->mods_count; i++)
850 printf(" mod%02u: %08x-%08x: %s\n",
851 i, _module_info_start[i].start,
852 _module_info_start[i].start + _module_info_start[i].size,
853 L4_CHAR_PTR(_module_info_start[i].name));
856 destbuf = l4_round_page(mods[mbi->mods_count - 1].mod_end);
857 if (destbuf < _mod_addr)
860 // advance to last module end
861 for (i = 0; i < mbi->mods_count; i++)
862 destbuf += l4_round_page(_module_info_start[i].size_uncompressed);
864 // check for overlaps and adjust mod_addr accordingly
865 unsigned long d = destbuf;
866 for (i = mbi->mods_count; i > 0; --i)
868 d -= l4_round_page(_module_info_start[i - 1].size_uncompressed);
869 if (d <= _module_info_start[i-1].start + _module_info_start[i-1].size)
871 l4_addr_t x = (_module_info_start[i-1].start + _module_info_start[i-1].size + 0xfff) & ~0xfff;
872 l4_addr_t delta = x - d;
876 printf(" Adjusting modaddr to %lx {%d}\n", _mod_addr, i-1);
881 printf("Uncompressing modules (modaddr = %lx):\n", _mod_addr);
884 for (i = mbi->mods_count; i > 0; --i)
887 destbuf -= l4_round_page(_module_info_start[i - 1].size_uncompressed);
890 (l4_addr_t)decompress(L4_CONST_CHAR_PTR(_module_info_start[i - 1].name),
891 L4_VOID_PTR(_module_info_start[i - 1].start),
893 _module_info_start[i - 1].size,
894 _module_info_start[i - 1].size_uncompressed);
896 l4_addr_t image = _module_info_start[i - 1].start;
898 mods[i - 1].mod_start = image;
899 mods[i - 1].mod_end = image + _module_info_start[i - 1].size_uncompressed;
900 printf(" mod%02u: %08x-%08x: %s\n",
901 i - 1, mods[i - 1].mod_start, mods[i - 1].mod_end,
902 L4_CHAR_PTR(_module_info_start[i - 1].name));
904 panic("Panic: Failure decompressing image\n");
905 if (!ram.contains(Region(mods[i - 1].mod_start,
906 mods[i - 1].mod_end)))
907 panic("Panic: Module does not fit into RAM");
911 for (i = 0; i < mbi->mods_count; ++i)
912 check_md5(L4_CHAR_PTR(_module_info_start[i].name),
913 (u_int8_t *)mods[i].mod_start,
914 _module_info_start[i].size_uncompressed,
915 L4_CHAR_PTR(_module_info_start[i].md5sum_uncompr));
917 #endif /* IMAGE_MODE */
921 init_pc_serial(l4util_mb_info_t *mbi)
923 #if defined(ARCH_x86) || defined(ARCH_amd64)
927 if ((s = check_arg(mbi, "-comport")))
928 comport = strtoul(s + 9, 0, 0);
930 if (check_arg(mbi, "-serial"))
934 extern unsigned long search_pci_serial_devs(bool scan_only);
937 && (port = search_pci_serial_devs(false)))
944 com_cons_init(comport);
954 // check that our is_precious_ram function can work ok
955 #error For ARM, IMAGE_MODE must always be enabled
958 /* Occupied RAM at the point we are scannig it */
960 is_precious_ram(unsigned long addr)
962 extern int _start, _end;
963 unsigned i, c = _module_info_end - _module_info_start;
965 if ((unsigned long)&_start <= addr && addr <= (unsigned long)&_end)
968 if ((unsigned long)_module_info_start <= addr
969 && addr <= (unsigned long)_module_info_end)
972 if ((unsigned long)_modules_mbi_start <= addr
973 && addr <= (unsigned long)_modules_mbi_end)
976 for (i = 0; i < c; ++i)
977 if (_module_info_start[i].start <= addr
978 && _module_info_start[i].start + _module_info_start[i].size_uncompressed <= addr)
985 scan_ram_size(unsigned long base_addr, unsigned long max_scan_size_mb)
987 // scan the RAM to find out the RAM size, note that at this point we have
988 // two regions in RAM that we cannot touch, &_start - &_end and the
991 unsigned long offset;
992 const unsigned long increment = 1 << 20; // must be multiple of (1 << 20)
994 printf(" Scanning up to %ld MB RAM\n", max_scan_size_mb);
996 // initialize memory points
997 for (offset = increment; offset < (max_scan_size_mb << 20); offset += offset)
998 if (!is_precious_ram(base_addr + offset))
999 *(unsigned long *)(base_addr + offset) = 0;
1001 // write something at offset 0, does it appear elsewhere?
1002 *(unsigned long *)base_addr = 0x12345678;
1003 asm volatile("" : : : "memory");
1004 for (offset = increment; offset < (max_scan_size_mb << 20); offset += offset)
1005 if (*(unsigned long *)(base_addr + offset) == 0x12345678)
1006 return offset >> 20;
1008 return max_scan_size_mb;
1013 * \brief Startup, started from crt0.S
1017 startup(l4util_mb_info_t *mbi, l4_umword_t flag,
1018 void *realmode_si, ptab64_mem_info_t *ptab64_info);
1020 startup(l4util_mb_info_t *mbi, l4_umword_t flag,
1021 void *realmode_si, ptab64_mem_info_t *ptab64_info)
1024 boot_info_t boot_info;
1025 l4util_mb_mod_t *mb_mod;
1027 /* fire up serial port if specificed on the command line */
1028 init_pc_serial(mbi);
1030 if (!Platform_base::platform)
1032 // will we ever see this?
1033 printf("No platform found, hangup.");
1038 puts("\nL4 Bootstrapper");
1039 puts(" Build: #" BUILD_NR " " BUILD_DATE);
1041 regions.init(__regs, sizeof(__regs)/sizeof(__regs[0]), "regions");
1042 ram.init(__ram, sizeof(__ram)/sizeof(__ram[0]), "RAM",
1043 get_memory_limit(mbi));
1046 // add the page-table on which we're running in 64bit mode
1047 regions.add(Region::n(ptab64_info->addr, ptab64_info->addr + ptab64_info->size,
1048 ".bootstrap-ptab64", Region::Boot));
1053 #if defined(ARCH_x86) || defined(ARCH_amd64)
1055 #ifdef REALMODE_LOADING
1056 /* create synthetic multi boot info */
1057 mbi = init_loader_mbi(realmode_si);
1060 assert(flag == L4UTIL_MB_VALID); /* we need to be multiboot-booted */
1063 #elif defined(ARCH_arm)
1064 l4util_mb_info_t my_mbi;
1065 memset(&my_mbi, 0, sizeof(my_mbi));
1071 #elif defined(ARCH_ppc32)
1075 l4util_mb_info_t my_mbi;
1076 L4_drivers::Of_if of_if;
1078 printf(" Detecting ram size ...\n");
1079 unsigned long ram_size = of_if.detect_ramsize();
1080 printf(" Total memory size is %luMB\n", ram_size / (1024 * 1024));
1082 /* setup mbi and detect OF devices */
1083 memset(&my_mbi, 0, sizeof(my_mbi));
1085 unsigned long drives_addr, drives_length;
1087 if (of_if.detect_devices(&drives_addr, &drives_length))
1089 mbi->flags |= L4UTIL_MB_DRIVE_INFO;
1090 mbi->drives_addr = drives_addr;
1091 mbi->drives_length = drives_length;
1093 ram.add(Region::n(0x0, ram_size, ".ram", Region::Ram));
1096 #error Unknown arch!
1099 setup_memory_map(mbi);
1101 /* basically add the bootstrap binary to the allocated regions */
1104 /* check command line */
1105 if (check_arg(mbi, "-no-sigma0"))
1108 if (check_arg(mbi, "-no-roottask"))
1111 if (const char *s = check_arg(mbi, "-modaddr"))
1112 _mod_addr = strtoul(s + 9, 0, 0);
1118 /* move vbe and ctrl structures to a known location, it might be in the
1119 * way when moving modules around */
1120 #if defined(ARCH_x86) || defined(ARCH_amd64)
1121 if (mbi->flags & L4UTIL_MB_VIDEO_INFO)
1123 if (mbi->vbe_mode_info)
1125 memcpy(&__mb_vbe, L4_VOID_PTR(mbi->vbe_mode_info),
1126 sizeof(l4util_mb_vbe_mode_t));
1127 mbi->vbe_mode_info = (l4_addr_t)&__mb_vbe;
1130 if (mbi->vbe_ctrl_info)
1132 memcpy(&__mb_ctrl, L4_VOID_PTR(mbi->vbe_ctrl_info),
1133 sizeof(l4util_mb_vbe_ctrl_t));
1134 mbi->vbe_ctrl_info = (l4_addr_t)&__mb_ctrl;
1140 move_modules(mbi, _mod_addr);
1142 /* We need at least two boot modules */
1143 assert(mbi->flags & L4UTIL_MB_MODS);
1144 /* We have at least the L4 kernel and the first user task */
1145 assert(mbi->mods_count >= 2);
1146 assert(mbi->mods_count <= MODS_MAX);
1148 /* we're just a GRUB-booted kernel! */
1149 add_boot_modules_region(mbi);
1151 if (const char *s = get_cmdline(mbi))
1153 /* patch modules with content given at command line */
1154 while ((s = check_arg_str((char *)s, "-patch=")))
1155 patch_module(&s, mbi);
1159 add_elf_regions(mbi, kernel_module, Region::Kernel);
1162 add_elf_regions(mbi, sigma0_module, Region::Sigma0);
1165 add_elf_regions(mbi, roottask_module, Region::Root);
1168 /* copy Multiboot data structures, we still need to a safe place
1169 * before playing with memory we don't own and starting L4 */
1170 mb_info = relocate_mbi(mbi, &boot_info.mbi_low, &boot_info.mbi_high);
1172 panic("could not copy multiboot info to memory below 4MB");
1174 mb_mod = (l4util_mb_mod_t*)mb_info->mods_addr;
1176 /* --- Shouldn't touch original Multiboot parameters after here. -- */
1178 /* setup kernel PART ONE */
1179 printf(" Loading ");
1180 print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
1184 boot_info.kernel_start = load_elf_module(mb_mod + kernel_module);
1189 printf(" Loading ");
1190 print_module_name(L4_CONST_CHAR_PTR(mb_mod[sigma0_module].cmdline),
1194 boot_info.sigma0_start = load_elf_module(mb_mod + sigma0_module);
1195 boot_info.sigma0_stack = (l4_addr_t)sigma0_init_stack
1196 + sizeof(sigma0_init_stack);
1199 /* setup roottask */
1203 printf(" Loading ");
1204 print_module_name(L4_CONST_CHAR_PTR(mb_mod[roottask_module].cmdline),
1208 boot_info.roottask_start = load_elf_module(mb_mod + roottask_module);
1209 boot_info.roottask_stack = (l4_addr_t)roottask_init_stack
1210 + sizeof(roottask_init_stack);
1213 /* setup kernel PART TWO (special kernel initialization) */
1216 #if defined(ARCH_x86) || defined(ARCH_amd64) || defined(ARCH_ppc32)
1217 /* setup multi boot info structure for kernel */
1218 l4util_mb_info_t kernel_mbi;
1219 kernel_mbi = *mb_info;
1220 kernel_mbi.flags = L4UTIL_MB_MEMORY;
1221 if (mb_mod[kernel_module].cmdline)
1223 kernel_mbi.cmdline = mb_mod[kernel_module].cmdline;
1224 kernel_mbi.flags |= L4UTIL_MB_CMDLINE;
1231 if (char *c = check_arg(mbi, "-presetmem="))
1233 unsigned fill_value = strtoul(c + 11, NULL, 0);
1234 fill_mem(fill_value);
1237 /* setup the L4 kernel info page before booting the L4 microkernel:
1238 * patch ourselves into the booter task addresses */
1239 unsigned long api_version = get_api_version(l4i);
1240 unsigned major = api_version >> 24;
1241 printf(" API Version: (%x) %s\n", major, (major & 0x80)?"experimental":"");
1244 case 0x02: // Version 2 API
1245 case 0x03: // Version X.0 and X.1
1246 case 0x87: // Fiasco
1247 init_kip_v2(l4i, &boot_info, mb_info, &ram, ®ions);
1248 //init_kip_kuart_info(l4i, &kip_kernel_uart_info);
1252 init_kip_v4(l4i, &boot_info, mb_info, &ram, ®ions);
1255 panic("cannot boot a kernel with unknown api version %lx\n", api_version);
1259 printf(" Starting kernel ");
1260 print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
1262 printf(" at "l4_addr_fmt"\n", boot_info.kernel_start);
1264 #if defined(ARCH_x86)
1266 ("pushl $exit ; jmp *%3"
1268 : "a" (L4UTIL_MB_VALID),
1271 "r" (boot_info.kernel_start));
1273 #elif defined(ARCH_amd64)
1276 ("push $exit; jmp *%2"
1278 : "S" (L4UTIL_MB_VALID), "D" (&kernel_mbi), "r" (boot_info.kernel_start));
1280 #elif defined(ARCH_arm)
1281 typedef void (*startup_func)(void);
1282 startup_func f = (startup_func)boot_info.kernel_start;
1285 #elif defined(ARCH_ppc32)
1287 init_kip_v2_arch((l4_kernel_info_t*)l4i);
1288 printf("CPU at %lu Khz/Bus at %lu Hz\n",
1289 ((l4_kernel_info_t*)l4i)->frequency_cpu,
1290 ((l4_kernel_info_t*)l4i)->frequency_bus);
1291 typedef void (*startup_func)(l4util_mb_info_t *, unsigned long);
1292 startup_func f = (startup_func)boot_info.kernel_start;
1293 of_if.boot_finish();
1294 f(&kernel_mbi, of_if.get_prom());
1297 #error "How to enter the kernel?"
1305 l4_exec_read_exec(void * handle,
1306 l4_addr_t file_ofs, l4_size_t file_size,
1307 l4_addr_t mem_addr, l4_addr_t /*v_addr*/,
1309 exec_sectype_t section_type)
1311 exec_task_t *exec_task = (exec_task_t*)handle;
1315 if (! (section_type & EXEC_SECTYPE_ALLOC))
1318 if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
1321 if (mem_addr < exec_task->begin)
1322 exec_task->begin = mem_addr;
1323 if (mem_addr + mem_size > exec_task->end)
1324 exec_task->end = mem_addr + mem_size;
1327 printf(" [%p-%p]\n", (void *) mem_addr, (void *) (mem_addr + mem_size));
1330 if (!ram.contains(Region::n(mem_addr, mem_addr + mem_size)))
1332 printf("To be loaded binary region is out of memory region.\n");
1333 printf(" Binary region: %lx - %lx\n", mem_addr, mem_addr + mem_size);
1335 panic("Binary outside memory");
1338 memcpy((void *) mem_addr,
1339 (char*)(exec_task->mod_start) + file_ofs, file_size);
1340 if (file_size < mem_size)
1341 memset((void *) (mem_addr + file_size), 0, mem_size - file_size);
1344 Region *f = regions.find(mem_addr);
1347 printf("could not find %lx\n", mem_addr);
1349 panic("Oops: region for module not found\n");
1352 f->name(exec_task->mod->cmdline
1353 ? L4_CONST_CHAR_PTR(exec_task->mod->cmdline)
1359 l4_exec_add_region(void * handle,
1360 l4_addr_t /*file_ofs*/, l4_size_t /*file_size*/,
1361 l4_addr_t mem_addr, l4_addr_t v_addr,
1363 exec_sectype_t section_type)
1365 exec_task_t *exec_task = (exec_task_t*)handle;
1370 if (! (section_type & EXEC_SECTYPE_ALLOC))
1373 if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
1376 regions.add(Region::n(mem_addr, mem_addr + mem_size,
1377 exec_task->mod->cmdline
1378 ? L4_CONST_CHAR_PTR(exec_task->mod->cmdline)
1379 : ".[Unknown]", Region::Type(exec_task->type),
1380 mem_addr == v_addr ? 1 : 0));