]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/bootstrap/server/src/startup.cc
update
[l4.git] / l4 / pkg / bootstrap / server / src / startup.cc
index 2d025ecb8926ed28ed74f8e525be183a02d6744c..c202cf2a73785f995a8c84630f46015f33e01292 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * \file       bootstrap/server/src/startup.c
+ * \file       bootstrap/server/src/startup.cc
  * \brief      Main functions
  *
  * \date       09/2004
@@ -11,7 +11,9 @@
  */
 
 /*
- * (c) 2005-2009 Technische Universität Dresden
+ * (c) 2005-2009 Author(s)
+ *     economic rights: Technische Universität Dresden (Germany)
+ *
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
  * Please see the COPYING-GPL-2 file for details.
 #include "init_kip.h"
 #include "patch.h"
 #include "loader_mbi.h"
-#include "startup.h"
-#if defined (ARCH_x86) || defined(ARCH_amd64)
-#include "ARCH-x86/serial.h"
-#endif
+#include "koptions.h"
 
 #if defined (ARCH_ppc32)
 #include <l4/drivers/of_if.h>
 
 #undef getchar
 
+enum { Verbose_load = 0 };
+
 static l4util_mb_info_t *mb_info;
 /* management of allocated memory regions */
 static Region_list regions;
-static Region __regs[MAX_REGION];
+static Region __regs[300];
 
 /* management of conventional memory regions */
 static Region_list ram;
-static Region __ram[8];
+static Region __ram[16];
 
 #if defined(ARCH_x86) || defined(ARCH_amd64)
 static l4util_mb_vbe_mode_t __mb_vbe;
 static l4util_mb_vbe_ctrl_t __mb_ctrl;
 #endif
 
-l4_kip_kernel_uart_info kip_kernel_uart_info;
+L4_kernel_options::Uart kuart;
+unsigned int kuart_flags;
 
 /*
  * IMAGE_MODE means that all boot modules are linked together to one
@@ -175,9 +177,25 @@ void *find_kip()
   return k;
 }
 
+static
+L4_kernel_options::Options *find_kopts(void *kip)
+{
+  unsigned long a = (unsigned long)kip + sizeof(l4_kernel_info_t);
+
+  // kernel-option directly follow the KIP page
+  a = (a + 4096 - 1) & ~0xfff;
+
+  L4_kernel_options::Options *ko = (L4_kernel_options::Options *)a;
+
+  if (ko->magic != L4_kernel_options::Magic)
+    panic("Could not find kernel options page");
+
+  return ko;
+}
+
 const char *get_cmdline(l4util_mb_info_t *mbi)
 {
-  if (mbi->flags & L4UTIL_MB_CMDLINE)
+  if (mbi && mbi->flags & L4UTIL_MB_CMDLINE)
     return L4_CHAR_PTR(mbi->cmdline);
 
   if (*builtin_cmdline)
@@ -218,7 +236,7 @@ check_arg_str(char *cmdline, const char *arg)
  *
  * return pointer after argument, NULL if not found
  */
-static char *
+char *
 check_arg(l4util_mb_info_t *mbi, const char *arg)
 {
   const char *c = get_cmdline(mbi);
@@ -232,32 +250,37 @@ check_arg(l4util_mb_info_t *mbi, const char *arg)
 /**
  * Calculate the maximum memory limit in MB.
  *
- * The limit is the highes physical address where conventional RAM is allowed.
- *
- * If available the '-maxmem=xx' command line option is used.
- * If not then the memory is limited to 3 GB IA32 and unlimited on other
- * systems.
+ * The limit is the highest physical address where conventional RAM is allowed.
+ * The memory is limited to 3 GB IA32 and unlimited on other systems.
  */
 static
 unsigned long
-get_memory_limit(l4util_mb_info_t *mbi)
+get_memory_max_address()
 {
-  char *c;
+#if defined(ARCH_x86)
+  /* Limit memory, we cannot really handle more right now. In fact, the
+   * problem is roottask. It maps as many superpages/pages as it gets.
+   * After that, the remaining pages are mapped using l4sigma0_map_anypage()
+   * with a receive window of L4_WHOLE_ADDRESS_SPACE. In response Sigma0
+   * could deliver pages beyond the 3GB user space limit. */
+  return 3024UL << 20;
+#endif
+
+  return ~0UL;
+}
 
+/*
+ * If available the '-maxmem=xx' command line option is used.
+ */
+static
+unsigned long
+get_memory_max_size(l4util_mb_info_t *mbi)
+{
   /* maxmem= parameter? */
-  if ((c = check_arg(mbi, "-maxmem=")))
+  if (char *c = check_arg(mbi, "-maxmem="))
     return strtoul(c + 8, NULL, 10) << 20;
-  else
-#if defined(ARCH_x86)
-    /* Limit memory, we cannot really handle more right now. In fact, the
-     * problem is roottask. It maps as many superpages/pages as it gets.
-     * After that, the remaining pages are mapped using l4sigma0_map_anypage()
-     * with a receive window of L4_WHOLE_ADDRESS_SPACE. In response Sigma0
-     * could deliver pages beyond the 3GB user space limit. */
-    return 3024UL << 20;
-#else
-    return ~0UL;
-#endif
+
+  return ~0UL;
 }
 
 static int
@@ -302,6 +325,33 @@ parse_mem_layout(const char *s, unsigned long *sz, unsigned long *offset)
   return 0;
 }
 
