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>
36 #include <l4/util/kip.h>
52 /* management of allocated memory regions */
53 static Region_list regions;
54 static Region __regs[300];
56 /* management of conventional memory regions */
57 static Region_list ram;
58 static Region __ram[16];
60 static Memory _mem_manager = { &ram, ®ions };
61 Memory *mem_manager = &_mem_manager;
63 L4_kernel_options::Uart kuart;
64 unsigned int kuart_flags;
67 * IMAGE_MODE means that all boot modules are linked together to one
71 static l4_addr_t _mod_addr = RAM_BASE + MODADDR;
73 static l4_addr_t _mod_addr;
76 static const char *builtin_cmdline = CMDLINE;
85 /// Info passed through our ELF interpreter code
88 Boot_modules::Module mod;
92 static exec_handler_func_t l4_exec_read_exec;
93 static exec_handler_func_t l4_exec_add_region;
98 dump_mbi(l4util_mb_info_t *mbi)
100 printf("%p-%p\n", (void*)(mbi->mem_lower << 10), (void*)(mbi->mem_upper << 10));
101 printf("MBI: [%p-%p]\n", mbi, mbi + 1);
102 printf("MODINFO: [%p-%p]\n", (char*)mbi->mods_addr,
103 (l4util_mb_mod_t*)(mbi->mods_addr) + mbi->mods_count);
105 printf("VBEINFO: [%p-%p]\n", (char*)mbi->vbe_ctrl_info,
106 (l4util_mb_vbe_ctrl_t*)(mbi->vbe_ctrl_info) + 1);
107 printf("VBEMODE: [%p-%p]\n", (char*)mbi->vbe_mode_info,
108 (l4util_mb_vbe_mode_t*)(mbi->vbe_mode_info) + 1);
110 l4util_mb_mod_t *m = (l4util_mb_mod_t*)(mbi->mods_addr);
111 l4util_mb_mod_t *me = m + mbi->mods_count;
114 printf(" MOD: [%p-%p]\n", (void*)m->mod_start, (void*)m->mod_end);
115 printf(" CMD: [%p-%p]\n", (char*)m->cmdline,
116 (char*)m->cmdline + strlen((char*)m->cmdline));
123 * Scan the memory regions with type == Region::Kernel for a
124 * kernel interface page (KIP).
126 * After loading the kernel we scan for the magic number at page boundaries.
131 unsigned char *p, *end;
134 printf(" find kernel info page...\n");
135 for (Region const *m = regions.begin(); m != regions.end(); ++m)
137 if (m->type() != Region::Kernel)
140 if (sizeof(unsigned long) < 8
141 && m->end() >= (1ULL << 32))
142 end = (unsigned char *)(~0UL - 0x1000);
144 end = (unsigned char *) (unsigned long)m->end();
146 for (p = (unsigned char *) (unsigned long)(m->begin() & 0xfffff000);
150 l4_umword_t magic = L4_KERNEL_INFO_MAGIC;
151 if (memcmp(p, &magic, 4) == 0)
154 printf(" found kernel info page at %p\n", p);
164 panic("could not find kernel info page, maybe your kernel is too old");
170 L4_kernel_options::Options *find_kopts(void *kip)
172 unsigned long a = (unsigned long)kip + sizeof(l4_kernel_info_t);
174 // kernel-option directly follow the KIP page
175 a = (a + 4096 - 1) & ~0xfff;
177 L4_kernel_options::Options *ko = (L4_kernel_options::Options *)a;
179 if (ko->magic != L4_kernel_options::Magic)
180 panic("Could not find kernel options page");
182 unsigned long need_version = 1;
184 if (ko->version != need_version)
185 panic("Cannot boot kernel with incompatible options version: %lu, need %lu",
186 (unsigned long)ko->version, need_version);
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 const *cmdline, const char *arg)
204 char const *s = cmdline;
205 while ((s = strstr(s, arg)))
215 check_arg_str(char *cmdline, const char *arg)
217 return const_cast<char *>(check_arg_str(const_cast<char const *>(cmdline), arg));
221 * Scan the command line for the given argument.
223 * The cmdline string may either be including the calling program
224 * (.../bootstrap -arg1 -arg2) or without (-arg1 -arg2) in the realmode
225 * case, there, we do not have a leading space
227 * return pointer after argument, NULL if not found
230 check_arg(char const *cmdline, const char *arg)
233 return check_arg_str(cmdline, arg);
240 * Calculate the maximum memory limit in MB.
242 * The limit is the highest physical address where conventional RAM is allowed.
243 * The memory is limited to 3 GB IA32 and unlimited on other systems.
247 get_memory_max_address()
250 /* Limit memory, we cannot really handle more right now. In fact, the
251 * problem is roottask. It maps as many superpages/pages as it gets.
252 * After that, the remaining pages are mapped using l4sigma0_map_anypage()
253 * with a receive window of L4_WHOLE_ADDRESS_SPACE. In response Sigma0
254 * could deliver pages beyond the 3GB user space limit. */
255 return 3024ULL << 20;
262 * If available the '-maxmem=xx' command line option is used.
266 get_memory_max_size(char const *cmdline)
268 /* maxmem= parameter? */
269 if (char const *c = check_arg(cmdline, "-maxmem="))
270 return strtoul(c + 8, NULL, 10) << 20;
276 parse_memvalue(const char *s, unsigned long *val, char **ep)
279 *val = strtoul(s, ep, 0);
285 case 'G': *val <<= 10;
286 case 'M': *val <<= 10;
287 case 'k': case 'K': *val <<= 10; (*ep)++;
294 * Parse a memory layout string: size@offset
295 * E.g.: 256M@0x40000000, or 128M@128M
298 parse_mem_layout(const char *s, unsigned long *sz, unsigned long *offset)
302 if (parse_memvalue(s, sz, &ep))
311 if (parse_memvalue(ep + 1, offset, &ep))
318 dump_ram_map(bool show_total = false)
321 unsigned long long sum = 0;
322 for (Region *i = ram.begin(); i < ram.end(); ++i)
324 printf(" RAM: %016llx - %016llx: %lldkB\n",
325 i->begin(), i->end(), i->size() >> 10);
329 printf(" Total RAM: %lldMB\n", sum >> 20);
333 setup_memory_map(char const *cmdline)
335 bool parsed_mem_option = false;
336 const char *s = cmdline;
340 while ((s = check_arg_str((char *)s, "-mem=")))
343 unsigned long sz, offset = 0;
344 if (!parse_mem_layout(s, &sz, &offset))
346 parsed_mem_option = true;
347 ram.add(Region::n(offset, offset + sz, ".ram", Region::Ram));
352 if (!parsed_mem_option)
353 // No -mem option given, use the one given by the platform
354 Platform_base::platform->setup_memory_map();
359 static void do_the_memset(unsigned long s, unsigned val, unsigned long len)
361 printf("Presetting memory %16lx - %16lx to '%x'\n",
362 s, s + len - 1, val);
363 memset((void *)s, val, len);
366 static void fill_mem(unsigned fill_value)
369 for (Region const *r = ram.begin(); r != ram.end(); ++r)
371 unsigned long long b = r->begin();
372 // The regions list must be sorted!
373 for (Region const *reg = regions.begin(); reg != regions.end(); ++reg)
375 // completely before ram?
376 if (reg->end() < r->begin())
378 // completely after ram?
379 if (reg->begin() > r->end())
382 if (reg->begin() <= r->begin())
384 else if (b > reg->begin()) // some overlapping
386 if (reg->end() + 1 > b)
391 do_the_memset(b, fill_value, reg->begin() - 1 - b + 1);
397 do_the_memset(b, fill_value, r->end() - b + 1);
403 * Add the bootstrap binary itself to the allocated memory regions.
408 extern int _start; /* begin of image -- defined in crt0.S */
409 extern int _end; /* end of image -- defined by bootstrap.ld */
411 auto *p = Platform_base::platform;
413 regions.add(Region::n(p->to_phys((unsigned long)&_start),
414 p->to_phys((unsigned long)&_end),
415 ".bootstrap", Region::Boot));
419 * Add all sections of the given ELF binary to the allocated regions.
420 * Actually does not load the ELF binary (see load_elf_module()).
423 add_elf_regions(Boot_modules::Module const &m, Region::Type type)
428 const char *error_msg;
433 printf(" Scanning %s\n", m.cmdline);
435 r = exec_load_elf(l4_exec_add_region, &info,
442 printf("\n%p: ", (void*)m.start);
443 for (int i = 0; i < 4; ++i)
444 printf("%08x ", *((unsigned *)m.start + i));
446 for (int i = 0; i < 16; ++i)
448 unsigned char c = *(unsigned char *)((char *)m.start + i);
449 printf("%c", c < 32 ? '.' : c);
452 panic("\n\nThis is an invalid binary, fix it (%s).", error_msg);
458 * Load the given ELF binary into memory and free the source
462 load_elf_module(Boot_modules::Module const &mod)
466 const char *error_msg;
468 r = exec_load_elf(l4_exec_read_exec, const_cast<Boot_modules::Module *>(&mod),
472 /* clear the image for debugging and security reasons */
473 memset((void*)mod.start, 0, mod.end - mod.start);
477 printf(" => can't load module (%s)\n", error_msg);
480 Region m = Region::n(mod.start, l4_round_page(mod.end));
483 Region m = Region::n(mod.start, mod.end);
488 panic ("could not free region for load ELF module");
497 * Simple linear memory allocator.
499 * Allocate size bytes starting from *ptr and set *ptr to *ptr + size.
502 lin_alloc(l4_size_t size, char **ptr)
505 *ptr += (size + 3) & ~3;;
511 static inline l4_umword_t
512 running_in_hyp_mode()
515 asm volatile("mrs %0, cpsr" : "=r"(cpsr));
516 return (cpsr & 0x1f) == 0x1a;
520 setup_and_check_kernel_config(Platform_base *plat, l4_kernel_info_t *kip)
522 l4_kip_platform_info_arch *ia = &kip->platform_info.arch;
524 asm("mrc p15, 0, %0, c0, c0, 0" : "=r" (ia->cpuinfo.MIDR));
525 asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (ia->cpuinfo.CTR));
526 asm("mrc p15, 0, %0, c0, c0, 2" : "=r" (ia->cpuinfo.TCMTR));
527 asm("mrc p15, 0, %0, c0, c0, 3" : "=r" (ia->cpuinfo.TLBTR));
528 asm("mrc p15, 0, %0, c0, c0, 5" : "=r" (ia->cpuinfo.MPIDR));
529 asm("mrc p15, 0, %0, c0, c0, 6" : "=r" (ia->cpuinfo.REVIDR));
531 if (((ia->cpuinfo.MIDR >> 16) & 0xf) >= 7)
533 asm("mrc p15, 0, %0, c0, c1, 0" : "=r" (ia->cpuinfo.ID_PFR[0]));
534 asm("mrc p15, 0, %0, c0, c1, 1" : "=r" (ia->cpuinfo.ID_PFR[1]));
535 asm("mrc p15, 0, %0, c0, c1, 2" : "=r" (ia->cpuinfo.ID_DFR0));
536 asm("mrc p15, 0, %0, c0, c1, 3" : "=r" (ia->cpuinfo.ID_AFR0));
537 asm("mrc p15, 0, %0, c0, c1, 4" : "=r" (ia->cpuinfo.ID_MMFR[0]));
538 asm("mrc p15, 0, %0, c0, c1, 5" : "=r" (ia->cpuinfo.ID_MMFR[1]));
539 asm("mrc p15, 0, %0, c0, c1, 6" : "=r" (ia->cpuinfo.ID_MMFR[2]));
540 asm("mrc p15, 0, %0, c0, c1, 7" : "=r" (ia->cpuinfo.ID_MMFR[3]));
541 asm("mrc p15, 0, %0, c0, c2, 0" : "=r" (ia->cpuinfo.ID_ISAR[0]));
542 asm("mrc p15, 0, %0, c0, c2, 1" : "=r" (ia->cpuinfo.ID_ISAR[1]));
543 asm("mrc p15, 0, %0, c0, c2, 2" : "=r" (ia->cpuinfo.ID_ISAR[2]));
544 asm("mrc p15, 0, %0, c0, c2, 3" : "=r" (ia->cpuinfo.ID_ISAR[3]));
545 asm("mrc p15, 0, %0, c0, c2, 4" : "=r" (ia->cpuinfo.ID_ISAR[4]));
546 asm("mrc p15, 0, %0, c0, c2, 5" : "=r" (ia->cpuinfo.ID_ISAR[5]));
549 const char *s = l4_kip_version_string(kip);
553 bool is_hyp_kernel = false;
554 l4util_kip_for_each_feature(s)
555 if (!strcmp(s, "arm:hyp"))
557 if (!running_in_hyp_mode())
559 printf(" Detected HYP kernel, switching to HYP mode\n");
560 plat->arm_switch_to_hyp();
561 if (!running_in_hyp_mode())
562 panic("\nFailed to switch to HYP as required by Fiasco.OC.\n");
564 is_hyp_kernel = true;
568 if (!is_hyp_kernel && running_in_hyp_mode())
570 printf(" Non-HYP kernel detected but running in HYP mode, switching back.\n");
571 asm volatile("mcr p15, 0, sp, c13, c0, 2 \n"
574 ".inst 0xe12ef300 \n" // msr elr_hyp, r0
575 ".inst 0xe160006e \n" // eret
576 "1: mrc p15, 0, sp, c13, c0, 2 \n"
577 : : "r" (0x1d3) : "r0", "memory");
583 load_elf_module(Boot_modules::Module const &mod, char const *n)
585 printf(" Loading "); print_module_name(mod.cmdline, n); putchar('\n');
586 return load_elf_module(mod);
590 * \brief Startup, started from crt0.S
594 startup(char const *cmdline)
596 if (!cmdline || !*cmdline)
597 cmdline = builtin_cmdline;
599 if (check_arg(cmdline, "-noserial"))
600 set_stdio_uart(NULL);
602 if (!Platform_base::platform)
604 // will we ever see this?
605 printf("No platform found, hangup.");
610 Platform_base *plat = Platform_base::platform;
612 if (check_arg(cmdline, "-wait"))
614 puts("\nL4 Bootstrapper is waiting for key input to continue...");
616 puts(" ...no key input available.");
618 puts(" ...going on.");
621 puts("\nL4 Bootstrapper");
622 puts(" Build: #" BUILD_NR " " BUILD_DATE
633 printf(" cmdline params: '%s'\n", cmdline);
634 regions.init(__regs, "regions");
635 ram.init(__ram, "RAM", get_memory_max_size(cmdline), get_memory_max_address());
637 setup_memory_map(cmdline);
639 /* basically add the bootstrap binary to the allocated regions */
641 plat->modules()->reserve();
643 /* modules to load by bootstrap */
644 bool sigma0 = true; /* we need sigma0 */
645 bool roottask = true; /* we need a roottask */
647 /* check command line */
648 if (check_arg(cmdline, "-no-sigma0"))
651 if (check_arg(cmdline, "-no-roottask"))
654 if (const char *s = check_arg(cmdline, "-modaddr"))
655 _mod_addr = RAM_BASE + strtoul(s + 9, 0, 0);
657 _mod_addr = l4_round_page(_mod_addr);
660 Boot_modules *mods = plat->modules();
662 add_elf_regions(mods->module(kernel_module), Region::Kernel);
665 add_elf_regions(mods->module(sigma0_module), Region::Sigma0);
668 add_elf_regions(mods->module(roottask_module), Region::Root);
670 l4util_mb_info_t *mbi = plat->modules()->construct_mbi(_mod_addr);
672 /* We need at least two boot modules */
673 assert(mbi->flags & L4UTIL_MB_MODS);
674 /* We have at least the L4 kernel and the first user task */
675 assert(mbi->mods_count >= 2);
676 assert(mbi->mods_count <= MODS_MAX);
678 if (const char *s = cmdline)
680 /* patch modules with content given at command line */
681 while ((s = check_arg_str((char *)s, "-patch=")))
682 patch_module(&s, mbi);
685 boot_info_t boot_info;
686 l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t *)(unsigned long)mbi->mods_addr;
689 /* setup kernel PART ONE */
690 boot_info.kernel_start = load_elf_module(mods->module(kernel_module), "[KERNEL]");
694 boot_info.sigma0_start = load_elf_module(mods->module(sigma0_module), "[SIGMA0]");
698 boot_info.roottask_start = load_elf_module(mods->module(roottask_module),
701 /* setup kernel PART TWO (special kernel initialization) */
702 void *l4i = find_kip();
707 if (char const *c = check_arg(cmdline, "-presetmem="))
709 unsigned fill_value = strtoul(c + 11, NULL, 0);
710 fill_mem(fill_value);
713 L4_kernel_options::Options *lko = find_kopts(l4i);
714 kcmdline_parse(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline), lko);
716 lko->flags |= kuart_flags;
719 /* setup the L4 kernel info page before booting the L4 microkernel:
720 * patch ourselves into the booter task addresses */
721 unsigned long api_version = get_api_version(l4i);
722 unsigned major = api_version >> 24;
723 printf(" API Version: (%x) %s\n", major, (major & 0x80)?"experimental":"");
727 init_kip_f(l4i, &boot_info, mbi, &ram, ®ions);
730 panic("cannot boot V.2 API kernels: %lx\n", api_version);
733 panic("cannot boot X.0 and X.1 API kernels: %lx\n", api_version);
736 panic("cannot boot Fiasco V.4 API kernels: %lx\n", api_version);
739 panic("cannot boot V.4 API kernels: %lx\n", api_version);
741 panic("cannot boot a kernel with unknown api version %lx\n", api_version);
745 printf(" Starting kernel ");
746 print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
748 printf(" at " l4_addr_fmt "\n", boot_info.kernel_start);
750 #if defined(ARCH_arm)
752 setup_and_check_kernel_config(plat, (l4_kernel_info_t *)l4i);
754 #if defined(ARCH_ppc32)
755 init_kip_v2_arch((l4_kernel_info_t*)l4i);
757 printf("CPU at %lu Khz/Bus at %lu Hz\n",
758 ((l4_kernel_info_t*)l4i)->frequency_cpu,
759 ((l4_kernel_info_t*)l4i)->frequency_bus);
762 plat->boot_kernel(boot_info.kernel_start);
767 l4_exec_read_exec(void * handle,
768 l4_addr_t file_ofs, l4_size_t file_size,
769 l4_addr_t mem_addr, l4_addr_t /*v_addr*/,
771 exec_sectype_t section_type)
773 Boot_modules::Module const *m = (Boot_modules::Module const *)handle;
777 if (! (section_type & EXEC_SECTYPE_ALLOC))
780 if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
784 printf(" [%p-%p]\n", (void *) mem_addr, (void *) (mem_addr + mem_size));
786 if (!ram.contains(Region::n(mem_addr, mem_addr + mem_size)))
788 printf("To be loaded binary region is out of memory region.\n");
789 printf(" Binary region: %lx - %lx\n", mem_addr, mem_addr + mem_size);
791 panic("Binary outside memory");
794 memcpy((void *) mem_addr, (char const *)m->start + file_ofs, file_size);
795 if (file_size < mem_size)
796 memset((void *) (mem_addr + file_size), 0, mem_size - file_size);
799 Region *f = regions.find(mem_addr);
802 printf("could not find %lx\n", mem_addr);
804 panic("Oops: region for module not found\n");
807 f->name(m->cmdline ? m->cmdline : ".[Unknown]");
813 l4_exec_add_region(void *handle,
814 l4_addr_t /*file_ofs*/, l4_size_t /*file_size*/,
815 l4_addr_t mem_addr, l4_addr_t v_addr,
817 exec_sectype_t section_type)
819 Elf_info const *info = (Elf_info const *)handle;
824 if (! (section_type & EXEC_SECTYPE_ALLOC))
827 if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
830 Region n = Region::n(mem_addr, mem_addr + mem_size,
831 info->mod.cmdline ? info->mod.cmdline : ".[Unknown]",
832 info->type, mem_addr == v_addr ? 1 : 0);
834 for (Region *r = regions.begin(); r != regions.end(); ++r)
835 if (r->overlaps(n) && r->name() != Boot_modules::Mod_reg)
837 printf(" New region for list %s:\t", n.name());
839 printf(" overlaps with: \t");
842 panic("region overlap");
845 regions.add(Region::n(mem_addr, mem_addr + mem_size,
846 info->mod.cmdline ? info->mod.cmdline : ".[Unknown]",
847 info->type, mem_addr == v_addr ? 1 : 0), true);