]> 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 27bfe4b305201227d6291e69cbeb89471a7e243f..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
 #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
@@ -177,6 +177,22 @@ 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 && mbi->flags & L4UTIL_MB_CMDLINE)
@@ -220,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);
@@ -234,35 +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()
 {
-  unsigned long arch_limit = ~0UL;
 #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. */
-  arch_limit = 3024UL << 20;
+  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 (char *c = check_arg(mbi, "-maxmem="))
-    {
-      unsigned long l = strtoul(c + 8, NULL, 10) << 20;
-      if (l < arch_limit)
-       return l;
-    }
+    return strtoul(c + 8, NULL, 10) << 20;
 
-  return arch_limit;
+  return ~0UL;
 }
 
 static int
@@ -307,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)
 {
@@ -315,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);
@@ -391,6 +436,72 @@ static void fill_mem(unsigned fill_value)
     }
 }
 
+static void
+move_module(l4util_mb_info_t *mbi, int i, Region *from, Region *to,
+            bool overlap_check)
+{
+  unsigned long start = from->begin();
+  unsigned long size = from->end() - start + 1;
+
+  if (Verbose_load)
+    {
+      unsigned char c[5];
+      c[0] = *(unsigned char*)(start + 0);
+      c[1] = *(unsigned char*)(start + 1);
+      c[2] = *(unsigned char*)(start + 2);
+      c[3] = *(unsigned char*)(start + 3);
+      c[4] = 0;
+      c[0] = c[0] < 32 ? '.' : c[0];
+      c[1] = c[1] < 32 ? '.' : c[1];
+      c[2] = c[2] < 32 ? '.' : c[2];
+      c[3] = c[3] < 32 ? '.' : c[3];
+      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("%08x%s", *(unsigned *)(start + a), (a % 32 == 28) ? "\n" : " ");
+      printf("\n");
+    }
+  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");
+
+  if (overlap_check)
+    {
+      Region *overlap = regions.find(*to);
+      if (overlap)
+        {
+          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.
@@ -400,64 +511,123 @@ static void fill_mem(unsigned fill_value)
 static void
 move_modules(l4util_mb_info_t *mbi, unsigned long modaddr)
 {
-  long offset = modaddr - (L4_MB_MOD_PTR(mbi->mods_addr))[0].mod_start;
-  unsigned i, i_end;
-  unsigned dir = offset > 0 ? -1 : 1;
+  printf("  Moving up to %d modules behind %lx\n", mbi->mods_count, modaddr);
 
-  if (!offset)
+  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)
     {
-      printf("  => Images in place\n");
-      return;
+      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;
     }
 
-  printf("  Moving %d modules to %lx with offset %lx\n",
-         mbi->mods_count, modaddr, offset);
-
-  i     = dir == 1 ? 1 : mbi->mods_count;
-  i_end = dir == 1 ? mbi->mods_count + 1 : 0;
-  for (; i != i_end ; i += dir)
+  for (unsigned i = 0; i < mbi->mods_count; ++i)
     {
-      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;
+      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;
 
-#ifdef VERBOSE_LOAD
-      unsigned char c[5];
-      c[0] = *(unsigned char*)(start + 0);
-      c[1] = *(unsigned char*)(start + 1);
-      c[2] = *(unsigned char*)(start + 2);
-      c[3] = *(unsigned char*)(start + 3);
-      c[4] = 0;
-      c[0] = c[0] < 32 ? '.' : c[0];
-      c[1] = c[1] < 32 ? '.' : c[1];
-      c[2] = c[2] < 32 ? '.' : c[2];
-      c[3] = c[3] < 32 ? '.' : c[3];
-      printf("  moving module %02d { %lx, %lx } (%s) -> { %lx - %lx }\n",
-             i, start, end, c, start + offset, end + offset);
+      Region from(start, end - 1);
+      Region *this_module = regions.find(from);
+      assert(this_module->begin() == from.begin()
+             && this_module->end() == from.end());
 
-      for (int a = 0; a < 0x100; a += 4)
-       printf("%08lx%s", *(unsigned long *)(start + a), (a % 32 == 28) ? "\n" : " ");
-      printf("\n");
-#else
-      printf("  moving module %02d { %lx-%lx } -> { %lx-%lx }\n",
-             i, start, end, start + offset, end + offset);
-#endif
+      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;
+        }
 
-      Region *overlap = regions.find(Region(start + offset, end + offset));
-      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;
+      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);
     }
 }
 
@@ -475,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.
@@ -482,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()).
@@ -501,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);
 
@@ -519,22 +716,18 @@ 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
+          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);
     }
 }
@@ -592,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)
@@ -606,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,
@@ -650,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
@@ -686,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 *
@@ -751,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),
@@ -821,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
@@ -920,66 +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;
-  int pci = 0;
-
-  if ((s = check_arg(mbi, "-comport")))
-    {
-      char const *a = s + 9;
-      if (!strncmp(a, "pci:", 4))
-       {
-         pci = 1;
-         a = a + 4;
-       }
-    
-      comport = strtoul(a, 0, 0);
-    }
-
-  if (check_arg(mbi, "-serial"))
-    {
-      if (pci)
-        {
-          extern unsigned long search_pci_serial_devs(int port_idx, bool scan_only);
-          if (unsigned long port = search_pci_serial_devs(comport, true))
-            comport = port;
-         else
-           comport = -1;
-
-         printf("PCI IO port = %x\n", comport);
-        }
-
-      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;
@@ -990,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;
 }
@@ -1022,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
@@ -1039,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?
@@ -1050,6 +1165,20 @@ 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
 #ifdef ARCH_x86
@@ -1063,9 +1192,9 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
 #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
@@ -1079,7 +1208,7 @@ 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;
@@ -1087,27 +1216,24 @@ startup(l4util_mb_info_t *mbi, l4_umword_t flag,
 #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))
@@ -1118,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
@@ -1135,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)
@@ -1162,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 */
@@ -1174,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 */
@@ -1181,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)
@@ -1190,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. -- */
 
@@ -1260,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);
@@ -1271,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:
@@ -1318,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?"
@@ -1349,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)))
     {