+static
+void
+print_e820_map(l4util_mb_info_t *mbi)
+{
+#ifndef ARCH_arm
+  printf("  Bootloader MMAP%s\n", mbi->flags & L4UTIL_MB_MEM_MAP
+                                   ? ":" : " not available.");
+#endif
+
+  if (mbi->flags & L4UTIL_MB_MEM_MAP)
+    {
+      l4util_mb_addr_range_t *mmap;
+      l4util_mb_for_each_mmap_entry(mmap, mbi)
+       {
+         const char *types[] = { "unknown", "RAM", "reserved", "ACPI",
+                                  "ACPI NVS", "unusable" };
+         const char *type_str = (mmap->type < (sizeof(types) / sizeof(types[0])))
+                                 ? types[mmap->type] : types[0];
+
+         printf("    [%9llx, %9llx) %s (%d)\n",
+                 (unsigned long long) mmap->addr,
+                 (unsigned long long) mmap->addr + (unsigned long long) mmap->size,
+                 type_str, (unsigned) mmap->type);
+       }
+    }
+}
+
 static void
 dump_ram_map(bool show_total = false)
 {
@@ -310,8 +360,8 @@ dump_ram_map(bool show_total = false)
   for (Region *i = ram.begin(); i < ram.end(); ++i)
     {
       printf("  RAM: %016llx - %016llx: %lldkB\n",
-             i->begin(), i->end(), (i->end() - i->begin() + 1) >> 10);
-      sum += i->end() - i->begin() + 1;
+             i->begin(), i->end(), i->size() >> 10);
+      sum += i->size();
     }
   if (show_total)
     printf("  Total RAM: %lldMB\n", sum >> 20);
@@ -386,36 +436,15 @@ static void fill_mem(unsigned fill_value)
     }
 }
 
-
-/**
- * Move modules to another address.
- *
- * Source and destination regions may overlap.
- */
 static void
