]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/bootstrap_custom/server/src/startup.cc
d29ac932e7ad81196335eb31652bfec837cb5841
[l4.git] / l4 / pkg / bootstrap_custom / server / src / startup.cc
1 /**
2  * \file        bootstrap/server/src/startup.cc
3  * \brief       Main functions
4  *
5  * \date        09/2004
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>
11  */
12
13 /*
14  * (c) 2005-2009 Author(s)
15  *     economic rights: Technische Universität Dresden (Germany)
16  *
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.
20  */
21
22 /* LibC stuff */
23 #ifndef _GNU_SOURCE
24 #define _GNU_SOURCE
25 #endif
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <ctype.h>
31
32 /* L4 stuff */
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>
37 #include "panic.h"
38
39 /* local stuff */
40 #include "exec.h"
41 #include "macros.h"
42 #include "region.h"
43 #include "module.h"
44 #include "startup.h"
45 #include "support.h"
46 #include "init_kip.h"
47 #include "patch.h"
48 #include "koptions.h"
49
50 #undef getchar
51
52 /* management of allocated memory regions */
53 static Region_list regions;
54 static Region __regs[300];
55
56 /* management of conventional memory regions */
57 static Region_list ram;
58 static Region __ram[16];
59
60 static Memory _mem_manager = { &ram, &regions };
61 Memory *mem_manager = &_mem_manager;
62
63 L4_kernel_options::Uart kuart;
64 unsigned int kuart_flags;
65
66 /*
67  * IMAGE_MODE means that all boot modules are linked together to one
68  * big binary.
69  */
70 #ifdef IMAGE_MODE
71 static l4_addr_t _mod_addr = RAM_BASE + MODADDR;
72 #else
73 static l4_addr_t _mod_addr;
74 #endif
75
76 static const char *builtin_cmdline = CMDLINE;
77
78
79 enum {
80   kernel_module,
81   sigma0_module,
82   roottask_module,
83 };
84
85 /// Info passed through our ELF interpreter code
86 struct Elf_info
87 {
88   Boot_modules::Module mod;
89   Region::Type type;
90 };
91
92 static exec_handler_func_t l4_exec_read_exec;
93 static exec_handler_func_t l4_exec_add_region;
94
95
96 #if 0
97 static void
98 dump_mbi(l4util_mb_info_t *mbi)
99 {
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);
104
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);
109
110   l4util_mb_mod_t *m = (l4util_mb_mod_t*)(mbi->mods_addr);
111   l4util_mb_mod_t *me = m + mbi->mods_count;
112   for (; m < me; ++m)
113     {
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));
117     }
118 }
119 #endif
120
121
122 /**
123  * Scan the memory regions with type == Region::Kernel for a
124  * kernel interface page (KIP).
125  *
126  * After loading the kernel we scan for the magic number at page boundaries.
127  */
128 static
129 void *find_kip()
130 {
131   unsigned char *p, *end;
132   void *k = 0;
133
134   printf("  find kernel info page...\n");
135   for (Region const *m = regions.begin(); m != regions.end(); ++m)
136     {
137       if (m->type() != Region::Kernel)
138         continue;
139
140       if (sizeof(unsigned long) < 8
141           && m->end() >= (1ULL << 32))
142         end = (unsigned char *)(~0UL - 0x1000);
143       else
144         end = (unsigned char *) (unsigned long)m->end();
145
146       for (p = (unsigned char *) (unsigned long)(m->begin() & 0xfffff000);
147            p < end;
148            p += 0x1000)
149         {
150           l4_umword_t magic = L4_KERNEL_INFO_MAGIC;
151           if (memcmp(p, &magic, 4) == 0)
152             {
153               k = p;
154               printf("  found kernel info page at %p\n", p);
155               break;
156             }
157         }
158
159       if (k)
160         break;
161     }
162
163   if (!k)
164     panic("could not find kernel info page, maybe your kernel is too old");
165
166   return k;
167 }
168
169 static
170 L4_kernel_options::Options *find_kopts(void *kip)
171 {
172   unsigned long a = (unsigned long)kip + sizeof(l4_kernel_info_t);
173
174   // kernel-option directly follow the KIP page
175   a = (a + 4096 - 1) & ~0xfff;
176
177   L4_kernel_options::Options *ko = (L4_kernel_options::Options *)a;
178
179   if (ko->magic != L4_kernel_options::Magic)
180     panic("Could not find kernel options page");
181
182   unsigned long need_version = 1;
183
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);
187
188   return ko;
189 }
190
191 /**
192  * Get the API version from the KIP.
193  */
194 static inline
195 unsigned long get_api_version(void *kip)
196 {
197   return ((unsigned long *)kip)[1];
198 }
199
200
201 static char const *
202 check_arg_str(char const *cmdline, const char *arg)
203 {
204   char const *s = cmdline;
205   while ((s = strstr(s, arg)))
206     {
207       if (s == cmdline
208           || isspace(s[-1]))
209         return s;
210     }
211   return NULL;
212 }
213
214 static char *
215 check_arg_str(char *cmdline, const char *arg)
216 {
217   return const_cast<char *>(check_arg_str(const_cast<char const *>(cmdline), arg));
218 }
219
220 /**
221  * Scan the command line for the given argument.
222  *
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
226  *
227  * return pointer after argument, NULL if not found
228  */
229 char const *
230 check_arg(char const *cmdline, const char *arg)
231 {
232   if (cmdline)
233     return check_arg_str(cmdline, arg);
234
235   return NULL;
236 }
237
238
239 /**
240  * Calculate the maximum memory limit in MB.
241  *
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.
244  */
245 static
246 unsigned long long
247 get_memory_max_address()
248 {
249 #ifndef __LP64__
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;
256 #endif
257
258   return ~0ULL;
259 }
260
261 /*
262  * If available the '-maxmem=xx' command line option is used.
263  */
264 static
265 unsigned long long
266 get_memory_max_size(char const *cmdline)
267 {
268   /* maxmem= parameter? */
269   if (char const *c = check_arg(cmdline, "-maxmem="))
270     return strtoul(c + 8, NULL, 10) << 20;
271
272   return ~0ULL;
273 }
274
275 static int
276 parse_memvalue(const char *s, unsigned long *val, char **ep)
277 {
278
279   *val = strtoul(s, ep, 0);
280   if (*val == ~0UL)
281     return 1;
282
283   switch (**ep)
284     {
285     case 'G': *val <<= 10;
286     case 'M': *val <<= 10;
287     case 'k': case 'K': *val <<= 10; (*ep)++;
288     };
289
290   return 0;
291 }
292
293 /*
294  * Parse a memory layout string: size@offset
295  * E.g.: 256M@0x40000000, or 128M@128M
296  */
297 static int
298 parse_mem_layout(const char *s, unsigned long *sz, unsigned long *offset)
299 {
300   char *ep;
301
302   if (parse_memvalue(s, sz, &ep))
303     return 1;
304
305   if (*sz == 0)
306     return 1;
307
308   if (*ep != '@')
309     return 1;
310
311   if (parse_memvalue(ep + 1, offset, &ep))
312     return 1;
313
314   return 0;
315 }
316
317 static void
318 dump_ram_map(bool show_total = false)
319 {
320   // print RAM summary
321   unsigned long long sum = 0;
322   for (Region *i = ram.begin(); i < ram.end(); ++i)
323     {
324       printf("  RAM: %016llx - %016llx: %lldkB\n",
325              i->begin(), i->end(), i->size() >> 10);
326       sum += i->size();
327     }
328   if (show_total)
329     printf("  Total RAM: %lldMB\n", sum >> 20);
330 }
331
332 static void
333 setup_memory_map(char const *cmdline)
334 {
335   bool parsed_mem_option = false;
336   const char *s = cmdline;
337
338   if (s)
339     {
340       while ((s = check_arg_str((char *)s, "-mem=")))
341         {
342           s += 5;
343           unsigned long sz, offset = 0;
344           if (!parse_mem_layout(s, &sz, &offset))
345             {
346               parsed_mem_option = true;
347               ram.add(Region::n(offset, offset + sz, ".ram", Region::Ram));
348             }
349         }
350     }
351
352   if (!parsed_mem_option)
353     // No -mem option given, use the one given by the platform
354     Platform_base::platform->setup_memory_map();
355
356   dump_ram_map(true);
357 }
358
359 static void do_the_memset(unsigned long s, unsigned val, unsigned long len)
360 {
361   printf("Presetting memory %16lx - %16lx to '%x'\n",
362          s, s + len - 1, val);
363   memset((void *)s, val, len);
364 }
365
366 static void fill_mem(unsigned fill_value)
367 {
368   regions.sort();
369   for (Region const *r = ram.begin(); r != ram.end(); ++r)
370     {
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)
374         {
375           // completely before ram?
376           if (reg->end() < r->begin())
377             continue;
378           // completely after ram?
379           if (reg->begin() > r->end())
380             break;
381
382           if (reg->begin() <= r->begin())
383             b = reg->end() + 1;
384           else if (b > reg->begin()) // some overlapping
385             {
386               if (reg->end() + 1 > b)
387                 b = reg->end() + 1;
388             }
389           else
390             {
391               do_the_memset(b, fill_value, reg->begin() - 1 - b + 1);
392               b = reg->end() + 1;
393             }
394         }
395
396       if (b < r->end())
397         do_the_memset(b, fill_value, r->end() - b + 1);
398     }
399 }
400
401
402 /**
403  * Add the bootstrap binary itself to the allocated memory regions.
404  */
405 static void
406 init_regions()
407 {
408   extern int _start;    /* begin of image -- defined in crt0.S */
409   extern int _end;      /* end   of image -- defined by bootstrap.ld */
410
411   auto *p = Platform_base::platform;
412
413   regions.add(Region::n(p->to_phys((unsigned long)&_start),
414                         p->to_phys((unsigned long)&_end),
415                         ".bootstrap", Region::Boot));
416 }
417
418 /**
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()).
421  */
422 static void
423 add_elf_regions(Boot_modules::Module const &m, Region::Type type)
424 {
425   Elf_info info;
426   l4_addr_t entry;
427   int r;
428   const char *error_msg;
429
430   info.type = type;
431   info.mod = m;
432
433   printf("  Scanning %s\n", m.cmdline);
434
435   r = exec_load_elf(l4_exec_add_region, &info,
436                     &error_msg, &entry);
437
438   if (r)
439     {
440       if (Verbose_load)
441         {
442           printf("\n%p: ", (void*)m.start);
443           for (int i = 0; i < 4; ++i)
444             printf("%08x ", *((unsigned *)m.start + i));
445           printf("  ");
446           for (int i = 0; i < 16; ++i)
447             {
448               unsigned char c = *(unsigned char *)((char *)m.start + i);
449               printf("%c", c < 32 ? '.' : c);
450             }
451         }
452       panic("\n\nThis is an invalid binary, fix it (%s).", error_msg);
453     }
454 }
455
456
457 /**
458  * Load the given ELF binary into memory and free the source
459  * memory region.
460  */
461 static l4_addr_t
462 load_elf_module(Boot_modules::Module const &mod)
463 {
464   l4_addr_t entry;
465   int r;
466   const char *error_msg;
467
468   r = exec_load_elf(l4_exec_read_exec, const_cast<Boot_modules::Module *>(&mod),
469                     &error_msg, &entry);
470
471 #ifndef RELEASE_MODE
472   /* clear the image for debugging and security reasons */
473   memset((void*)mod.start, 0, mod.end - mod.start);
474 #endif
475
476   if (r)
477     printf("  => can't load module (%s)\n", error_msg);
478   else
479     {
480       Region m = Region::n(mod.start, l4_round_page(mod.end));
481       if (!regions.sub(m))
482         {
483           Region m = Region::n(mod.start, mod.end);
484           if (!regions.sub(m))
485             {
486               m.vprint();
487               regions.dump();
488               panic ("could not free region for load ELF module");
489             }
490         }
491     }
492
493   return entry;
494 }
495
496 /**
497  * Simple linear memory allocator.
498  *
499  * Allocate size bytes starting from *ptr and set *ptr to *ptr + size.
500  */
501 static inline void*
502 lin_alloc(l4_size_t size, char **ptr)
503 {
504   void *ret = *ptr;
505   *ptr += (size + 3) & ~3;;
506   return ret;
507 }
508
509
510 #ifdef ARCH_arm
511 static inline l4_umword_t
512 running_in_hyp_mode()
513 {
514   l4_umword_t cpsr;
515   asm volatile("mrs %0, cpsr" : "=r"(cpsr));
516   return (cpsr & 0x1f) == 0x1a;
517 }
518
519 static void
520 setup_and_check_kernel_config(Platform_base *plat, l4_kernel_info_t *kip)
521 {
522   l4_kip_platform_info_arch *ia = &kip->platform_info.arch;
523
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));
530
531   if (((ia->cpuinfo.MIDR >> 16) & 0xf) >= 7)
532     {
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]));
547     }
548
549   const char *s = l4_kip_version_string(kip);
550   if (!s)
551     return;
552
553   bool is_hyp_kernel = false;
554   l4util_kip_for_each_feature(s)
555     if (!strcmp(s, "arm:hyp"))
556       {
557         if (!running_in_hyp_mode())
558           {
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");
563           }
564         is_hyp_kernel = true;
565         break;
566       }
567
568   if (!is_hyp_kernel && running_in_hyp_mode())
569     {
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"
572                    "msr spsr, %0                  \n"
573                    "adr r0, 1f                    \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");
578     }
579 }
580 #endif /* arm */
581
582 static unsigned long
583 load_elf_module(Boot_modules::Module const &mod, char const *n)
584 {
585   printf("  Loading "); print_module_name(mod.cmdline, n); putchar('\n');
586   return load_elf_module(mod);
587 }
588
589 /**
590  * \brief  Startup, started from crt0.S
591  */
592 /* entry point */
593 void
594 startup(char const *cmdline)
595 {
596   if (!cmdline || !*cmdline)
597     cmdline = builtin_cmdline;
598
599   if (check_arg(cmdline, "-noserial"))
600     set_stdio_uart(NULL);
601
602   if (!Platform_base::platform)
603     {
604       // will we ever see this?
605       printf("No platform found, hangup.");
606       while (1)
607         ;
608     }
609
610   Platform_base *plat = Platform_base::platform;
611
612   if (check_arg(cmdline, "-wait"))
613     {
614       puts("\nL4 Bootstrapper is waiting for key input to continue...");
615       if (getchar() == -1)
616         puts("   ...no key input available.");
617       else
618         puts("    ...going on.");
619     }
620
621   puts("\nL4 Bootstrapper");
622   puts("  Build: #" BUILD_NR " " BUILD_DATE
623 #ifdef ARCH_x86
624       ", x86-32"
625 #endif
626 #ifdef ARCH_amd64
627       ", x86-64"
628 #endif
629 #ifdef __VERSION__
630        ", " __VERSION__
631 #endif
632       );
633
634   regions.init(__regs, "regions");
635   ram.init(__ram, "RAM", get_memory_max_size(cmdline), get_memory_max_address());
636
637   setup_memory_map(cmdline);
638
639   /* basically add the bootstrap binary to the allocated regions */
640   init_regions();
641   plat->modules()->reserve();
642
643   /* modules to load by bootstrap */
644   bool sigma0 = true;   /* we need sigma0 */
645   bool roottask = true; /* we need a roottask */
646
647   /* check command line */
648   if (check_arg(cmdline, "-no-sigma0"))
649     sigma0 = 0;
650
651   if (check_arg(cmdline, "-no-roottask"))
652     roottask = 0;
653
654   if (const char *s = check_arg(cmdline, "-modaddr"))
655     _mod_addr = RAM_BASE + strtoul(s + 9, 0, 0);
656
657   _mod_addr = l4_round_page(_mod_addr);
658
659
660   Boot_modules *mods = plat->modules();
661
662   add_elf_regions(mods->module(kernel_module), Region::Kernel);
663
664   if (sigma0)
665     add_elf_regions(mods->module(sigma0_module), Region::Sigma0);
666
667   if (roottask)
668     add_elf_regions(mods->module(roottask_module), Region::Root);
669
670   l4util_mb_info_t *mbi = plat->modules()->construct_mbi(_mod_addr);
671
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);
677
678   if (const char *s = cmdline)
679     {
680       /* patch modules with content given at command line */
681       while ((s = check_arg_str((char *)s, "-patch=")))
682         patch_module(&s, mbi);
683     }
684
685   boot_info_t boot_info;
686   l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t *)(unsigned long)mbi->mods_addr;
687   regions.optimize();
688
689   /* setup kernel PART ONE */
690   boot_info.kernel_start = load_elf_module(mods->module(kernel_module), "[KERNEL]");
691
692   /* setup sigma0 */
693   if (sigma0)
694     boot_info.sigma0_start = load_elf_module(mods->module(sigma0_module), "[SIGMA0]");
695
696   /* setup roottask */
697   if (roottask)
698     boot_info.roottask_start = load_elf_module(mods->module(roottask_module),
699                                                "[ROOTTASK]");
700
701   /* setup kernel PART TWO (special kernel initialization) */
702   void *l4i = find_kip();
703
704   regions.optimize();
705   regions.dump();
706
707   if (char const *c = check_arg(cmdline, "-presetmem="))
708     {
709       unsigned fill_value = strtoul(c + 11, NULL, 0);
710       fill_mem(fill_value);
711     }
712
713   L4_kernel_options::Options *lko = find_kopts(l4i);
714   kcmdline_parse(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline), lko);
715   lko->uart   = kuart;
716   lko->flags |= kuart_flags;
717
718
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":"");
724   switch (major)
725     {
726     case 0x87: // Fiasco
727       init_kip_f(l4i, &boot_info, mbi, &ram, &regions);
728       break;
729     case 0x02:
730       panic("cannot boot V.2 API kernels: %lx\n", api_version);
731       break;
732     case 0x03:
733       panic("cannot boot X.0 and X.1 API kernels: %lx\n", api_version);
734       break;
735     case 0x84:
736       panic("cannot boot Fiasco V.4 API kernels: %lx\n", api_version);
737       break;
738     case 0x04:
739       panic("cannot boot V.4 API kernels: %lx\n", api_version);
740     default:
741       panic("cannot boot a kernel with unknown api version %lx\n", api_version);
742       break;
743     }
744
745   printf("  Starting kernel ");
746   print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
747                     "[KERNEL]");
748   printf(" at " l4_addr_fmt "\n", boot_info.kernel_start);
749
750 #if defined(ARCH_arm)
751   if (major == 0x87)
752     setup_and_check_kernel_config(plat, (l4_kernel_info_t *)l4i);
753 #endif
754 #if defined(ARCH_ppc32)
755   init_kip_v2_arch((l4_kernel_info_t*)l4i);
756
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);
760 #endif
761
762   plat->boot_kernel(boot_info.kernel_start);
763   /*NORETURN*/
764 }
765
766 static int
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*/,
770                   l4_size_t mem_size,
771                   exec_sectype_t section_type)
772 {
773   Boot_modules::Module const *m = (Boot_modules::Module const *)handle;
774   if (!mem_size)
775     return 0;
776
777   if (! (section_type & EXEC_SECTYPE_ALLOC))
778     return 0;
779
780   if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
781     return 0;
782
783   if (Verbose_load)
784     printf("    [%p-%p]\n", (void *) mem_addr, (void *) (mem_addr + mem_size));
785
786   if (!ram.contains(Region::n(mem_addr, mem_addr + mem_size)))
787     {
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);
790       dump_ram_map();
791       panic("Binary outside memory");
792     }
793
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);
797
798
799   Region *f = regions.find(mem_addr);
800   if (!f)
801     {
802       printf("could not find %lx\n", mem_addr);
803       regions.dump();
804       panic("Oops: region for module not found\n");
805     }
806
807   f->name(m->cmdline ? m->cmdline :  ".[Unknown]");
808   return 0;
809 }
810
811
812 static int
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,
816                   l4_size_t mem_size,
817                   exec_sectype_t section_type)
818 {
819   Elf_info const *info = (Elf_info const *)handle;
820
821   if (!mem_size)
822     return 0;
823
824   if (! (section_type & EXEC_SECTYPE_ALLOC))
825     return 0;
826
827   if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
828     return 0;
829
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);
833
834   for (Region *r = regions.begin(); r != regions.end(); ++r)
835     if (r->overlaps(n) && r->name() != Boot_modules::Mod_reg)
836       {
837         printf("  New region for list %s:\t", n.name());
838         n.vprint();
839         printf("  overlaps with:         \t");
840         r->vprint();
841         regions.dump();
842         panic("region overlap");
843       }
844
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);
848   return 0;
849 }