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.");
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)
930 if ((s = check_arg(mbi, "-comport")))
931 comport = strtoul(s + 9, 0, 0);
933 if (check_arg(mbi, "-serial"))
937 extern unsigned long search_pci_serial_devs(bool scan_only);
940 && (port = search_pci_serial_devs(false)))
947 com_cons_init(comport);
957 // check that our is_precious_ram function can work ok
958 #error For ARM, IMAGE_MODE must always be enabled
961 /* Occupied RAM at the point we are scannig it */
963 is_precious_ram(unsigned long addr)
965 extern int _start, _end;
966 unsigned i, c = _module_info_end - _module_info_start;
968 if ((unsigned long)&_start <= addr && addr <= (unsigned long)&_end)
971 if ((unsigned long)_module_info_start <= addr
972 && addr <= (unsigned long)_module_info_end)
975 if ((unsigned long)_modules_mbi_start <= addr
976 && addr <= (unsigned long)_modules_mbi_end)
979 for (i = 0; i < c; ++i)
980 if (_module_info_start[i].start <= addr
981 && _module_info_start[i].start + _module_info_start[i].size_uncompressed <= addr)
988 scan_ram_size(unsigned long base_addr, unsigned long max_scan_size_mb)
990 // scan the RAM to find out the RAM size, note that at this point we have
991 // two regions in RAM that we cannot touch, &_start - &_end and the
994 unsigned long offset;
995 const unsigned long increment = 1 << 20; // must be multiple of (1 << 20)
997 printf(" Scanning up to %ld MB RAM\n", max_scan_size_mb);
999 // initialize memory points
1000 for (offset = increment; offset < (max_scan_size_mb << 20); offset += offset)
1001 if (!is_precious_ram(base_addr + offset))
1002 *(unsigned long *)(base_addr + offset) = 0;
1004 // write something at offset 0, does it appear elsewhere?
1005 *(unsigned long *)base_addr = 0x12345678;
1006 asm volatile("" : : : "memory");
1007 for (offset = increment; offset < (max_scan_size_mb << 20); offset += offset)
1008 if (*(unsigned long *)(base_addr + offset) == 0x12345678)
1009 return offset >> 20;
1011 return max_scan_size_mb;
1016 * \brief Startup, started from crt0.S
1020 startup(l4util_mb_info_t *mbi, l4_umword_t flag,
1021 void *realmode_si, ptab64_mem_info_t *ptab64_info);
1023 startup(l4util_mb_info_t *mbi, l4_umword_t flag,
1024 void *realmode_si, ptab64_mem_info_t *ptab64_info)
1027 boot_info_t boot_info;
1028 l4util_mb_mod_t *mb_mod;
1030 /* fire up serial port if specificed on the command line */
1031 init_pc_serial(mbi);
1033 if (!Platform_base::platform)
1035 // will we ever see this?
1036 printf("No platform found, hangup.");
1041 puts("\nL4 Bootstrapper");
1042 puts(" Build: #" BUILD_NR " " BUILD_DATE);
1044 regions.init(__regs, sizeof(__regs)/sizeof(__regs[0]), "regions");
1045 ram.init(__ram, sizeof(__ram)/sizeof(__ram[0]), "RAM",
1046 get_memory_limit(mbi));
1049 // add the page-table on which we're running in 64bit mode
1050 regions.add(Region::n(ptab64_info->addr, ptab64_info->addr + ptab64_info->size,
1051 ".bootstrap-ptab64", Region::Boot));
1056 #if defined(ARCH_x86) || defined(ARCH_amd64)
1058 #ifdef REALMODE_LOADING
1059 /* create synthetic multi boot info */
1060 mbi = init_loader_mbi(realmode_si);
1063 assert(flag == L4UTIL_MB_VALID); /* we need to be multiboot-booted */
1066 #elif defined(ARCH_arm)
1067 l4util_mb_info_t my_mbi;
1068 memset(&my_mbi, 0, sizeof(my_mbi));
1074 #elif defined(ARCH_ppc32)
1078 l4util_mb_info_t my_mbi;
1079 L4_drivers::Of_if of_if;
1081 printf(" Detecting ram size ...\n");
1082 unsigned long ram_size = of_if.detect_ramsize();
1083 printf(" Total memory size is %luMB\n", ram_size / (1024 * 1024));
1085 /* setup mbi and detect OF devices */
1086 memset(&my_mbi, 0, sizeof(my_mbi));
1088 unsigned long drives_addr, drives_length;
1090 if (of_if.detect_devices(&drives_addr, &drives_length))
1092 mbi->flags |= L4UTIL_MB_DRIVE_INFO;
1093 mbi->drives_addr = drives_addr;
1094 mbi->drives_length = drives_length;
1096 ram.add(Region::n(0x0, ram_size, ".ram", Region::Ram));
1099 #error Unknown arch!
1102 setup_memory_map(mbi);
1104 /* basically add the bootstrap binary to the allocated regions */
1107 /* check command line */
1108 if (check_arg(mbi, "-no-sigma0"))
1111 if (check_arg(mbi, "-no-roottask"))
1114 if (const char *s = check_arg(mbi, "-modaddr"))
1115 _mod_addr = strtoul(s + 9, 0, 0);
1121 /* move vbe and ctrl structures to a known location, it might be in the
1122 * way when moving modules around */
1123 #if defined(ARCH_x86) || defined(ARCH_amd64)
1124 if (mbi->flags & L4UTIL_MB_VIDEO_INFO)
1126 if (mbi->vbe_mode_info)
1128 memcpy(&__mb_vbe, L4_VOID_PTR(mbi->vbe_mode_info),
1129 sizeof(l4util_mb_vbe_mode_t));
1130 mbi->vbe_mode_info = (l4_addr_t)&__mb_vbe;
1133 if (mbi->vbe_ctrl_info)
1135 memcpy(&__mb_ctrl, L4_VOID_PTR(mbi->vbe_ctrl_info),
1136 sizeof(l4util_mb_vbe_ctrl_t));
1137 mbi->vbe_ctrl_info = (l4_addr_t)&__mb_ctrl;
1143 move_modules(mbi, _mod_addr);
1145 /* We need at least two boot modules */
1146 assert(mbi->flags & L4UTIL_MB_MODS);
1147 /* We have at least the L4 kernel and the first user task */
1148 assert(mbi->mods_count >= 2);
1149 assert(mbi->mods_count <= MODS_MAX);
1151 /* we're just a GRUB-booted kernel! */
1152 add_boot_modules_region(mbi);
1154 if (const char *s = get_cmdline(mbi))
1156 /* patch modules with content given at command line */
1157 while ((s = check_arg_str((char *)s, "-patch=")))
1158 patch_module(&s, mbi);
1162 add_elf_regions(mbi, kernel_module, Region::Kernel);
1165 add_elf_regions(mbi, sigma0_module, Region::Sigma0);
1168 add_elf_regions(mbi, roottask_module, Region::Root);
1171 /* copy Multiboot data structures, we still need to a safe place
1172 * before playing with memory we don't own and starting L4 */
1173 mb_info = relocate_mbi(mbi, &boot_info.mbi_low, &boot_info.mbi_high);
1175 panic("could not copy multiboot info to memory below 4MB");
1177 mb_mod = (l4util_mb_mod_t*)mb_info->mods_addr;
1179 /* --- Shouldn't touch original Multiboot parameters after here. -- */
1181 /* setup kernel PART ONE */
1182 printf(" Loading ");
1183 print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
1187 boot_info.kernel_start = load_elf_module(mb_mod + kernel_module);
1192 printf(" Loading ");
1193 print_module_name(L4_CONST_CHAR_PTR(mb_mod[sigma0_module].cmdline),
1197 boot_info.sigma0_start = load_elf_module(mb_mod + sigma0_module);
1198 boot_info.sigma0_stack = (l4_addr_t)sigma0_init_stack
1199 + sizeof(sigma0_init_stack);
1202 /* setup roottask */
1206 printf(" Loading ");
1207 print_module_name(L4_CONST_CHAR_PTR(mb_mod[roottask_module].cmdline),
1211 boot_info.roottask_start = load_elf_module(mb_mod + roottask_module);
1212 boot_info.roottask_stack = (l4_addr_t)roottask_init_stack
1213 + sizeof(roottask_init_stack);
1216 /* setup kernel PART TWO (special kernel initialization) */
1219 #if defined(ARCH_x86) || defined(ARCH_amd64) || defined(ARCH_ppc32)
1220 /* setup multi boot info structure for kernel */
1221 l4util_mb_info_t kernel_mbi;
1222 kernel_mbi = *mb_info;
1223 kernel_mbi.flags = L4UTIL_MB_MEMORY;
1224 if (mb_mod[kernel_module].cmdline)
1226 kernel_mbi.cmdline = mb_mod[kernel_module].cmdline;
1227 kernel_mbi.flags |= L4UTIL_MB_CMDLINE;
1234 if (char *c = check_arg(mbi, "-presetmem="))
1236 unsigned fill_value = strtoul(c + 11, NULL, 0);
1237 fill_mem(fill_value);
1240 /* setup the L4 kernel info page before booting the L4 microkernel:
1241 * patch ourselves into the booter task addresses */
1242 unsigned long api_version = get_api_version(l4i);
1243 unsigned major = api_version >> 24;
1244 printf(" API Version: (%x) %s\n", major, (major & 0x80)?"experimental":"");
1247 case 0x02: // Version 2 API
1248 case 0x03: // Version X.0 and X.1
1249 case 0x87: // Fiasco
1250 init_kip_v2(l4i, &boot_info, mb_info, &ram, ®ions);
1251 //init_kip_kuart_info(l4i, &kip_kernel_uart_info);
1255 init_kip_v4(l4i, &boot_info, mb_info, &ram, ®ions);
1258 panic("cannot boot a kernel with unknown api version %lx\n", api_version);
1262 printf(" Starting kernel ");
1263 print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
1265 printf(" at "l4_addr_fmt"\n", boot_info.kernel_start);
1267 #if defined(ARCH_x86)
1269 ("pushl $exit ; jmp *%3"
1271 : "a" (L4UTIL_MB_VALID),
1274 "r" (boot_info.kernel_start));
1276 #elif defined(ARCH_amd64)
1279 ("push $exit; jmp *%2"
1281 : "S" (L4UTIL_MB_VALID), "D" (&kernel_mbi), "r" (boot_info.kernel_start));
1283 #elif defined(ARCH_arm)
1284 typedef void (*startup_func)(void);
1285 startup_func f = (startup_func)boot_info.kernel_start;
1288 #elif defined(ARCH_ppc32)
1290 init_kip_v2_arch((l4_kernel_info_t*)l4i);
1291 printf("CPU at %lu Khz/Bus at %lu Hz\n",
1292 ((l4_kernel_info_t*)l4i)->frequency_cpu,
1293 ((l4_kernel_info_t*)l4i)->frequency_bus);
1294 typedef void (*startup_func)(l4util_mb_info_t *, unsigned long);
1295 startup_func f = (startup_func)boot_info.kernel_start;
1296 of_if.boot_finish();
1297 f(&kernel_mbi, of_if.get_prom());
1300 #error "How to enter the kernel?"
1308 l4_exec_read_exec(void * handle,
1309 l4_addr_t file_ofs, l4_size_t file_size,
1310 l4_addr_t mem_addr, l4_addr_t /*v_addr*/,
1312 exec_sectype_t section_type)
1314 exec_task_t *exec_task = (exec_task_t*)handle;
1318 if (! (section_type & EXEC_SECTYPE_ALLOC))
1321 if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
1324 if (mem_addr < exec_task->begin)
1325 exec_task->begin = mem_addr;
1326 if (mem_addr + mem_size > exec_task->end)
1327 exec_task->end = mem_addr + mem_size;
1330 printf(" [%p-%p]\n", (void *) mem_addr, (void *) (mem_addr + mem_size));
1333 if (!ram.contains(Region::n(mem_addr, mem_addr + mem_size)))
1335 printf("To be loaded binary region is out of memory region.\n");
1336 printf(" Binary region: %lx - %lx\n", mem_addr, mem_addr + mem_size);
1338 panic("Binary outside memory");
1341 memcpy((void *) mem_addr,
1342 (char*)(exec_task->mod_start) + file_ofs, file_size);
1343 if (file_size < mem_size)
1344 memset((void *) (mem_addr + file_size), 0, mem_size - file_size);
1347 Region *f = regions.find(mem_addr);
1350 printf("could not find %lx\n", mem_addr);
1352 panic("Oops: region for module not found\n");
1355 f->name(exec_task->mod->cmdline
1356 ? L4_CONST_CHAR_PTR(exec_task->mod->cmdline)
1362 l4_exec_add_region(void * handle,
1363 l4_addr_t /*file_ofs*/, l4_size_t /*file_size*/,
1364 l4_addr_t mem_addr, l4_addr_t v_addr,
1366 exec_sectype_t section_type)
1368 exec_task_t *exec_task = (exec_task_t*)handle;
1373 if (! (section_type & EXEC_SECTYPE_ALLOC))
1376 if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
1379 regions.add(Region::n(mem_addr, mem_addr + mem_size,
1380 exec_task->mod->cmdline
1381 ? L4_CONST_CHAR_PTR(exec_task->mod->cmdline)
1382 : ".[Unknown]", Region::Type(exec_task->type),
1383 mem_addr == v_addr ? 1 : 0));