-move_modules(l4util_mb_info_t *mbi, unsigned long modaddr)
+move_module(l4util_mb_info_t *mbi, int i, Region *from, Region *to,
+            bool overlap_check)
 {
-  long offset = modaddr - (L4_MB_MOD_PTR(mbi->mods_addr))[0].mod_start;
-  unsigned i;
-  unsigned dir = offset > 0 ? mbi->mods_count : 1;
-
-  if (!offset)
-    {
-      printf("  => Images in place\n");
-      return;
-    }
+  unsigned long start = from->begin();
+  unsigned long size = from->end() - start + 1;
 
-  printf("  move modules to %lx with offset %lx\n", modaddr, offset);
-
-  for (i = dir; i != mbi->mods_count - dir ; offset > 0 ? i-- : i++)
+  if (Verbose_load)
     {
-      unsigned long start = (L4_MB_MOD_PTR(mbi->mods_addr))[i-1].mod_start;
-      unsigned long end = (L4_MB_MOD_PTR(mbi->mods_addr))[i-1].mod_end;
-
-      if (start == end)
-       continue;
-
-#ifdef VERBOSE_LOAD
       unsigned char c[5];
       c[0] = *(unsigned char*)(start + 0);
       c[1] = *(unsigned char*)(start + 1);
@@ -426,30 +455,179 @@ move_modules(l4util_mb_info_t *mbi, unsigned long modaddr)
       c[1] = c[1] < 32 ? '.' : c[1];
       c[2] = c[2] < 32 ? '.' : c[2];
       c[3] = c[3] < 32 ? '.' : c[3];
-      printf("  move module %02d { %lx, %lx } (%s) -> { %lx - %lx }\n",
-             i, start, end, c, start + offset, end + offset);
+      printf("  moving module %02d { %lx, %llx } (%s) -> { %llx - %llx } [%ld]\n",
+             i, start, from->end(), c, to->begin(), to->end(), size);
 
       for (int a = 0; a < 0x100; a += 4)
-       printf("%08lx%s", *(unsigned long *)(start + a), (a % 32 == 28) ? "\n" : " ");
+        printf("%08x%s", *(unsigned *)(start + a), (a % 32 == 28) ? "\n" : " ");
       printf("\n");
-#else
-      printf("  move module %02d { %lx-%lx } -> { %lx-%lx }\n",
-             i, start, end, start + offset, end + offset);
-#endif
+    }
+  else
+    printf("  moving module %02d { %lx-%llx } -> { %llx-%llx } [%ld]\n",
+           i, start, from->end(), to->begin(), to->end(), size);
+
+  if (!ram.contains(*to))
+    panic("Panic: Would move outside of RAM");
 
-      Region *overlap = regions.find(Region(start + offset, end + offset));
+  if (overlap_check)
+    {
+      Region *overlap = regions.find(*to);
       if (overlap)
-       {
-         printf("ERROR: module target [%lx-%lx) overlaps\n", start + offset, 
-             end + offset);
-         overlap->vprint();
-         panic("can not move module");
-       }
-      if (!ram.contains(Region(start + offset, end + offset)))
-        panic("Panic: Would move outside of RAM");
-      memmove((void *)(start+offset), (void *)start, end-start);
-      (L4_MB_MOD_PTR(mbi->mods_addr))[i-1].mod_start += offset;
-      (L4_MB_MOD_PTR(mbi->mods_addr))[i-1].mod_end += offset;
+        {
+          printf("ERROR: module target [%llx-%llx) overlaps\n",
+                 to->begin(), to->end());
+          overlap->vprint();
+          regions.dump();
+          panic("cannot move module");
+        }
+    }
+  memmove((void *)to->begin(), (void *)start, size);
+  unsigned long x = to->end() + 1;
+  memset((char *)x, 0, l4_round_page(x) - x);
+
+  (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_start = to->begin();
+  (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_end   = to->end() + 1;
+  from->begin(to->begin());
+  from->end(to->end());
+}
+
+static inline
+unsigned long mbi_mod_start(l4util_mb_info_t *mbi, int i)
+{ return (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_start; }
+
+static inline
+unsigned long mbi_mod_end(l4util_mb_info_t *mbi, int i)
+{ return (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_end; }
+
+static inline
+unsigned long mbi_mod_size(l4util_mb_info_t *mbi, int i)
+{ return mbi_mod_end(mbi, i) - mbi_mod_start(mbi, i); }
+
+/**
+ * Move modules to another address.
+ *
+ * Source and destination regions may overlap.
+ */
+static void
+move_modules(l4util_mb_info_t *mbi, unsigned long modaddr)
+{
+  printf("  Moving up to %d modules behind %lx\n", mbi->mods_count, modaddr);
+
+  Region *ramr = ram.find(Region(modaddr, modaddr));
+  Region module_area(modaddr, ramr->end(), "ram for modules");
+
+  unsigned long firstmodulestart = ~0UL, lastmoduleend = 0;
+  for (unsigned i = 0; i < mbi->mods_count; ++i)
+    {
+      if (lastmoduleend < mbi_mod_end(mbi, i))
+        lastmoduleend = mbi_mod_end(mbi, i);
+      if (firstmodulestart > mbi_mod_start(mbi, i))
+        firstmodulestart = mbi_mod_start(mbi, i);
+    }
+  lastmoduleend = l4_round_page(lastmoduleend);
+  if (firstmodulestart < modaddr)
+    {
+      Region s(lastmoduleend, ramr->end());
+      unsigned long sz = modaddr - firstmodulestart;
+      lastmoduleend = regions.find_free(s, sz, L4_PAGESHIFT) + sz;
+    }
+
+  for (unsigned i = 0; i < mbi->mods_count; ++i)
+    {
+      unsigned long start = mbi_mod_start(mbi, i);
+      unsigned long end = mbi_mod_end(mbi, i);
+      unsigned long size = mbi_mod_size(mbi, i);
+
+      if (start == end)
+        continue;
+
+      Region from(start, end - 1);
+      Region *this_module = regions.find(from);
+      assert(this_module->begin() == from.begin()
+             && this_module->end() == from.end());
+
+      if (i < 3)
+        {
+          if (start < lastmoduleend)
+            {
+              Region to(lastmoduleend, lastmoduleend + (end - start) - 1);
+              if (module_area.contains(to))
+                {
+                  move_module(mbi, i, this_module, &to, true);
+                  lastmoduleend = l4_round_page(this_module->end());
+                }
+            }
+          continue;
+        }
+
+      if (start >= modaddr)
+        continue;
+
+      unsigned long long to = regions.find_free(module_area, size, L4_PAGESHIFT);
+      assert(to);
+
+      Region m_to = Region(to, to + size - 1);
+      move_module(mbi, i, this_module, &m_to, true);
+    }
+
+  // now everything is behind modaddr -> pull close to modaddr now
+  // this is optional but avoids holes and gives more consecutive memory
+
+  if (Verbose_load)
+    printf("  Compactifying\n");
+
+  regions.sort();
+  unsigned long lastend = modaddr;
+
+  // Now check whether modaddr is ok or if some non-modules are still above
+  // modaddr, so that we need to have lastend higher
+    {
+      unsigned long end_last_pre_module = 0;
+      bool seen_modules = false;
+
+      for (Region *i = regions.begin(); i < regions.end(); ++i)
+        {
+          if (strcmp(i->name(), ".Module"))
+            {
+              unsigned long mod_end = l4_round_page(i->end());
+              if (!seen_modules && end_last_pre_module < mod_end)
+                end_last_pre_module = mod_end;
+            }
+          else
+            seen_modules = true;
+        }
+
+      if (end_last_pre_module > lastend)
+        lastend = end_last_pre_module;
+    }
+
+  if (Verbose_load)
+    printf("  Moving modules down to %lx\n", lastend);
+
+  for (Region *i = regions.begin(); i < regions.end(); ++i)
+    {
+      if (i->begin() < modaddr)
+        continue;
+
+      // find in mbi
+      unsigned mi = 0;
+      for (; mi < mbi->mods_count; ++mi)
+        if (i->begin() == mbi_mod_start(mbi, mi))
+          break;
+
+      if (mi < 3 || mbi->mods_count == mi)
+        continue;
+
+      unsigned long start = mbi_mod_start(mbi, mi);
+      unsigned long end = mbi_mod_end(mbi, mi);
+
+      if (start > lastend)
+        {
+          Region to(lastend, end - 1 - (start - lastend));
+          move_module(mbi, mi, i, &to, false);
+          end = i->end();
+        }
+      lastend = l4_round_page(end);
     }
 }
 
@@ -467,6 +645,35 @@ init_regions()
               ".bootstrap", Region::Boot));
 }
 
+/**
+ * Add memory used by MBI to the allocated memory regions.
+ */
+static void
+reserve_mbi_memory(l4util_mb_info_t *mbi)
+{
+  regions.add(Region::n((unsigned long)mbi,
+                        (unsigned long)mbi + sizeof(*mbi),
+                        ".mbi", Region::Boot));
+
+  if (mbi->flags & L4UTIL_MB_CMDLINE)
+    regions.add(Region::n((unsigned long)mbi->cmdline,
+                          (unsigned long)mbi->cmdline
+                          + strlen(L4_CONST_CHAR_PTR(mbi->cmdline)),
+                          ".mbi", Region::Boot));
+
+  l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t*)(unsigned long)mbi->mods_addr;
+  regions.add(Region::n((unsigned long)mb_mod,
+                        (unsigned long)&mb_mod[mbi->mods_count],
+                        ".mbi", Region::Boot));
+
+  for (unsigned i = 0; i < mbi->mods_count; ++i)
+    regions.add(Region::n(mb_mod[i].cmdline,
+                          (unsigned long)mb_mod[i].cmdline
+                          + strlen(L4_CONST_CHAR_PTR(mb_mod[i].cmdline)),
+                          ".mbi", Region::Boot));
+
+  regions.optimize();
+}
 
 /**
  * Add the memory containing the boot modules to the allocated regions.
@@ -474,13 +681,11 @@ init_regions()
 static void
 add_boot_modules_region(l4util_mb_info_t *mbi)
 {
-  regions.add(
-      Region::n((L4_MB_MOD_PTR(mbi->mods_addr))[0].mod_start,
-            (L4_MB_MOD_PTR(mbi->mods_addr))[mbi->mods_count-1].mod_end,
-            ".Modules Memory", Region::Root));
+  for (unsigned int i = 0; i < mbi->mods_count; ++i)
+    regions.add(Region(mbi_mod_start(mbi, i), mbi_mod_end(mbi, i) - 1,
+                       ".Module", Region::Root));
 }
 
-
 /**
  * Add all sections of the given ELF binary to the allocated regions.
  * Actually does not load the ELF binary (see load_elf_module()).
@@ -493,7 +698,7 @@ add_elf_regions(l4util_mb_info_t *mbi, l4_umword_t module,
   l4_addr_t entry;
   int r;
   const char *error_msg;
-  l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t*)mbi->mods_addr;
+  l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t*)(unsigned long)mbi->mods_addr;
 
   assert(module < mbi->mods_count);
 
@@ -511,23 +716,19 @@ add_elf_regions(l4util_mb_info_t *mbi, l4_umword_t module,
 
   if (r)
     {
-#ifdef VERBOSE_LOAD
-      int i;
-      printf("\n%p: ", exec_task.mod_start);
-      for (i = 0; i < 16; ++i)
-        {
-         printf("%02x", *(unsigned char *)exec_task.mod_start);
-         if (i % 4 == 3)
-           printf(" ");
-       }
-      printf("  ");
-      for (i = 0; i < 16; ++i)
+      if (Verbose_load)
         {
-         unsigned char c = *(unsigned char *)exec_task.mod_start;
-         printf("%c", c < 32 ? '.' : c);
-       }
-#endif
-      panic("\n\nThis is an invalid binary, fix it.");
+          printf("\n%p: ", exec_task.mod_start);
+          for (int i = 0; i < 4; ++i)
+            printf("%08x ", *((unsigned *)exec_task.mod_start + i));
+          printf("  ");
+          for (int i = 0; i < 16; ++i)
+            {
+              unsigned char c = *(unsigned char *)((char *)exec_task.mod_start + i);
+              printf("%c", c < 32 ? '.' : c);
+            }
+        }
+      panic("\n\nThis is an invalid binary, fix it (%s).", error_msg);
     }
 }
 
@@ -584,7 +785,7 @@ load_elf_module(l4util_mb_mod_t *mb_mod)
 /**
  * Simple linear memory allocator.
  *
- * Allocate size bytes startting from *ptr and set *ptr to *ptr + size.
+ * Allocate size bytes starting from *ptr and set *ptr to *ptr + size.
  */
 static inline void*
 lin_alloc(l4_size_t size, char **ptr)
