]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/bootstrap/server/src/startup.cc
update
[l4.git] / l4 / pkg / bootstrap / 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 "panic.h"
37
38 /* local stuff */
39 #include "exec.h"
40 #include "macros.h"
41 #include "region.h"
42 #include "module.h"
43 #include "startup.h"
44 #include "support.h"
45 #include "init_kip.h"
46 #include "patch.h"
47 #include "loader_mbi.h"
48 #include "koptions.h"
49
50 #if defined (ARCH_ppc32)
51 #include <l4/drivers/of_if.h>
52 #include <l4/drivers/of_dev.h>
53 #endif
54
55 #undef getchar
56
57 enum { Verbose_load = 0 };
58
59 static l4util_mb_info_t *mb_info;
60 /* management of allocated memory regions */
61 static Region_list regions;
62 static Region __regs[300];
63
64 /* management of conventional memory regions */
65 static Region_list ram;
66 static Region __ram[16];
67
68 #if defined(ARCH_x86) || defined(ARCH_amd64)
69 static l4util_mb_vbe_mode_t __mb_vbe;
70 static l4util_mb_vbe_ctrl_t __mb_ctrl;
71 #endif
72
73 L4_kernel_options::Uart kuart;
74 unsigned int kuart_flags;
75
76 /*
77  * IMAGE_MODE means that all boot modules are linked together to one
78  * big binary.
79  */
80 #ifdef IMAGE_MODE
81 static l4_addr_t _mod_addr = RAM_BASE + MODADDR;
82 #else
83 static l4_addr_t _mod_addr;
84 #endif
85
86 static const char *builtin_cmdline = CMDLINE;
87
88 /* modules to load by bootstrap */
89 static int sigma0 = 1;   /* we need sigma0 */
90 static int roottask = 1; /* we need a roottask */
91
92 enum {
93   kernel_module,
94   sigma0_module,
95   roottask_module,
96 };
97
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 */
104
105
106 static exec_handler_func_t l4_exec_read_exec;
107 static exec_handler_func_t l4_exec_add_region;
108
109
110 #if 0
111 static void
112 dump_mbi(l4util_mb_info_t *mbi)
113 {
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);
118
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);
123
124   l4util_mb_mod_t *m = (l4util_mb_mod_t*)(mbi->mods_addr);
125   l4util_mb_mod_t *me = m + mbi->mods_count;
126   for (; m < me; ++m)
127     {
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));
131     }
132 }
133 #endif
134
135
136 /**
137  * Scan the memory regions with type == Region::Kernel for a
138  * kernel interface page (KIP).
139  *
140  * After loading the kernel we scan for the magic number at page boundaries.
141  */
142 static
143 void *find_kip()
144 {
145   unsigned char *p, *end;
146   void *k = 0;
147
148   printf("  find kernel info page...\n");
149   for (Region const *m = regions.begin(); m != regions.end(); ++m)
150     {
151       if (m->type() != Region::Kernel)
152         continue;
153
154       if (sizeof(unsigned long) < 8
155           && m->end() >= (1ULL << 32))
156         end = (unsigned char *)(~0UL - 0x1000);
157       else
158         end = (unsigned char *) (unsigned long)m->end();
159
160       for (p = (unsigned char *) (unsigned long)(m->begin() & 0xfffff000);
161            p < end;
162            p += 0x1000)
163         {
164           l4_umword_t magic = L4_KERNEL_INFO_MAGIC;
165           if (memcmp(p, &magic, 4) == 0)
166             {
167               k = p;
168               printf("  found kernel info page at %p\n", p);
169               break;
170             }
171         }
172     }
173
174   if (!k)
175     panic("could not find kernel info page, maybe your kernel is too old");
176
177   return k;
178 }
179
180 static
181 L4_kernel_options::Options *find_kopts(void *kip)
182 {
183   unsigned long a = (unsigned long)kip + sizeof(l4_kernel_info_t);
184
185   // kernel-option directly follow the KIP page
186   a = (a + 4096 - 1) & ~0xfff;
187
188   L4_kernel_options::Options *ko = (L4_kernel_options::Options *)a;
189
190   if (ko->magic != L4_kernel_options::Magic)
191     panic("Could not find kernel options page");
192
193   return ko;
194 }
195
196 const char *get_cmdline(l4util_mb_info_t *mbi)
197 {
198   if (mbi && mbi->flags & L4UTIL_MB_CMDLINE)
199     return L4_CHAR_PTR(mbi->cmdline);
200
201   if (*builtin_cmdline)
202     return builtin_cmdline;
203
204   return 0;
205 }
206
207 /**
208  * Get the API version from the KIP.
209  */
210 static inline
211 unsigned long get_api_version(void *kip)
212 {
213   return ((unsigned long *)kip)[1];
214 }
215
216
217 static char *
218 check_arg_str(char *cmdline, const char *arg)
219 {
220   char *s = cmdline;
221   while ((s = strstr(s, arg)))
222     {
223       if (s == cmdline
224           || isspace(s[-1]))
225         return s;
226     }
227   return NULL;
228 }
229
230 /**
231  * Scan the command line for the given argument.
232  *
233  * The cmdline string may either be including the calling program
234  * (.../bootstrap -arg1 -arg2) or without (-arg1 -arg2) in the realmode
235  * case, there, we do not have a leading space
236  *
237  * return pointer after argument, NULL if not found
238  */
239 char *
240 check_arg(l4util_mb_info_t *mbi, const char *arg)
241 {
242   const char *c = get_cmdline(mbi);
243   if (c)
244     return check_arg_str((char *)c, arg);
245
246   return NULL;
247 }
248
249
250 /**
251  * Calculate the maximum memory limit in MB.
252  *
253  * The limit is the highest physical address where conventional RAM is allowed.
254  * The memory is limited to 3 GB IA32 and unlimited on other systems.
255  */
256 static
257 unsigned long
258 get_memory_max_address()
259 {
260 #if defined(ARCH_x86)
261   /* Limit memory, we cannot really handle more right now. In fact, the
262    * problem is roottask. It maps as many superpages/pages as it gets.
263    * After that, the remaining pages are mapped using l4sigma0_map_anypage()
264    * with a receive window of L4_WHOLE_ADDRESS_SPACE. In response Sigma0
265    * could deliver pages beyond the 3GB user space limit. */
266   return 3024UL << 20;
267 #endif
268
269   return ~0UL;
270 }
271
272 /*
273  * If available the '-maxmem=xx' command line option is used.
274  */
275 static
276 unsigned long
277 get_memory_max_size(l4util_mb_info_t *mbi)
278 {
279   /* maxmem= parameter? */
280   if (char *c = check_arg(mbi, "-maxmem="))
281     return strtoul(c + 8, NULL, 10) << 20;
282
283   return ~0UL;
284 }
285
286 static int
287 parse_memvalue(const char *s, unsigned long *val, char **ep)
288 {
289
290   *val = strtoul(s, ep, 0);
291   if (*val == ~0UL)
292     return 1;
293
294   switch (**ep)
295     {
296     case 'G': *val <<= 10;
297     case 'M': *val <<= 10;
298     case 'k': case 'K': *val <<= 10; (*ep)++;
299     };
300
301   return 0;
302 }
303
304 /*
305  * Parse a memory layout string: size@offset
306  * E.g.: 256M@0x40000000, or 128M@128M
307  */
308 static int
309 parse_mem_layout(const char *s, unsigned long *sz, unsigned long *offset)
310 {
311   char *ep;
312
313   if (parse_memvalue(s, sz, &ep))
314     return 1;
315
316   if (*sz == 0)
317     return 1;
318
319   if (*ep != '@')
320     return 1;
321
322   if (parse_memvalue(ep + 1, offset, &ep))
323     return 1;
324
325   return 0;
326 }
327
328 static void
329 dump_ram_map(bool show_total = false)
330 {
331   // print RAM summary
332   unsigned long long sum = 0;
333   for (Region *i = ram.begin(); i < ram.end(); ++i)
334     {
335       printf("  RAM: %016llx - %016llx: %lldkB\n",
336              i->begin(), i->end(), i->size() >> 10);
337       sum += i->size();
338     }
339   if (show_total)
340     printf("  Total RAM: %lldMB\n", sum >> 20);
341 }
342
343 static void
344 setup_memory_map(l4util_mb_info_t *mbi)
345 {
346   bool parsed_mem_option = false;
347   const char *s = get_cmdline(mbi);
348
349   if (s)
350     {
351       while ((s = check_arg_str((char *)s, "-mem=")))
352         {
353           s += 5;
354           unsigned long sz, offset = 0;
355           if (!parse_mem_layout(s, &sz, &offset))
356             {
357               parsed_mem_option = true;
358               ram.add(Region::n(offset, offset + sz, ".ram", Region::Ram));
359             }
360         }
361     }
362
363   if (!parsed_mem_option)
364     // No -mem option given, use the one given by the platform
365     Platform_base::platform->setup_memory_map(mbi, &ram, &regions);
366
367   dump_ram_map(true);
368 }
369
370 static void do_the_memset(unsigned long s, unsigned val, unsigned long len)
371 {
372   printf("Presetting memory %16lx - %16lx to '%x'\n",
373          s, s + len - 1, val);
374   memset((void *)s, val, len);
375 }
376
377 static void fill_mem(unsigned fill_value)
378 {
379   regions.sort();
380   for (Region const *r = ram.begin(); r != ram.end(); ++r)
381     {
382       unsigned long long b = r->begin();
383       // The regions list must be sorted!
384       for (Region const *reg = regions.begin(); reg != regions.end(); ++reg)
385         {
386           // completely before ram?
387           if (reg->end() < r->begin())
388             continue;
389           // completely after ram?
390           if (reg->begin() > r->end())
391             break;
392
393           if (reg->begin() <= r->begin())
394             b = reg->end() + 1;
395           else if (b > reg->begin()) // some overlapping
396             {
397               if (reg->end() + 1 > b)
398                 b = reg->end() + 1;
399             }
400           else
401             {
402               do_the_memset(b, fill_value, reg->begin() - 1 - b + 1);
403               b = reg->end() + 1;
404             }
405         }
406
407       if (b < r->end())
408         do_the_memset(b, fill_value, r->end() - b + 1);
409     }
410 }
411
412 static void
413 move_module(l4util_mb_info_t *mbi, int i, Region *from, Region *to,
414             bool overlap_check)
415 {
416   unsigned long start = from->begin();
417   unsigned long size = from->end() - start + 1;
418
419   if (Verbose_load)
420     {
421       unsigned char c[5];
422       c[0] = *(unsigned char*)(start + 0);
423       c[1] = *(unsigned char*)(start + 1);
424       c[2] = *(unsigned char*)(start + 2);
425       c[3] = *(unsigned char*)(start + 3);
426       c[4] = 0;
427       c[0] = c[0] < 32 ? '.' : c[0];
428       c[1] = c[1] < 32 ? '.' : c[1];
429       c[2] = c[2] < 32 ? '.' : c[2];
430       c[3] = c[3] < 32 ? '.' : c[3];
431       printf("  moving module %02d { %lx, %llx } (%s) -> { %llx - %llx } [%ld]\n",
432              i, start, from->end(), c, to->begin(), to->end(), size);
433
434       for (int a = 0; a < 0x100; a += 4)
435         printf("%08lx%s", *(unsigned long *)(start + a), (a % 32 == 28) ? "\n" : " ");
436       printf("\n");
437     }
438   else
439     printf("  moving module %02d { %lx-%llx } -> { %llx-%llx } [%ld]\n",
440            i, start, from->end(), to->begin(), to->end(), size);
441
442   if (!ram.contains(*to))
443     panic("Panic: Would move outside of RAM");
444
445   if (overlap_check)
446     {
447       Region *overlap = regions.find(*to);
448       if (overlap)
449         {
450           printf("ERROR: module target [%llx-%llx) overlaps\n",
451                  to->begin(), to->end());
452           overlap->vprint();
453           regions.dump();
454           panic("cannot move module");
455         }
456     }
457   memmove((void *)to->begin(), (void *)start, size);
458   unsigned long x = to->end() + 1;
459   memset((char *)x, 0, l4_round_page(x) - x);
460
461   (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_start = to->begin();
462   (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_end   = to->end() + 1;
463   from->begin(to->begin());
464   from->end(to->end());
465 }
466
467 static inline
468 unsigned long mbi_mod_start(l4util_mb_info_t *mbi, int i)
469 { return (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_start; }
470
471 static inline
472 unsigned long mbi_mod_end(l4util_mb_info_t *mbi, int i)
473 { return (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_end; }
474
475 static inline
476 unsigned long mbi_mod_size(l4util_mb_info_t *mbi, int i)
477 { return mbi_mod_end(mbi, i) - mbi_mod_start(mbi, i); }
478
479 /**
480  * Move modules to another address.
481  *
482  * Source and destination regions may overlap.
483  */
484 static void
485 move_modules(l4util_mb_info_t *mbi, unsigned long modaddr)
486 {
487   printf("  Moving up to %d modules behind %lx\n", mbi->mods_count, modaddr);
488
489   Region *ramr = ram.find(Region(modaddr, modaddr));
490   Region module_area(modaddr, ramr->end(), "ram for modules");
491
492   unsigned long firstmodulestart = ~0UL, lastmoduleend = 0;
493   for (unsigned i = 0; i < mbi->mods_count; ++i)
494     {
495       if (lastmoduleend < mbi_mod_end(mbi, i))
496         lastmoduleend = mbi_mod_end(mbi, i);
497       if (firstmodulestart > mbi_mod_start(mbi, i))
498         firstmodulestart = mbi_mod_start(mbi, i);
499     }
500   lastmoduleend = l4_round_page(lastmoduleend);
501   if (firstmodulestart < modaddr)
502     {
503       Region s(lastmoduleend, ramr->end());
504       unsigned long sz = modaddr - firstmodulestart;
505       lastmoduleend = regions.find_free(s, sz, L4_PAGESHIFT) + sz;
506     }
507
508   for (unsigned i = 0; i < mbi->mods_count; ++i)
509     {
510       unsigned long start = mbi_mod_start(mbi, i);
511       unsigned long end = mbi_mod_end(mbi, i);
512       unsigned long size = mbi_mod_size(mbi, i);
513
514       if (start == end)
515         continue;
516
517       Region from(start, end - 1);
518       Region *this_module = regions.find(from);
519       assert(this_module->begin() == from.begin()
520              && this_module->end() == from.end());
521
522       if (i < 3)
523         {
524           if (start < lastmoduleend)
525             {
526               Region to(lastmoduleend, lastmoduleend + (end - start) - 1);
527               if (module_area.contains(to))
528                 {
529                   move_module(mbi, i, this_module, &to, true);
530                   lastmoduleend = l4_round_page(this_module->end());
531                 }
532             }
533           continue;
534         }
535
536       if (start >= modaddr)
537         continue;
538
539       unsigned long long to = regions.find_free(module_area, size, L4_PAGESHIFT);
540       assert(to);
541
542       Region m_to = Region(to, to + size - 1);
543       move_module(mbi, i, this_module, &m_to, true);
544     }
545
546   // now everything is behind modaddr -> pull close to modaddr now
547   // this is optional but avoids holes and gives more consecutive memory
548
549   if (0)
550     printf("  Compactifying\n");
551
552   regions.sort();
553   unsigned long lastend = modaddr;
554   for (Region *i = regions.begin(); i < regions.end(); ++i)
555     {
556       if (i->begin() < modaddr)
557         continue;
558
559       // find in mbi
560       unsigned mi = 0;
561       for (; mi < mbi->mods_count; ++mi)
562         if (i->begin() == mbi_mod_start(mbi, mi))
563           break;
564
565       if (mi < 3 || mbi->mods_count == mi)
566         continue;
567
568       unsigned long start = mbi_mod_start(mbi, mi);
569       unsigned long end = mbi_mod_end(mbi, mi);
570
571       if (start > lastend)
572         {
573           Region to(lastend, end - 1 - (start - lastend));
574           move_module(mbi, mi, i, &to, false);
575           end = i->end();
576         }
577       lastend = l4_round_page(end);
578     }
579 }
580
581
582 /**
583  * Add the bootstrap binary itself to the allocated memory regions.
584  */
585 static void
586 init_regions()
587 {
588   extern int _start;    /* begin of image -- defined in crt0.S */
589   extern int _end;      /* end   of image -- defined by bootstrap.ld */
590
591   regions.add(Region::n((unsigned long)&_start, (unsigned long)&_end,
592               ".bootstrap", Region::Boot));
593 }
594
595
596 /**
597  * Add the memory containing the boot modules to the allocated regions.
598  */
599 static void
600 add_boot_modules_region(l4util_mb_info_t *mbi)
601 {
602   for (unsigned int i = 0; i < mbi->mods_count; ++i)
603     regions.add(Region(mbi_mod_start(mbi, i), mbi_mod_end(mbi, i) - 1,
604                        ".Module", Region::Root));
605 }
606
607
608 /**
609  * Add all sections of the given ELF binary to the allocated regions.
610  * Actually does not load the ELF binary (see load_elf_module()).
611  */
612 static void
613 add_elf_regions(l4util_mb_info_t *mbi, l4_umword_t module,
614                 Region::Type type)
615 {
616   exec_task_t exec_task;
617   l4_addr_t entry;
618   int r;
619   const char *error_msg;
620   l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t*)(unsigned long)mbi->mods_addr;
621
622   assert(module < mbi->mods_count);
623
624   exec_task.begin = 0xffffffff;
625   exec_task.end   = 0;
626   exec_task.type = type;
627
628   exec_task.mod_start = L4_VOID_PTR(mb_mod[module].mod_start);
629   exec_task.mod       = mb_mod + module;
630
631   printf("  Scanning %s\n", L4_CHAR_PTR(mb_mod[module].cmdline));
632
633   r = exec_load_elf(l4_exec_add_region, &exec_task,
634                     &error_msg, &entry);
635
636   if (r)
637     {
638       if (Verbose_load)
639         {
640           printf("\n%p: ", exec_task.mod_start);
641           for (int i = 0; i < 4; ++i)
642             {
643               printf("%08lx ", *((unsigned long *)exec_task.mod_start + i));
644             }
645           printf("  ");
646           for (int i = 0; i < 16; ++i)
647             {
648               unsigned char c = *(unsigned char *)((char *)exec_task.mod_start + i);
649               printf("%c", c < 32 ? '.' : c);
650             }
651         }
652       panic("\n\nThis is an invalid binary, fix it (%s).", error_msg);
653     }
654 }
655
656
657 /**
658  * Load the given ELF binary into memory and free the source
659  * memory region.
660  */
661 static l4_addr_t
662 load_elf_module(l4util_mb_mod_t *mb_mod)
663 {
664   exec_task_t exec_task;
665   l4_addr_t entry;
666   int r;
667   const char *error_msg;
668
669   exec_task.begin = 0xffffffff;
670   exec_task.end   = 0;
671
672   exec_task.mod_start = L4_VOID_PTR(mb_mod->mod_start);
673   exec_task.mod       = mb_mod;
674
675   r = exec_load_elf(l4_exec_read_exec, &exec_task,
676                     &error_msg, &entry);
677
678 #ifndef RELEASE_MODE
679   /* clear the image for debugging and security reasons */
680   memset(L4_VOID_PTR(mb_mod->mod_start), 0,
681          mb_mod->mod_end - mb_mod->mod_start);
682 #endif
683
684   if (r)
685     printf("  => can't load module (%s)\n", error_msg);
686   else
687     {
688       Region m = Region::n(mb_mod->mod_start, mb_mod->mod_end);
689       Region *x = regions.find(m);
690       if (x)
691         {
692           if (x->begin() == m.begin())
693             {
694               unsigned long b = l4_round_page(m.end()+1);
695               if (x->end() <= b)
696                 regions.remove(x);
697               else
698                 x->begin(b);
699             }
700         }
701     }
702
703   return entry;
704 }
705
706 /**
707  * Simple linear memory allocator.
708  *
709  * Allocate size bytes starting from *ptr and set *ptr to *ptr + size.
710  */
711 static inline void*
712 lin_alloc(l4_size_t size, char **ptr)
713 {
714   void *ret = *ptr;
715   *ptr += (size + 3) & ~3;;
716   return ret;
717 }
718
719
720 /**
721  * Duplicate the given command line.
722  *
723  * This function is used for relocating the multi-boot info.
724  * The new location is *ptr and *ptr is incremented by the size of the
725  * string (basically like lin_alloc() does).
726  *
727  * This function also implements the mechanism to replace the command line
728  * of a module from the bootstrap command line.
729  */
730 static
731 char *dup_cmdline(l4util_mb_info_t *mbi, unsigned mod_nr, char **ptr,
732     char const *orig)
733 {
734   char *res = *ptr;
735   if (!orig)
736     return 0;
737
738   char* name_end = strchr(orig, ' ');
739   if (name_end && *name_end)
740     *name_end = 0;
741   else
742     name_end = 0;
743
744   unsigned size;
745   char const *new_args = get_arg_module(mbi, orig, &size);
746
747   if (new_args && size)
748     printf("    new args for %d = \"%.*s\"\n", mod_nr, size, new_args);
749   else
750     if (name_end)
751       *name_end = ' ';
752
753   strcpy(*ptr, orig);
754   *ptr+= strlen(*ptr)+1;
755
756   if (new_args)
757     {
758       *((*ptr)-1) = ' ';
759       strncpy(*ptr, new_args, size);
760       *ptr += size;
761       *((*ptr)++) = 0;
762     }
763   return res;
764 }
765
766
767 static
768 void
769 print_e820_map(l4util_mb_info_t *mbi)
770 {
771 #ifndef ARCH_arm
772   printf("  Bootloader MMAP%s\n", mbi->flags & L4UTIL_MB_MEM_MAP
773                                    ? ":" : " not available.");
774 #endif
775
776   if (mbi->flags & L4UTIL_MB_MEM_MAP)
777     {
778       l4util_mb_addr_range_t *mmap;
779       l4util_mb_for_each_mmap_entry(mmap, mbi)
780         {
781           const char *types[] = { "unknown", "RAM", "reserved", "ACPI",
782                                   "ACPI NVS", "unusable" };
783           const char *type_str = (mmap->type < (sizeof(types) / sizeof(types[0])))
784                                  ? types[mmap->type] : types[0];
785
786           printf("    [%9llx, %9llx) %s (%d)\n",
787                  (unsigned long long) mmap->addr,
788                  (unsigned long long) mmap->addr + (unsigned long long) mmap->size,
789                  type_str, (unsigned) mmap->type);
790         }
791     }
792 }
793
794 /**
795  * Relocate and compact the multi-boot infomation (MBI).
796  *
797  * This function relocates the MBI into the first 4MB of physical memory.
798  * Substructures such as module information, the VESA information, and
799  * the command lines of the modules are also relocated.
800  * During relocation of command lines they may be substituted according
801  * to '-arg=' options from the bootstrap command line.
802  *
803  * The memory map is discarded and not relocated, because everything after
804  * bootstrap has to use the KIP memory descriptors.
805  */
806 static
807 l4util_mb_info_t *
808 relocate_mbi(l4util_mb_info_t *src_mbi, unsigned long* start,
809              unsigned long* end)
810 {
811   l4util_mb_info_t *dst_mbi;
812   l4_addr_t x;
813
814   print_e820_map(src_mbi);
815
816   static char mbi_store[16 << 10] __attribute__((aligned(L4_PAGESIZE)));
817
818   x = (l4_addr_t)&mbi_store;
819
820   void *mbi_start = (void*)x;
821
822   char *p = (char*)x;
823   *start = x;
824
825   dst_mbi = (l4util_mb_info_t*)lin_alloc(sizeof(l4util_mb_info_t), &p);
826
827   /* copy (extended) multiboot info structure */
828   memcpy(dst_mbi, src_mbi, sizeof(l4util_mb_info_t));
829
830   dst_mbi->flags &= ~(L4UTIL_MB_CMDLINE | L4UTIL_MB_MEM_MAP | L4UTIL_MB_MEMORY);
831
832   /* copy extended VIDEO information, if available */
833   if (dst_mbi->flags & L4UTIL_MB_VIDEO_INFO)
834     {
835       if (src_mbi->vbe_mode_info)
836         {
837           l4util_mb_vbe_mode_t *m
838             = (l4util_mb_vbe_mode_t*)lin_alloc(sizeof(l4util_mb_vbe_mode_t),
839                 &p);
840
841           memcpy(m, L4_VOID_PTR(src_mbi->vbe_mode_info),
842                  sizeof(l4util_mb_vbe_mode_t));
843           dst_mbi->vbe_mode_info = (l4_addr_t)m;
844         }
845
846       /* copy VBE controller info structure */
847       if (src_mbi->vbe_ctrl_info)
848         {
849           l4util_mb_vbe_ctrl_t *m
850             = (l4util_mb_vbe_ctrl_t*)lin_alloc(sizeof(l4util_mb_vbe_ctrl_t),
851                 &p);
852           memcpy(m, L4_VOID_PTR(src_mbi->vbe_ctrl_info),
853                  sizeof(l4util_mb_vbe_ctrl_t));
854           dst_mbi->vbe_ctrl_info = (l4_addr_t)m;
855         }
856     }
857
858   /* copy module descriptions */
859   l4util_mb_mod_t *mods = (l4util_mb_mod_t*)lin_alloc(sizeof(l4util_mb_mod_t)*
860       src_mbi->mods_count, &p);
861   memcpy(mods, L4_VOID_PTR(dst_mbi->mods_addr),
862          dst_mbi->mods_count * sizeof (l4util_mb_mod_t));
863   dst_mbi->mods_addr = (l4_addr_t)mods;
864
865   /* copy command lines of modules */
866   for (unsigned i = 0; i < dst_mbi->mods_count; i++)
867     {
868       char *n = dup_cmdline(src_mbi, i, &p, (char const *)(unsigned long)mods[i].cmdline);
869       if (n)
870           mods[i].cmdline = (l4_addr_t) n;
871     }
872   *end = (l4_addr_t)p;
873
874   printf("  Relocated mbi to [%p-%p]\n", mbi_start, (void *)(*end));
875   regions.add(Region::n((unsigned long)mbi_start,
876                         ((unsigned long)*end) + 0xfe,
877                         ".Multiboot info", Region::Root),
878               true /* we overlap with the Bootstrap binary, we are in BSS*/);
879
880   return dst_mbi;
881 }
882
883 #ifdef IMAGE_MODE
884
885 #ifdef COMPRESS
886 #include "uncompress.h"
887 #endif
888
889 //#define DO_CHECK_MD5
890 #ifdef DO_CHECK_MD5
891 #include <bsd/md5.h>
892
893 static void check_md5(const char *name, u_int8_t *start, unsigned size,
894                       const char *md5sum)
895 {
896   MD5_CTX md5ctx;
897   unsigned char digest[MD5_DIGEST_LENGTH];
898   char s[MD5_DIGEST_STRING_LENGTH];
899   static const char hex[] = "0123456789abcdef";
900   int j;
901
902   printf(" Checking checksum of %s\n", name);
903
904   MD5Init(&md5ctx);
905   MD5Update(&md5ctx, start, size);
906   MD5Final(digest, &md5ctx);
907
908   for (j = 0; j < MD5_DIGEST_LENGTH; j++)
909     {
910       s[j + j] = hex[digest[j] >> 4];
911       s[j + j + 1] = hex[digest[j] & 0x0f];
912     }
913   s[j + j] = '\0';
914
915   if (strcmp(s, md5sum))
916     panic("md5sum mismatch");
917 }
918 #else
919 static inline void check_md5(const char *, u_int8_t *, unsigned, const char *)
920 {}
921 #endif
922
923 typedef struct
924 {
925   l4_uint32_t  start;
926   l4_uint32_t  size;
927   l4_uint32_t  size_uncompressed;
928   l4_uint32_t  name;
929   l4_uint32_t  md5sum_compr;
930   l4_uint32_t  md5sum_uncompr;
931 } mod_info;
932
933 extern mod_info _module_info_start[];
934 extern mod_info _module_info_end[];
935
936 extern l4util_mb_mod_t _modules_mbi_start[];
937 extern l4util_mb_mod_t _modules_mbi_end[];
938 extern char _mbi_cmdline[];
939
940 /**
941  * Create the basic multi-boot structure in IMAGE_MODE
942  */
943 static void
944 construct_mbi(l4util_mb_info_t *mbi)
945 {
946   unsigned i;
947   l4util_mb_mod_t *mods = _modules_mbi_start;
948 #ifdef COMPRESS
949   l4_addr_t destbuf;
950 #endif
951
952   mbi->mods_count  = _module_info_end - _module_info_start;
953   mbi->flags      |= L4UTIL_MB_MODS;
954   mbi->mods_addr   = (l4_addr_t)mods;
955
956   assert(mbi->mods_count >= 2);
957
958   for (i = 0; i < mbi->mods_count; ++i)
959     check_md5(L4_CHAR_PTR(_module_info_start[i].name),
960               (u_int8_t *)_module_info_start[i].start,
961               _module_info_start[i].size,
962               L4_CHAR_PTR(_module_info_start[i].md5sum_compr));
963
964 #ifdef COMPRESS
965   printf("Compressed modules:\n");
966   for (i = 0; i < mbi->mods_count; i++)
967     {
968       printf("  mod%02u: %08x-%08x: %s\n",
969              i, _module_info_start[i].start,
970              _module_info_start[i].start + _module_info_start[i].size,
971              L4_CHAR_PTR(_module_info_start[i].name));
972     }
973
974   destbuf = l4_round_page(mods[mbi->mods_count - 1].mod_end);
975   if (destbuf < _mod_addr)
976     destbuf = _mod_addr;
977
978   // advance to last module end
979   for (i = 0; i < mbi->mods_count; i++)
980     destbuf += l4_round_page(_module_info_start[i].size_uncompressed);
981
982   // check for overlaps and adjust mod_addr accordingly
983   unsigned long d = destbuf;
984   for (i = mbi->mods_count; i > 0; --i)
985     {
986       d -= l4_round_page(_module_info_start[i - 1].size_uncompressed);
987       if (d <= _module_info_start[i-1].start + _module_info_start[i-1].size)
988         {
989           l4_addr_t x = (_module_info_start[i-1].start + _module_info_start[i-1].size + 0xfff) & ~0xfff;
990           l4_addr_t delta = x - d;
991
992           _mod_addr += delta;
993           destbuf += delta;
994           printf("  Adjusting modaddr to %lx {%d}\n", _mod_addr, i-1);
995           d = x;
996         }
997     }
998
999   printf("Uncompressing modules (modaddr = %lx):\n", _mod_addr);
1000 #endif
1001
1002   for (i = mbi->mods_count; i > 0; --i)
1003     {
1004 #ifdef COMPRESS
1005       destbuf -= l4_round_page(_module_info_start[i - 1].size_uncompressed);
1006
1007       l4_addr_t image =
1008          (l4_addr_t)decompress(L4_CONST_CHAR_PTR(_module_info_start[i - 1].name),
1009                                L4_VOID_PTR(_module_info_start[i - 1].start),
1010                                (void *)destbuf,
1011                                _module_info_start[i - 1].size,
1012                                _module_info_start[i - 1].size_uncompressed);
1013 #else
1014       l4_addr_t image = _module_info_start[i - 1].start;
1015 #endif
1016       mods[i - 1].mod_start = image;
1017       mods[i - 1].mod_end   = image + _module_info_start[i - 1].size_uncompressed;
1018       printf("  mod%02u: %08x-%08x: %s\n",
1019              i - 1, mods[i - 1].mod_start, mods[i - 1].mod_end,
1020              L4_CHAR_PTR(_module_info_start[i - 1].name));
1021       if (image == 0)
1022         panic("Panic: Failure decompressing image\n");
1023       if (!ram.contains(Region(mods[i - 1].mod_start,
1024                                mods[i - 1].mod_end)))
1025         panic("Panic: Module does not fit into RAM");
1026
1027     }
1028
1029   for (i = 0; i < mbi->mods_count; ++i)
1030     check_md5(L4_CHAR_PTR(_module_info_start[i].name),
1031               (u_int8_t *)mods[i].mod_start,
1032               _module_info_start[i].size_uncompressed,
1033               L4_CHAR_PTR(_module_info_start[i].md5sum_uncompr));
1034 }
1035 #endif /* IMAGE_MODE */
1036
1037
1038 /* Occupied RAM at the point we are scanning it */
1039 static int
1040 is_precious_ram(unsigned long addr)
1041 {
1042   extern int _start, _end;
1043
1044   if ((unsigned long)&_start <= addr && addr <= (unsigned long)&_end)
1045     return 1;
1046
1047 #ifdef IMAGE_MODE
1048   unsigned i, c = _module_info_end - _module_info_start;
1049   if ((unsigned long)_module_info_start <= addr
1050        && addr <= (unsigned long)_module_info_end)
1051     return 1;
1052
1053   if ((unsigned long)_modules_mbi_start <= addr
1054       && addr <= (unsigned long)_modules_mbi_end)
1055     return 1;
1056
1057   for (i = 0; i < c; ++i)
1058     if (_module_info_start[i].start <= addr
1059         && addr < _module_info_start[i].start + _module_info_start[i].size_uncompressed)
1060       return 1;
1061 #endif
1062
1063   return 0;
1064 }
1065
1066 unsigned long
1067 scan_ram_size(unsigned long base_addr, unsigned long max_scan_size_mb)
1068 {
1069   // scan the RAM to find out the RAM size, note that at this point we have
1070   // two regions in RAM that we cannot touch, &_start - &_end and the
1071   // modules
1072
1073   unsigned long offset;
1074   const unsigned long increment = 1 << 20; // must be multiple of (1 << 20)
1075
1076   printf("  Scanning up to %ld MB RAM\n", max_scan_size_mb);
1077
1078   // initialize memory points
1079   for (offset = increment; offset < (max_scan_size_mb << 20); offset += offset)
1080     if (!is_precious_ram(base_addr + offset))
1081       *(unsigned long *)(base_addr + offset) = 0;
1082
1083   // write something at offset 0, does it appear elsewhere?
1084   *(unsigned long *)base_addr = 0x12345678;
1085   asm volatile("" : : : "memory");
1086   for (offset = increment; offset < (max_scan_size_mb << 20); offset += offset)
1087     if (*(unsigned long *)(base_addr + offset) == 0x12345678)
1088       return offset >> 20;
1089
1090   return max_scan_size_mb;
1091 }
1092
1093 /**
1094  * \brief  Startup, started from crt0.S
1095  */
1096 /* entry point */
1097 extern "C" void
1098 startup(l4util_mb_info_t *mbi, l4_umword_t flag,
1099         void *realmode_si, ptab64_mem_info_t *ptab64_info);
1100 void
1101 startup(l4util_mb_info_t *mbi, l4_umword_t flag,
1102         void *realmode_si, ptab64_mem_info_t *ptab64_info)
1103 {
1104   void *l4i;
1105   boot_info_t boot_info;
1106   l4util_mb_mod_t *mb_mod;
1107
1108   if (!Platform_base::platform)
1109     {
1110       // will we ever see this?
1111       printf("No platform found, hangup.");
1112       while (1)
1113         ;
1114     }
1115
1116 #ifdef LOADER_MBI
1117   loader_mbi_add_cmdline(_mbi_cmdline);
1118   mbi = loader_mbi();
1119 #endif
1120
1121   if (check_arg(mbi, "-wait"))
1122     {
1123       puts("\nL4 Bootstrapper is waiting for key input to continue...");
1124       if (getchar() == -1)
1125         puts("   ...no key input available.");
1126       else
1127         puts("    ...going on.");
1128     }
1129
1130   puts("\nL4 Bootstrapper");
1131   puts("  Build: #" BUILD_NR " " BUILD_DATE
1132 #ifdef ARCH_x86
1133       ", x86-32"
1134 #endif
1135 #ifdef ARCH_amd64
1136       ", x86-64"
1137 #endif
1138 #ifdef __VERSION__
1139        ", " __VERSION__
1140 #endif
1141       );
1142
1143   regions.init(__regs, sizeof(__regs) / sizeof(__regs[0]), "regions");
1144   ram.init(__ram, sizeof(__ram) / sizeof(__ram[0]), "RAM",
1145            get_memory_max_size(mbi), get_memory_max_address());
1146
1147 #ifdef ARCH_amd64
1148   // add the page-table on which we're running in 64bit mode
1149   regions.add(Region::n(ptab64_info->addr, ptab64_info->addr + ptab64_info->size,
1150               ".bootstrap-ptab64", Region::Boot));
1151 #else
1152   (void)ptab64_info;
1153 #endif
1154
1155 #if defined(ARCH_x86) || defined(ARCH_amd64)
1156
1157 #ifdef REALMODE_LOADING
1158   /* create synthetic multi boot info */
1159   mbi = init_loader_mbi_x86_realmode(realmode_si);
1160   (void)flag;
1161 #else
1162   (void)realmode_si;
1163   assert(flag == L4UTIL_MB_VALID); /* we need to be multiboot-booted */
1164 #endif
1165
1166 #elif defined(ARCH_arm)
1167   mbi = loader_mbi();
1168
1169   (void)realmode_si;
1170   (void)flag;
1171
1172 #elif defined(ARCH_ppc32)
1173   mbi = loader_mbi();
1174
1175   (void)realmode_si;
1176   (void)flag;
1177
1178   L4_drivers::Of_if of_if;
1179
1180   printf("  Detecting ram size ...\n");
1181   unsigned long ram_size = of_if.detect_ramsize();
1182   printf("    Total memory size is %luMB\n", ram_size / (1024 * 1024));
1183
1184   /* detect OF devices */
1185   unsigned long drives_addr, drives_length;
1186
1187   if (of_if.detect_devices(&drives_addr, &drives_length))
1188     {
1189       mbi->flags |= L4UTIL_MB_DRIVE_INFO;
1190       mbi->drives_addr   = drives_addr;
1191       mbi->drives_length = drives_length;
1192     }
1193   ram.add(Region::n(0x0, ram_size, ".ram", Region::Ram));
1194
1195 #elif defined(ARCH_sparc)
1196   mbi = loader_mbi();
1197
1198   (void)realmode_si;
1199   (void)flag;
1200 #else
1201 #error Unknown arch!
1202 #endif
1203
1204   setup_memory_map(mbi);
1205
1206   /* basically add the bootstrap binary to the allocated regions */
1207   init_regions();
1208
1209   /* check command line */
1210   if (check_arg(mbi, "-no-sigma0"))
1211     sigma0 = 0;
1212
1213   if (check_arg(mbi, "-no-roottask"))
1214     roottask = 0;
1215
1216   if (const char *s = check_arg(mbi, "-modaddr"))
1217     _mod_addr = RAM_BASE + strtoul(s + 9, 0, 0);
1218
1219   _mod_addr = l4_round_page(_mod_addr);
1220
1221 #ifdef IMAGE_MODE
1222   construct_mbi(mbi);
1223 #endif
1224
1225   /* move vbe and ctrl structures to a known location, it might be in the
1226    * way when moving modules around */
1227 #if defined(ARCH_x86) || defined(ARCH_amd64)
1228   if (mbi->flags & L4UTIL_MB_VIDEO_INFO)
1229     {
1230       if (mbi->vbe_mode_info)
1231         {
1232           memcpy(&__mb_vbe, L4_VOID_PTR(mbi->vbe_mode_info),
1233                  sizeof(l4util_mb_vbe_mode_t));
1234           mbi->vbe_mode_info = (l4_addr_t)&__mb_vbe;
1235         }
1236
1237       if (mbi->vbe_ctrl_info)
1238         {
1239           memcpy(&__mb_ctrl, L4_VOID_PTR(mbi->vbe_ctrl_info),
1240                  sizeof(l4util_mb_vbe_ctrl_t));
1241           mbi->vbe_ctrl_info = (l4_addr_t)&__mb_ctrl;
1242         }
1243     }
1244 #endif
1245
1246   /* We need at least two boot modules */
1247   assert(mbi->flags & L4UTIL_MB_MODS);
1248   /* We have at least the L4 kernel and the first user task */
1249   assert(mbi->mods_count >= 2);
1250   assert(mbi->mods_count <= MODS_MAX);
1251
1252   /* we're just a GRUB-booted kernel! */
1253   add_boot_modules_region(mbi);
1254
1255   if (_mod_addr)
1256     move_modules(mbi, _mod_addr);
1257
1258   if (const char *s = get_cmdline(mbi))
1259     {
1260       /* patch modules with content given at command line */
1261       while ((s = check_arg_str((char *)s, "-patch=")))
1262         patch_module(&s, mbi);
1263     }
1264
1265
1266   add_elf_regions(mbi, kernel_module, Region::Kernel);
1267
1268   if (sigma0)
1269     add_elf_regions(mbi, sigma0_module, Region::Sigma0);
1270
1271   if (roottask)
1272     add_elf_regions(mbi, roottask_module, Region::Root);
1273
1274
1275   /* copy Multiboot data structures, we still need to a safe place
1276    * before playing with memory we don't own and starting L4 */
1277   mb_info = relocate_mbi(mbi, &boot_info.mbi_low, &boot_info.mbi_high);
1278   if (!mb_info)
1279     panic("could not copy multiboot info to memory below 4MB");
1280
1281   mb_mod = (l4util_mb_mod_t *)(unsigned long)mb_info->mods_addr;
1282
1283   /* --- Shouldn't touch original Multiboot parameters after here. -- */
1284
1285   /* setup kernel PART ONE */
1286   printf("  Loading ");
1287   print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
1288       "[KERNEL]");
1289   putchar('\n');
1290
1291   boot_info.kernel_start = load_elf_module(mb_mod + kernel_module);
1292
1293   /* setup sigma0 */
1294   if (sigma0)
1295     {
1296       printf("  Loading ");
1297       print_module_name(L4_CONST_CHAR_PTR(mb_mod[sigma0_module].cmdline),
1298                          "[SIGMA0]");
1299       putchar('\n');
1300
1301       boot_info.sigma0_start = load_elf_module(mb_mod + sigma0_module);
1302       boot_info.sigma0_stack = (l4_addr_t)sigma0_init_stack
1303                                + sizeof(sigma0_init_stack);
1304     }
1305
1306   /* setup roottask */
1307   if (roottask)
1308     {
1309
1310       printf("  Loading ");
1311       print_module_name(L4_CONST_CHAR_PTR(mb_mod[roottask_module].cmdline),
1312                          "[ROOTTASK]");
1313       putchar('\n');
1314
1315       boot_info.roottask_start = load_elf_module(mb_mod + roottask_module);
1316       boot_info.roottask_stack = (l4_addr_t)roottask_init_stack
1317                                  + sizeof(roottask_init_stack);
1318     }
1319
1320   /* setup kernel PART TWO (special kernel initialization) */
1321   l4i = find_kip();
1322
1323 #if defined(ARCH_x86) || defined(ARCH_amd64) || defined(ARCH_ppc32)
1324   /* setup multi boot info structure for kernel */
1325   l4util_mb_info_t kernel_mbi;
1326   kernel_mbi = *mb_info;
1327   kernel_mbi.flags = L4UTIL_MB_MEMORY;
1328   if (mb_mod[kernel_module].cmdline)
1329     {
1330       kernel_mbi.cmdline = mb_mod[kernel_module].cmdline;
1331       kernel_mbi.flags  |= L4UTIL_MB_CMDLINE;
1332     }
1333 #endif
1334
1335   regions.optimize();
1336   regions.dump();
1337
1338   if (char *c = check_arg(mbi, "-presetmem="))
1339     {
1340       unsigned fill_value = strtoul(c + 11, NULL, 0);
1341       fill_mem(fill_value);
1342     }
1343
1344   L4_kernel_options::Options *lko = find_kopts(l4i);
1345   kcmdline_parse(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline), lko);
1346   lko->uart   = kuart;
1347   lko->flags |= kuart_flags;
1348
1349
1350   /* setup the L4 kernel info page before booting the L4 microkernel:
1351    * patch ourselves into the booter task addresses */
1352   unsigned long api_version = get_api_version(l4i);
1353   unsigned major = api_version >> 24;
1354   printf("  API Version: (%x) %s\n", major, (major & 0x80)?"experimental":"");
1355   switch (major)
1356     {
1357     case 0x02: // Version 2 API
1358     case 0x03: // Version X.0 and X.1
1359     case 0x87: // Fiasco
1360       init_kip_v2(l4i, &boot_info, mb_info, &ram, &regions);
1361       break;
1362     case 0x84:
1363     case 0x04:
1364       init_kip_v4(l4i, &boot_info, mb_info, &ram, &regions);
1365       break;
1366     default:
1367       panic("cannot boot a kernel with unknown api version %lx\n", api_version);
1368       break;
1369     }
1370
1371   printf("  Starting kernel ");
1372   print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
1373                     "[KERNEL]");
1374   printf(" at "l4_addr_fmt"\n", boot_info.kernel_start);
1375
1376 #if defined(ARCH_x86)
1377   asm volatile
1378     ("pushl $exit ; jmp *%3"
1379      :
1380      : "a" (L4UTIL_MB_VALID),
1381        "b" (&kernel_mbi),
1382        "S" (realmode_si),
1383        "r" (boot_info.kernel_start));
1384
1385 #elif defined(ARCH_amd64)
1386
1387   asm volatile
1388     ("push $exit; jmp *%2"
1389      :
1390      : "S" (L4UTIL_MB_VALID), "D" (&kernel_mbi), "r" (boot_info.kernel_start));
1391
1392 #elif defined(ARCH_arm)
1393   typedef void (*startup_func)(void);
1394   startup_func f = (startup_func)boot_info.kernel_start;
1395   f();
1396
1397 #elif defined(ARCH_ppc32)
1398
1399   init_kip_v2_arch((l4_kernel_info_t*)l4i);
1400   printf("CPU at %lu Khz/Bus at %lu Hz\n",
1401          ((l4_kernel_info_t*)l4i)->frequency_cpu,
1402          ((l4_kernel_info_t*)l4i)->frequency_bus);
1403   typedef void (*startup_func)(l4util_mb_info_t *, unsigned long);
1404   startup_func f = (startup_func)boot_info.kernel_start;
1405   of_if.boot_finish();
1406   f(&kernel_mbi, of_if.get_prom());
1407
1408 #elif defined(ARCH_sparc)
1409
1410   printf("ENTER THE KERNEL!\n");
1411   asm volatile("or %%g0,%0,%%g2\n\t"
1412                "jmpl %%g2,%%g0\n\t"
1413                "nop\n\t" : : "r"(boot_info.kernel_start));
1414
1415 #else
1416
1417 #error "How to enter the kernel?"
1418
1419 #endif
1420
1421   /*NORETURN*/
1422 }
1423
1424 static int
1425 l4_exec_read_exec(void * handle,
1426                   l4_addr_t file_ofs, l4_size_t file_size,
1427                   l4_addr_t mem_addr, l4_addr_t /*v_addr*/,
1428                   l4_size_t mem_size,
1429                   exec_sectype_t section_type)
1430 {
1431   exec_task_t *exec_task = (exec_task_t*)handle;
1432   if (!mem_size)
1433     return 0;
1434
1435   if (! (section_type & EXEC_SECTYPE_ALLOC))
1436     return 0;
1437
1438   if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
1439     return 0;
1440
1441   if (mem_addr < exec_task->begin)
1442     exec_task->begin = mem_addr;
1443   if (mem_addr + mem_size > exec_task->end)
1444     exec_task->end = mem_addr + mem_size;
1445
1446   if (Verbose_load)
1447     printf("    [%p-%p]\n", (void *) mem_addr, (void *) (mem_addr + mem_size));
1448
1449   if (!ram.contains(Region::n(mem_addr, mem_addr + mem_size)))
1450     {
1451       printf("To be loaded binary region is out of memory region.\n");
1452       printf(" Binary region: %lx - %lx\n", mem_addr, mem_addr + mem_size);
1453       dump_ram_map();
1454       panic("Binary outside memory");
1455     }
1456
1457   memcpy((void *) mem_addr,
1458          (char*)(exec_task->mod_start) + file_ofs, file_size);
1459   if (file_size < mem_size)
1460     memset((void *) (mem_addr + file_size), 0, mem_size - file_size);
1461
1462
1463   Region *f = regions.find(mem_addr);
1464   if (!f)
1465     {
1466       printf("could not find %lx\n", mem_addr);
1467       regions.dump();
1468       panic("Oops: region for module not found\n");
1469     }
1470
1471   f->name(exec_task->mod->cmdline
1472                ? L4_CONST_CHAR_PTR(exec_task->mod->cmdline)
1473                :  ".[Unknown]");
1474   return 0;
1475 }
1476
1477 static int
1478 l4_exec_add_region(void * handle,
1479                   l4_addr_t /*file_ofs*/, l4_size_t /*file_size*/,
1480                   l4_addr_t mem_addr, l4_addr_t v_addr,
1481                   l4_size_t mem_size,
1482                   exec_sectype_t section_type)
1483 {
1484   exec_task_t *exec_task = (exec_task_t*)handle;
1485
1486   if (!mem_size)
1487     return 0;
1488
1489   if (! (section_type & EXEC_SECTYPE_ALLOC))
1490     return 0;
1491
1492   if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
1493     return 0;
1494
1495   regions.add(Region::n(mem_addr, mem_addr + mem_size,
1496              exec_task->mod->cmdline
1497                ? L4_CONST_CHAR_PTR(exec_task->mod->cmdline)
1498                :  ".[Unknown]", Region::Type(exec_task->type),
1499                mem_addr == v_addr ? 1 : 0));
1500   return 0;
1501 }