@@ -598,12 +799,12 @@ lin_alloc(l4_size_t size, char **ptr)
 /**
  * Duplicate the given command line.
  *
- * This function is use for relocating the multi-boot info.
- * The new location is *ptr and *ptr is incemented by the size of the
+ * This function is used for relocating the multi-boot info.
+ * The new location is *ptr and *ptr is incremented by the size of the
  * string (basically like lin_alloc() does).
  *
  * This function also implements the mechanism to replace the command line
- * of a module from the bootstrap comand line.
+ * of a module from the bootstrap command line.
  */
 static
 char *dup_cmdline(l4util_mb_info_t *mbi, unsigned mod_nr, char **ptr,
@@ -642,35 +843,8 @@ char *dup_cmdline(l4util_mb_info_t *mbi, unsigned mod_nr, char **ptr,
 }
 
 
-static
-void
-print_e820_map(l4util_mb_info_t *mbi)
-{
-#ifndef ARCH_arm
-  printf("  Bootloader MMAP%s\n", mbi->flags & L4UTIL_MB_MEM_MAP
-                                   ? ":" : " not available.");
-#endif
-
-  if (mbi->flags & L4UTIL_MB_MEM_MAP)
-    {
-      l4util_mb_addr_range_t *mmap;
-      l4util_mb_for_each_mmap_entry(mmap, mbi)
-       {
-         const char *types[] = { "unknown", "RAM", "reserved", "ACPI",
-                                  "ACPI NVS", "unusable" };
-         const char *type_str = (mmap->type < (sizeof(types) / sizeof(types[0])))
-                                 ? types[mmap->type] : types[0];
-
-         printf("    [%9llx, %9llx) %s (%d)\n",
-                 (unsigned long long) mmap->addr,
-                 (unsigned long long) mmap->addr + (unsigned long long) mmap->size,
-                 type_str, (unsigned) mmap->type);
-       }
-    }
-}
-
 /**
- * Relocate and compact the multi-boot infomation (MBI).
+ * Relocate and compact the multi-boot information (MBI).
  *
  * This function relocates the MBI into the first 4MB of physical memory.
  * Substructures such as module information, the VESA information, and
@@ -678,8 +852,8 @@ print_e820_map(l4util_mb_info_t *mbi)
  * During relocation of command lines they may be substituted according
  * to '-arg=' options from the bootstrap command line.
  *
- * The memory map is discared and not relocated, because everything after 
- * bootstrap has to use the KIP memory desriptors.
+ * The memory map is discarded and not relocated, because everything after
+ * bootstrap has to use the KIP memory descriptors.
  */
 static
 l4util_mb_info_t *
@@ -743,13 +917,13 @@ relocate_mbi(l4util_mb_info_t *src_mbi, unsigned long* start,
   /* copy command lines of modules */
   for (unsigned i = 0; i < dst_mbi->mods_count; i++)
     {
-      char *n = dup_cmdline(src_mbi, i, &p, (char const *)(mods[i].cmdline));
+      char *n = dup_cmdline(src_mbi, i, &p, (char const *)(unsigned long)mods[i].cmdline);
       if (n)
          mods[i].cmdline = (l4_addr_t) n;
     }
   *end = (l4_addr_t)p;
 
-  printf("  Relocated mbi to [%p-%p]\n", mbi_start, (void*)(*end));
+  printf("  Relocated mbi to [%p-%p]\n", mbi_start, (void *)(*end));
   regions.add(Region::n((unsigned long)mbi_start,
                         ((unsigned long)*end) + 0xfe,
                         ".Multiboot info", Region::Root),
@@ -813,6 +987,7 @@ extern mod_info _module_info_end[];
 
 extern l4util_mb_mod_t _modules_mbi_start[];
 extern l4util_mb_mod_t _modules_mbi_end[];
+extern char _mbi_cmdline[];
 
 /**
  * Create the basic multi-boot structure in IMAGE_MODE
@@ -912,54 +1087,17 @@ construct_mbi(l4util_mb_info_t *mbi)
 #endif /* IMAGE_MODE */
 
 
-void
-init_pc_serial(l4util_mb_info_t *mbi)
-{
-#if defined(ARCH_x86) || defined(ARCH_amd64)
-  const char *s;
-  int comport = -1;
-
-  if ((s = check_arg(mbi, "-comport")))
-    comport = strtoul(s + 9, 0, 0);
-
-  if (check_arg(mbi, "-serial"))
-    {
-      if (0)
-        {
-          extern unsigned long search_pci_serial_devs(bool scan_only);
-          unsigned long port;
-          if (comport == -1
-              && (port = search_pci_serial_devs(false)))
-            comport = port;
-        }
-
-      if (comport == -1)
-        comport = 1;
-
-      com_cons_init(comport);
-    }
-#else
-  (void)mbi;
-#endif
-
-}
-
-#ifdef ARCH_arm
-#ifndef IMAGE_MODE
-// check that our is_precious_ram function can work ok
-#error For ARM, IMAGE_MODE must always be enabled
-#endif
-
-/* Occupied RAM at the point we are scannig it */
+/* Occupied RAM at the point we are scanning it */
 static int
 is_precious_ram(unsigned long addr)
 {
   extern int _start, _end;
-  unsigned i, c = _module_info_end - _module_info_start;
 
   if ((unsigned long)&_start <= addr && addr <= (unsigned long)&_end)
     return 1;
 
+#ifdef IMAGE_MODE
+  unsigned i, c = _module_info_end - _module_info_start;
   if ((unsigned long)_module_info_start <= addr
        && addr <= (unsigned long)_module_info_end)
     return 1;
@@ -970,8 +1108,9 @@ is_precious_ram(unsigned long addr)
 
   for (i = 0; i < c; ++i)
     if (_module_info_start[i].start <= addr
-        && _module_info_start[i].start + _module_info_start[i].size_uncompressed <= addr)
+        && addr < _module_info_start[i].start + _module_info_start[i].size_uncompressed)
       return 1;
+#endif
 
   return 0;
 }
@@ -1002,7 +1141,6 @@ scan_ram_size(unsigned long base_addr, unsigned long max_scan_size_mb)
 
   return max_scan_size_mb;
 }
-#endif
 
 /**
  * \brief  Startup, started from crt0.S
@@ -1019,9 +1157,6 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
   boot_info_t boot_info;
   l4util_mb_mod_t *mb_mod;
 
-  /* fire up serial port if specificed on the command line */
-  init_pc_serial(mbi);
-
   if (!Platform_base::platform)
     {
       // will we ever see this?
@@ -1030,12 +1165,36 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
         ;
     }
 
+#ifdef LOADER_MBI
+  loader_mbi_add_cmdline(_mbi_cmdline);
+  mbi = loader_mbi();
+#endif
+
+  if (check_arg(mbi, "-wait"))
+    {
+      puts("\nL4 Bootstrapper is waiting for key input to continue...");
+      if (getchar() == -1)
+        puts("   ...no key input available.");
+      else
+        puts("    ...going on.");
+    }
+
   puts("\nL4 Bootstrapper");
-  puts("  Build: #" BUILD_NR " " BUILD_DATE);
+  puts("  Build: #" BUILD_NR " " BUILD_DATE
+#ifdef ARCH_x86
+      ", x86-32"
+#endif
+#ifdef ARCH_amd64
+      ", x86-64"
+#endif
+#ifdef __VERSION__
+       ", " __VERSION__
+#endif
+      );
 
-  regions.init(__regs, sizeof(__regs)/sizeof(__regs[0]), "regions");
-  ram.init(__ram, sizeof(__ram)/sizeof(__ram[0]), "RAM",
-           get_memory_limit(mbi));
+  regions.init(__regs, sizeof(__regs) / sizeof(__regs[0]), "regions");
+  ram.init(__ram, sizeof(__ram) / sizeof(__ram[0]), "RAM",
+           get_memory_max_size(mbi), get_memory_max_address());
 
 #ifdef ARCH_amd64
   // add the page-table on which we're running in 64bit mode
@@ -1049,34 +1208,32 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
 
 #ifdef REALMODE_LOADING
   /* create synthetic multi boot info */
-  mbi = init_loader_mbi(realmode_si);
+  mbi = init_loader_mbi_x86_realmode(realmode_si);
+  (void)flag;
 #else
   (void)realmode_si;
   assert(flag == L4UTIL_MB_VALID); /* we need to be multiboot-booted */
 #endif
 
 #elif defined(ARCH_arm)
-  l4util_mb_info_t my_mbi;
-  memset(&my_mbi, 0, sizeof(my_mbi));
-  mbi = &my_mbi;
+  mbi = loader_mbi();
 
   (void)realmode_si;
   (void)flag;
 
 #elif defined(ARCH_ppc32)
+  mbi = loader_mbi();
+
   (void)realmode_si;
   (void)flag;
 
-  l4util_mb_info_t my_mbi;
   L4_drivers::Of_if of_if;
 
   printf("  Detecting ram size ...\n");
   unsigned long ram_size = of_if.detect_ramsize();
   printf("    Total memory size is %luMB\n", ram_size / (1024 * 1024));
 
-  /* setup mbi and detect OF devices */
-  memset(&my_mbi, 0, sizeof(my_mbi));
-  mbi = &my_mbi;
+  /* detect OF devices */
   unsigned long drives_addr, drives_length;
 
   if (of_if.detect_devices(&drives_addr, &drives_length))
@@ -1087,6 +1244,11 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
     }
   ram.add(Region::n(0x0, ram_size, ".ram", Region::Ram));
 
+#elif defined(ARCH_sparc)
+  mbi = loader_mbi();
+
+  (void)realmode_si;
+  (void)flag;
 #else
 #error Unknown arch!
 #endif
@@ -1104,12 +1266,16 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
     roottask = 0;
 
   if (const char *s = check_arg(mbi, "-modaddr"))
-    _mod_addr = strtoul(s + 9, 0, 0);
+    _mod_addr = RAM_BASE + strtoul(s + 9, 0, 0);
+
+  _mod_addr = l4_round_page(_mod_addr);
 
 #ifdef IMAGE_MODE
   construct_mbi(mbi);
 #endif
 
+  reserve_mbi_memory(mbi);
+
   /* move vbe and ctrl structures to a known location, it might be in the
    * way when moving modules around */
 #if defined(ARCH_x86) || defined(ARCH_amd64)
@@ -1131,9 +1297,6 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
     }
 #endif
 
-  if (_mod_addr)
-    move_modules(mbi, _mod_addr);
-
   /* We need at least two boot modules */
   assert(mbi->flags & L4UTIL_MB_MODS);
   /* We have at least the L4 kernel and the first user task */
@@ -1143,6 +1306,9 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
   /* we're just a GRUB-booted kernel! */
   add_boot_modules_region(mbi);
 
+  if (_mod_addr)
+    move_modules(mbi, _mod_addr);
+
   if (const char *s = get_cmdline(mbi))
     {
       /* patch modules with content given at command line */
@@ -1150,7 +1316,6 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
        patch_module(&s, mbi);
     }
 
-
   add_elf_regions(mbi, kernel_module, Region::Kernel);
 
   if (sigma0)
@@ -1159,14 +1324,13 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
   if (roottask)
     add_elf_regions(mbi, roottask_module, Region::Root);
 
-
   /* copy Multiboot data structures, we still need to a safe place
    * before playing with memory we don't own and starting L4 */
   mb_info = relocate_mbi(mbi, &boot_info.mbi_low, &boot_info.mbi_high);
   if (!mb_info)
     panic("could not copy multiboot info to memory below 4MB");
 
-  mb_mod = (l4util_mb_mod_t*)mb_info->mods_addr;
+  mb_mod = (l4util_mb_mod_t *)(unsigned long)mb_info->mods_addr;
 
   /* --- Shouldn't touch original Multiboot parameters after here. -- */
 
@@ -1229,6 +1393,12 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
       fill_mem(fill_value);
     }
 
+  L4_kernel_options::Options *lko = find_kopts(l4i);
+  kcmdline_parse(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline), lko);
+  lko->uart   = kuart;
+  lko->flags |= kuart_flags;
+
+
   /* setup the L4 kernel info page before booting the L4 microkernel:
    * patch ourselves into the booter task addresses */
   unsigned long api_version = get_api_version(l4i);
@@ -1240,7 +1410,6 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
     case 0x03: // Version X.0 and X.1
     case 0x87: // Fiasco
       init_kip_v2(l4i, &boot_info, mb_info, &ram, &regions);
-      //init_kip_kuart_info(l4i, &kip_kernel_uart_info);
       break;
     case 0x84:
     case 0x04:
@@ -1287,6 +1456,14 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
   startup_func f = (startup_func)boot_info.kernel_start;
   of_if.boot_finish();
   f(&kernel_mbi, of_if.get_prom());
+
+#elif defined(ARCH_sparc)
+
+  printf("ENTER THE KERNEL!\n");
+  asm volatile("or %%g0,%0,%%g2\n\t"
+               "jmpl %%g2,%%g0\n\t"
+               "nop\n\t" : : "r"(boot_info.kernel_start));
+
 #else
 
 #error "How to enter the kernel?"
@@ -1318,9 +1495,8 @@ l4_exec_read_exec(void * handle,
   if (mem_addr + mem_size > exec_task->end)
     exec_task->end = mem_addr + mem_size;
 
-#ifdef VERBOSE_LOAD
-  printf("    [%p-%p]\n", (void *) mem_addr, (void *) (mem_addr + mem_size));
-#endif
+  if (Verbose_load)
+    printf("    [%p-%p]\n", (void *) mem_addr, (void *) (mem_addr + mem_size));
 
   if (!ram.contains(Region::n(mem_addr, mem_addr + mem_size)))
     {