]> rtime.felk.cvut.cz Git - l4.git/commitdiff
fiasco: bootstrap: copy bootstrap into bootstrap_custom for to port this into Jailhouse.
authorMaxim Baryshnikov <barysmax@fel.cvut.cz>
Mon, 11 Apr 2016 11:16:55 +0000 (13:16 +0200)
committerMaxim Baryshnikov <barysmax@fel.cvut.cz>
Mon, 11 Apr 2016 11:16:55 +0000 (13:16 +0200)
130 files changed:
l4/pkg/bootstrap_custom/Control [new file with mode: 0644]
l4/pkg/bootstrap_custom/LEGAL [new file with mode: 0644]
l4/pkg/bootstrap_custom/Makefile [new file with mode: 0644]
l4/pkg/bootstrap_custom/README [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/Makefile [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot.S [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_cpu.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_cpu.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_idt.S [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_kernel.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_paging.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/bootstrap32.ld [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/load_elf.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/load_elf.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/minilibc_support.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/crt0.S [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/Makefile [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/__assert_fail.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/__lltostr.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/__ltostr.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/__v_printf.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/assert.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/cdefs.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/ctype.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/libc_backend.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/memcpy.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/panic.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stdarg-cruft.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stdarg.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stddef.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stdio.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stdlib.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/string.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/strings.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/isspace.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/memcpy.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/memmove.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/memset.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/printf.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/puts.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/strtol.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/strtoul.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/vprintf.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/vprintf_backend.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-amd64/macros.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-arm/bootstrap.ld.in [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-arm/crt0.S [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-arm/head.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-arm/macros.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-arm/reboot.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/bootstrap.ld.in [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/crt0.S [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/head.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/init_kip_v2-arch.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/macros.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/reboot.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-sparc/bootstrap.ld.in [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-sparc/crt0.S [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-sparc/head.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-sparc/leon_ahb.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-sparc/macros.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-sparc/reboot.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-x86/bootsect.S [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-x86/bootstrap.ld.in [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-x86/crt0.S [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-x86/inmate.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-x86/macros.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-x86/reboot.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-x86/setup.S [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ARCH-x86/xen.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/Make.rules [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/Makeconf.local [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/Makefile [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/Makefile.platform [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/README [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/base_critical.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/base_critical.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/boot_modules.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/build.pl [new file with mode: 0755]
l4/pkg/bootstrap_custom/server/src/exec.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/exec.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/gunzip.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/gunzip.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/init_kip-arch.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/init_kip.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/init_kip_f.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/koptions-def.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/koptions.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/koptions.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/ldscript.inc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/libc_support+.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/memory.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/mod_info.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/module.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/module.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/panic.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/patch.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/patch.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/armada38x.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/exynos.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/imx.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/integrator.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/kirkwood.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/leon3.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/mmio_16550.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/mpc5200.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/om.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/omap.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/pxa.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/rpi.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/rv.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/rv_vexpress.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/sa1000.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/sunxi.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/tegra2.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/tegra3.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/x86_efi_pc.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/x86_pc-base.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/x86_pc.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform/zynq.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/platform_common.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/region.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/region.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/startup.cc [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/startup.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/support.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/types.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/uncompress.c [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/uncompress.h [new file with mode: 0644]
l4/pkg/bootstrap_custom/server/src/unpack [new file with mode: 0755]

diff --git a/l4/pkg/bootstrap_custom/Control b/l4/pkg/bootstrap_custom/Control
new file mode 100644 (file)
index 0000000..ac78c53
--- /dev/null
@@ -0,0 +1,2 @@
+requires: drivers_uart drivers_of libc_minimal l4util cxx_io
+Maintainer: adam@os.inf.tu-dresden.de warg@os.inf.tu-dresden.de
diff --git a/l4/pkg/bootstrap_custom/LEGAL b/l4/pkg/bootstrap_custom/LEGAL
new file mode 100644 (file)
index 0000000..1ade4a8
--- /dev/null
@@ -0,0 +1,43 @@
+# Format: (all on one line)
+#   Source file : Copyright Owner(s) : License
+# Please use "TUD" when referring to TU Dresden.
+# If sole owner is TUD, the license field defaults to GPL and can be
+# left empty.
+# Source-file spec can be a directory name or a wildcard like "src/*.c".
+Makefile : TUD
+server/Makefile : TUD
+server/src/ARCH-x86/bootsect.S : GPL
+server/src/ARCH-x86/bootstrap.ld.in : TUD
+server/src/ARCH-x86/crt0.S : TUD
+server/src/ARCH-x86/oskit_support.c : TUD
+server/src/ARCH-x86/serial.c : TUD
+server/src/ARCH-x86/serial.h : TUD
+server/src/ARCH-x86/setup.S : GPL
+server/src/ARCH-x86/xen.c
+server/src/ARCH-arm/bootstrap.ld.in : TUD
+server/src/Makefile : TUD
+server/src/base_critical.c : TUD
+server/src/base_critical.h : TUD
+server/src/build.pl : TUD
+server/src/exec.c : TUD
+server/src/exec.h : TUD
+server/src/gunzip.c : GPL
+server/src/gunzip.h : GPL
+server/src/init.h : TUD
+server/src/init_hazelnut.c : TUD
+server/src/init_ibm_nucleus.c : TUD
+server/src/init_l4_gmd.c : TUD
+server/src/libc_support.c : TUD
+server/src/loader_mbi.c : TUD
+server/src/loader_mbi.h : TUD
+server/src/module.h : TUD
+server/src/modules.list : TUD
+server/src/region.c : TUD
+server/src/region.h : TUD
+server/src/startup.c : TUD
+server/src/startup.h : TUD
+server/src/types.h : TUD : TUD
+server/src/uncompress.c : TUD
+server/src/uncompress.h : TUD
+server/src/version.h : TUD
+
diff --git a/l4/pkg/bootstrap_custom/Makefile b/l4/pkg/bootstrap_custom/Makefile
new file mode 100644 (file)
index 0000000..f8ca7cc
--- /dev/null
@@ -0,0 +1,4 @@
+PKGDIR = .
+L4DIR  ?= $(PKGDIR)/../..
+
+include $(L4DIR)/mk/subdir.mk
diff --git a/l4/pkg/bootstrap_custom/README b/l4/pkg/bootstrap_custom/README
new file mode 100644 (file)
index 0000000..850419c
--- /dev/null
@@ -0,0 +1,40 @@
+L4 Bootstrapper for booting Fiasco and other L4 compatible kernels.
+
+Command line parameters (in alphabetical order):
+
+  -comport=<port>
+      If serial logging is enabled, <port> defines which serial port to use,
+      where 1 is the first port found.
+      NOTE: Bootstrap does not support the -comspeed=<speed> option and uses
+      the port with 115200 bps.
+
+  -hercules
+      --- DOCUMENTATION MISSING ---
+
+  -maxmem=<size in MB>
+      Set the mem_upper field of the multiboot info structure.
+
+  -patch=<modname>,<text>=<replacement>,...
+      <modname> is compared with the path name of each module to decide which
+      module should be patched. If the module was found, each occurrence of
+      <text> is replaced by <replacement>. <replacement> can also be quoted
+      text. Otherwise no spaces are allowed.
+
+  -arg=<modname>,<replacement>
+      <modname> is compared with the path name of each module to decide which
+      module arguments should be replaced. If the module was found, the module
+      arguments, that is all text of the module command line after the first
+      ' ' is replaced by <replacement>. <replacement> can also be quoted text.
+
+  -roottask
+      No effect -- Provided for compatibility with RMGR.
+
+  -serial
+      Enables support for logging to serial line.
+
+  -sigma0
+      No effect -- Provided for compatibility with RMGR.
+
+  -modaddr=<addr>
+      Relocate modules to the physical address ADDR.  Eliminates the
+      need for a specialized GRUB that supports the modaddr command.
diff --git a/l4/pkg/bootstrap_custom/server/Makefile b/l4/pkg/bootstrap_custom/server/Makefile
new file mode 100644 (file)
index 0000000..04ac0da
--- /dev/null
@@ -0,0 +1,4 @@
+PKGDIR         ?= ..
+L4DIR          ?= $(PKGDIR)/../..
+
+include $(L4DIR)/mk/subdir.mk
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot.S b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot.S
new file mode 100644 (file)
index 0000000..c67c912
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * (c) 2009 Frank Mehnert <fm3@os.inf.tu-dresden.de>,
+ *          Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ *     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.
+ */
+/* -*- c -*- */
+
+       .globl  _start
+       .p2align 4
+_start:
+#ifdef REALMODE_LOADING
+       cld
+       cli
+       mov     $(3 * 8), %eax
+       mov     %eax, %ds
+       mov     %eax, %es
+       mov     %eax, %fs
+       mov     %eax, %gs
+
+       /* We have the following problem: Our image is loaded at 0x00100000
+        * by the boot loader but we don't want to get into conflict with
+        * the AMD64 executable. Therefore we move ourself out of the way.
+        * We are linked to 0x01000000 (see ARCH-amd64/boot32/bootstrap.ld) */
+       mov     %esi, %ebx
+       mov     $0x00100000, %esi
+       mov     $0x01000000, %edi
+       mov     $_image_end, %ecx
+       sub     $_image_start, %ecx
+       rep     movsb
+       mov     $1f, %eax
+       jmp     *%eax
+1:     mov     %ebx, %esi
+       lss     _stack_seg, %esp
+#else
+       leal    _stack,%esp
+#endif
+
+       pushl   %esi                    /* ptr to real mode */
+       pushl   %eax
+       pushl   %ebx
+       pushl   $0                      /* no return address */
+       jmp     bootstrap
+
+        .align  4
+
+       .p2align(2), 0x90
+       .long   0x1BADB002              /* magic */
+       .long   0x00000000              /* feature flags */
+       .long   0 - 0x1BADB002
+
+#ifdef REALMODE_LOADING
+_stack_seg:
+       .long   _stack
+       .word   (3 * 8)
+#endif
+
+       .bss
+       .space  8192
+_stack:
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_cpu.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_cpu.c
new file mode 100644 (file)
index 0000000..87cf1a4
--- /dev/null
@@ -0,0 +1,639 @@
+/*
+ * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *          Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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 <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "types.h"
+#include "boot_cpu.h"
+#include "boot_paging.h"
+
+
+unsigned  KERNEL_CS_64         = 0x20; // XXX
+
+enum
+{
+  PML4ESHIFT           = 38,
+  PML4EMASK            = 0x1ff,
+  PDPESHIFT            = 30,
+  PDPEMASK             = 0x1ff,
+  PDESHIFT             = 21,
+  PDEMASK              = 0x1ff,
+  PTESHIFT             = 12,
+  PTEMASK              = 0x1ff,
+
+  INTEL_PTE_VALID      = 0x0000000000000001LL,
+  INTEL_PTE_WRITE      = 0x0000000000000002LL,
+  INTEL_PTE_USER       = 0x0000000000000004LL,
+  INTEL_PTE_WTHRU      = 0x00000008,
+  INTEL_PTE_NCACHE      = 0x00000010,
+  INTEL_PTE_REF                = 0x00000020,
+  INTEL_PTE_MOD                = 0x00000040,
+  INTEL_PTE_GLOBAL     = 0x00000100,
+  INTEL_PTE_AVAIL      = 0x00000e00,
+  INTEL_PTE_PFN                = 0x000ffffffffff000LL,
+
+  INTEL_PDE_VALID      = 0x0000000000000001LL,
+  INTEL_PDE_WRITE      = 0x0000000000000002LL,
+  INTEL_PDE_USER       = 0x0000000000000004LL,
+  INTEL_PDE_WTHRU      = 0x00000008,
+  INTEL_PDE_NCACHE      = 0x00000010,
+  INTEL_PDE_REF                = 0x00000020,
+  INTEL_PDE_MOD                = 0x00000040,
+  INTEL_PDE_SUPERPAGE  = 0x0000000000000080LL,
+  INTEL_PDE_GLOBAL     = 0x00000100,
+  INTEL_PDE_AVAIL      = 0x00000e00,
+  INTEL_PDE_PFN                = 0x000ffffffffff000LL,
+
+  INTEL_PDPE_VALID     = 0x0000000000000001LL,
+  INTEL_PDPE_WRITE     = 0x0000000000000002LL,
+  INTEL_PDPE_USER      = 0x0000000000000004LL,
+  INTEL_PDPE_PFN       = 0x000ffffffffff000LL,
+
+  INTEL_PML4E_VALID    = 0x0000000000000001LL,
+  INTEL_PML4E_WRITE    = 0x0000000000000002LL,
+  INTEL_PML4E_USER     = 0x0000000000000004LL,
+  INTEL_PML4E_PFN      = 0x000ffffffffff000LL,
+
+  CPUF_4MB_PAGES       = 0x00000008,
+
+  CR0_PG               = 0x80000000,
+  CR4_PSE              = 0x00000010,
+  CR4_PAE              = 0x00000020,
+  EFL_AC               = 0x00040000,
+  EFL_ID               = 0x00200000,
+  EFER_LME             = 0x00000100,
+
+  BASE_TSS             = 0x08,
+  KERNEL_CS            = 0x10,
+  KERNEL_DS            = 0x18,
+
+  DBF_TSS              = 0x28, // XXX check this value
+
+  ACC_TSS              = 0x09,
+  ACC_TSS_BUSY         = 0x02,
+  ACC_CODE_R           = 0x1a,
+  ACC_DATA_W           = 0x12,
+  ACC_PL_K             = 0x00,
+  ACC_P                        = 0x80,
+  SZ_32                        = 0x4,
+  SZ_16                        = 0x0,
+  SZ_G                 = 0x8,
+  SZ_CODE_64           = 0x2, // XXX 64 Bit Code Segment
+
+  GDTSZ                        = (0x30/8), // XXX check this value
+  IDTSZ                        = 256,
+};
+
+
+struct pseudo_descriptor
+{
+  l4_uint16_t pad;
+  l4_uint16_t limit;
+  l4_uint32_t linear_base;
+};
+
+struct x86_desc
+{
+  l4_uint16_t limit_low;               /* limit 0..15 */
+  l4_uint16_t base_low;                /* base  0..15 */
+  l4_uint8_t  base_med;                /* base  16..23 */
+  l4_uint8_t  access;          /* access byte */
+  l4_uint8_t  limit_high:4;    /* limit 16..19 */
+  l4_uint8_t  granularity:4;   /* granularity */
+  l4_uint8_t  base_high;               /* base 24..31 */
+} __attribute__((packed));
+
+struct x86_gate
+{
+  l4_uint16_t offset_low;      /* offset 0..15 */
+  l4_uint16_t selector;
+  l4_uint8_t  word_count;
+  l4_uint8_t  access;
+  l4_uint16_t offset_high;     /* offset 16..31 */
+} __attribute__((packed));
+
+struct x86_tss
+{
+  l4_uint32_t back_link;
+  l4_uint32_t esp0, ss0;
+  l4_uint32_t esp1, ss1;
+  l4_uint32_t esp2, ss2;
+  l4_uint32_t cr3;
+  l4_uint32_t eip, eflags;
+  l4_uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi;
+  l4_uint32_t es, cs, ss, ds, fs, gs;
+  l4_uint32_t ldt;
+  l4_uint16_t trace_trap;
+  l4_uint16_t io_bit_map_offset;
+};
+
+struct gate_init_entry
+{
+  l4_uint32_t entrypoint;
+  l4_uint16_t vector;
+  l4_uint16_t type;
+};
+
+struct trap_state
+{
+  l4_uint32_t gs, fs, es, ds;
+  l4_uint32_t edi, esi, ebp, cr2, ebx, edx, ecx, eax;
+  l4_uint32_t trapno, err;
+  l4_uint32_t eip, cs, eflags, esp, ss;
+};
+
+static l4_uint32_t       cpu_feature_flags;
+static l4_uint32_t        base_pml4_pa;
+static struct x86_tss   base_tss;
+static struct x86_desc  base_gdt[GDTSZ];
+static struct x86_gate  base_idt[IDTSZ];
+
+static void handle_dbf(void);
+static char           dbf_stack[2048];
+static struct x86_tss dbf_tss =
+  {
+    0/*back_link*/,
+    0/*esp0*/, 0/*ss0*/, 0/*esp1*/, 0/*ss1*/, 0/*esp2*/, 0/*ss2*/,
+    0/*cr3*/,
+    (l4_uint32_t)handle_dbf/*eip*/, 0x00000082/*eflags*/,
+    0/*eax*/, 0/*ecx*/, 0/*edx*/, 0/*ebx*/,
+    (l4_uint32_t)dbf_stack + sizeof(dbf_stack)/*esp*/,
+    0/*ebp*/, 0/*esi*/, 0/*edi*/,
+    KERNEL_DS/*es*/, KERNEL_CS/*cs*/, KERNEL_DS/*ss*/,
+    KERNEL_DS/*ds*/, KERNEL_DS/*fs*/, KERNEL_DS/*gs*/,
+    0/*ldt*/, 0/*trace_trap*/, 0x8000/*io_bit_map_offset*/
+  };
+
+static inline l4_uint64_t* find_pml4e(l4_uint32_t pml4_pa, l4_uint64_t la)
+{ return (&((l4_uint64_t*)pml4_pa)[(la >> PML4ESHIFT) & PML4EMASK]); }
+
+static inline l4_uint64_t* find_pdpe(l4_uint32_t pdp_pa, l4_uint64_t la)
+{ return (&((l4_uint64_t*)pdp_pa)[(la >> PDPESHIFT) & PDPEMASK]); }
+
+static inline l4_uint64_t* find_pde(l4_uint32_t pdir_pa, l4_uint64_t la)
+{ return (&((l4_uint64_t*)pdir_pa)[(la >> PDESHIFT) & PDEMASK]); }
+
+static inline l4_uint64_t* find_pte(l4_uint32_t ptab_pa, l4_uint64_t la)
+{ return (&((l4_uint64_t*)ptab_pa)[(la >> PTESHIFT) & PTEMASK]); }
+
+static inline l4_uint32_t get_eflags(void)
+{ l4_uint32_t efl; asm volatile("pushf ; popl %0" : "=r" (efl)); return efl; }
+
+static inline void set_eflags(l4_uint32_t efl)
+{ asm volatile("pushl %0 ; popf" : : "r" (efl) : "memory"); }
+
+static inline void set_ds(l4_uint16_t ds)
+{ asm volatile("movw %w0,%%ds" : : "r" (ds)); }
+
+static inline void set_es(l4_uint16_t es)
+{ asm volatile("movw %w0,%%es" : : "r" (es)); }
+
+static inline void set_fs(l4_uint16_t fs)
+{ asm volatile("movw %w0,%%fs" : : "r" (fs)); }
+
+static inline void set_gs(l4_uint16_t gs)
+{ asm volatile("movw %w0,%%gs" : : "r" (gs)); }
+
+static inline void set_ss(l4_uint16_t ss)
+{ asm volatile("movw %w0,%%ss" : : "r" (ss)); }
+
+static inline l4_uint16_t get_ss(void)
+{ l4_uint16_t ss; asm volatile("movw %%ss,%w0" : "=r" (ss)); return ss; }
+
+#define set_idt(pseudo_desc) \
+ asm volatile("lidt %0" : : "m" ((pseudo_desc)->limit) : "memory")
+
+#define set_gdt(pseudo_desc) \
+ asm volatile("lgdt %0" : : "m" ((pseudo_desc)->limit) : "memory")
+
+#define        set_tr(seg) \
+ asm volatile("ltr %0" : : "rm" ((l4_uint16_t)(seg)))
+
+#define get_esp() \
+ ({ register l4_uint32_t _temp__; \
+    asm("movl %%esp, %0" : "=r" (_temp__)); _temp__; })
+
+#define        get_cr0() \
+ ({ register l4_uint32_t _temp__; \
+    asm volatile("mov %%cr0, %0" : "=r" (_temp__)); _temp__; })
+
+#define        set_cr3(value) \
+ ({ register l4_uint32_t _temp__ = (value); \
+    asm volatile("mov %0, %%cr3" : : "r" (_temp__)); })
+
+#define get_cr4() \
+ ({ register l4_uint32_t _temp__; \
+    asm volatile("mov %%cr4, %0" : "=r" (_temp__)); _temp__; })
+
+#define set_cr4(value) \
+ ({ register l4_uint32_t _temp__ = (value); \
+    asm volatile("mov %0, %%cr4" : : "r" (_temp__)); })
+
+
+static inline void enable_longmode(void)
+{
+  l4_uint32_t dummy;
+  asm volatile("rdmsr; bts $8, %%eax; wrmsr"
+               :"=a"(dummy), "=d"(dummy) : "c"(0xc0000080));
+}
+
+static inline void
+fill_descriptor(struct x86_desc *desc, l4_uint32_t base, l4_uint32_t limit,
+               l4_uint8_t access, l4_uint8_t sizebits)
+{
+  if (limit > 0xfffff)
+    {
+      limit >>= 12;
+      sizebits |= SZ_G;
+    }
+  desc->limit_low = limit & 0xffff;
+  desc->base_low = base & 0xffff;
+  desc->base_med = (base >> 16) & 0xff;
+  desc->access = access | ACC_P;
+  desc->limit_high = limit >> 16;
+  desc->granularity = sizebits;
+  desc->base_high = base >> 24;
+}
+
+static inline void
+fill_gate(struct x86_gate *gate, l4_uint32_t offset,
+         l4_uint16_t selector, l4_uint8_t access)
+{
+  gate->offset_low  = offset & 0xffff;
+  gate->selector    = selector;
+  gate->word_count  = 0;
+  gate->access      = access | ACC_P;
+  gate->offset_high = (offset >> 16) & 0xffff;
+}
+
+static inline void
+paging_enable(l4_uint32_t pml4)
+{
+  /* Enable Physical l4_uint64_t Extension (PAE). */
+  set_cr4(get_cr4() | CR4_PAE);
+
+  /* Load the page map level 4.  */
+  set_cr3(pml4);
+
+  /* Enable long mode. */
+  enable_longmode();
+
+  /* Turn on paging and switch to long mode. */
+  asm volatile("movl  %0,%%cr0 ; jmp  1f ; 1:" : : "r" (get_cr0() | CR0_PG));
+}
+
+static void
+panic(const char *str)
+{
+  printf("PANIC: %s\n", str);
+  while (1)
+    ;
+  _exit(-1);
+}
+
+static void
+cpuid(void)
+{
+  int orig_eflags = get_eflags();
+
+  /* Check for a dumb old 386 by trying to toggle the AC flag.  */
+  set_eflags(orig_eflags ^ EFL_AC);
+  if ((get_eflags() ^ orig_eflags) & EFL_AC)
+    {
+      /* It's a 486 or better.  Now try toggling the ID flag.  */
+      set_eflags(orig_eflags ^ EFL_ID);
+      if ((get_eflags() ^ orig_eflags) & EFL_ID)
+       {
+         int highest_val, dummy;
+         asm volatile("cpuid"
+                       : "=a" (highest_val)
+                       : "a" (0) : "ebx", "ecx", "edx");
+
+         if (highest_val >= 1)
+           {
+             asm volatile("cpuid"
+                          : "=a" (dummy),
+                             "=d" (cpu_feature_flags)
+                          : "a" (1)
+                          : "ebx", "ecx");
+           }
+       }
+    }
+
+  set_eflags(orig_eflags);
+}
+
+extern struct gate_init_entry boot_idt_inittab[];
+static void
+base_idt_init(void)
+{
+  struct x86_gate *dst = base_idt;
+  const struct gate_init_entry *src = boot_idt_inittab;
+
+  while (src->entrypoint)
+    {
+      if ((src->type & 0x1f) == 0x05)
+       // task gate
+       fill_gate(&dst[src->vector], 0, src->entrypoint, src->type);
+      else
+       // interrupt gate
+       fill_gate(&dst[src->vector], src->entrypoint, KERNEL_CS, src->type);
+      src++;
+    }
+}
+
+static void
+base_gdt_init(void)
+{
+  /* Initialize the base TSS descriptor.  */
+  fill_descriptor(&base_gdt[BASE_TSS / 8],
+                 (l4_uint32_t)&base_tss, sizeof(base_tss) - 1,
+                  ACC_PL_K | ACC_TSS, 0);
+  /* Initialize the TSS descriptor for the double fault handler */
+  fill_descriptor(&base_gdt[DBF_TSS / 8],
+                 (l4_uint32_t)&dbf_tss, sizeof(dbf_tss) - 1,
+                 ACC_PL_K | ACC_TSS, 0);
+  /* Initialize the 32-bit kernel code and data segment descriptors
+     to point to the base of the kernel linear space region.  */
+  fill_descriptor(&base_gdt[KERNEL_CS / 8], 0, 0xffffffff,
+                  ACC_PL_K | ACC_CODE_R, SZ_32);
+  fill_descriptor(&base_gdt[KERNEL_DS / 8], 0, 0xffffffff,
+                  ACC_PL_K | ACC_DATA_W, SZ_32);
+  /* XXX Initialize the 64-bit kernel code segment descriptor */
+  fill_descriptor(&base_gdt[KERNEL_CS_64 / 8], 0, 0xffffffff,
+                  ACC_PL_K | ACC_CODE_R, SZ_CODE_64);
+}
+
+static void
+base_tss_init(void)
+{
+  base_tss.ss0 = KERNEL_DS;
+  base_tss.esp0 = get_esp(); /* only temporary */
+  base_tss.io_bit_map_offset = sizeof(base_tss);
+}
+
+static void
+base_gdt_load(void)
+{
+  struct pseudo_descriptor pdesc;
+
+  /* Create a pseudo-descriptor describing the GDT.  */
+  pdesc.limit = sizeof(base_gdt) - 1;
+  pdesc.linear_base = (l4_uint32_t)&base_gdt;
+
+  /* Load it into the CPU.  */
+  set_gdt(&pdesc);
+
+  /* Reload all the segment registers from the new GDT. */
+  asm volatile("ljmp  %0,$1f ;  1:" : : "i" (KERNEL_CS));
+  set_ds(KERNEL_DS);
+  set_es(KERNEL_DS);
+  set_ss(KERNEL_DS);
+  set_fs(0);
+  set_gs(0);
+}
+
+static void
+base_idt_load(void)
+{
+  struct pseudo_descriptor pdesc;
+
+  /* Create a pseudo-descriptor describing the GDT.  */
+  pdesc.limit = sizeof(base_idt) - 1;
+  pdesc.linear_base = (l4_uint32_t)&base_idt;
+  set_idt(&pdesc);
+}
+
+static void
+base_tss_load(void)
+{
+  /* Make sure the TSS isn't marked busy.  */
+  base_gdt[BASE_TSS / 8].access &= ~ACC_TSS_BUSY;
+  asm volatile ("" : : : "memory");
+  set_tr(BASE_TSS);
+}
+
+void
+base_cpu_setup(void)
+{
+  cpuid();
+  base_idt_init();
+  base_gdt_init();
+  base_tss_init();
+  // force tables to memory before loading segment registers
+  asm volatile ("" : : : "memory");
+  base_gdt_load();
+  base_idt_load();
+  base_tss_load();
+}
+
+struct ptab64_mem_info_t ptab64_mem_info;
+
+static void
+ptab_alloc(l4_uint32_t *out_ptab_pa)
+{
+  static char pool[6 << 12] __attribute__((aligned(4096)));
+  static l4_uint32_t pdirs;
+  static int initialized;
+
+  if (! initialized)
+    {
+      initialized = 1;
+      ptab64_mem_info.addr = (l4_uint32_t)pool;
+      ptab64_mem_info.size = sizeof(pool);
+      memset(pool, 0, sizeof(pool));
+      pdirs = ((l4_uint32_t)pool + PAGE_SIZE - 1) & ~PAGE_MASK;
+    }
+
+  if (pdirs > (l4_uint32_t)pool + sizeof(pool))
+    panic("Cannot allocate page table -- increase ptab_alloc::pool");
+
+  *out_ptab_pa = pdirs;
+  pdirs += PAGE_SIZE;
+}
+
+static void
+pdir_map_range(l4_uint32_t pml4_pa, l4_uint64_t la, l4_uint64_t pa,
+               l4_uint64_t size, l4_uint32_t mapping_bits)
+{
+  assert(size);
+  assert(la+size-1 > la); // avoid 4GB wrap around
+
+  while (size > 0)
+    {
+      l4_uint64_t *pml4e = find_pml4e(pml4_pa, la);
+
+      /* Create new pml4e with corresponding pdp (page directory pointer)
+       * if no valid entry exists. */
+      if (!(*pml4e & INTEL_PML4E_VALID))
+       {
+         l4_uint32_t pdp_pa;
+
+         /* Allocate new page for pdp. */
+         ptab_alloc(&pdp_pa);
+
+         /* Set the pml4 to point to it. */
+         *pml4e = (pdp_pa & INTEL_PML4E_PFN)
+           | INTEL_PML4E_VALID | INTEL_PML4E_USER | INTEL_PML4E_WRITE;
+       }
+
+      do
+       {
+         l4_uint64_t *pdpe = find_pdpe(*pml4e & INTEL_PML4E_PFN, la);
+
+         /* Create new pdpe with corresponding pd (page directory)
+          * if no valid entry exists. */
+         if (!(*pdpe & INTEL_PDPE_VALID))
+           {
+             l4_uint32_t pd_pa;
+
+             /* Allocate new page for pd. */
+             ptab_alloc(&pd_pa);
+
+             /* Set the pdpe to point to it. */
+             *pdpe = (pd_pa & INTEL_PDPE_PFN)
+               | INTEL_PDPE_VALID | INTEL_PDPE_USER | INTEL_PDPE_WRITE;
+           }
+
+         do
+           {
+             l4_uint64_t *pde = find_pde(*pdpe & INTEL_PDPE_PFN, la);
+
+             /* Use a 2MB page if we can.  */
+             if (superpage_aligned(la) && superpage_aligned(pa)
+                 && (size >= SUPERPAGE_SIZE))
+                 //&& (cpu_feature_flags & CPUF_4MB_PAGES)) XXX
+               {
+                 /* a failed assertion here may indicate a memory wrap
+                    around problem */
+                 assert(!(*pde & INTEL_PDE_VALID));
+                 /* XXX what if an empty page table exists
+                    from previous finer-granularity mappings? */
+                 *pde = pa | mapping_bits | INTEL_PDE_SUPERPAGE;
+                 la += SUPERPAGE_SIZE;
+                 pa += SUPERPAGE_SIZE;
+                 size -= SUPERPAGE_SIZE;
+               }
+             else
+               {
+                 /* Find the page table, creating one if necessary.  */
+                 if (!(*pde & INTEL_PDE_VALID))
+                   {
+                     l4_uint32_t ptab_pa;
+
+                     /* Allocate a new page table.  */
+                     ptab_alloc(&ptab_pa);
+
+                     /* Set the pde to point to it.  */
+                     *pde = (ptab_pa & INTEL_PTE_PFN)
+                       | INTEL_PDE_VALID | INTEL_PDE_USER | INTEL_PDE_WRITE;
+                   }
+                 assert(!(*pde & INTEL_PDE_SUPERPAGE));
+
+
+                 /* Use normal 4KB page mappings.  */
+                 do
+                   {
+                     l4_uint64_t *pte = find_pte(*pde & INTEL_PDE_PFN, la);
+                     assert(!(*pte & INTEL_PTE_VALID));
+
+                     /* Insert the mapping.  */
+                     *pte = pa | mapping_bits;
+
+                     /* Advance to the next page.  */
+                     //pte++;
+                     la += PAGE_SIZE;
+                     pa += PAGE_SIZE;
+                     size -= PAGE_SIZE;
+                   }
+                 while ((size > 0) && !superpage_aligned(la));
+               }
+           }
+         while ((size > 0) && !pd_aligned(la));
+       }
+      while ((size > 0) && !pdp_aligned(la));
+    }
+}
+
+void
+base_paging_init(l4_uint64_t phys_mem_max)
+{
+  ptab_alloc(&base_pml4_pa);
+
+  // Establish one-to-one mappings for the physical memory
+  pdir_map_range(base_pml4_pa, 0, 0, phys_mem_max,
+                INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER);
+
+  //dbf_tss.cr3 = base_pml4_pa;
+
+  // XXX Turn on paging and activate long mode
+  paging_enable(base_pml4_pa);
+}
+
+void trap_dump_panic(const struct trap_state *st);
+void trap_dump_panic(const struct trap_state *st)
+{
+  int from_user = st->cs & 3;
+  int i;
+
+  printf("EAX %08x EBX %08x ECX %08x EDX %08x\n",
+         st->eax, st->ebx, st->ecx, st->edx);
+  printf("ESI %08x EDI %08x EBP %08x ESP %08x\n",
+         st->esi, st->edi, st->ebp,
+         from_user ? st->esp : (l4_uint32_t)&st->esp);
+  printf("EIP %08x EFLAGS %08x\n", st->eip, st->eflags);
+  printf("CS %04x SS %04x DS %04x ES %04x FS %04x GS %04x\n",
+         st->cs & 0xffff, from_user ? st->ss & 0xffff : get_ss(),
+         st->ds & 0xffff, st->es & 0xffff,
+         st->fs & 0xffff, st->gs & 0xffff);
+  printf("trapno %d, error %08x, from %s mode\n",
+         st->trapno, st->err, from_user ? "user" : "kernel");
+
+  if (st->trapno == 0x0d)
+    {
+      if (st->err & 1)
+       printf("(external event");
+      else
+       printf("(internal event");
+      if (st->err & 2)
+        printf(" regarding IDT gate descriptor no. 0x%02x)\n", st->err >> 3);
+      else
+        printf(" regarding %s entry no. 0x%02x)\n",
+               st->err & 4 ? "LDT" : "GDT", st->err >> 3);
+    }
+  else if (st->trapno == 0x0e)
+    printf("page fault linear address %08x\n", st->cr2);
+
+  if (!from_user)
+    for (i = 0; i < 32; i++)
+      printf("%08x%c", (&st->esp)[i], ((i & 7) == 7) ? '\n' : ' ');
+
+  panic("Unexpected trap while booting Fiasco!");
+}
+
+static void
+handle_dbf(void)
+{
+  /*
+  printf("\n"
+         "EAX %08x EBX %08x ECX %08x EDX %08x\n"
+        "ESI %08x EDI %08x EBP %08x ESP %08x\n"
+        "EIP %08x EFLAGS %08x\n"
+        "CS %04x SS %04x DS %04x ES %04x FS %04x GS %04x\n\n",
+        base_tss.eax, base_tss.ebx, base_tss.ecx, base_tss.edx,
+        base_tss.esi, base_tss.edi, base_tss.ebp, base_tss.esp,
+        base_tss.eip, base_tss.eflags,
+        base_tss.cs & 0xffff, base_tss.ss & 0xffff, base_tss.ds & 0xffff,
+        base_tss.es & 0xffff, base_tss.fs & 0xffff, base_tss.gs & 0xffff);
+  */
+  panic("Unexpected DOUBLE FAULT while booting Fiasco!");
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_cpu.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_cpu.h
new file mode 100644 (file)
index 0000000..54a8477
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *          Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef BOOT_CPU_H
+#define BOOT_CPU_H
+
+#include "types.h"
+
+void base_paging_init (l4_uint64_t);
+void base_cpu_setup (void);
+
+extern struct ptab64_mem_info_t ptab64_mem_info;
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_idt.S b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_idt.S
new file mode 100644 (file)
index 0000000..7ded85f
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * (c) 2009 Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ *     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.
+ */
+
+#define GATE_INITTAB_BEGIN(name)       \
+       .text   1                       ;\
+       .globl  name                    ;\
+name:                                  ;\
+       .text
+
+#define        GATE_ENTRY(n,entry,type)        \
+       .text   1                       ;\
+       .long   entry                   ;\
+       .word   n                       ;\
+       .word   type                    ;\
+       .text
+
+#define GATE_INITTAB_END               \
+       .text   1                       ;\
+       .long   0                       ;\
+       .text
+
+#define        EXCEPTION(n,name)               \
+       GATE_ENTRY(n,name,0x0e)         ;\
+name:                                  ;\
+       pushl   $(0)                    ;\
+       pushl   $(n)                    ;\
+       jmp     alltraps
+
+#define        EXCEP_USR(n,name)               \
+       GATE_ENTRY(n,name,0x6e)         ;\
+name:                                  ;\
+       pushl   $(0)                    ;\
+       pushl   $(n)                    ;\
+       jmp     alltraps
+
+#define        EXCEP_ERR(n,name)               \
+       GATE_ENTRY(n,name,0x0e)         ;\
+name:                                  ;\
+       pushl   $(n)                    ;\
+       jmp     alltraps
+
+
+GATE_INITTAB_BEGIN(boot_idt_inittab)
+
+EXCEPTION(0x00,t_zero_div)
+EXCEPTION(0x01,t_debug)
+EXCEPTION(0x02,t_nmi)
+EXCEP_USR(0x03,t_int3)
+EXCEP_USR(0x04,t_into)
+EXCEP_USR(0x05,t_bounds)
+EXCEPTION(0x06,t_invop)
+EXCEPTION(0x07,t_nofpu)
+GATE_ENTRY(0x08,0x20,0x05)
+EXCEPTION(0x09,a_fpu_over)
+EXCEP_ERR(0x0a,a_inv_tss)
+EXCEP_ERR(0x0b,t_segnp)
+EXCEP_ERR(0x0c,t_stack_fault)
+EXCEP_ERR(0x0d,t_gen_prot)
+EXCEP_ERR(0x0e,t_page_fault)
+EXCEPTION(0x0f,t_trap_0f)
+EXCEPTION(0x10,t_fpu_err)
+EXCEPTION(0x11,t_trap_11)
+EXCEPTION(0x12,t_trap_12)
+EXCEPTION(0x13,t_trap_13)
+EXCEPTION(0x14,t_trap_14)
+EXCEPTION(0x15,t_trap_15)
+EXCEPTION(0x16,t_trap_16)
+EXCEPTION(0x17,t_trap_17)
+EXCEPTION(0x18,t_trap_18)
+EXCEPTION(0x19,t_trap_19)
+EXCEPTION(0x1a,t_trap_1a)
+EXCEPTION(0x1b,t_trap_1b)
+EXCEPTION(0x1c,t_trap_1c)
+EXCEPTION(0x1d,t_trap_1d)
+EXCEPTION(0x1e,t_trap_1e)
+EXCEPTION(0x1f,t_trap_1f)
+
+GATE_INITTAB_END
+
+alltraps:
+       pusha
+       pushl   %ds
+       pushl   %es
+       pushl   %fs
+       pushl   %gs
+
+       movl    %ss,%eax
+       movl    %eax,%ds
+       movl    %eax,%es
+       movl    %esp,%eax
+       pushl   %eax
+       call    trap_dump_panic
+
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_kernel.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_kernel.c
new file mode 100644 (file)
index 0000000..0bfdf4e
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *          Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *          Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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 <stdio.h>
+#include <l4/util/mb_info.h>
+#include "boot_cpu.h"
+#include "boot_paging.h"
+#include "load_elf.h"
+
+extern void _exit(int rc);
+
+extern unsigned KERNEL_CS_64;
+extern char _binary_bootstrap64_bin_start;
+
+static l4_uint64_t find_upper_mem(l4util_mb_info_t *mbi)
+{
+  l4_uint64_t max = 0;
+  l4util_mb_addr_range_t *mmap;
+  l4util_mb_for_each_mmap_entry(mmap, mbi)
+    {
+      if (max < mmap->addr + mmap->size)
+        max = mmap->addr + mmap->size;
+    }
+  return max;
+}
+
+static void check_mbi_modules_in_limit(l4util_mb_info_t *mbi,
+                                       unsigned long long limit)
+{
+  l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t *)(unsigned long)mbi->mods_addr;
+  unsigned i;
+  for (i = 0; i < mbi->mods_count; ++i)
+    if (mb_mod[i].mod_end >= limit)
+      {
+        printf("Multiboot module outside of supported initial memory size.\n");
+        printf("mod%d: end=%x >= limit=%llx\n", i, mb_mod[i].mod_end, limit);
+        printf("Please adapt your boot process\n"
+               "  or supply more memory to bootstrap's allocator.\n");
+        while (1);
+        _exit(-1);
+      }
+}
+
+void bootstrap (l4util_mb_info_t *mbi, unsigned int flag, char *rm_pointer);
+void
+bootstrap (l4util_mb_info_t *mbi, unsigned int flag, char *rm_pointer)
+{
+  l4_uint32_t vma_start, vma_end;
+  struct
+  {
+    l4_uint32_t start;
+    l4_uint16_t cs __attribute__((packed));
+  } far_ptr;
+  l4_uint64_t mem_upper;
+
+  // setup stuff for base_paging_init()
+  base_cpu_setup();
+
+#ifdef REALMODE_LOADING
+  mem_upper = *(unsigned long*)(rm_pointer + 0x1e0);
+  mem_upper = 1024 * (1024 + mem_upper);
+#else
+  mem_upper = find_upper_mem(mbi);
+  if (!mem_upper)
+    mem_upper = 1024 * (1024 + mbi->mem_upper);
+#endif
+
+  printf("Highest physical memory address found: %llx (%llxMiB)\n",
+         mem_upper, mem_upper >> 20);
+
+  // our memory available for our initial identity mapped page table is
+  // enough to cover 4GB of physical memory that must contain anything that
+  // is required to boot, i.e. bootstrap, all modules, any required devices
+  // and the final location of sigma0 and moe
+  const unsigned long long Max_initial_mem = 4ull << 30;
+
+  check_mbi_modules_in_limit(mbi, Max_initial_mem);
+
+  if (mem_upper > Max_initial_mem)
+    mem_upper = Max_initial_mem;
+
+  // now do base_paging_init(): sets up paging with one-to-one mapping
+  base_paging_init(round_superpage(mem_upper));
+
+  printf("Loading 64bit part...\n");
+  // switch from 32 Bit compatibility mode to 64 Bit mode
+  far_ptr.cs    = KERNEL_CS_64;
+  far_ptr.start = load_elf(&_binary_bootstrap64_bin_start,
+                           &vma_start, &vma_end);
+
+  asm volatile("ljmp *(%4)"
+                :: "D"(mbi), "S"(flag), "d"(rm_pointer),
+                   "c"(&ptab64_mem_info),
+                   "r"(&far_ptr), "m"(far_ptr));
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_paging.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/boot_paging.h
new file mode 100644 (file)
index 0000000..59320f1
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *          Frank Mehnert <fm3@os.inf.tu-dresden.de>,
+ *          Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef BOOT_PAGING_H
+#define BOOT_PAGING_H
+
+#include "types.h"
+
+enum
+{
+  PAGE_SIZE                    = (1 << 12),
+  PAGE_MASK                    = (PAGE_SIZE - 1),
+  SUPERPAGE_SIZE               = (1 << 21),
+  SUPERPAGE_MASK               = (SUPERPAGE_SIZE - 1),
+  PD_SIZE                      = (1 << 30),
+  PD_MASK                      = (PD_SIZE - 1),
+  PDP_SIZE                     = (1LL << 39),
+  PDP_MASK                     = (PDP_SIZE - 1),
+};
+
+static inline int
+superpage_aligned(l4_uint32_t x)
+{ return (x & SUPERPAGE_MASK) == 0; }
+
+static inline int
+pd_aligned(l4_uint32_t x)
+{ return (x & PD_MASK) == 0; }
+
+static inline int
+pdp_aligned(l4_uint32_t x)
+{ return (x & PDP_MASK) == 0; }
+
+static inline l4_uint64_t round_superpage(l4_uint64_t x)
+{ return (x + SUPERPAGE_MASK) & ~SUPERPAGE_MASK; }
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/bootstrap32.ld b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/bootstrap32.ld
new file mode 100644 (file)
index 0000000..e32d8f5
--- /dev/null
@@ -0,0 +1,32 @@
+ENTRY(_start)
+SECTIONS
+{
+  . = 0x01000000;
+  _image_start = .;
+  .text :
+  {
+    *(.text .text.*)
+    *(.rodata .rodata.*)
+  } =0x9090
+
+  .data :
+  {
+    *(.data .data.*)
+    *(.bss .bss.*)
+    *(COMMON)
+  }
+  _image_end = .;
+
+  /* Value of DEFAULT_RELOC_amd64 */
+  .sixtyfour 0x2d0000 :
+  {
+    . = . + 500000;
+  }
+
+  /DISCARD/ : {
+    *(.interp)
+    *(.comment)
+    *(.note)
+    *(.eh_frame)
+  }
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/load_elf.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/load_elf.c
new file mode 100644 (file)
index 0000000..f81fd63
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * (c) 2009 Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *          Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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 <stdio.h>
+#include <string.h>
+
+#include "types.h"
+#include <l4/util/elf.h>
+#include "load_elf.h"
+
+extern char _image_start;
+extern char _image_end;
+
+static void check_overlap(unsigned long s, unsigned long e)
+{
+  if (   (unsigned long)&_image_end >= s
+      && (unsigned long)&_image_start <= e)
+    {
+      printf("Overwrite: ELF-PH: %lx - %lx, bootstrap loader: %lx - %lx\n",
+             s, e, (unsigned long)&_image_start, (unsigned long)&_image_end);
+      printf("Change your 'modaddr' setting.\n");
+      while (1)
+        ;
+    }
+}
+
+l4_uint32_t
+load_elf (void *elf, l4_uint32_t *vma_start, l4_uint32_t *vma_end)
+{
+  char *_elf = (char *) elf;
+  Elf64_Ehdr *eh = (Elf64_Ehdr *)(_elf);
+  Elf64_Phdr *ph = (Elf64_Phdr *)(_elf + eh->e_phoff);
+  l4_uint32_t _vma_start = ~0, _vma_end = 0;
+  int i;
+
+  for (i = 0; i < eh->e_phnum; i++, ph++)
+    {
+      if (ph->p_type != PT_LOAD)
+        continue;
+
+      if (ph->p_vaddr < _vma_start)
+        _vma_start = ph->p_vaddr;
+
+      if (ph->p_vaddr + ph->p_memsz > _vma_end)
+        _vma_end = ph->p_vaddr + ph->p_memsz;
+
+      check_overlap(ph->p_paddr, ph->p_paddr + ph->p_filesz);
+
+      memcpy((void*)((Elf32_Addr)ph->p_paddr),
+             _elf + ph->p_offset, ph->p_filesz);
+
+      if (ph->p_filesz < ph->p_memsz)
+        {
+          check_overlap(ph->p_paddr + ph->p_filesz, ph->p_paddr + ph->p_memsz);
+          memset((void*)((Elf32_Addr)(ph->p_paddr + ph->p_filesz)), 0,
+                 ph->p_memsz - ph->p_filesz);
+        }
+    }
+
+  if (vma_start)
+    *vma_start = _vma_start;
+  if (vma_end)
+    *vma_end = _vma_end;
+
+  return eh->e_entry;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/load_elf.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/load_elf.h
new file mode 100644 (file)
index 0000000..0a86c58
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * (c) 2009 Frank Mehnert <fm3@os.inf.tu-dresden.de>,
+ *          Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef LOAD_ELF_H__
+#define LOAD_ELF_H__ 1
+
+#include "types.h"
+
+typedef void (*Startup_func)(void);
+
+l4_uint32_t load_elf(void *addr, l4_uint32_t *vma_start, l4_uint32_t *vma_end);
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/minilibc_support.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/boot32/minilibc_support.c
new file mode 100644 (file)
index 0000000..530cba9
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *          Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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 <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <l4/util/port_io.h>
+#include <l4/util/reboot.h>
+
+//#include "version.h"
+
+extern int hercules;   /* provided by startup.c */
+
+static void direct_cons_putchar(unsigned char c, int to_hercules);
+static int  direct_cons_try_getchar(void);
+       int  have_hercules(void);
+       void reboot(void);
+
+int __libc_backend_outs( const char *s, size_t len);
+int __getchar(void);
+
+static void porte9(unsigned char c)
+{
+  l4util_out8(c, 0xe9);
+  if (c == 10)
+    l4util_out8(13, 0xe9);
+}
+
+int
+__libc_backend_outs( const char *s, size_t len)
+{
+  size_t i;
+  for (i = 0; i < len; i++)
+    {
+      direct_cons_putchar(s[i], 0);
+      if (0)
+        porte9(s[i]);
+    }
+
+  return 1;
+}
+
+void __attribute__((noreturn))
+reboot(void)
+{
+  l4util_out8(0x80, 0x70);
+  l4util_iodelay();
+  l4util_in8(0x71);
+  l4util_iodelay();
+
+  while (l4util_in8(0x64) & 0x02)
+    ;
+
+  l4util_out8(0x8F, 0x70);
+  l4util_iodelay();
+  l4util_out8(0x00, 0x71);
+  l4util_iodelay();
+
+  l4util_out8(0xFE, 0x64);
+  l4util_iodelay();
+
+  for (;;)
+    ;
+}
+
+int
+__getchar(void)
+{
+  int c = 0;
+  do
+    {
+      if (c == -1)
+       c = direct_cons_try_getchar();
+    } while (c == -1);
+  return c;
+}
+
+void
+_exit(int fd)
+{
+  (void)fd;
+  printf("\n\033[1mReturn reboots...\033[m\n");
+  __getchar();
+  printf("Rebooting.\n");
+  reboot();
+}
+
+static void
+direct_cons_putchar(unsigned char c, int to_hercules)
+{
+  static int ofs  = -1;
+  static int esc;
+  static int esc_val;
+  static int attr = 0x07;
+  unsigned char *vidbase = (unsigned char*)(to_hercules ? 0xb0000 : 0xb8000);
+
+
+  if (ofs < 0)
+    {
+      /* Called for the first time - initialize.  */
+      ofs = 80*2*24;
+      direct_cons_putchar('\n', to_hercules);
+    }
+
+  switch (esc)
+    {
+    case 1:
+      if (c == '[')
+       {
+         esc++;
+         goto done;
+       }
+      esc = 0;
+      break;
+
+    case 2:
+      if (c >= '0' && c <= '9')
+       {
+         esc_val = 10*esc_val + c - '0';
+         goto done;
+       }
+      if (c == 'm')
+       {
+         attr = esc_val ? 0x0f : 0x07;
+         goto done;
+       }
+      esc = 0;
+      break;
+    }
+
+  switch (c)
+    {
+    case '\n':
+      memcpy(vidbase, vidbase+80*2, 80*2*24);
+      memset(vidbase+80*2*24, 0, 80*2);
+      /* fall through... */
+    case '\r':
+      ofs = 0;
+      break;
+
+    case '\t':
+      ofs = (ofs + 8) & ~7;
+      break;
+
+    case '\033':
+      esc = 1;
+      esc_val = 0;
+      break;
+
+    default:
+      /* Wrap if we reach the end of a line.  */
+      if (ofs >= 80)
+       direct_cons_putchar('\n', to_hercules);
+
+      /* Stuff the character into the video buffer. */
+       {
+         volatile unsigned char *p = vidbase + 80*2*24 + ofs*2;
+         p[0] = c;
+         p[1] = attr;
+         ofs++;
+       }
+      break;
+    }
+
+done:
+  return;
+}
+
+int
+have_hercules(void)
+{
+  unsigned short *p, p_save;
+  int count = 0;
+  unsigned long delay;
+  
+  /* check for video memory */
+  p = (unsigned short*)0xb0000;
+  p_save = *p;
+  *p = 0xaa55; if (*p == 0xaa55) count++;
+  *p = 0x55aa; if (*p == 0x55aa) count++;
+  *p = p_save;
+  if (count != 2)
+    return 0;
+
+  /* check for I/O ports (HW cursor) */
+  l4util_out8(0x0f, 0x3b4);
+  l4util_iodelay();
+  l4util_out8(0x66, 0x3b5);
+  for (delay=0; delay<0x100000UL; delay++)
+    asm volatile ("nop" : :);
+  if (l4util_in8(0x3b5) != 0x66)
+    return 0;
+  
+  l4util_iodelay();
+  l4util_out8(0x0f, 0x3b4);
+  l4util_iodelay();
+  l4util_out8(0x99, 0x3b5);
+
+  for (delay=0; delay<0x10000; delay++)
+    l4util_iodelay();
+  if (l4util_in8(0x3b5) != 0x99)
+    return 0;
+
+  /* reset position */
+  l4util_out8(0xf, 0x3b4);
+  l4util_iodelay();
+  l4util_out8(0x0, 0x3b5);
+  l4util_iodelay();
+  return 1;
+}
+
+#define SHIFT -1
+
+static const char keymap[128][2] = {
+  {0},                 /* 0 */
+  {27, 27},            /* 1 - ESC */
+  {'1',        '!'},           /* 2 */
+  {'2',        '@'},
+  {'3',        '#'},
+  {'4',        '$'},
+  {'5',        '%'},
+  {'6',        '^'},
+  {'7',        '&'},
+  {'8',        '*'},
+  {'9',        '('},
+  {'0',        ')'},
+  {'-',        '_'},
+  {'=',        '+'},
+  {8,  8},             /* 14 - Backspace */
+  {'\t','\t'},         /* 15 */
+  {'q',        'Q'},
+  {'w',        'W'},
+  {'e',        'E'},
+  {'r',        'R'},
+  {'t',        'T'},
+  {'y',        'Y'},
+  {'u',        'U'},
+  {'i',        'I'},
+  {'o',        'O'},
+  {'p',        'P'},
+  {'[',        '{'},
+//   {']','}'},                /* 27 */
+  {'+',        '*'},           /* 27 */
+  {'\r','\r'},         /* 28 - Enter */
+  {0,  0},             /* 29 - Ctrl */
+  {'a',        'A'},           /* 30 */
+  {'s',        'S'},
+  {'d',        'D'},
+  {'f',        'F'},
+  {'g',        'G'},
+  {'h',        'H'},
+  {'j',        'J'},
+  {'k',        'K'},
+  {'l',        'L'},
+  {';',        ':'},
+  {'\'','"'},          /* 40 */
+  {'`',        '~'},           /* 41 */
+  {SHIFT, SHIFT},      /* 42 - Left Shift */
+  {'\\', '|'},         /* 43 */
+  {'z',        'Z'},           /* 44 */
+  {'x',        'X'},
+  {'c',        'C'},
+  {'v',        'V'},
+  {'b',        'B'},
+  {'n',        'N'},
+  {'m',        'M'},
+  {',',        '<'},
+  {'.',        '>'},
+  //  {'/','?'},       /* 53 */
+  {'-',        '_'},           /* 53 */
+  {SHIFT, SHIFT},      /* 54 - Right Shift */
+  {0,  0},             /* 55 - Print Screen */
+  {0,  0},             /* 56 - Alt */
+  {' ',        ' '},           /* 57 - Space bar */
+  {0,  0},             /* 58 - Caps Lock */
+  {0,  0},             /* 59 - F1 */
+  {0,  0},             /* 60 - F2 */
+  {0,  0},             /* 61 - F3 */
+  {0,  0},             /* 62 - F4 */
+  {0,  0},             /* 63 - F5 */
+  {0,  0},             /* 64 - F6 */
+  {0,  0},             /* 65 - F7 */
+  {0,  0},             /* 66 - F8 */
+  {0,  0},             /* 67 - F9 */
+  {0,  0},             /* 68 - F10 */
+  {0,  0},             /* 69 - Num Lock */
+  {0,  0},             /* 70 - Scroll Lock */
+  {'7',        '7'},           /* 71 - Numeric keypad 7 */
+  {'8',        '8'},           /* 72 - Numeric keypad 8 */
+  {'9',        '9'},           /* 73 - Numeric keypad 9 */
+  {'-',        '-'},           /* 74 - Numeric keypad '-' */
+  {'4',        '4'},           /* 75 - Numeric keypad 4 */
+  {'5',        '5'},           /* 76 - Numeric keypad 5 */
+  {'6',        '6'},           /* 77 - Numeric keypad 6 */
+  {'+',        '+'},           /* 78 - Numeric keypad '+' */
+  {'1',        '1'},           /* 79 - Numeric keypad 1 */
+  {'2',        '2'},           /* 80 - Numeric keypad 2 */
+  {'3',        '3'},           /* 81 - Numeric keypad 3 */
+  {'0',        '0'},           /* 82 - Numeric keypad 0 */
+  {'.',        '.'},           /* 83 - Numeric keypad '.' */
+};
+
+int
+direct_cons_try_getchar(void)
+{
+  static unsigned shift_state;
+  unsigned status, scan_code, ch;
+
+retry:
+  __asm__ __volatile__ ("rep; nop");
+
+  /* Wait until a scan code is ready and read it. */
+  status = l4util_in8(0x64);
+  if ((status & 0x01) == 0)
+    {
+      return -1;
+    }
+  scan_code = l4util_in8(0x60);
+
+  /* Drop mouse events */
+  if ((status & 0x20) != 0)
+    {
+      return -1;
+    }
+
+  /* Handle key releases - only release of SHIFT is important. */
+  if (scan_code & 0x80)
+    {
+      scan_code &= 0x7f;
+      if (keymap[scan_code][0] == SHIFT)
+       shift_state = 0;
+      goto retry;
+    }
+
+  /* Translate the character through the keymap. */
+  ch = keymap[scan_code][shift_state];
+  if (ch == (unsigned)SHIFT)
+    {
+      shift_state = 1;
+      goto retry;
+    } else if (ch == 0)
+      goto retry;
+
+  return ch;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/crt0.S b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/crt0.S
new file mode 100644 (file)
index 0000000..90d9641
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Frank Mehnert <fm3@os.inf.tu-dresden.de>,
+ *               Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ *     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 <l4/sys/compiler.h>
+       
+       .section .init
+
+       .globl  _start
+_start:
+#if defined(REALMODE_LOADING) && !defined(IMAGE_MODE)
+       cld
+       cli
+       mov     $(3 * 8), %eax
+       mov     %eax, %ds
+       mov     %eax, %es
+       mov     %eax, %fs
+       mov     %eax, %gs
+
+       lss     _stack_seg, %esp
+#else
+#ifdef __PIC__
+       lea     _stack(%rip),%esp
+#else
+       lea     _stack,%esp
+#endif
+#endif
+
+#ifdef __PIC__
+       push    $_exit@plt
+       jmp     __main@plt
+#else
+       push    $_exit
+       jmp     __main
+#endif
+
+
+        /* MultiBoot header - see multiboot.h.  */
+       .p2align(2)
+
+_mb_header:
+        .long   0x1BADB002             /* magic */
+        .long   0                      /* flags: AOUT_KLUDGE */
+        .long   0 - 0x1BADB002
+
+#if defined(REALMODE_LOADING) && !defined(IMAGE_MODE)
+_stack_seg:
+       .long   _stack
+       .word   (3 * 8)
+#endif
+
+       .bss
+
+       .globl  _stack
+       .space  8192
+_stack:
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/Makefile b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/Makefile
new file mode 100644 (file)
index 0000000..b79c07d
--- /dev/null
@@ -0,0 +1,17 @@
+PKGDIR   ?= ../../../..
+L4DIR    ?= $(PKGDIR)/../..
+
+TARGET    = libc32.a
+
+SYSTEMS   = amd64
+
+
+SRC_C    = __assert_fail.c __lltostr.c __ltostr.c __v_printf.c \
+           isspace.c memcpy.c memmove.c memset.c printf.c puts.c \
+           strtol.c strtoul.c vprintf.c
+
+include $(L4DIR)/mk/lib.mk
+
+CFLAGS  := $(filter-out $(CCXX_FLAGS) $(CARCHFLAGS), $(CFLAGS)) -mno-sse
+CPPFLAGS := -nostdinc -I$(SRC_DIR)/include -m32
+OPTS     := -Os
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/__assert_fail.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/__assert_fail.c
new file mode 100644 (file)
index 0000000..36c6b67
--- /dev/null
@@ -0,0 +1,17 @@
+#include "assert.h"
+#include "stdio.h"
+#include "stdlib.h"
+
+extern void _exit(int rc);
+
+void
+__assert_fail (const char *__assertion, const char *__file,
+              unsigned int __line)
+{
+  printf("ASSERTION_FAILED (%s)\n"
+        "  in file %s:%d\n", __assertion, __file, __line);
+  _exit (EXIT_FAILURE);
+}
+
+extern __typeof(__assert_fail) __assert 
+  __attribute__((weak, alias("__assert_fail")));
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/__lltostr.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/__lltostr.c
new file mode 100644 (file)
index 0000000..813a408
--- /dev/null
@@ -0,0 +1,36 @@
+#include <string.h>
+//#include <moddiv.h>
+
+int __lltostr(char *s, int size, unsigned long long i, int base, char UpCase);
+
+int __lltostr(char *s, int size, unsigned long long i, int base, char UpCase)
+{
+  char *tmp;
+  unsigned int j=0;
+  //_moddiv_t r;
+
+  s[--size]=0;
+
+  tmp=s+size;
+
+  if ((base==0)||(base>36)) base=10;
+
+  j=0;
+  if (!i)
+  {
+    *(--tmp)='0';
+    j=1;
+  }
+
+  while((tmp>s)&&(i))
+  {
+    tmp--;
+    //    r = moddiv(i,base);
+    if ((*tmp=i%base+'0')>'9') *tmp+=(UpCase?'A':'a')-'9'-1;
+    i=i/base;
+    j++;
+  }
+  memmove(s,tmp,j+1);
+
+  return j;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/__ltostr.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/__ltostr.c
new file mode 100644 (file)
index 0000000..b13b0e3
--- /dev/null
@@ -0,0 +1,35 @@
+#include <string.h>
+#include <stdlib.h>
+//#include <moddiv.h>
+
+int __ltostr(char *s, unsigned int size, unsigned long i, unsigned int base, int UpCase)
+{
+  char *tmp;
+  unsigned int j=0;
+  //_moddiv_t r;
+  
+  s[--size]=0;
+
+  tmp=s+size;
+
+  if ((base==0)||(base>36)) base=10;
+
+  j=0;
+  if (!i)
+  {
+    *(--tmp)='0';
+    j=1;
+  }
+
+  while((tmp>s)&&(i))
+  {
+    tmp--;
+    //r = moddiv(i,base);
+    if ((*tmp=i%base+'0')>'9') *tmp+=(UpCase?'A':'a')-'9'-1;
+    i=i/base;
+    j++;
+  }
+  memmove(s,tmp,j+1);
+
+  return j;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/__v_printf.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/__v_printf.c
new file mode 100644 (file)
index 0000000..eed60b1
--- /dev/null
@@ -0,0 +1,232 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vprintf_backend.h"
+
+static inline unsigned int skip_to(const char *format) {
+  int unsigned nr;
+  for (nr=0; format[nr] && (format[nr]!='%'); ++nr);
+  return nr;
+}
+
+#define A_WRITE(fn,buf,sz)     ((fn)->put((buf),(sz),(fn)->data))
+
+static char* pad_line[16]= { "                ", "0000000000000000", };
+static inline int write_pad(struct output_op* fn, int len, int padwith) {
+  int nr=0;
+  for (;len>15;len-=16,nr+=16) {
+    A_WRITE(fn,pad_line[(padwith=='0')?1:0],16);
+  }
+  if (len>0) {
+    A_WRITE(fn,pad_line[(padwith=='0')?1:0],(unsigned int)len); nr+=len;
+  }
+  return nr;
+}
+
+int __v_printf(struct output_op* fn, const char *format, va_list arg_ptr)
+{
+  int len=0;
+
+  while (*format) {
+    unsigned int sz = skip_to(format);
+    if (sz) {
+      A_WRITE(fn,format,sz); len+=sz;
+      format+=sz;
+    }
+    if (*format=='%') {
+      char buf[128];
+
+      char ch, padwith=' ';
+      char *s;
+
+      char flag_in_sign=0;
+      char flag_upcase=0;
+      char flag_hash=0;
+      char flag_left=0;
+      char flag_space=0;
+      char flag_sign=0;
+      char flag_dot=0;
+      signed char flag_long=0;
+
+      unsigned int base;
+      unsigned int width=0, preci=0;
+
+      long int number=0;
+      long long llnumber=0;
+
+      ++format;
+inn_printf:
+      switch(ch=*format++) {
+      case 0:
+       return -1;
+       break;
+
+      /* FLAGS */
+      case '#':
+       flag_hash=1;
+       goto inn_printf;
+
+      case 'h':
+       --flag_long;
+       goto inn_printf;
+      case 'l':
+       ++flag_long;
+       goto inn_printf;
+
+      case '0':
+       padwith='0';
+       goto inn_printf;
+
+      case '-':
+       flag_left=1;
+       goto inn_printf;
+
+      case ' ':
+       flag_space=1;
+       goto inn_printf;
+
+      case '+':
+       flag_sign=1;
+       goto inn_printf;
+
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+       if(flag_dot) return -1;
+       width=strtoul(format-1,&s,10);
+       format=s;
+       goto inn_printf;
+
+      case '*':
+       width=va_arg(arg_ptr,int);
+       goto inn_printf;
+
+      case '.':
+       flag_dot=1;
+       if (*format=='*') {
+         preci=va_arg(arg_ptr,int);
+         ++format;
+       } else {
+         long int tmp=strtol(format,&s,10);
+         preci=tmp<0?0:tmp;
+         format=s;
+       }
+       goto inn_printf;
+
+      /* print a char or % */
+      case 'c':
+       ch=(char)va_arg(arg_ptr,int);
+      case '%':
+       A_WRITE(fn,&ch,1); ++len;
+       break;
+
+      /* print a string */
+      case 's':
+       s=va_arg(arg_ptr,char *);
+       if (!s) s="(null)";
+       sz = strlen(s);
+       if (flag_dot && sz>preci) sz=preci;
+
+print_out:
+       if (width && (!flag_left)) {
+         len+=write_pad(fn,(signed int)width-(signed int)sz,padwith);
+       }
+       A_WRITE(fn,s,sz); len+=sz;
+       if (width && (flag_left)) {
+         len+=write_pad(fn,(signed int)width-(signed int)sz,' ');
+       }
+       break;
+
+      /* print an integer value */
+      case 'b':
+       base=2;
+       sz=0;
+       goto num_printf;
+      case 'p':
+       flag_hash=1;
+       if(sizeof(void*)>sizeof(unsigned)) 
+         ++flag_long;
+       if(sizeof(void*)>sizeof(long))
+         ++flag_long;
+       ch='x';
+      case 'X':
+       flag_upcase=(ch=='X');
+      case 'x':
+       base=16;
+       sz=0;
+       if (flag_hash) {
+         buf[1]='0';
+         buf[2]=ch;
+         sz=2;
+       }
+       goto num_printf;
+      case 'd':
+      case 'i':
+       flag_in_sign=1;
+      case 'u':
+       base=10;
+       sz=0;
+       goto num_printf;
+      case 'o':
+       base=8;
+       sz=0;
+       if (flag_hash) {
+         buf[1]='0';
+         ++sz;
+       }
+
+num_printf:
+       if (flag_long>0) {
+         if (flag_long>1)
+           llnumber=va_arg(arg_ptr,long long);
+         else
+           number=va_arg(arg_ptr,long);
+       }
+       else
+         number=va_arg(arg_ptr,int);
+
+       if (flag_in_sign) {
+         if ((flag_long>1)&&(llnumber<0)) {
+           llnumber=-llnumber;
+           flag_in_sign=2;
+         } else
+           if (number<0) {
+             number=-number;
+             flag_in_sign=2;
+           }
+       }
+       if (flag_long<0) number&=0xffff;
+       if (flag_long<-1) number&=0xff;
+       if (flag_long>1)
+         sz += __lltostr(buf+1+sz,sizeof(buf)-5,(unsigned long long) llnumber,base,flag_upcase);
+       else
+         sz += __ltostr(buf+1+sz,sizeof(buf)-5,(unsigned long) number,base,flag_upcase);
+
+       s=buf+1;
+
+       if (flag_in_sign==2) {
+         *(--s)='-';
+         ++sz;
+       } else if ((flag_in_sign)&&(flag_sign || flag_space)) {
+         *(--s)=(flag_sign)?'+':' ';
+         ++sz;
+       }
+
+       goto print_out;
+
+      default:
+       break;
+      }
+    }
+  }
+  return len;
+}
+
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/assert.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/assert.h
new file mode 100644 (file)
index 0000000..68f75f5
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _ASSERT_H
+#define _ASSERT_H
+
+#include <cdefs.h>
+
+__BEGIN_DECLS
+/* This prints an "Assertion failed" message and aborts.  */
+void __assert_fail (const char *__assertion, const char *__file,
+                   unsigned int __line)
+     __attribute__ ((__noreturn__));
+
+__END_DECLS
+
+#if (__GNUC__>=3)
+#  define ASSERT_EXPECT_FALSE(exp)     __builtin_expect((exp), 0)
+#else
+#  define ASSERT_EXPECT_FALSE(exp)     (exp)
+#endif
+
+/* We don't show information about the current function since needs
+ * additional space -- especially with gcc-2.95. The function name
+ * can be found by searching the EIP in the kernel image. */
+#undef assert
+#ifdef NDEBUG
+#define assert(expr)
+#define check(expr) (void)(expr)
+#else
+# define assert(expr)                                          \
+  ((void) ((ASSERT_EXPECT_FALSE(!(expr)))                      \
+       ? (__assert_fail (#expr, __FILE__, __LINE__), 0)        \
+       : 0))
+# define check(expr) assert(expr)
+#endif
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/cdefs.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/cdefs.h
new file mode 100644 (file)
index 0000000..b9fc187
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __CDEFS_H__
+#define __CDEFS_H__
+
+#ifndef __cplusplus
+#define __BEGIN_DECLS
+#define __END_DECLS
+#else
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#endif
+
+
+#endif // __CDEFS_H__
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/ctype.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/ctype.h
new file mode 100644 (file)
index 0000000..5ec2ba8
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef        _CTYPE_H
+#define _CTYPE_H
+
+#include <cdefs.h>
+
+__BEGIN_DECLS
+
+int isascii (int c) __attribute__ ((__const__));
+int isblank (int c) __attribute__ ((__const__));
+int isalnum (int c) __attribute__ ((__const__));
+int isalpha (int c) __attribute__ ((__const__));
+int isdigit (int c) __attribute__ ((__const__));
+int isspace (int c) __attribute__ ((__const__));
+
+int isupper (int c) __attribute__ ((__const__));
+int islower (int c) __attribute__ ((__const__));
+
+int tolower(int c) __attribute__ ((__const__));
+int toupper(int c) __attribute__ ((__const__));
+
+int isprint(int c) __attribute__ ((__const__));
+int ispunct(int c) __attribute__ ((__const__));
+int iscntrl(int c) __attribute__ ((__const__));
+
+/* fscking GNU extensions! */
+int isxdigit(int c) __attribute__ ((__const__));
+
+int isgraph(int c) __attribute__ ((__const__));
+
+__END_DECLS
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/libc_backend.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/libc_backend.h
new file mode 100644 (file)
index 0000000..fbfb534
--- /dev/null
@@ -0,0 +1,47 @@
+/* */
+
+
+
+/* This file defines the backend interface */
+/* of the kernel c-library. */
+
+#ifndef __LIBC_BACKEND_H__
+#define __LIBC_BACKEND_H__
+
+#include <stddef.h>
+#include <cdefs.h>
+
+__BEGIN_DECLS
+
+/** 
+ * The text output backend. 
+ * 
+ * This function must be provided to the c-library for
+ * text output. It must simply send len characters of s
+ * to an output device.
+ *
+ * @param s the string to send (not zero terminated).
+ * @param len the number of characters.
+ * @return 1 on success, 0 else.
+ */
+int __libc_backend_outs( const char *s, size_t len );
+
+
+/**
+ * The text input backend.
+ *
+ * This function must be provided to the c-library for 
+ * text input. It has to block til len characters are
+ * read or a newline is reached. The retrurn value gives 
+ * the number of characters virtually read.
+ *
+ * @param s a poiznter to the buffer for the read text.
+ * @param len the size of the buffer.
+ * @return the number of characters virtually read.
+ */
+int __libc_backend_ins( char *s, size_t len );
+
+__END_DECLS
+
+
+#endif //__LIBC_BACKEND_H__
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/memcpy.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/memcpy.h
new file mode 100644 (file)
index 0000000..18484d0
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef MLC_MEMCPY_H__
+#define MLC_MEMCPY_H__
+
+#include <cdefs.h>
+#include <stddef.h>
+
+__BEGIN_DECLS
+
+void *memcpy(void *dest, const void *src, size_t n);
+
+__END_DECLS
+
+#endif // MLC_MEMCPY_H__
+
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/panic.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/panic.h
new file mode 100644 (file)
index 0000000..1910225
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef PANIC_H
+#define PANIC_H
+
+#include <cdefs.h>
+
+__BEGIN_DECLS
+
+void panic (const char *format, ...) __attribute__ ((__noreturn__));
+
+__END_DECLS
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stdarg-cruft.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stdarg-cruft.h
new file mode 100644 (file)
index 0000000..20c9445
--- /dev/null
@@ -0,0 +1,299 @@
+#if defined(__sparc__) || defined(__alpha__)
+enum {
+  __no_type_class = -1,
+  __void_type_class,
+  __integer_type_class,
+  __char_type_class,
+  __enumeral_type_class,
+  __boolean_type_class,
+  __pointer_type_class,
+  __reference_type_class,
+  __offset_type_class,
+  __real_type_class,
+  __complex_type_class,
+  __function_type_class,
+  __method_type_class,
+  __record_type_class,
+  __union_type_class,
+  __array_type_class,
+  __string_type_class,
+  __set_type_class,
+  __file_type_class,
+  __lang_type_class
+};
+#endif
+
+#if defined(__sparc__)
+
+typedef char* va_list;
+#define va_end(ap) ap=0
+
+#define va_start(AP, LASTARG) \
+  (__builtin_next_arg (LASTARG), AP = (char *) __builtin_saveregs ())
+
+#define __va_rounded_size(TYPE)  \
+  (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
+
+/* We don't declare the union member `d' to have type TYPE
+   because that would lose in C++ if TYPE has a constructor.  */
+/* We cast to void * and then to TYPE * because this avoids
+   a warning about increasing the alignment requirement.
+   The casts to char * avoid warnings about invalid pointer arithmetic.  */
+#define va_arg(pvar,TYPE)                                      \
+__extension__                                                  \
+(*({((__builtin_classify_type (*(TYPE*) 0) >= __record_type_class \
+      || (__builtin_classify_type (*(TYPE*) 0) == __real_type_class \
+         && sizeof (TYPE) == 16))                              \
+    ? ((pvar) = (char *)(pvar) + __va_rounded_size (TYPE *),   \
+       *(TYPE **) (void *) ((char *)(pvar) - __va_rounded_size (TYPE *))) \
+    : __va_rounded_size (TYPE) == 8                            \
+    ? ({ union {char __d[sizeof (TYPE)]; int __i[2];} __u;     \
+        __u.__i[0] = ((int *) (void *) (pvar))[0];             \
+        __u.__i[1] = ((int *) (void *) (pvar))[1];             \
+        (pvar) = (char *)(pvar) + 8;                           \
+        (TYPE *) (void *) __u.__d; })                          \
+    : ((pvar) = (char *)(pvar) + __va_rounded_size (TYPE),     \
+       ((TYPE *) (void *) ((char *)(pvar) - __va_rounded_size (TYPE)))));}))
+
+
+#elif defined(__mips__)
+
+typedef char * va_list;
+
+#ifdef __mips64
+#define __va_rounded_size(__TYPE)  \
+  (((sizeof (__TYPE) + 8 - 1) / 8) * 8)
+#else
+#define __va_rounded_size(__TYPE)  \
+  (((sizeof (__TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
+#endif
+#ifdef __mips64
+#define __va_reg_size 8
+#else
+#define __va_reg_size 4
+#endif
+
+#define va_start(__AP, __LASTARG) \
+  (__AP = (va_list) __builtin_next_arg (__LASTARG))
+
+#ifdef __mips64
+#ifdef __MIPSEB__
+#define va_arg(__AP, __type)                                    \
+  ((__type *) (void *) (__AP = (char *)                         \
+                       ((((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8) \
+                           + __va_rounded_size (__type))))[-1]
+#else
+#define va_arg(__AP, __type)                                    \
+  ((__AP = (char *) ((((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8)    \
+                     + __va_rounded_size (__type))),            \
+   *(__type *) (void *) (__AP - __va_rounded_size (__type)))
+#endif
+
+#else /* not __mips64 */
+
+#ifdef __MIPSEB__
+/* For big-endian machines.  */
+#define va_arg(__AP, __type)                                    \
+  ((__AP = (char *) ((__alignof__ (__type) > 4                  \
+                      ? ((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8   \
+                      : ((__PTRDIFF_TYPE__)__AP + 4 - 1) & -4)  \
+                     + __va_rounded_size (__type))),            \
+   *(__type *) (void *) (__AP - __va_rounded_size (__type)))
+#else
+/* For little-endian machines.  */
+#define va_arg(__AP, __type)                                                \
+  ((__type *) (void *) (__AP = (char *) ((__alignof__(__type) > 4           \
+                                ? ((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8     \
+                                : ((__PTRDIFF_TYPE__)__AP + 4 - 1) & -4)    \
+                                         + __va_rounded_size(__type))))[-1]
+#endif
+#endif
+
+#elif defined(__powerpc__)
+
+typedef struct __va_list_tag {
+  unsigned char gpr;           /* index into the array of 8 GPRs stored in the
+                                  register save area gpr=0 corresponds to r3,
+                                  gpr=1 to r4, etc. */
+  unsigned char fpr;           /* index into the array of 8 FPRs stored in the
+                                  register save area fpr=0 corresponds to f1,
+                                  fpr=1 to f2, etc. */
+  char *overflow_arg_area;     /* location on stack that holds the next
+                                  overflow argument */
+  char *reg_save_area;         /* where r3:r10 and f1:f8, if saved are stored */
+} va_list[1];
+
+#define __va_overflow(AP) (AP)->overflow_arg_area
+#ifdef __OPTIMIZE__
+extern void __va_arg_type_violation(void) __attribute__((__noreturn__));
+#else
+#define __va_arg_type_violation()
+#endif
+
+typedef struct {
+  long   __gp_save[8];         /* save area for GP registers */
+  double __fp_save[8];         /* save area for FP registers */
+} __va_regsave_t;
+
+/* Macros to access the register save area */
+/* We cast to void * and then to TYPE * because this avoids
+   a warning about increasing the alignment requirement.  */
+#define __VA_FP_REGSAVE(AP,OFS,TYPE)                                   \
+  ((TYPE *) (void *) (&(((__va_regsave_t *)                            \
+                        (AP)->reg_save_area)->__fp_save[OFS])))
+
+#define __VA_GP_REGSAVE(AP,OFS,TYPE)                                   \
+  ((TYPE *) (void *) (&(((__va_regsave_t *)                            \
+                        (AP)->reg_save_area)->__gp_save[OFS])))
+
+#define __va_start_common(AP, FAKE) \
+  __builtin_memcpy ((AP), __builtin_saveregs (), sizeof(va_list))
+
+#define va_start(AP,LASTARG) \
+  (__builtin_next_arg (LASTARG), __va_start_common (AP, 0))
+
+#ifdef _SOFT_FLOAT
+#define __va_float_p(TYPE)     0
+#else
+#define __va_float_p(TYPE)     (__builtin_classify_type(*(TYPE *)0) == 8)
+#endif
+
+#define __va_aggregate_p(TYPE) (__builtin_classify_type(*(TYPE *)0) >= 12)
+#define __va_size(TYPE)                ((sizeof(TYPE) + sizeof (long) - 1) / sizeof (long))
+
+#define va_arg(AP,TYPE)                                                           \
+__extension__ (*({                                                        \
+  register TYPE *__ptr;                                                           \
+                                                                          \
+  if (__va_float_p (TYPE) && sizeof (TYPE) < 16)                          \
+    {                                                                     \
+      unsigned char __fpr = (AP)->fpr;                                    \
+      if (__fpr < 8)                                                      \
+       {                                                                  \
+         __ptr = __VA_FP_REGSAVE (AP, __fpr, TYPE);                       \
+         (AP)->fpr = __fpr + 1;                                           \
+       }                                                                  \
+      else if (sizeof (TYPE) == 8)                                        \
+       {                                                                  \
+         unsigned long __addr = (unsigned long) (__va_overflow (AP));     \
+         __ptr = (TYPE *)((__addr + 7) & -8);                             \
+         __va_overflow (AP) = (char *)(__ptr + 1);                        \
+       }                                                                  \
+      else                                                                \
+       {                                                                  \
+         /* float is promoted to double.  */                              \
+         __va_arg_type_violation ();                                      \
+       }                                                                  \
+    }                                                                     \
+                                                                          \
+  /* Aggregates and long doubles are passed by reference.  */             \
+  else if (__va_aggregate_p (TYPE) || __va_float_p (TYPE))                \
+    {                                                                     \
+      unsigned char __gpr = (AP)->gpr;                                    \
+      if (__gpr < 8)                                                      \
+       {                                                                  \
+         __ptr = * __VA_GP_REGSAVE (AP, __gpr, TYPE *);                   \
+         (AP)->gpr = __gpr + 1;                                           \
+       }                                                                  \
+      else                                                                \
+       {                                                                  \
+         TYPE **__pptr = (TYPE **) (__va_overflow (AP));                  \
+         __ptr = * __pptr;                                                \
+         __va_overflow (AP) = (char *) (__pptr + 1);                      \
+       }                                                                  \
+    }                                                                     \
+                                                                          \
+  /* Only integrals remaining.  */                                        \
+  else                                                                    \
+    {                                                                     \
+      /* longlong is aligned.  */                                         \
+      if (sizeof (TYPE) == 8)                                             \
+       {                                                                  \
+         unsigned char __gpr = (AP)->gpr;                                 \
+         if (__gpr < 7)                                                   \
+           {                                                              \
+             __gpr += __gpr & 1;                                          \
+             __ptr = __VA_GP_REGSAVE (AP, __gpr, TYPE);                   \
+             (AP)->gpr = __gpr + 2;                                       \
+           }                                                              \
+         else                                                             \
+           {                                                              \
+             unsigned long __addr = (unsigned long) (__va_overflow (AP)); \
+             __ptr = (TYPE *)((__addr + 7) & -8);                         \
+             (AP)->gpr = 8;                                               \
+             __va_overflow (AP) = (char *)(__ptr + 1);                    \
+           }                                                              \
+       }                                                                  \
+      else if (sizeof (TYPE) == 4)                                        \
+       {                                                                  \
+         unsigned char __gpr = (AP)->gpr;                                 \
+         if (__gpr < 8)                                                   \
+           {                                                              \
+             __ptr = __VA_GP_REGSAVE (AP, __gpr, TYPE);                   \
+             (AP)->gpr = __gpr + 1;                                       \
+           }                                                              \
+         else                                                             \
+           {                                                              \
+             __ptr = (TYPE *) __va_overflow (AP);                         \
+             __va_overflow (AP) = (char *)(__ptr + 1);                    \
+           }                                                              \
+       }                                                                  \
+      else                                                                \
+       {                                                                  \
+         /* Everything else was promoted to int.  */                      \
+         __va_arg_type_violation ();                                      \
+       }                                                                  \
+    }                                                                     \
+  __ptr;                                                                  \
+}))
+
+#define va_end(AP)     ((void)0)
+
+/* Copy va_list into another variable of this type.  */
+#define __va_copy(dest, src) *(dest) = *(src)
+
+#elif defined(__alpha__)
+
+typedef struct {
+  char *__base;                        /* Pointer to first integer register. */
+  int __offset;                        /* Byte offset of args so far. */
+} va_list;
+
+#define va_start(pvar, firstarg)                               \
+  (__builtin_next_arg (firstarg),                              \
+   (pvar) = *(va_list *) __builtin_saveregs ())
+#define va_end(__va)   ((void) 0)
+
+#define __va_tsize(__type)  \
+  (((sizeof (__type) + __extension__ sizeof (long long) - 1)   \
+    / __extension__ sizeof (long long)) * __extension__ sizeof (long long))
+
+#define va_arg(__va, __type)                                           \
+(*(((__va).__offset += __va_tsize (__type)),                           \
+   (__type *)(void *)((__va).__base + (__va).__offset                  \
+             - (((__builtin_classify_type (* (__type *) 0)             \
+                  == __real_type_class) && (__va).__offset <= (6 * 8)) \
+                ? (6 * 8) + 8 : __va_tsize (__type)))))
+
+#else  /* !__sparc__ && !__powerpc__ && !__mips__ && !__alpha__*/
+
+typedef char* va_list;
+
+/* this only works when everything is passed on the stack (i.e. x86) */
+#if __WORDSIZE == 64
+#define va_start(ap,argn) ap=((char*)&argn)+8
+#else
+#define va_start(ap,argn) ap=((char*)&argn)+4
+#endif
+#define va_arg(ap,type) (ap+=sizeof(type), *(type*)((char*)((void*)ap)-sizeof(type)))
+
+#endif
+
+#ifndef __va_copy
+#define __va_copy(x,y) x=y
+#endif
+
+#ifndef va_end
+#define va_end(ap) ((void)0)
+#endif
+
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stdarg.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stdarg.h
new file mode 100644 (file)
index 0000000..307f51d
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _STDARG_H
+#define _STDARG_H
+
+
+
+#ifdef __GNUC__
+#if (__GNUC__ > 2) || (__GNUC__ == 2) && (__GNUC_MINOR__ > 96)
+
+typedef __builtin_va_list va_list;
+#define va_start(v,l)  __builtin_va_start((v),(l))
+#define va_end         __builtin_va_end
+#define va_arg         __builtin_va_arg
+#define __va_copy(d,s) __builtin_va_copy((d),(s))
+
+#endif
+#endif
+
+#ifndef va_end
+#include <stdarg-cruft.h>
+#endif
+
+#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L
+#define va_copy(d,s)   __va_copy(d,s)
+#endif
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stddef.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stddef.h
new file mode 100644 (file)
index 0000000..4136767
--- /dev/null
@@ -0,0 +1,7 @@
+
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+typedef unsigned size_t;
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stdio.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stdio.h
new file mode 100644 (file)
index 0000000..1a6fea5
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _STDIO_H
+#define _STDIO_H
+
+#include <cdefs.h>
+#include <stddef.h>
+
+__BEGIN_DECLS
+
+int putchar(int c);
+int puts(const char *s);
+int printf(const char *format, ...) __attribute__((format(printf,1,2)));
+int sprintf(char *str, const char *format, ...) __attribute__((format(printf,2,3)));
+int snprintf(char *str, size_t size, const char *format, ...) __attribute__((format(printf,3,4)));
+int asprintf(char **ptr, const char* format, ...) __attribute__((format(printf,2,3)));
+
+#if 0
+int scanf(const char *format, ...) __attribute__((format(scanf,1,2)));
+int sscanf(const char *str, const char *format, ...) __attribute__((format(scanf,2,3)));
+#endif
+
+#include <stdarg.h>
+
+int vprintf(const char *format, va_list ap) __attribute__((format(printf,1,0)));
+int vsprintf(char *str, const char *format, va_list ap) __attribute__((format(printf,2,0)));
+int vsnprintf(char *str, size_t size, const char *format, va_list ap) __attribute__((format(printf,3,0)));
+
+
+typedef int FILE;
+
+int vscanf(const char *format, va_list ap) __attribute__((format(scanf,1,0)));
+int vsscanf(const char *str, const char *format, va_list ap) __attribute__((format(scanf,2,0)));
+
+int sscanf(const char *str, const char *format, ...);
+
+__END_DECLS
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stdlib.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/stdlib.h
new file mode 100644 (file)
index 0000000..c03396e
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef _STDLIB_H
+#define _STDLIB_H
+
+#include <cdefs.h>
+#include <stddef.h>
+
+__BEGIN_DECLS
+
+int atexit(void (*function)(void));
+
+double strtod(const char *nptr, char **endptr);
+long int strtol(const char *nptr, char **endptr, int base);
+unsigned long int strtoul(const char *nptr, char **endptr, int base);
+
+extern int __ltostr(char *s, unsigned int size, unsigned long i, unsigned int base, int UpCase);
+extern int __dtostr(double d,char *buf,unsigned int maxlen,unsigned int prec);
+
+#ifndef __STRICT_ANSI__
+__extension__ long long int strtoll(const char *nptr, char **endptr, int base);
+__extension__ unsigned long long int strtoull(const char *nptr, char **endptr, int base);
+__extension__ int __lltostr(char *s, unsigned int size, unsigned long long i, unsigned int base, int UpCase);
+#endif
+
+int atoi(const char *nptr);
+long int atol(const char *nptr);
+double atof(const char *nptr);
+
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+
+void exit(int status) __attribute__((noreturn));
+void abort(void);
+
+/* warning: the rand() implementation of the diet libc really sucks. */
+#define RAND_MAX 32767
+
+typedef struct { int quot,rem; } div_t;
+div_t div(int numer, int denom) __attribute__((const));
+
+typedef struct { long int quot,rem; } ldiv_t;
+ldiv_t ldiv(long int numer, long int denom) __attribute__((const));
+
+typedef struct { long long int quot,rem; } lldiv_t;
+lldiv_t lldiv(long long int numer, long long int denom) __attribute__((const));
+
+int abs(int i) __attribute__((const));
+long int labs(long int i) __attribute__((const));
+__extension__ long long int llabs(long long int i) __attribute__((const));
+
+__END_DECLS
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/string.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/string.h
new file mode 100644 (file)
index 0000000..61c9ce2
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef _STRING_H
+#define _STRING_H
+
+#include <cdefs.h>
+#include <stddef.h>
+
+#include <memcpy.h>
+
+__BEGIN_DECLS
+
+char *strcpy(char *dest, const char *src);
+char *strncpy(char *dest, const char *src, size_t n);
+
+void *memccpy(void *dest, const void *src, int c, size_t n);
+void *memmove(void *dest, const void *src, size_t n);
+
+int memccmp(const void *s1, const void *s2, int c, size_t n);
+int memcmp(const void *s1, const void *s2, size_t n);
+int strcmp(const char *s1, const char *s2);
+int strncmp(const char *s1, const char *s2, size_t n);
+
+int strcasecmp(const char *s1, const char *s2);
+int strncasecmp(const char *s1, const char *s2, size_t n);
+
+#if (__GNUC__>=3)
+size_t strlen(const char *s) __attribute__((pure));
+#else
+size_t strlen(const char *s);
+#endif
+
+char *strstr(const char *haystack, const char *needle);
+
+char *strdup(const char *s);
+
+char *strchr(const char *s, int c);
+char *strrchr(const char *s, int c);
+
+char *strcat(char *dest, const char *src);
+char *strncat(char *dest, const char *src, size_t n);
+
+size_t strspn(const char *s, const char *_accept);
+size_t strcspn(const char *s, const char *reject);
+
+char *strpbrk(const char *s, const char *_accept);
+char *strsep(char **stringp, const char *delim);
+
+void* memset(void *s, int c, size_t n);
+void* memchr(const void *s, int c, size_t n);
+
+int strcoll(const char *s1, const char *s2);
+
+
+__END_DECLS
+
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/strings.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/include/strings.h
new file mode 100644 (file)
index 0000000..ec947a9
--- /dev/null
@@ -0,0 +1,2 @@
+#warning "your code included obsolescent <strings.h>.  Please change that to <string.h>!"
+#include <string.h>
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/isspace.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/isspace.c
new file mode 100644 (file)
index 0000000..bfa4664
--- /dev/null
@@ -0,0 +1,9 @@
+#include <ctype.h>
+
+int __isspace_ascii ( int ch );
+int __isspace_ascii ( int ch )
+{
+    return (unsigned int)(ch - 9) < 5u  ||  ch == ' ';
+}
+
+int isspace ( int ch ) __attribute__((weak,alias("__isspace_ascii")));
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/memcpy.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/memcpy.c
new file mode 100644 (file)
index 0000000..13acc63
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stddef.h>
+#include <string.h>
+
+void* memcpy(void* dst, const void* src, size_t count) {
+  register char *d=dst;
+  register const char *s=src;
+  ++count;     /* this actually produces better code than using count-- */
+  while (--count) {
+    *d = *s;
+    ++d; ++s;
+  }
+  return dst;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/memmove.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/memmove.c
new file mode 100644 (file)
index 0000000..be21a7c
--- /dev/null
@@ -0,0 +1,24 @@
+#define _POSIX_SOURCE
+#define _XOPEN_SOURCE
+#include <stddef.h>
+#include <string.h>
+
+void *memmove(void *dst, const void *src, size_t count)
+{
+  char *a = dst;
+  const char *b = src;
+  if (src!=dst)
+  {
+    if (src>dst)
+    {
+      while (count--) *a++ = *b++;
+    }
+    else
+    {
+      a+=count-1;
+      b+=count-1;
+      while (count--) *a-- = *b--;
+    }
+  }
+  return dst;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/memset.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/memset.c
new file mode 100644 (file)
index 0000000..d1a367e
--- /dev/null
@@ -0,0 +1,10 @@
+#include <stddef.h>
+#include <string.h>
+
+void * memset(void * dst, int s, size_t count) {
+    register char * a = dst;
+    count++;   /* this actually creates smaller code than using count-- */
+    while (--count)
+       *a++ = s;
+    return dst;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/printf.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/printf.c
new file mode 100644 (file)
index 0000000..1b8643e
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdarg.h>
+#include <stdio.h>
+
+int printf (const char *format, ...) {
+
+  int n;
+  va_list args;
+  
+  va_start    (args, format);
+  n = vprintf (format, args);
+  va_end      (args);
+  
+  return n;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/puts.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/puts.c
new file mode 100644 (file)
index 0000000..a9e70c9
--- /dev/null
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include <string.h>
+#include "libc_backend.h"
+
+size_t strlen(const char *s)
+{
+  size_t l = 0;
+  while (*s)
+    {
+      l++;
+      s++;
+    }
+  return l;
+}
+
+
+int puts(const char *c)
+{
+  __libc_backend_outs(c, strlen(c));
+  return __libc_backend_outs("\n", 1);
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/strtol.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/strtol.c
new file mode 100644 (file)
index 0000000..c9a581a
--- /dev/null
@@ -0,0 +1,29 @@
+#include <ctype.h>
+#include <stdlib.h>
+
+#define ABS_LONG_MIN 2147483648UL
+
+long int strtol (const char *nptr, char **endptr, int base) {
+
+  int neg = 0;
+  unsigned long int v;
+
+  while (isspace (*nptr))
+    nptr++;
+
+  if (*nptr == '-') {
+    neg = -1;
+    ++nptr;
+  }
+  
+  v = strtoul (nptr, endptr, base);
+  
+  if (v >= ABS_LONG_MIN) {
+    if (v == ABS_LONG_MIN && neg) {
+      return v;
+    }
+    return 0; //(neg ? LONG_MIN : LONG_MAX);
+  }
+  
+  return (neg ? -v : v);
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/strtoul.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/strtoul.c
new file mode 100644 (file)
index 0000000..4612c13
--- /dev/null
@@ -0,0 +1,40 @@
+#include <ctype.h>
+#include <stdlib.h>
+
+unsigned long int strtoul (const char *nptr, char **endptr, int base) {
+
+  unsigned long int v=0;
+
+  while(isspace(*nptr)) ++nptr;
+  if (*nptr == '+') ++nptr;
+  if (base==16 && nptr[0]=='0') goto skip0x;
+  if (!base) {
+    if (*nptr=='0') {
+      base=8;
+skip0x:
+      if (nptr[1]=='x'||nptr[1]=='X') {
+       nptr+=2;
+       base=16;
+      }
+    } else
+      base=10;
+  }
+  while(*nptr) {
+    register unsigned char c=*nptr;
+    c=(c>='a'?c-'a'+10:c>='A'?c-'A'+10:c<='9'?c-'0':0xff);
+    if (c>=base) break;
+    {
+      register unsigned long int w=v << 4;/*=v*base*/;
+      if(base==8) w = v << 3;
+      //if(base==16) w = v << 4;
+      if(base==10) w = (v << 3) + (v << 1);
+      if (w<v) {
+       return (unsigned long)-1;
+      }
+      v=w+c;
+    }
+    ++nptr;
+  }
+  if (endptr) *endptr=(char *)nptr;
+  return v;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/vprintf.c b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/vprintf.c
new file mode 100644 (file)
index 0000000..5206bb1
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "vprintf_backend.h"
+#include "libc_backend.h"
+
+
+
+int vprintf(const char *format, va_list ap)
+{
+  struct output_op _ap = { 0, (output_func*) &__libc_backend_outs };
+  return __v_printf(&_ap,format,ap);
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/vprintf_backend.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/libc32/vprintf_backend.h
new file mode 100644 (file)
index 0000000..1200277
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __VPRINTF_BACKEND_H__
+#define __VPRINTF_BACKEND_H__
+
+#include <stddef.h>
+#include <cdefs.h>
+
+typedef int (output_func)(char const *, size_t, void*);
+
+struct output_op {
+  void *data;
+  output_func *put;
+};
+
+__BEGIN_DECLS
+
+int __v_printf(struct output_op* fn, const char *format, va_list arg_ptr);
+
+__END_DECLS
+
+
+#endif // __VPRINTF_BACKEND_H__
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/macros.h b/l4/pkg/bootstrap_custom/server/src/ARCH-amd64/macros.h
new file mode 100644 (file)
index 0000000..5be8da5
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * (c) 2008-2009 Frank Mehnert <fm3@os.inf.tu-dresden.de>,
+ *               Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef __ARCH_AMD64_MACROS_H__
+#define __ARCH_AMD64_MACROS_H__
+
+/* We need this typecasts since addresses of the GRUB multiboot info
+ * have always a size of 32 Bit. */
+
+#define L4_CHAR_PTR(x)         (char*)(l4_addr_t)(x)
+#define L4_CONST_CHAR_PTR(x)   (const char*)(l4_addr_t)(x)
+#define L4_VOID_PTR(x)         (void*)(l4_addr_t)(x)
+#define L4_MB_MOD_PTR(x)       (l4util_mb_mod_t*)(l4_addr_t)(x)
+
+#endif  /* ! __ARCH_AMD64_MACROS_H__ */
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-arm/bootstrap.ld.in b/l4/pkg/bootstrap_custom/server/src/ARCH-arm/bootstrap.ld.in
new file mode 100644 (file)
index 0000000..b4ee8d6
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *               Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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 "ldscript.inc"
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",
+              "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+
+PHDRS {
+  common PT_LOAD;
+#ifndef SINGLE_SECTION
+  mods PT_LOAD;
+#endif
+}
+
+/* Some explanation for SINGLE_SECTION thing: For bootstrap we want to have
+ * a single program header only because some boot-loaders require that.
+ * Unfortunately it does not seem to be possible to have the following
+ * order:
+ *         text - data - bss - modules
+ * because bss is smaller in the binary than unpacked and things get screwed
+ * up. So what we do it the following:
+ *         text - data_including_bss - modules
+ * This way things seem to work and we only have one program header.
+ */
+
+SECTIONS
+{
+  /* Read-only sections, merged into text segment. The start address of
+   * the text segment is : */
+  . = LINKADDR;
+  .text :
+  {
+    _stext = .;
+    *(.text.init) 
+    *(.init)
+    *(.text .text.* .gnu.linkonce.t.*)
+    *(.glue_7t) *(.glue_7)
+    KEEP (*(.fini))
+    LONG(0xc3)  /* terminate .fini */
+    . = ALIGN(0x40);
+    *(.rodata .rodata.* .gnu.linkonce.r.* .rodata1)
+  } : common
+
+  _etext = .;
+  PROVIDE (etext = .);
+
+  /* ensure that data starts at a new L4 page */
+  . = ALIGN(4096);
+  .data :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+    *(.anno)
+
+    CTORS
+    PLATFORMS
+
+    . = ALIGN(4);
+    _module_info_start = .;
+    *(.module_info)
+    _module_info_end   = .;
+
+#ifndef SINGLE_SECTION
+  } : common
+
+  /* exception frames for C++ */
+  .eh_frame :
+  {
+#endif
+    KEEP (*(.eh_frame))
+    LONG(0) /* terminate .eh_frame */
+#ifndef SINGLE_SECTION
+  } : common
+#endif
+
+  . = ALIGN(4);
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  _bss_start = .;
+#ifndef SINGLE_SECTION
+  .bss :
+  {
+#endif
+   *(.dynbss)
+   *(.bss .gnu.linkonce.b.*)
+   *(COMMON)
+  } : common
+  _bss_end = .;
+  _end = . ;
+  PROVIDE (end = .);
+
+/* Only move modules to modaddr if bootstrap is being loaded by an elf
+ * loader, and we do not need to copy images around at runtime (e.g. with
+ * compression) */
+#if defined(PLACE_MODULES_AT_MODADDR) && !defined(SINGLE_SECTION)
+  . = RAM_BASE + MODADDR;
+#endif
+  . = ALIGN(4096);
+  .data.m :
+  {
+    . = ALIGN(4096);
+    _module_data_start = .;
+    *(EXCLUDE_FILE (*mod00.bin *mod01.bin *mod02.bin) .module_data)
+    *(.module_data)
+    _module_data_end = .;
+#ifndef SINGLE_SECTION
+  } : mods
+#else
+  } : common
+#endif
+
+  /* Moved here to ensure that these sections are located _after_ the text
+   * section. In the other case we would get program sections with a virtual
+   * address of 0 */
+  .hash    : { *(.hash)    }
+  .dynsym  : { *(.dynsym)  }
+  .dynstr  : { *(.dynstr)  }
+  .rel.dyn : { *(.rel.dyn) }
+
+  /* drop the following sections since we do not need them for DROPS */
+  /DISCARD/ : {
+    *(.interp)
+    *(.comment)
+    *(.note)
+    *(.stab)
+    *(.fini)
+    *(.ARM.exidx*)
+  }
+}
+
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-arm/crt0.S b/l4/pkg/bootstrap_custom/server/src/ARCH-arm/crt0.S
new file mode 100644 (file)
index 0000000..63bd63a
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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.
+ */
+/* -*- c -*- */
+
+#define MIMIC_A_VMLINUZ
+
+.section .text.init,#alloc,#execinstr
+.type _start,#function
+.globl _start
+_start:
+/* Some bootloaders like it this way, for others it won't harm */
+#ifdef MIMIC_A_VMLINUZ
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       b 10f
+       .word 0x016f2818
+       .word _start
+       .word _module_data_end
+10:
+#endif
+       /*
+        * It might be the case that we're not run at the position where we
+        * have been linked to. If this is the case we copy ourselves to the
+        * position we're linked to.
+        */
+       adr     r4, run         /* Running version */
+       ldr     r5, .LCrun      /* supposed to be version */
+       cmp     r4, r5          /* If equal ... */
+       beq     run             /* ... go to run */
+
+       /* Disable caches as we're moving code around */
+       mcr p15, 0, r3, c7, c5, 0 /* ICIALLU */
+       mrc p15, 0, r0, c1, c0
+       bic r0, #0x0004
+       bic r0, #0x1000
+       mcr p15, 0, r0, c1, c0
+
+       /* Figure how to move */
+        ldr     r7, .LCend_bin
+       subs    r8, r5, r4      /* r8 is the distance between the blocks */
+       bpl     move_behind
+
+       /* Copy before, copy forwards */
+       /* First, copy our copy loop to the very beginning to avoid code
+        * overwrites */
+       mov     r9, r5                  /* r9: run address */
+       ldr     r0, .LCstart_bin
+       ldr     r3, 3f
+       str     r3, [r0], #4
+       ldr     r3, 32f
+       str     r3, [r0], #4
+       ldr     r3, 33f
+       str     r3, [r0], #4
+       ldr     r3, 34f
+       str     r3, [r0], #4
+       ldr     r3, 35f
+       str     r3, [r0], #4
+       ldr     pc, .LCstart_bin
+
+3:     ldr     r6, [r4], #4
+32:    str     r6, [r5], #4
+33:    cmp     r5, r7
+34:    blt     3b
+35:    mov     pc, r9
+
+       /* Copy behind, copy backwards */
+move_behind:
+       sub     r8, r7, r8      /* r8 points to the end of source image */
+3:     ldr     r6, [r8, #-4]!  /* Take bytes */
+       str     r6, [r7, #-4]!  /* Put bytes */
+       cmp     r5, r7
+       blt     3b
+       ldr     pc, .LCrun
+
+
+.LCrun:       .word run
+.LCstart_bin: .word _start
+.LCend_bin:   .word _module_data_end
+
+run:
+       mov     r3, #0x1000
+       sub     r3, r3, #1                 /* r3 == 0xfff */
+       mrc     p15, 0, r0, c0, c0, 0      /* Main ID */
+       lsr     r0, #4
+       and     r0, r0, r3
+
+       /* Check for processors that understand CPU ID */
+       mov     r9, #0xb00
+       orr     r9, #0x002
+       cmp     r0, r9
+       beq     do_cpuid
+
+        mov     r3, #0xc00
+       orr     r9, r3, #0x00f
+       cmp     r0, r9
+       beq     do_cpuid
+
+       orr     r9, r3, #0x007
+       cmp     r0, r9
+       beq     do_cpuid
+
+       orr     r9, r3, #0x009
+       cmp     r0, r9
+       bne     do_bootstrap               /* None matched, normal startup */
+
+do_cpuid:
+       mrc     p15, 0, r0, c0, c0, 5      /* CPU ID */
+       and     r0, r0, #0xf               /* CPU id */
+       cmp     r0, #0                     /* CPU0 continues with bootstrap */
+       beq     do_bootstrap    
+
+/* CPU1+ wait for bootup */
+
+       // I-cache on
+       mrc p15, 0, r0, c1, c0, 0
+       orr r0, r0, #(1 << 12)
+       mcr p15, 0, r0, c1, c0, 0
+
+       // IRQs off, SVC
+       mrs r0, cpsr
+       orr r0, #0xd3
+       msr cpsr_c, r0
+
+#if defined(PLATFORM_TYPE_rv) || defined(PLATFORM_TYPE_rv_pbx) || \
+    defined(PLATFORM_TYPE_rv_vexpress) || defined(PLATFORM_TYPE_rv_vexpress_a15)
+
+       // enable GIC CPU interface + prio mask for IRQs
+       mrc     p15, 0, r0, c0, c0, 0    // r0: cpu-id
+       and     r0, r0, #0x70
+       cmp     r0, #0x70
+
+       // get board ID and retrieve MPCore-base from table
+       movne   r7, #0x10000000
+       moveq   r7, #0x00010000
+       orreq   r7, #0x1c000000
+       ldr     r5, [r7]
+       bic     r5, #0xff
+
+       adr     r6, .Lboard_data_table
+2:
+       ldr     r4, [r6]
+       cmp     r4, #0
+       beq     3f
+       cmp     r4, r5
+       bne     4f
+
+       ldr     r3, [r6, #4]
+       cmp     r0, r3
+       beq     3f
+       cmp     r3, #0
+       beq     3f
+4:     add     r6, #12
+       b       2b
+
+3:
+       ldr     r4, [r6, #8]
+       mov     r0, #0x1
+       str     r0, [r4, #0]
+       mov     r0, #0xf0
+       str     r0, [r4, #4]
+
+1:
+       ldr     r6, [r7, #0x30]
+       cmp     r6, #0
+       movne   pc, r6
+       .inst   0xe320f003 /* wfi */
+       ldr     r0, [r4, #12]
+       str     r0, [r4, #16]
+       b       1b
+
+.Lboard_data_table:
+       /* VExpress */
+       .word   0x1190f500 /* Board ID */
+       .word   0x00000070 /* CPU ID */
+       .word   0x2c002000 /* MPCore base */
+
+       .word   0x1190f500 /* Board ID */
+       .word   0x00000000 /* CPU ID */
+       .word   0x1e000100 /* MPCore base */
+
+       /* Default value (with #0) must come last! */
+       /* Realview */
+       .word   0
+       .word   0
+       .word   0x1f000100
+
+#else
+1:     .word 0xe320f003 /* wfi */
+       b       1b
+#endif
+
+do_bootstrap:
+       ldr     r3, .LCcrt0_tramppage      /* Load address of tramppage var */
+       str     sp, [r3]                   /* Store SP in variable          */
+       ldr     sp, .LCstack
+
+       mov     r0, r2                     /* ATAG pointer */
+       bl      __main
+1:     b       1b
+
+.LCcrt0_tramppage:      .word crt0_tramppage
+.LCstack: .word crt0_stack_high
+
+.section ".bss"
+
+       .global crt0_tramppage
+crt0_tramppage:
+       .space 4
+
+       .global crt0_stack_low
+       .align 3
+crt0_stack_low:
+       .space  8192
+       .global crt0_stack_high
+crt0_stack_high:
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-arm/head.cc b/l4/pkg/bootstrap_custom/server/src/ARCH-arm/head.cc
new file mode 100644 (file)
index 0000000..9e5755c
--- /dev/null
@@ -0,0 +1,28 @@
+#include "support.h"
+#include "startup.h"
+
+extern "C" int __aeabi_unwind_cpp_pr0(void);
+extern "C" int __aeabi_unwind_cpp_pr1(void);
+
+enum { _URC_FAILURE  = 9 };
+int __aeabi_unwind_cpp_pr0(void) { return _URC_FAILURE; }
+int __aeabi_unwind_cpp_pr1(void) { return _URC_FAILURE; }
+
+extern "C" void __main();
+void __main()
+{
+  unsigned long r;
+
+  asm volatile("mrc p15, 0, %0, c1, c0, 0" : "=r" (r) : : "memory");
+  r &= ~1UL;
+  r |= 2; // alignment check on
+  asm volatile("mcr p15, 0, %0, c1, c0, 0" : : "r" (r) : "memory");
+
+  clear_bss();
+  ctor_init();
+  Platform_base::iterate_platforms();
+
+  startup(_mbi_cmdline);
+  while(1)
+    ;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-arm/macros.h b/l4/pkg/bootstrap_custom/server/src/ARCH-arm/macros.h
new file mode 100644 (file)
index 0000000..682fdcc
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *     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 "ARCH-x86/macros.h"
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-arm/reboot.cc b/l4/pkg/bootstrap_custom/server/src/ARCH-arm/reboot.cc
new file mode 100644 (file)
index 0000000..70e3f48
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *     economic rights: Technische Universität Dresden (Germany)
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU Lesser General Public License 2.1.
+ * Please see the COPYING-LGPL-2.1 file for details.
+ */
+
+#include "support.h"
+
+void
+reboot_arch(void) __attribute__((noreturn));
+
+void
+reboot_arch(void)
+{
+  Platform_base::platform->reboot();
+
+  while (1)
+    ;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/bootstrap.ld.in b/l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/bootstrap.ld.in
new file mode 100644 (file)
index 0000000..3b2c3ba
--- /dev/null
@@ -0,0 +1,105 @@
+
+#include "ldscript.inc"
+
+OUTPUT_FORMAT("elf32-powerpc", "elf32-big",
+              "elf32-little")
+ENTRY(_start)
+
+PHDRS {
+  text PT_LOAD;
+  data PT_LOAD;
+  mods PT_LOAD;
+}
+
+SECTIONS
+{
+  /* Read-only sections, merged into text segment. The start address of
+   * the text segment is : */
+  . = LINKADDR;
+  .text :
+  {
+    . = ALIGN(4);
+    _stext = .;
+    *(.text.init) 
+    *(.init)
+    *(.text .text.* .gnu.linkonce.t.*)
+    *(.glue_7t) *(.glue_7)
+    KEEP (*(.fini))
+    LONG(0xc3)  /* terminate .fini */
+    . = ALIGN(0x40);
+    *(.rodata .rodata.* .gnu.linkonce.r.* .rodata1)
+  } : text
+
+  _etext = .;
+  PROVIDE (etext = .);
+
+  /* ensure that data starts at a new L4 page */
+  . = ALIGN(4096);
+  .data :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+    *(.anno)
+
+    CTORS
+    PLATFORMS
+
+    . = ALIGN(4);
+    _module_info_start = .;
+    *(.module_info)
+    _module_info_end   = .;
+  } : data
+  /* exception frames for C++ */
+  .eh_frame : 
+  { 
+    KEEP (*(.eh_frame)) 
+    LONG(0) /* terminate .eh_frame */
+  } : data
+
+  . = ALIGN(4);
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  _bss_start = .;
+  .bss :
+  {
+   *(.dynbss)
+   *(.bss .gnu.linkonce.b.*)
+   *(COMMON)
+  } : data
+  _bss_end = .;
+  _end = . ;
+  PROVIDE (end = .);
+
+  /* Moved here to ensure that these sections are located _after_ the text
+   * section. In the other case we would get program sections with a virtual
+   * address of 0 */
+  .hash    : { *(.hash)    }
+  .dynsym  : { *(.dynsym)  }
+  .dynstr  : { *(.dynstr)  }
+  .rel.dyn : { *(.rel.dyn) }
+
+/* Only move modules to modaddr if bootstrap is being loaded by an elf
+ * loader, and we do not need to copy images around at runtime (e.g. with
+ * compression) */
+#if defined(PLACE_MODULES_AT_MODADDR) && !defined(SINGLE_SECTION)
+  . = MODADDR;
+#else
+  . = ALIGN(4096);
+#endif
+  _module_data_start = .;
+  .module_data : {
+    *(EXCLUDE_FILE (*mod00.bin *mod01.bin *mod02.bin) .module_data)
+    *(.module_data)
+  } : mods
+  _module_data_end = .;
+
+  /* drop the following sections since we do not need them for DROPS */
+  /DISCARD/ : {
+    *(.interp)
+    *(.comment)
+    *(.note)
+    *(.stab)
+    *(.stabstr*)
+  } 
+}
+
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/crt0.S b/l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/crt0.S
new file mode 100644 (file)
index 0000000..9bc1630
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *     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.
+ */
+/* -*- c -*- */
+
+.section .text.init, "ax"
+.type _start, @function
+.globl _start
+_start:
+  lis  %r1, crt0_stack_high@ha  /* load stack pointer */
+  addi %r1, %r1, crt0_stack_high@l
+  b    __main
+1:
+  b 1b
+
+.section ".bss", "aw"
+
+.global crt0_stack_low
+crt0_stack_low:
+  .space 4096
+.global crt0_stack_high
+crt0_stack_high:
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/head.cc b/l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/head.cc
new file mode 100644 (file)
index 0000000..1c79c72
--- /dev/null
@@ -0,0 +1,18 @@
+#include "support.h"
+#include "startup.h"
+
+#include <l4/drivers/of.h>
+
+extern "C" void __main(unsigned long p1, unsigned long p2, unsigned long p3);
+void __main(unsigned long, unsigned long, unsigned long p3)
+{
+  clear_bss();
+  ctor_init();
+  L4_drivers::Of::set_prom(p3); //p3 is OF prom pointer
+  Platform_base::iterate_platforms();
+
+  printf("PPC platform initialized\n");
+  startup(_mbi_cmdline);
+  while(1)
+    ;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/init_kip_v2-arch.cc b/l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/init_kip_v2-arch.cc
new file mode 100644 (file)
index 0000000..f40c004
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *     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 <l4/drivers/of_if.h>
+
+void
+init_kip_v2_arch(l4_kernel_info_t* l4i)
+{
+  L4_drivers::Of_if of_if;
+  //l4i->total_ram = of_if.detect_ramsize();
+  printf("TBD: set total RAM via mem-descs!\n");
+  l4i->frequency_cpu = (l4_uint32_t)of_if.detect_cpu_freq() / 1000; //kHz
+  l4i->frequency_bus = (l4_uint32_t)of_if.detect_bus_freq();
+
+  of_if.vesa_set_mode(0x117);
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/macros.h b/l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/macros.h
new file mode 100644 (file)
index 0000000..b2edd95
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *     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 "ARCH-x86/macros.h"
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/reboot.cc b/l4/pkg/bootstrap_custom/server/src/ARCH-ppc32/reboot.cc
new file mode 100644 (file)
index 0000000..e0bd6f2
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *     economic rights: Technische Universität Dresden (Germany)
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU Lesser General Public License 2.1.
+ * Please see the COPYING-LGPL-2.1 file for details.
+ */
+
+void
+reboot_arch(void) __attribute__((noreturn));
+
+void
+reboot_arch(void)
+{
+  for (;;)
+    ;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-sparc/bootstrap.ld.in b/l4/pkg/bootstrap_custom/server/src/ARCH-sparc/bootstrap.ld.in
new file mode 100644 (file)
index 0000000..27ba043
--- /dev/null
@@ -0,0 +1,78 @@
+
+#include "ldscript.inc"
+
+ENTRY(_start)
+
+PHDRS {
+  common PT_LOAD;
+#ifdef IMAGE_MODE
+  mods PT_LOAD;
+#endif
+}
+
+SECTIONS
+{
+  . = LINKADDR;
+  /* Merge .text, .rodata, and .data in one segment to save space */
+  .text :
+  {
+       _stext = .;
+    *(.init)
+    *(.text .text.* .gnu.linkonce.t.*)
+  } : common
+
+  .data :
+  {
+    *(.rodata* .gnu.linkonce.r.*)
+    . = ALIGN(8);
+    *(.data)
+    *(.data.*)
+
+    CTORS
+    PLATFORMS
+
+    _module_info_start = .;
+    *(.module_info)
+    _module_info_end = .;
+
+  } : common
+
+  _edata  =  .;
+  PROVIDE (edata = .);
+  . = ALIGN(4096);
+  _bss_start = .;
+  .bss :
+  {
+   *(.bss)
+   *(COMMON)
+   *(.bss_memmap)
+  } : common
+  _bss_end = .;
+  _end = . ;
+  PROVIDE (end = .);
+
+/* Only move modules to modaddr if bootstrap is being loaded by an elf
+ * loader, and we do not need to copy images around at runtime (e.g. with
+ * compression) */
+#ifdef IMAGE_MODE
+#if defined(PLACE_MODULES_AT_MODADDR) && !defined(SINGLE_SECTION)
+  . = RAM_BASE + MODADDR;
+#endif
+  _module_data_start = .;
+  .module_data : {
+    *(EXCLUDE_FILE (*mod00.bin *mod01.bin *mod02.bin) .module_data)
+    *(.module_data)
+  } : mods
+  _module_data_end = .;
+#endif
+
+  /DISCARD/ : {
+    *(.interp)
+    *(.comment)
+    *(.note)
+    *(.eh_frame)
+    *(.stab)
+    *(.stabstr)
+    *(.fini)
+  }
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-sparc/crt0.S b/l4/pkg/bootstrap_custom/server/src/ARCH-sparc/crt0.S
new file mode 100644 (file)
index 0000000..2473235
--- /dev/null
@@ -0,0 +1,168 @@
+#define TRAP(H)  mov %psr, %l0; sethi %hi(H), %l4; jmp %l4+%lo(H); nop;
+#define TRAP_ENTRY(H) rd %psr, %l0; b H; rd %wim, %l3; nop;
+#define TRAP_ENTRY_INTERRUPT(int_level) \
+        mov int_level, %l7; rd %psr, %l0; b _prom_leonbare_irq_entry; rd %wim, %l3;
+#define BAD_TRAP ta 0; nop; nop; nop;
+
+.section ".bss"
+.align(0x2000)
+       .global crt0_stack_low
+_stack:
+crt0_stack_low:
+.space 8192
+       .global crt0_stack_high
+crt0_stack_high:
+
+.text
+/*
+ * Trap handler table -> must be aligned to page size
+ * as specified by the SPARC v8 manual (p. 31).
+ */
+.globl _leon_traphandlers
+.align(0x1000)
+_leon_traphandlers:
+  BAD_TRAP
+  BAD_TRAP
+  BAD_TRAP
+  BAD_TRAP
+  BAD_TRAP
+  TRAP(sparc_window_overflow);
+  TRAP(sparc_window_underflow);
+  BAD_TRAP
+  BAD_TRAP
+  BAD_TRAP
+  BAD_TRAP
+  BAD_TRAP
+  BAD_TRAP
+  BAD_TRAP
+  BAD_TRAP
+  BAD_TRAP
+  BAD_TRAP
+
+.globl _start
+_start:
+
+  rd %asr17, %g1
+
+  /*
+   * setup trap handler table
+   */
+  sethi %hi(_leon_traphandlers), %g2
+  wr %g2, %tbr
+
+  /* the TBR setup above comes into effect three instructions from now!
+   * Right now, we assume that no trap occurs in between.
+   */
+
+  /* set stack pointer */
+  sethi %hi(_stack), %sp
+  or %sp, %lo(_stack), %sp
+
+  /*
+   * setup task with enough space for registers %l0-%l7 and %i0-%i7
+   */
+  sub %sp, 64, %sp
+
+  sethi %hi(_stack), %fp
+  or %fp, %lo(_stack), %fp
+
+  /* enable traps */
+  mov %psr, %l0
+  or  %l0, (1 << 5), %l0
+  mov %l0, %psr
+
+  ba __main
+  nop
+
+  ta 0
+
+
+.globl sparc_window_overflow
+sparc_window_overflow:
+  mov %wim, %l3  /* need to determine new WIM */
+  mov %g1, %l7
+  srl %l3, 1, %g1
+
+  /*
+   * Find out if we are on LEON3 (PSR[24:27] == 3)
+   * or on LEON2. For LEON3, we can read the number of
+   * register windows from ASR17
+   */
+  mov %psr, %l4
+  srl %l4, 24, %l4
+  and %l4, 3, %l4
+  subcc %l4, 3, %g0
+  bne 1f
+  nop
+
+  /*
+   * It's a LEON3
+   */
+  mov %asr17, %l4
+
+  /* calculate new WIM */
+  and %l4, 0x1f, %l4
+  sll %l3, %l4, %l4
+  or %l4, %g1, %g1
+
+  /*
+   * The trick here is to move to a valid stack frame
+   * and store the register window contents there.
+   */
+  save
+     mov %g1, %wim
+     nop; nop; nop
+
+     std %l0, [%sp + 0];
+     std %l2, [%sp + 8];
+     std %l4, [%sp + 16];
+     std %l6, [%sp + 24];
+     std %i0, [%sp + 32];
+     std %i2, [%sp + 40];
+     std %i4, [%sp + 48];
+     std %i6, [%sp + 56];
+
+  restore
+  mov %l7, %g1
+  jmp %l1
+  rett %l2
+
+1: ta 0
+
+.globl sparc_window_underflow
+sparc_window_underflow:
+  mov %wim, %l3  /* need to determine new WIM */
+  sll %l3, 1, %l4
+
+  /* Determine LEON version */
+  mov %psr, %l5
+  srl %l5, 24, %l5
+  and %l5, 3, %l5
+  subcc %l5, 3, %g0
+  bne 1f
+  nop
+
+  mov %asr17, %l5
+  and %l5, 0x1f, %l5
+  srl %l3, %l5, %l5
+  or  %l5, %l4, %l5
+  mov %l5, %wim
+  nop; nop; nop
+
+  restore             ! Two restores to get into the
+  restore             ! window to restore
+  ldd   [%sp + 0], %l0;       ! Restore window from the stack
+  ldd   [%sp + 8], %l2;
+  ldd   [%sp + 16], %l4;
+  ldd   [%sp + 24], %l6;
+  ldd   [%sp + 32], %i0;
+  ldd   [%sp + 40], %i2;
+  ldd   [%sp + 48], %i4;
+  ldd   [%sp + 56], %i6;
+  save                ! Get back to the trap window.
+  save
+
+  jmp %l1
+  rett %l2
+
+1: ta 0
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-sparc/head.cc b/l4/pkg/bootstrap_custom/server/src/ARCH-sparc/head.cc
new file mode 100644 (file)
index 0000000..4258cdf
--- /dev/null
@@ -0,0 +1,14 @@
+#include "support.h"
+#include "startup.h"
+
+extern "C" void __main();
+void __main()
+{
+  clear_bss();
+  ctor_init();
+  Platform_base::iterate_platforms();
+
+  startup(_mbi_cmdline);
+  while(1)
+    ;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-sparc/leon_ahb.h b/l4/pkg/bootstrap_custom/server/src/ARCH-sparc/leon_ahb.h
new file mode 100644 (file)
index 0000000..3d8f4bc
--- /dev/null
@@ -0,0 +1,69 @@
+#pragma once
+
+enum Leon_memory_map
+{
+       LEON_PROM_BASE = 0x00000000,
+       LEON_IO_BASE   = 0x20000000,
+       LEON_RAM_BASE  = 0x40000000,
+       LEON_AHB_BASE  = 0x80000000,
+       LEON_ETH_BASE  = 0xFFFB0000,
+       LEON_CAN_BASE  = 0xFFFC0000,
+       LEON_PNP_BASE  = 0xFFFFF000,
+};
+
+
+enum Leon_register_offsets
+{
+       LEON_MCTRL    =       0,
+       LEON_APBUART  =   0x100,
+       LEON_IRQMP    =   0x200,
+       LEON_GPTIMER  =   0x300,
+       LEON_PS2      =   0x500,
+       LEON_VGA      =   0x600,
+       LEON_AHBUART  =   0x700,
+       LEON_GRGPIO   =   0x800,
+       LEON_GRSPW1   =   0xA00,
+       LEON_GRSPW2   =   0xB00,
+       LEON_GRSPW3   =   0xD00,
+       LEON_AHBSTAT  =   0xF00,
+       LEON_AHBPNP   = 0xFF000,
+};
+
+
+enum Leon_traps
+{
+       LEON_TR_RESET            = 0x00,
+       LEON_TR_INSTR_ACCESS_ERR = 0x01,
+       LEON_TR_ILLEGAL_INSTR    = 0x02,
+       LEON_TR_PRIV_INSTR       = 0x03,
+       LEON_TR_FP_DISABLED      = 0x04,
+       LEON_TR_WRITE_ERR        = 0x2B,
+       LEON_TR_CP_DISABLED      = 0x2f,
+       LEON_TR_WATCHPOINT       = 0x0B,
+       LEON_TR_WINDOW_OVERFL    = 0x05,
+       LEON_TR_WINDOW_UNDERFL   = 0x06,
+       LEON_TR_REG_HW_ERR       = 0x20,
+       LEON_TR_ALIGN            = 0x07,
+       LEON_TR_FP_EXC           = 0x08,
+       LEON_TR_CP_EXC           = 0x28,
+       LEON_TR_DATA_ACCESS_EXC  = 0x09,
+       LEON_TR_TAG_OVERFL       = 0x0A,
+       LEON_TR_DIVIDE_EXC       = 0x2A,
+       LEON_TR_IRQ1             = 0x11,
+       LEON_TR_IRQ2             = 0x12,
+       LEON_TR_IRQ3             = 0x13,
+       LEON_TR_IRQ4             = 0x14,
+       LEON_TR_IRQ5             = 0x15,
+       LEON_TR_IRQ6             = 0x16,
+       LEON_TR_IRQ7             = 0x17,
+       LEON_TR_IRQ8             = 0x18,
+       LEON_TR_IRQ9             = 0x19,
+       LEON_TR_IRQ10            = 0x1A,
+       LEON_TR_IRQ11            = 0x1B,
+       LEON_TR_IRQ12            = 0x1C,
+       LEON_TR_IRQ13            = 0x1D,
+       LEON_TR_IRQ14            = 0x1E,
+       LEON_TR_IRQ15            = 0x1F,
+       LEON_TR_SW_MIN           = 0x80,
+       LEON_TR_SW_MAX           = 0xFF,
+};
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-sparc/macros.h b/l4/pkg/bootstrap_custom/server/src/ARCH-sparc/macros.h
new file mode 100644 (file)
index 0000000..9017680
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * (c) 2009 Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef __ARCH_SPARC_MACROS_H__
+#define __ARCH_SPARC_MACROS_H__
+
+#define L4_CHAR_PTR            (char*)
+#define L4_CONST_CHAR_PTR      (const char*)
+#define L4_VOID_PTR            (void*)
+#define L4_MB_MOD_PTR          (l4util_mb_mod_t*)
+
+#endif  /* ! __ARCH_SPARC_MACROS_H__ */
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-sparc/reboot.cc b/l4/pkg/bootstrap_custom/server/src/ARCH-sparc/reboot.cc
new file mode 100644 (file)
index 0000000..e0bd6f2
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *     economic rights: Technische Universität Dresden (Germany)
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU Lesser General Public License 2.1.
+ * Please see the COPYING-LGPL-2.1 file for details.
+ */
+
+void
+reboot_arch(void) __attribute__((noreturn));
+
+void
+reboot_arch(void)
+{
+  for (;;)
+    ;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-x86/bootsect.S b/l4/pkg/bootstrap_custom/server/src/ARCH-x86/bootsect.S
new file mode 100644 (file)
index 0000000..c13b768
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *     bootsect.S              Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ *     modified by Drew Eckhardt
+ *     modified by Bruce Evans (bde)
+ *     modified by Chris Noe (May 1999) (as86 -> gas)
+ *     gutted by H. Peter Anvin (Jan 2003)
+ *
+ * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
+ * addresses must be multiplied by 16 to obtain their respective linear
+ * addresses. To avoid confusion, linear addresses are written using leading
+ * hex while segment addresses are written as segment:offset.
+ *
+ */
+
+/* Don't touch these, unless you really know what you're doing. */
+#define DEF_INITSEG    0x9000
+#define DEF_SYSSEG     0x1000
+#define DEF_SETUPSEG   0x9020
+#define DEF_SYSSIZE    0x7F00
+
+/* Internal svga startup constants */
+#define NORMAL_VGA     0xffff          /* 80x25 mode */
+#define EXTENDED_VGA   0xfffe          /* 80x50 mode */
+#define ASK_VGA                0xfffd          /* ask for it at bootup */
+
+
+SETUPSECTS     = 6                     /* default nr of setup-sectors */
+BOOTSEG                = 0x07C0                /* original address of boot-sector */
+INITSEG                = DEF_INITSEG           /* we move boot here - out of the way */
+SETUPSEG       = DEF_SETUPSEG          /* setup starts here */
+SYSSEG         = DEF_SYSSEG            /* system loaded at 0x10000 (65536) */
+SYSSIZE                = DEF_SYSSIZE           /* system size: # of 16-byte clicks */
+                                       /* to be loaded */
+ROOT_DEV       = 0                     /* ROOT_DEV is now written by "build" */
+SWAP_DEV       = 0                     /* SWAP_DEV is now written by "build" */
+
+#ifndef SVGA_MODE
+#define SVGA_MODE ASK_VGA
+#endif
+
+#ifndef RAMDISK
+#define RAMDISK 0
+#endif
+
+#ifndef ROOT_RDONLY
+#define ROOT_RDONLY 1
+#endif
+
+.code16
+.text
+
+.global _start
+_start:
+
+       # Normalize the start address
+       jmpl    $BOOTSEG, $start2
+
+start2:
+       movw    %cs, %ax
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %ss
+       movw    $0x7c00, %sp
+       sti
+       cld
+
+       movw    $bugger_off_msg, %si
+
+msg_loop:
+       lodsb
+       andb    %al, %al
+       jz      die
+       movb    $0xe, %ah
+       movw    $7, %bx
+       int     $0x10
+       jmp     msg_loop
+
+die:
+       # Allow the user to press a key, then reboot
+       xorw    %ax, %ax
+       int     $0x16
+       int     $0x19
+
+       # int 0x19 should never return.  In case it does anyway,
+       # invoke the BIOS reset code...
+       ljmp    $0xf000,$0xfff0
+
+
+bugger_off_msg:
+       .ascii  "Direct booting from floppy is no longer supported.\r\n"
+       .ascii  "Please use a boot loader program instead.\r\n"
+       .ascii  "\n"
+       .ascii  "Remove disk and press any key to reboot . . .\r\n"
+       .byte   0
+       
+
+       # Kernel attributes; used by setup
+
+       .org 497
+setup_sects:   .byte SETUPSECTS
+root_flags:    .word ROOT_RDONLY
+syssize:       .word SYSSIZE
+swap_dev:      .word SWAP_DEV
+ram_size:      .word RAMDISK
+vid_mode:      .word SVGA_MODE
+root_dev:      .word ROOT_DEV
+boot_flag:     .word 0xAA55
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-x86/bootstrap.ld.in b/l4/pkg/bootstrap_custom/server/src/ARCH-x86/bootstrap.ld.in
new file mode 100644 (file)
index 0000000..d808d03
--- /dev/null
@@ -0,0 +1,155 @@
+
+#include "ldscript.inc"
+
+ENTRY(_start)
+
+PHDRS {
+  data PT_LOAD;
+#ifdef IMAGE_MODE
+  mods PT_LOAD;
+#endif
+}
+
+SECTIONS
+{
+#define JH
+#define ENTRY_OFFSET (0x0)
+#ifdef JH
+  #define ENTRY_OFFSET (0xf0000)
+  . = 0;
+
+  /* 16-bit sections */
+  .jh-startup : { *(.jh.startup) }
+
+  . = 0xfff0;
+  .jh-boot    : {
+      *(.jh.boot)
+    . = ALIGN(16);
+  }
+#endif
+
+#ifdef ARCH_amd64
+  . = LINKADDR + SIZEOF_HEADERS + ENTRY_OFFSET;
+#else
+  . = LINKADDR;
+#endif
+  PROVIDE (ImageBase = LINKADDR);
+  .hash : AT (ADDR(.hash) - ENTRY_OFFSET) { *(.hash) } : data    /* this MUST come first! */
+  /* Merge .text, .rodata, and .data in one segment to save space */
+
+  /* provide at least 1K space for PE header in case of EFI */
+  /* NOTE: the .hash section is not used for EFI, so we declare
+   *       this as free space for PE too
+   */
+  /* FXIME: should make this depending on EFI */
+  . = (. < (0x400 + LINKADDR)) ? (LINKADDR + 0x400) : .;
+
+  .text : AT (ADDR(.text) - ENTRY_OFFSET) 
+  {
+    *(.init)
+    *(.text .text.* .gnu.linkonce.t*)
+
+    *(.rodata*)
+  } : data
+
+  .dynsym   : AT (ADDR(.dynsym) - ENTRY_OFFSET) { *(.dynsym) } : data
+  .dynstr   : AT (ADDR(.dynstr) - ENTRY_OFFSET) { *(.dynstr) } : data
+  .reloc    : AT (ADDR(.reloc) - ENTRY_OFFSET) { *(.reloc) } : data
+  .rel.dyn : AT (ADDR(.rel.dyn) - ENTRY_OFFSET)
+  {
+    *(.rel.*) *(.rel.module_info)
+  } : data
+
+  .data : AT (ADDR(.data) - ENTRY_OFFSET)
+  {
+    . = ALIGN(8);
+    *(.data)
+    *(.data.*)
+    *(.plt)
+    *(.got.plt)
+    *(.got)
+
+    CTORS
+    PLATFORMS
+
+  } : data
+
+  .data.module_info : AT (ADDR(.data.module_info) - ENTRY_OFFSET)
+  {
+    . = ALIGN(16);
+    _module_info_start = .;
+    *(.module_info .module_info.*)
+    _module_info_end = .;
+  } : data
+
+  .dynamic  : AT (ADDR(.dynamic) - ENTRY_OFFSET)  { *(.dynamic) } : data
+  .rela.dyn : AT (ADDR(.rela.dyn) - ENTRY_OFFSET)
+  {
+    *(.rela.init)
+    *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+    *(.rela.fini)
+    *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+    *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+    *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+    *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+    *(.rela.ctors)
+    *(.rela.dtors)
+    *(.rela.got)
+    *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+    *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+    *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+    *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+    *(.rela.ifunc)
+    *(.rela.module*)
+    *(.rela.init_array)
+  } : data
+  .rela.plt : AT (ADDR(.rela.plt) - ENTRY_OFFSET)
+  {
+    *(.rela.plt)
+    *(.rela.iplt)
+  } : data
+
+  _edata  =  .;
+  PROVIDE (edata = .);
+  . = ALIGN(4096);
+  __bss_start = .;
+  .bss : AT (ADDR(.bss) - ENTRY_OFFSET)
+  {
+   *(.bss)
+   *(.bss.*)
+   *(COMMON)
+   *(.dynbss)
+   *(.bss_memmap)
+  } : data
+  _end = . ;
+  PROVIDE (end = .);
+  . = ALIGN(4096);
+
+/* Only move modules to modaddr if bootstrap is being loaded by an elf
+ * loader, and we do not need to copy images around at runtime (e.g. with
+ * compression) */
+#ifdef IMAGE_MODE
+#if defined(PLACE_MODULES_AT_MODADDR) && !defined(SINGLE_SECTION)
+  . = RAM_BASE + MODADDR;
+#endif
+  _module_data_start = .;
+  .module_data : AT (ADDR(.module_data) - ENTRY_OFFSET) {
+    *(EXCLUDE_FILE (*mod00.bin *mod01.bin *mod02.bin) .module_data)
+    *(.module_data)
+  } : mods
+  _module_data_end = .;
+#endif
+
+  /DISCARD/ : {
+    *(.rela.reloc)
+    *(.note.GNU-stack)
+    *(.jcr)
+    *(.interp)
+    *(.comment)
+    *(.note)
+    *(.eh_frame)
+    *(.stab)
+    *(.stabstr)
+    *(.fini)
+  }
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-x86/crt0.S b/l4/pkg/bootstrap_custom/server/src/ARCH-x86/crt0.S
new file mode 100644 (file)
index 0000000..6fd4558
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *          Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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 <l4/sys/compiler.h>
+#define JH
+#ifdef JH
+#include "inmate.h" 
+#define X86_CR0_PE             0x00000001
+
+.code16
+    .section ".jh.boot", "ax"
+
+    .globl __reset_entry
+__reset_entry:
+    ljmp $0xf000,$start16
+
+    .section ".jh.startup", "ax"
+
+start16:
+    lgdtl %cs:gdt_ptr
+
+    mov %cr0,%eax
+    or $X86_CR0_PE,%al
+    mov %eax,%cr0
+
+    ljmpl $INMATE_CS32,$_start + FSEGMENT_BASE
+
+.code32
+
+loader_gdt:
+       .quad   0
+       .quad   0x00cf9b000000ffff
+       .quad   0x00af9b000000ffff
+       .quad   0x00cf93000000ffff
+
+gdt_ptr:
+       .short  gdt_ptr - loader_gdt - 1
+       .long   loader_gdt + FSEGMENT_BASE
+
+       .align(4096)
+       .global loader_pdpt
+loader_pdpt:
+       .long   0x00000083
+       .align(4096)
+#endif 
+
+       
+       .section .init
+
+       .globl  _start
+_start:
+#ifdef REALMODE_LOADING
+       cld
+       cli
+       mov     $(3 * 8), %eax
+       mov     %eax, %ds
+       mov     %eax, %es
+       mov     %eax, %fs
+       mov     %eax, %gs
+       mov     %eax, %ss
+       lss     _stack_seg, %esp
+#else
+       leal    _stack, %esp
+#endif
+       pushl   $0
+       pushl   %esi    /* Pointer to real mode or Xen start_info pointer */
+       pushl   %eax
+       pushl   %ebx
+
+#ifndef XEN
+       /* initialize vector for exception 6 */
+       movl    $trap6_entry,%eax
+       movw    %ax, _idt_offset_low
+       shrl    $16, %eax
+       movw    %ax, _idt_offset_high
+       movw    %cs, %ax
+       movw    %ax, _idt_selector
+
+       /* load tiny interrupt descriptor table to catch exception 6 */
+       lidtl   _idtdesc
+#endif
+
+       pushl   $_exit
+       jmp     __main
+
+       /* Show an error message and wait for keypress to reboot. */
+trap6_entry:
+       pusha
+       cld
+
+       jmp 8f
+
+       /* printhex
+        * edx: value to print
+        * eax: location on screen
+        */
+99:    mov     %eax, %edi
+       add     $(2*8), %edi
+98:    mov     $numbers,%ebx
+       mov     %edx,%ecx
+       shr     $28,%ecx
+       shl     $4,%edx
+       movzbl  (%ebx,%ecx,1),%ecx
+       mov     $0x4, %ch
+       mov     %cx,(%eax)
+       add     $0x2,%eax
+       cmp     %edi,%eax
+       jne     98b
+       ret
+
+8:
+       /* print out warning */
+       movl    $trap6_warning, %esi
+       movl    $(0xb8000 + (24*80*2)), %edi
+       movb    $0x0F, %ah
+       
+1:     /* read next character from string */
+       lodsb
+
+       /* check for end-of-string */
+       cmpb    $0, %al
+       je      3f
+
+       /* Check for hex number */
+       cmpb    $'      ', %al
+       jne     4f
+       pusha
+       mov     (32 + 32)(%esp),%edx
+       mov     %edi, %eax
+       call    99b
+       popa
+       add     $(8*2), %edi
+       jmp     1b
+       
+4:     /* check for newline */
+       cmpb    $'\n', %al
+       jne     2f
+       
+       pushl   %eax
+       pushl   %esi
+       
+       /* move screen upwards 1 line */
+       movl    $((24*80*2)/4), %ecx
+       movl    $(0xb8000 + 1*80*2), %esi
+       movl    $0xb8000, %edi
+       rep     movsl
+
+       /* clear last line of screen */
+       movl    $((1*80*2)/4), %ecx
+       movl    $0x07200720, %eax
+       rep     stosl
+
+       popl    %esi
+       popl    %eax
+       
+       /* jump to new line */
+       movl    $(0xb8000 + (24*80*2)), %edi
+       jmp     1b
+       
+2:     /* print character */
+       stosw
+       jmp     1b
+
+3:     /* wait for keypress */
+       inb     $0x64, %al
+       testb   $0x01, %al
+       je      3b
+
+       movb    %al, %ah
+
+       /* empty keyboard buffer */
+       inb     $0x60, %al
+       
+       /* ignore PS/2 mouse events */
+       testb   $0x20, %ah
+       jne     3b
+
+       jmp     reboot
+
+
+       /* the warning text */
+trap6_warning:
+       .ascii  "\n"
+       .ascii  "Bootstrap: Invalid opcode at    detected!\n"
+       .ascii  "Be sure that you don't use any CPU optimization flags like\n"
+       .ascii  "           -march=i686\n"
+       .ascii  "when compiling Bootstrap and the depending libraries.\n"
+       .ascii  "\n"
+       .asciz  "           Press any key to reboot..."
+
+numbers:
+       .ascii  "0123456789abcdef"
+
+        /* MultiBoot header - see multiboot.h.  */
+       .p2align(2)
+
+#define MULTIBOOT_MEMORY_INFO 0x00000002
+_mb_header:
+        .long   0x1BADB002             /* magic */
+        .long   MULTIBOOT_MEMORY_INFO  /* flags: AOUT_KLUDGE */
+        .long   0 - 0x1BADB002 - MULTIBOOT_MEMORY_INFO
+
+#ifndef XEN
+       .word   0
+_idtdesc:
+       .word   (7*8)-1
+       .long   _idt
+
+_idt:
+       .word   0,0,0,0                 /* trap 0 */
+       .word   0,0,0,0                 /* trap 1 */
+       .word   0,0,0,0                 /* trap 2 */
+       .word   0,0,0,0                 /* trap 3 */
+       .word   0,0,0,0                 /* trap 4 */
+       .word   0,0,0,0                 /* trap 5 */
+
+_idt_offset_low:
+       .word   0
+_idt_selector:
+       .word   0
+       .byte   0
+       .byte   0xee
+_idt_offset_high:
+       .word   0
+#endif
+
+#ifdef REALMODE_LOADING
+_stack_seg:
+       .long   _stack
+       .long   (3 * 8)
+#endif
+
+       .bss
+       .space  8192
+       .globl  _stack
+_stack:
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-x86/inmate.h b/l4/pkg/bootstrap_custom/server/src/ARCH-x86/inmate.h
new file mode 100644 (file)
index 0000000..16940a3
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) Siemens AG, 2013
+ *
+ * Authors:
+ *  Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#define NULL                   ((void *)0)
+
+#define HEAP_BASE              0x000000
+#define FSEGMENT_BASE          0x0f0000
+#define COMM_REGION_BASE       0x100000
+
+#define INMATE_CS32            0x8
+#define INMATE_CS64            0x10
+#define INMATE_DS32            0x18
+
+#define NS_PER_USEC            1000UL
+#define NS_PER_MSEC            1000000UL
+#define NS_PER_SEC             1000000000UL
+
+#define PAGE_SIZE              (4 * 1024ULL)
+#ifdef __x86_64__
+#define BITS_PER_LONG          64
+#define HUGE_PAGE_SIZE         (2 * 1024 * 1024ULL)
+#else
+#define BITS_PER_LONG          32
+#define HUGE_PAGE_SIZE         (4 * 1024 * 1024ULL)
+#endif
+#define PAGE_MASK              (~(PAGE_SIZE - 1))
+#define HUGE_PAGE_MASK         (~(HUGE_PAGE_SIZE - 1))
+
+#define X2APIC_ID              0x802
+#define X2APIC_ICR             0x830
+
+#define APIC_LVL_ASSERT                (1 << 14)
+
+#define PCI_CFG_VENDOR_ID      0x000
+#define PCI_CFG_DEVICE_ID      0x002
+#define PCI_CFG_COMMAND                0x004
+# define PCI_CMD_IO            (1 << 0)
+# define PCI_CMD_MEM           (1 << 1)
+# define PCI_CMD_MASTER                (1 << 2)
+# define PCI_CMD_INTX_OFF      (1 << 10)
+#define PCI_CFG_STATUS         0x006
+# define PCI_STS_INT           (1 << 3)
+# define PCI_STS_CAPS          (1 << 4)
+#define PCI_CFG_BAR            0x010
+# define PCI_BAR_64BIT         0x4
+#define PCI_CFG_CAP_PTR                0x034
+
+#define PCI_ID_ANY             0xffff
+
+#define PCI_CAP_MSI            0x05
+#define PCI_CAP_MSIX           0x11
+
+#define MSIX_CTRL_ENABLE       0x8000
+#define MSIX_CTRL_FMASK                0x4000
+
+#define SMP_MAX_CPUS           255
+
+#if 0 //turned off by coon on 11 april. //ifndef __ASSEMBLY__
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+typedef s8 __s8;
+typedef u8 __u8;
+
+typedef s16 __s16;
+typedef u16 __u16;
+
+typedef s32 __s32;
+typedef u32 __u32;
+
+typedef s64 __s64;
+typedef u64 __u64;
+
+typedef enum { true=1, false=0 } bool;
+
+static inline void cpu_relax(void)
+{
+       asm volatile("rep; nop" : : : "memory");
+}
+
+static inline void outb(u8 v, u16 port)
+{
+       asm volatile("outb %0,%1" : : "a" (v), "dN" (port));
+}
+
+static inline void outw(u16 v, u16 port)
+{
+       asm volatile("outw %0,%1" : : "a" (v), "dN" (port));
+}
+
+static inline void outl(u32 v, u16 port)
+{
+       asm volatile("outl %0,%1" : : "a" (v), "dN" (port));
+}
+
+static inline u8 inb(u16 port)
+{
+       u8 v;
+       asm volatile("inb %1,%0" : "=a" (v) : "dN" (port));
+       return v;
+}
+
+static inline u16 inw(u16 port)
+{
+       u16 v;
+       asm volatile("inw %1,%0" : "=a" (v) : "dN" (port));
+       return v;
+}
+
+static inline u32 inl(u16 port)
+{
+       u32 v;
+       asm volatile("inl %1,%0" : "=a" (v) : "dN" (port));
+       return v;
+}
+
+static inline u8 mmio_read8(void *address)
+{
+       return *(volatile u8 *)address;
+}
+
+static inline u16 mmio_read16(void *address)
+{
+       return *(volatile u16 *)address;
+}
+
+static inline u32 mmio_read32(void *address)
+{
+       u32 value;
+
+       /* assembly-encoded to match the hypervisor MMIO parser support */
+       asm volatile("movl (%1),%0" : "=r" (value) : "r" (address));
+       return value;
+}
+
+static inline u64 mmio_read64(void *address)
+{
+       return *(volatile u64 *)address;
+}
+
+static inline void mmio_write8(void *address, u8 value)
+{
+       *(volatile u8 *)address = value;
+}
+
+static inline void mmio_write16(void *address, u16 value)
+{
+       *(volatile u16 *)address = value;
+}
+
+static inline void mmio_write32(void *address, u32 value)
+{
+       /* assembly-encoded to match the hypervisor MMIO parser support */
+       asm volatile("movl %0,(%1)" : : "r" (value), "r" (address));
+}
+
+static inline void mmio_write64(void *address, u64 value)
+{
+       *(volatile u64 *)address = value;
+}
+
+static inline u64 read_msr(unsigned int msr)
+{
+       u32 low, high;
+
+       asm volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
+       return low | ((u64)high << 32);
+}
+
+static inline void write_msr(unsigned int msr, u64 val)
+{
+       asm volatile("wrmsr"
+               : /* no output */
+               : "c" (msr), "a" ((u32)val), "d" ((u32)(val >> 32))
+               : "memory");
+}
+
+static inline unsigned int cpu_id(void)
+{
+       return read_msr(X2APIC_ID);
+}
+
+#include <jailhouse/hypercall.h>
+
+#define comm_region    ((struct jailhouse_comm_region *)COMM_REGION_BASE)
+
+extern unsigned int printk_uart_base;
+void printk(const char *fmt, ...);
+
+void *memset(void *s, int c, unsigned long n);
+void *memcpy(void *d, const void *s, unsigned long n);
+
+typedef void(*int_handler_t)(void);
+
+void int_init(void);
+void int_set_handler(unsigned int vector, int_handler_t handler);
+void int_send_ipi(unsigned int cpu_id, unsigned int vector);
+
+enum ioapic_trigger_mode {
+       TRIGGER_EDGE = 0,
+       TRIGGER_LEVEL_ACTIVE_HIGH = 1 << 15,
+       TRIGGER_LEVEL_ACTIVE_LOW = (1 << 15) | (1 << 13),
+};
+
+void ioapic_init(void);
+void ioapic_pin_set_vector(unsigned int pin,
+                          enum ioapic_trigger_mode trigger_mode,
+                          unsigned int vector);
+
+void inmate_main(void);
+
+void hypercall_init(void);
+
+unsigned long pm_timer_read(void);
+
+unsigned long tsc_read(void);
+unsigned long tsc_init(void);
+
+void delay_us(unsigned long microsecs);
+
+unsigned long apic_timer_init(unsigned int vector);
+void apic_timer_set(unsigned long timeout_ns);
+
+enum map_type { MAP_CACHED, MAP_UNCACHED };
+
+void *alloc(unsigned long size, unsigned long align);
+void map_range(void *start, unsigned long size, enum map_type map_type);
+
+u32 pci_read_config(u16 bdf, unsigned int addr, unsigned int size);
+void pci_write_config(u16 bdf, unsigned int addr, u32 value,
+                     unsigned int size);
+int pci_find_device(u16 vendor, u16 device, u16 start_bdf);
+int pci_find_cap(u16 bdf, u16 cap);
+void pci_msi_set_vector(u16 bdf, unsigned int vector);
+void pci_msix_set_vector(u16 bdf, unsigned int vector, u32 index);
+
+extern volatile u32 smp_num_cpus;
+extern u8 smp_cpu_ids[SMP_MAX_CPUS];
+void smp_wait_for_all_cpus(void);
+void smp_start_cpu(unsigned int cpu_id, void (*entry)(void));
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-x86/macros.h b/l4/pkg/bootstrap_custom/server/src/ARCH-x86/macros.h
new file mode 100644 (file)
index 0000000..1c08fb5
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * (c) 2009 Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef __ARCH_X86_MACROS_H__
+#define __ARCH_X86_MACROS_H__
+
+#define L4_CHAR_PTR            (char*)
+#define L4_CONST_CHAR_PTR      (const char*)
+#define L4_VOID_PTR            (void*)
+#define L4_MB_MOD_PTR          (l4util_mb_mod_t*)
+
+#endif  /* ! __ARCH_X86_MACROS_H__ */
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-x86/reboot.cc b/l4/pkg/bootstrap_custom/server/src/ARCH-x86/reboot.cc
new file mode 100644 (file)
index 0000000..5ab3ed1
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *     economic rights: Technische Universität Dresden (Germany)
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU Lesser General Public License 2.1.
+ * Please see the COPYING-LGPL-2.1 file for details.
+ */
+#include <l4/util/port_io.h>
+#include <l4/util/cpu.h>
+
+void
+reboot_arch(void) __attribute__((noreturn));
+
+void
+reboot_arch(void)
+{
+  while (l4util_in8(0x64) & 0x02)
+    l4util_iodelay();
+  l4util_out8(0x60, 0x64);
+  l4util_iodelay();
+
+  while (l4util_in8(0x64) & 0x02)
+    l4util_iodelay();
+  l4util_out8(0x04, 0x60);
+  l4util_iodelay();
+
+  while (l4util_in8(0x64) & 0x02)
+    l4util_iodelay();
+  l4util_out8(0xFE, 0x64);
+  l4util_iodelay();
+
+  for (;;)
+    l4util_cpu_pause();
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-x86/setup.S b/l4/pkg/bootstrap_custom/server/src/ARCH-x86/setup.S
new file mode 100644 (file)
index 0000000..f7405b5
--- /dev/null
@@ -0,0 +1,3039 @@
+/*
+ *     setup.S         Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * setup.s is responsible for getting the system data from the BIOS,
+ * and putting them into the appropriate places in system memory.
+ * both setup.s and system has been loaded by the bootblock.
+ *
+ * This code asks the bios for memory/disk/other parameters, and
+ * puts them in a "safe" place: 0x90000-0x901FF, ie where the
+ * boot-block used to be. It is then up to the protected mode
+ * system to read them from there before the area is overwritten
+ * for buffer-blocks.
+ *
+ * Move PS/2 aux init code to psaux.c
+ * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
+ *
+ * some changes and additional features by Christoph Niemann,
+ * March 1993/June 1994 (Christoph.Niemann@linux.org)
+ *
+ * add APM BIOS checking by Stephen Rothwell, May 1994
+ * (sfr@canb.auug.org.au)
+ *
+ * High load stuff, initrd support and position independency
+ * by Hans Lermen & Werner Almesberger, February 1996
+ * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
+ *
+ * Video handling moved to video.S by Martin Mares, March 1996
+ * <mj@k332.feld.cvut.cz>
+ *
+ * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
+ * parsons) to avoid loadlin confusion, July 1997
+ *
+ * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
+ * <stiker@northlink.com>
+ *
+ * Fix to work around buggy BIOSes which dont use carry bit correctly
+ * and/or report extended memory in CX/DX for e801h memory size detection 
+ * call.  As a result the kernel got wrong figures.  The int15/e801h docs
+ * from Ralf Brown interrupt list seem to indicate AX/BX should be used
+ * anyway.  So to avoid breaking many machines (presumably there was a reason
+ * to orginally use CX/DX instead of AX/BX), we do a kludge to see
+ * if CX/DX have been changed in the e801 call and if so use AX/BX .
+ * Michael Miller, April 2001 <michaelm@mjmm.org>
+ *
+ * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
+ * by Robert Schwebel, December 2001 <robert@schwebel.de>
+ */
+
+#define __BIG_KERNEL__ 1
+
+//#include <linux/config.h>
+//#include <asm/segment.h>
+//#include <asm/boot.h>
+
+/* Don't touch these, unless you really know what you're doing. */
+#define DEF_INITSEG    0x9000
+#define DEF_SYSSEG     0x1000
+#define DEF_SETUPSEG   0x9020
+#define DEF_SYSSIZE    0x7F00
+
+/* Internal svga startup constants */
+#define NORMAL_VGA     0xffff          /* 80x25 mode */
+#define EXTENDED_VGA   0xfffe          /* 80x50 mode */
+#define ASK_VGA                0xfffd          /* ask for it at bootup */
+
+
+//#include <asm/e820.h>
+#define E820MAP 0x2d0           /* our map */
+#define E820MAX 32              /* number of entries in E820MAP */
+#define E820NR  0x1e8           /* # entries in E820MAP */
+
+#define E820_RAM        1
+#define E820_RESERVED   2
+#define E820_ACPI       3 /* usable as RAM once ACPI tables have been read
+*/
+#define E820_NVS        4
+
+#define HIGH_MEMORY     (1024*1024)
+
+//#include <asm/page.h>
+       
+/* Signature words to ensure LILO loaded us right */
+#define SIG1   0xAA55
+#define SIG2   0x5A5A
+
+INITSEG  = DEF_INITSEG         # 0x9000, we move boot here, out of the way
+SYSSEG   = DEF_SYSSEG          # 0x1000, system loaded at 0x10000 (65536).
+SETUPSEG = DEF_SETUPSEG                # 0x9020, this is the current segment
+                               # ... and the former contents of CS
+
+DELTA_INITSEG = SETUPSEG - INITSEG     # 0x0020
+
+.code16
+.globl begtext, begdata, begbss, endtext, enddata, endbss
+
+.text
+begtext:
+.data
+begdata:
+.bss
+begbss:
+.text
+
+start:
+       jmp     trampoline
+
+# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
+
+               .ascii  "HdrS"          # header signature
+               .word   0x0203          # header version number (>= 0x0105)
+                                       # or else old loadlin-1.5 will fail)
+realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
+start_sys_seg: .word   SYSSEG
+               .word   kernel_version  # pointing to kernel version string
+                                       # above section of header is compatible
+                                       # with loadlin-1.5 (header v1.5). Don't
+                                       # change it.
+
+type_of_loader:        .byte   0               # = 0, old one (LILO, Loadlin,
+                                       #      Bootlin, SYSLX, bootsect...)
+                                       # See Documentation/i386/boot.txt for
+                                       # assigned ids
+       
+# flags, unused bits must be zero (RFU) bit within loadflags
+loadflags:
+LOADED_HIGH    = 1                     # If set, the kernel is loaded high
+CAN_USE_HEAP   = 0x80                  # If set, the loader also has set
+                                       # heap_end_ptr to tell how much
+                                       # space behind setup.S can be used for
+                                       # heap purposes.
+                                       # Only the loader knows what is free
+#ifndef __BIG_KERNEL__
+               .byte   0
+#else
+               .byte   LOADED_HIGH
+#endif
+
+setup_move_size: .word  0x8000         # size to move, when setup is not
+                                       # loaded at 0x90000. We will move setup 
+                                       # to 0x90000 then just before jumping
+                                       # into the kernel. However, only the
+                                       # loader knows how much data behind
+                                       # us also needs to be loaded.
+
+code32_start:                          # here loaders can put a different
+                                       # start address for 32-bit code.
+#ifndef __BIG_KERNEL__
+               .long   0x1000          #   0x1000 = default for zImage
+#else
+               .long   0x100000        # 0x100000 = default for big kernel
+#endif
+
+ramdisk_image: .long   0               # address of loaded ramdisk image
+                                       # Here the loader puts the 32-bit
+                                       # address where it loaded the image.
+                                       # This only will be read by the kernel.
+
+ramdisk_size:  .long   0               # its size in bytes
+
+bootsect_kludge:
+               .long   0               # obsolete
+
+heap_end_ptr:  .word   modelist+1024   # (Header version 0x0201 or later)
+                                       # space from here (exclusive) down to
+                                       # end of setup code can be used by setup
+                                       # for local heap purposes.
+
+pad1:          .word   0
+cmd_line_ptr:  .long 0                 # (Header version 0x0202 or later)
+                                       # If nonzero, a 32-bit pointer
+                                       # to the kernel command line.
+                                       # The command line should be
+                                       # located between the start of
+                                       # setup and the end of low
+                                       # memory (0xa0000), or it may
+                                       # get overwritten before it
+                                       # gets read.  If this field is
+                                       # used, there is no longer
+                                       # anything magical about the
+                                       # 0x90000 segment; the setup
+                                       # can be located anywhere in
+                                       # low memory 0x10000 or higher.
+
+ramdisk_max:   .long (-0xC0000000-(512 << 20)-1) & 0x7fffffff
+                                       # (Header version 0x0203 or later)
+                                       # The highest safe address for
+                                       # the contents of an initrd
+
+trampoline:    call    start_of_setup
+               .align 16
+                                       # The offset at this point is 0x240
+               .space  (0x7ff-0x240+1) # E820 & EDD space (ending at 0x7ff)
+# End of setup header #####################################################
+
+start_of_setup:
+# Bootlin depends on this being done early
+       movw    $0x01500, %ax
+       movb    $0x81, %dl
+       int     $0x13
+
+#ifdef SAFE_RESET_DISK_CONTROLLER
+# Reset the disk controller.
+       movw    $0x0000, %ax
+       movb    $0x80, %dl
+       int     $0x13
+#endif
+
+# Set %ds = %cs, we know that SETUPSEG = %cs at this point
+       movw    %cs, %ax                # aka SETUPSEG
+       movw    %ax, %ds
+# Check signature at end of setup
+       cmpw    $SIG1, setup_sig1
+       jne     bad_sig
+
+       cmpw    $SIG2, setup_sig2
+       jne     bad_sig
+
+       jmp     good_sig1
+
+# Routine to print asciiz string at ds:si
+prtstr:
+       lodsb
+       andb    %al, %al
+       jz      fin
+
+       call    prtchr
+       jmp     prtstr
+
+fin:   ret
+
+# Space printing
+prtsp2:        call    prtspc          # Print double space
+prtspc:        movb    $0x20, %al      # Print single space (note: fall-thru)
+
+# Part of above routine, this one just prints ascii al
+prtchr:        pushw   %ax
+       pushw   %cx
+       movw    $7,%bx
+       movw    $0x01, %cx
+       movb    $0x0e, %ah
+       int     $0x10
+       popw    %cx
+       popw    %ax
+       ret
+
+beep:  movb    $0x07, %al
+       jmp     prtchr
+       
+no_sig_mess: .string   "No setup signature found ..."
+
+good_sig1:
+       jmp     good_sig
+
+# We now have to find the rest of the setup code/data
+bad_sig:
+       movw    %cs, %ax                        # SETUPSEG
+       subw    $DELTA_INITSEG, %ax             # INITSEG
+       movw    %ax, %ds
+       xorb    %bh, %bh
+       movb    (497), %bl                      # get setup sect from bootsect
+       subw    $4, %bx                         # LILO loads 4 sectors of setup
+       shlw    $8, %bx                         # convert to words (1sect=2^8 words)
+       movw    %bx, %cx
+       shrw    $3, %bx                         # convert to segment
+       addw    $SYSSEG, %bx
+       movw    %bx, %cs:start_sys_seg
+# Move rest of setup code/data to here
+       movw    $2048, %di                      # four sectors loaded by LILO
+       subw    %si, %si
+       pushw   %cs
+       popw    %es
+       movw    $SYSSEG, %ax
+       movw    %ax, %ds
+       rep
+       movsw
+       movw    %cs, %ax                        # aka SETUPSEG
+       movw    %ax, %ds
+       cmpw    $SIG1, setup_sig1
+       jne     no_sig
+
+       cmpw    $SIG2, setup_sig2
+       jne     no_sig
+
+       jmp     good_sig
+
+no_sig:
+       lea     no_sig_mess, %si
+       call    prtstr
+
+no_sig_loop:
+       hlt
+       jmp     no_sig_loop
+
+good_sig:
+       movw    %cs, %ax                        # aka SETUPSEG
+       subw    $DELTA_INITSEG, %ax             # aka INITSEG
+       movw    %ax, %ds
+# Check if an old loader tries to load a big-kernel
+       testb   $LOADED_HIGH, %cs:loadflags     # Do we have a big kernel?
+       jz      loader_ok                       # No, no danger for old loaders.
+
+       cmpb    $0, %cs:type_of_loader          # Do we have a loader that
+                                               # can deal with us?
+       jnz     loader_ok                       # Yes, continue.
+
+       pushw   %cs                             # No, we have an old loader,
+       popw    %ds                             # die. 
+       lea     loader_panic_mess, %si
+       call    prtstr
+
+       jmp     no_sig_loop
+
+loader_panic_mess: .string "Wrong loader, giving up..."
+
+loader_ok:
+# Get memory size (extended mem, kB)
+
+       xorl    %eax, %eax
+       movl    %eax, (0x1e0)
+#ifndef STANDARD_MEMORY_BIOS_CALL
+       movb    %al, (E820NR)
+# Try three different memory detection schemes.  First, try
+# e820h, which lets us assemble a memory map, then try e801h,
+# which returns a 32-bit memory size, and finally 88h, which
+# returns 0-64m
+
+# method E820H:
+# the memory map from hell.  e820h returns memory classified into
+# a whole bunch of different types, and allows memory holes and
+# everything.  We scan through this memory map and build a list
+# of the first 32 memory areas, which we return at [E820MAP].
+# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.
+
+#define SMAP  0x534d4150
+
+meme820:
+       xorl    %ebx, %ebx                      # continuation counter
+       movw    $E820MAP, %di                   # point into the whitelist
+                                               # so we can have the bios
+                                               # directly write into it.
+
+jmpe820:
+       movl    $0x0000e820, %eax               # e820, upper word zeroed
+       movl    $SMAP, %edx                     # ascii 'SMAP'
+       movl    $20, %ecx                       # size of the e820rec
+       pushw   %ds                             # data record.
+       popw    %es
+       int     $0x15                           # make the call
+       jc      bail820                         # fall to e801 if it fails
+
+       cmpl    $SMAP, %eax                     # check the return is `SMAP'
+       jne     bail820                         # fall to e801 if it fails
+
+#      cmpl    $1, 16(%di)                     # is this usable memory?
+#      jne     again820
+
+       # If this is usable memory, we save it by simply advancing %di by
+       # sizeof(e820rec).
+       #
+good820:
+       movb    (E820NR), %al                   # up to 32 entries
+       cmpb    $E820MAX, %al
+       jnl     bail820
+
+       incb    (E820NR)
+       movw    %di, %ax
+       addw    $20, %ax
+       movw    %ax, %di
+again820:
+       cmpl    $0, %ebx                        # check to see if
+       jne     jmpe820                         # %ebx is set to EOF
+bail820:
+
+
+# method E801H:
+# memory size is in 1k chunksizes, to avoid confusing loadlin.
+# we store the 0xe801 memory size in a completely different place,
+# because it will most likely be longer than 16 bits.
+# (use 1e0 because that's what Larry Augustine uses in his
+# alternative new memory detection scheme, and it's sensible
+# to write everything into the same place.)
+
+meme801:
+       stc                                     # fix to work around buggy
+       xorw    %cx,%cx                         # BIOSes which dont clear/set
+       xorw    %dx,%dx                         # carry on pass/error of
+                                               # e801h memory size call
+                                               # or merely pass cx,dx though
+                                               # without changing them.
+       movw    $0xe801, %ax
+       int     $0x15
+       jc      mem88
+
+       cmpw    $0x0, %cx                       # Kludge to handle BIOSes
+       jne     e801usecxdx                     # which report their extended
+       cmpw    $0x0, %dx                       # memory in AX/BX rather than
+       jne     e801usecxdx                     # CX/DX.  The spec I have read
+       movw    %ax, %cx                        # seems to indicate AX/BX 
+       movw    %bx, %dx                        # are more reasonable anyway...
+
+e801usecxdx:
+       andl    $0xffff, %edx                   # clear sign extend
+       shll    $6, %edx                        # and go from 64k to 1k chunks
+       movl    %edx, (0x1e0)                   # store extended memory size
+       andl    $0xffff, %ecx                   # clear sign extend
+       addl    %ecx, (0x1e0)                   # and add lower memory into
+                                               # total size.
+
+# Ye Olde Traditional Methode.  Returns the memory size (up to 16mb or
+# 64mb, depending on the bios) in ax.
+mem88:
+
+#endif
+       movb    $0x88, %ah
+       int     $0x15
+       movw    %ax, (2)
+
+# Set the keyboard repeat rate to the max
+       movw    $0x0305, %ax
+       xorw    %bx, %bx
+       int     $0x16
+
+# Check for video adapter and its parameters and allow the
+# user to browse video modes.
+       call    video                           # NOTE: we need %ds pointing
+                                               # to bootsector
+
+# Get hd0 data...
+       xorw    %ax, %ax
+       movw    %ax, %ds
+       ldsw    (4 * 0x41), %si
+       movw    %cs, %ax                        # aka SETUPSEG
+       subw    $DELTA_INITSEG, %ax             # aka INITSEG
+       pushw   %ax
+       movw    %ax, %es
+       movw    $0x0080, %di
+       movw    $0x10, %cx
+       pushw   %cx
+       cld
+       rep
+       movsb
+# Get hd1 data...
+       xorw    %ax, %ax
+       movw    %ax, %ds
+       ldsw    (4 * 0x46), %si
+       popw    %cx
+       popw    %es
+       movw    $0x0090, %di
+       rep
+       movsb
+# Check that there IS a hd1 :-)
+       movw    $0x01500, %ax
+       movb    $0x81, %dl
+       int     $0x13
+       jc      no_disk1
+       
+       cmpb    $3, %ah
+       je      is_disk1
+
+no_disk1:
+       movw    %cs, %ax                        # aka SETUPSEG
+       subw    $DELTA_INITSEG, %ax             # aka INITSEG
+       movw    %ax, %es
+       movw    $0x0090, %di
+       movw    $0x10, %cx
+       xorw    %ax, %ax
+       cld
+       rep
+       stosb
+is_disk1:
+# check for Micro Channel (MCA) bus
+       movw    %cs, %ax                        # aka SETUPSEG
+       subw    $DELTA_INITSEG, %ax             # aka INITSEG
+       movw    %ax, %ds
+       xorw    %ax, %ax
+       movw    %ax, (0xa0)                     # set table length to 0
+       movb    $0xc0, %ah
+       stc
+       int     $0x15                           # moves feature table to es:bx
+       jc      no_mca
+
+       pushw   %ds
+       movw    %es, %ax
+       movw    %ax, %ds
+       movw    %cs, %ax                        # aka SETUPSEG
+       subw    $DELTA_INITSEG, %ax             # aka INITSEG
+       movw    %ax, %es
+       movw    %bx, %si
+       movw    $0xa0, %di
+       movw    (%si), %cx
+       addw    $2, %cx                         # table length is a short
+       cmpw    $0x10, %cx
+       jc      sysdesc_ok
+
+       movw    $0x10, %cx                      # we keep only first 16 bytes
+sysdesc_ok:
+       rep
+       movsb
+       popw    %ds
+no_mca:
+#ifdef CONFIG_X86_VOYAGER
+       movb    $0xff, 0x40     # flag on config found
+       movb    $0xc0, %al
+       mov     $0xff, %ah
+       int     $0x15           # put voyager config info at es:di
+       jc      no_voyager
+       movw    $0x40, %si      # place voyager info in apm table
+       cld
+       movw    $7, %cx
+voyager_rep:
+       movb    %es:(%di), %al
+       movb    %al,(%si)
+       incw    %di
+       incw    %si
+       decw    %cx
+       jnz     voyager_rep
+no_voyager:    
+#endif
+# Check for PS/2 pointing device
+       movw    %cs, %ax                        # aka SETUPSEG
+       subw    $DELTA_INITSEG, %ax             # aka INITSEG
+       movw    %ax, %ds
+       movw    $0, (0x1ff)                     # default is no pointing device
+       int     $0x11                           # int 0x11: equipment list
+       testb   $0x04, %al                      # check if mouse installed
+       jz      no_psmouse
+
+       movw    $0xAA, (0x1ff)                  # device present
+no_psmouse:
+
+#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
+       movl    $0x0000E980, %eax               # IST Support 
+       movl    $0x47534943, %edx               # Request value
+       int     $0x15
+
+       movl    %eax, (96)
+       movl    %ebx, (100)
+       movl    %ecx, (104)
+       movl    %edx, (108)
+#endif
+
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+# Then check for an APM BIOS...
+                                               # %ds points to the bootsector
+       movw    $0, 0x40                        # version = 0 means no APM BIOS
+       movw    $0x05300, %ax                   # APM BIOS installation check
+       xorw    %bx, %bx
+       int     $0x15
+       jc      done_apm_bios                   # Nope, no APM BIOS
+       
+       cmpw    $0x0504d, %bx                   # Check for "PM" signature
+       jne     done_apm_bios                   # No signature, no APM BIOS
+
+       andw    $0x02, %cx                      # Is 32 bit supported?
+       je      done_apm_bios                   # No 32-bit, no (good) APM BIOS
+
+       movw    $0x05304, %ax                   # Disconnect first just in case
+       xorw    %bx, %bx
+       int     $0x15                           # ignore return code
+       movw    $0x05303, %ax                   # 32 bit connect
+       xorl    %ebx, %ebx
+       xorw    %cx, %cx                        # paranoia :-)
+       xorw    %dx, %dx                        #   ...
+       xorl    %esi, %esi                      #   ...
+       xorw    %di, %di                        #   ...
+       int     $0x15
+       jc      no_32_apm_bios                  # Ack, error. 
+
+       movw    %ax,  (66)                      # BIOS code segment
+       movl    %ebx, (68)                      # BIOS entry point offset
+       movw    %cx,  (72)                      # BIOS 16 bit code segment
+       movw    %dx,  (74)                      # BIOS data segment
+       movl    %esi, (78)                      # BIOS code segment lengths
+       movw    %di,  (82)                      # BIOS data segment length
+# Redo the installation check as the 32 bit connect
+# modifies the flags returned on some BIOSs
+       movw    $0x05300, %ax                   # APM BIOS installation check
+       xorw    %bx, %bx
+       xorw    %cx, %cx                        # paranoia
+       int     $0x15
+       jc      apm_disconnect                  # error -> shouldn't happen
+
+       cmpw    $0x0504d, %bx                   # check for "PM" signature
+       jne     apm_disconnect                  # no sig -> shouldn't happen
+
+       movw    %ax, (64)                       # record the APM BIOS version
+       movw    %cx, (76)                       # and flags
+       jmp     done_apm_bios
+
+apm_disconnect:                                        # Tidy up
+       movw    $0x05304, %ax                   # Disconnect
+       xorw    %bx, %bx
+       int     $0x15                           # ignore return code
+
+       jmp     done_apm_bios
+
+no_32_apm_bios:
+       andw    $0xfffd, (76)                   # remove 32 bit support bit
+done_apm_bios:
+#endif
+
+//#include "edd.S"
+
+# Now we want to move to protected mode ...
+       cmpw    $0, %cs:realmode_swtch
+       jz      rmodeswtch_normal
+
+       lcall   *%cs:realmode_swtch
+
+       jmp     rmodeswtch_end
+
+rmodeswtch_normal:
+        pushw  %cs
+       call    default_switch
+
+rmodeswtch_end:
+# we get the code32 start address and modify the below 'jmpi'
+# (loader may have changed it)
+       movl    %cs:code32_start, %eax
+       movl    %eax, %cs:code32
+
+# Now we move the system to its rightful place ... but we check if we have a
+# big-kernel. In that case we *must* not move it ...
+       testb   $LOADED_HIGH, %cs:loadflags
+       jz      do_move0                        # .. then we have a normal low
+                                               # loaded zImage
+                                               # .. or else we have a high
+                                               # loaded bzImage
+       jmp     end_move                        # ... and we skip moving
+
+do_move0:
+       movw    $0x100, %ax                     # start of destination segment
+       movw    %cs, %bp                        # aka SETUPSEG
+       subw    $DELTA_INITSEG, %bp             # aka INITSEG
+       movw    %cs:start_sys_seg, %bx          # start of source segment
+       cld
+do_move:
+       movw    %ax, %es                        # destination segment
+       incb    %ah                             # instead of add ax,#0x100
+       movw    %bx, %ds                        # source segment
+       addw    $0x100, %bx
+       subw    %di, %di
+       subw    %si, %si
+       movw    $0x800, %cx
+       rep
+       movsw
+       cmpw    %bp, %bx                        # assume start_sys_seg > 0x200,
+                                               # so we will perhaps read one
+                                               # page more than needed, but
+                                               # never overwrite INITSEG
+                                               # because destination is a
+                                               # minimum one page below source
+       jb      do_move
+
+end_move:
+# then we load the segment descriptors
+       movw    %cs, %ax                        # aka SETUPSEG
+       movw    %ax, %ds
+               
+# Check whether we need to be downward compatible with version <=201
+       cmpl    $0, cmd_line_ptr
+       jne     end_move_self           # loader uses version >=202 features
+       cmpb    $0x20, type_of_loader
+       je      end_move_self           # bootsect loader, we know of it
+
+# Boot loader doesnt support boot protocol version 2.02.
+# If we have our code not at 0x90000, we need to move it there now.
+# We also then need to move the params behind it (commandline)
+# Because we would overwrite the code on the current IP, we move
+# it in two steps, jumping high after the first one.
+       movw    %cs, %ax
+       cmpw    $SETUPSEG, %ax
+       je      end_move_self
+
+       cli                                     # make sure we really have
+                                               # interrupts disabled !
+                                               # because after this the stack
+                                               # should not be used
+       subw    $DELTA_INITSEG, %ax             # aka INITSEG
+       movw    %ss, %dx
+       cmpw    %ax, %dx
+       jb      move_self_1
+
+       addw    $INITSEG, %dx
+       subw    %ax, %dx                        # this will go into %ss after
+                                               # the move
+move_self_1:
+       movw    %ax, %ds
+       movw    $INITSEG, %ax                   # real INITSEG
+       movw    %ax, %es
+       movw    %cs:setup_move_size, %cx
+       std                                     # we have to move up, so we use
+                                               # direction down because the
+                                               # areas may overlap
+       movw    %cx, %di
+       decw    %di
+       movw    %di, %si
+       subw    $move_self_here+0x200, %cx
+       rep
+       movsb
+       ljmp    $SETUPSEG, $move_self_here
+
+move_self_here:
+       movw    $move_self_here+0x200, %cx
+       rep
+       movsb
+       movw    $SETUPSEG, %ax
+       movw    %ax, %ds
+       movw    %dx, %ss
+end_move_self:                                 # now we are at the right place
+
+#
+# Enable A20.  This is at the very best an annoying procedure.
+# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin.
+# AMD Elan bug fix by Robert Schwebel.
+#
+
+#if defined(CONFIG_X86_ELAN)
+       movb $0x02, %al                 # alternate A20 gate
+       outb %al, $0x92                 # this works on SC410/SC520
+a20_elan_wait:
+       call a20_test
+       jz a20_elan_wait
+       jmp a20_done
+#endif
+
+
+A20_TEST_LOOPS         =  32           # Iterations per wait
+A20_ENABLE_LOOPS       = 255           # Total loops to try            
+
+
+#ifndef CONFIG_X86_VOYAGER
+a20_try_loop:
+
+       # First, see if we are on a system with no A20 gate.
+a20_none:
+       call    a20_test
+       jnz     a20_done
+
+       # Next, try the BIOS (INT 0x15, AX=0x2401)
+a20_bios:
+       movw    $0x2401, %ax
+       pushfl                                  # Be paranoid about flags
+       int     $0x15
+       popfl
+
+       call    a20_test
+       jnz     a20_done
+
+       # Try enabling A20 through the keyboard controller
+#endif /* CONFIG_X86_VOYAGER */
+a20_kbc:
+       call    empty_8042
+
+#ifndef CONFIG_X86_VOYAGER
+       call    a20_test                        # Just in case the BIOS worked
+       jnz     a20_done                        # but had a delayed reaction.
+#endif
+
+       movb    $0xD1, %al                      # command write
+       outb    %al, $0x64
+       call    empty_8042
+
+       movb    $0xDF, %al                      # A20 on
+       outb    %al, $0x60
+       call    empty_8042
+
+#ifndef CONFIG_X86_VOYAGER
+       # Wait until a20 really *is* enabled; it can take a fair amount of
+       # time on certain systems; Toshiba Tecras are known to have this
+       # problem.
+a20_kbc_wait:
+       xorw    %cx, %cx
+a20_kbc_wait_loop:
+       call    a20_test
+       jnz     a20_done
+       loop    a20_kbc_wait_loop
+
+       # Final attempt: use "configuration port A"
+a20_fast:
+       inb     $0x92, %al                      # Configuration Port A
+       orb     $0x02, %al                      # "fast A20" version
+       andb    $0xFE, %al                      # don't accidentally reset
+       outb    %al, $0x92
+
+       # Wait for configuration port A to take effect
+a20_fast_wait:
+       xorw    %cx, %cx
+a20_fast_wait_loop:
+       call    a20_test
+       jnz     a20_done
+       loop    a20_fast_wait_loop
+
+       # A20 is still not responding.  Try frobbing it again.
+       # 
+       decb    (a20_tries)
+       jnz     a20_try_loop
+       
+       movw    $a20_err_msg, %si
+       call    prtstr
+
+a20_die:
+       hlt
+       jmp     a20_die
+
+a20_tries:
+       .byte   A20_ENABLE_LOOPS
+
+a20_err_msg:
+       .ascii  "linux: fatal error: A20 gate not responding!"
+       .byte   13, 10, 0
+
+       # If we get here, all is good
+a20_done:
+
+#endif /* CONFIG_X86_VOYAGER */
+# set up gdt and idt
+       lidt    idt_48                          # load idt with 0,0
+       xorl    %eax, %eax                      # Compute gdt_base
+       movw    %ds, %ax                        # (Convert %ds:gdt to a linear ptr)
+       shll    $4, %eax
+       addl    $gdt, %eax
+       movl    %eax, (gdt_48+2)
+       lgdt    gdt_48                          # load gdt with whatever is
+                                               # appropriate
+
+# make sure any possible coprocessor is properly reset..
+       xorw    %ax, %ax
+       outb    %al, $0xf0
+       call    delay
+
+       outb    %al, $0xf1
+       call    delay
+
+# well, that went ok, I hope. Now we mask all interrupts - the rest
+# is done in init_IRQ().
+       movb    $0xFF, %al                      # mask all interrupts for now
+       outb    %al, $0xA1
+       call    delay
+       
+       movb    $0xFB, %al                      # mask all irq's but irq2 which
+       outb    %al, $0x21                      # is cascaded
+
+# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
+# need no steenking BIOS anyway (except for the initial loading :-).
+# The BIOS-routine wants lots of unnecessary data, and it's less
+# "interesting" anyway. This is how REAL programmers do it.
+#
+# Well, now's the time to actually move into protected mode. To make
+# things as simple as possible, we do no register set-up or anything,
+# we let the gnu-compiled 32-bit programs do that. We just jump to
+# absolute address 0x1000 (or the loader supplied one),
+# in 32-bit protected mode.
+#
+# Note that the short jump isn't strictly needed, although there are
+# reasons why it might be a good idea. It won't hurt in any case.
+       movw    $1, %ax                         # protected mode (PE) bit
+       lmsw    %ax                             # This is it!
+       jmp     flush_instr
+
+flush_instr:
+       xorw    %bx, %bx                        # Flag to indicate a boot
+       xorl    %esi, %esi                      # Pointer to real-mode code
+       movw    %cs, %si
+       subw    $DELTA_INITSEG, %si
+       shll    $4, %esi                        # Convert to 32-bit pointer
+
+# jump to startup_32 in arch/i386/boot/compressed/head.S
+#      
+# NOTE: For high loaded big kernels we need a
+#      jmpi    0x100000,__BOOT_CS
+#
+#      but we yet haven't reloaded the CS register, so the default size 
+#      of the target offset still is 16 bit.
+#       However, using an operand prefix (0x66), the CPU will properly
+#      take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
+#      Manual, Mixing 16-bit and 32-bit code, page 16-6)
+
+       .byte 0x66, 0xea                        # prefix + jmpi-opcode
+code32:        .long   0x1000                          # will be set to 0x100000
+                                               # for big kernels
+       .word   2 * 8
+
+# Here's a bunch of information about your current kernel..
+kernel_version:        .ascii  "bootstrap"
+               .byte   0
+
+# This is the default real mode switch routine.
+# to be called just before protected mode transition
+default_switch:
+       cli                                     # no interrupts allowed !
+       movb    $0x80, %al                      # disable NMI for bootup
+                                               # sequence
+       outb    %al, $0x70
+       lret
+
+
+#ifndef CONFIG_X86_VOYAGER
+# This routine tests whether or not A20 is enabled.  If so, it
+# exits with zf = 0.
+#
+# The memory address used, 0x200, is the int $0x80 vector, which
+# should be safe.
+
+A20_TEST_ADDR = 4*0x80
+
+a20_test:
+       pushw   %cx
+       pushw   %ax
+       xorw    %cx, %cx
+       movw    %cx, %fs                        # Low memory
+       decw    %cx
+       movw    %cx, %gs                        # High memory area
+       movw    $A20_TEST_LOOPS, %cx
+       movw    %fs:(A20_TEST_ADDR), %ax
+       pushw   %ax
+a20_test_wait:
+       incw    %ax
+       movw    %ax, %fs:(A20_TEST_ADDR)
+       call    delay                           # Serialize and make delay constant
+       cmpw    %gs:(A20_TEST_ADDR+0x10), %ax
+       loope   a20_test_wait
+
+       popw    %fs:(A20_TEST_ADDR)
+       popw    %ax
+       popw    %cx
+       ret     
+
+#endif /* CONFIG_X86_VOYAGER */
+
+# This routine checks that the keyboard command queue is empty
+# (after emptying the output buffers)
+#
+# Some machines have delusions that the keyboard buffer is always full
+# with no keyboard attached...
+#
+# If there is no keyboard controller, we will usually get 0xff
+# to all the reads.  With each IO taking a microsecond and
+# a timeout of 100,000 iterations, this can take about half a
+# second ("delay" == outb to port 0x80). That should be ok,
+# and should also be plenty of time for a real keyboard controller
+# to empty.
+#
+
+empty_8042:
+       pushl   %ecx
+       movl    $100000, %ecx
+
+empty_8042_loop:
+       decl    %ecx
+       jz      empty_8042_end_loop
+
+       call    delay
+
+       inb     $0x64, %al                      # 8042 status port
+       testb   $1, %al                         # output buffer?
+       jz      no_output
+
+       call    delay
+       inb     $0x60, %al                      # read it
+       jmp     empty_8042_loop
+
+no_output:
+       testb   $2, %al                         # is input buffer full?
+       jnz     empty_8042_loop                 # yes - loop
+empty_8042_end_loop:
+       popl    %ecx
+       ret
+
+# Read the cmos clock. Return the seconds in al
+gettime:
+       pushw   %cx
+       movb    $0x02, %ah
+       int     $0x1a
+       movb    %dh, %al                        # %dh contains the seconds
+       andb    $0x0f, %al
+       movb    %dh, %ah
+       movb    $0x04, %cl
+       shrb    %cl, %ah
+       aad
+       popw    %cx
+       ret
+
+# Delay is needed after doing I/O
+delay:
+       outb    %al,$0x80
+       ret
+
+# Descriptor tables
+#
+# NOTE: The intel manual says gdt should be sixteen bytes aligned for
+# efficiency reasons.  However, there are machines which are known not
+# to boot with misaligned GDTs, so alter this at your peril!  If you alter
+# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two
+# empty GDT entries (one for NULL and one reserved).
+#
+# NOTE:        On some CPUs, the GDT must be 8 byte aligned.  This is
+# true for the Voyager Quad CPU card which will not boot without
+# This directive.  16 byte aligment is recommended by intel.
+#
+       .align 16
+gdt:
+       .fill 2,8,0
+
+       .word   0xFFFF                          # 4Gb - (0x100000*0x1000 = 4Gb)
+       .word   0                               # base address = 0
+       .word   0x9A00                          # code read/exec
+       .word   0x00CF                          # granularity = 4096, 386
+                                               #  (+5th nibble of limit)
+
+       .word   0xFFFF                          # 4Gb - (0x100000*0x1000 = 4Gb)
+       .word   0                               # base address = 0
+       .word   0x9200                          # data read/write
+       .word   0x00CF                          # granularity = 4096, 386
+                                               #  (+5th nibble of limit)
+gdt_end:
+       .align  4
+       
+       .word   0                               # alignment byte
+idt_48:
+       .word   0                               # idt limit = 0
+       .word   0, 0                            # idt base = 0L
+
+       .word   0                               # alignment byte
+gdt_48:
+       .word   gdt_end - gdt - 1               # gdt limit
+       .word   0, 0                            # gdt base (filled in later)
+
+# Include video setup & detection code
+
+/* Enable autodetection of SVGA adapters and modes. */
+#undef CONFIG_VIDEO_SVGA
+
+/* Enable autodetection of VESA modes */
+#define CONFIG_VIDEO_VESA
+
+/* Enable compacting of mode table */
+#define CONFIG_VIDEO_COMPACT
+
+/* Retain screen contents when switching modes */
+#define CONFIG_VIDEO_RETAIN
+
+/* Enable local mode list */
+#undef CONFIG_VIDEO_LOCAL
+
+/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
+#undef CONFIG_VIDEO_400_HACK
+
+/* Hack that lets you force specific BIOS mode ID and specific dimensions */
+#undef CONFIG_VIDEO_GFX_HACK
+#define VIDEO_GFX_BIOS_AX 0x4f02       /* 800x600 on ThinkPad */
+#define VIDEO_GFX_BIOS_BX 0x0102
+#define VIDEO_GFX_DUMMY_RESOLUTION 0x6425      /* 100x37 */
+
+/* This code uses an extended set of video mode numbers. These include:
+ * Aliases for standard modes
+ *     NORMAL_VGA (-1)
+ *     EXTENDED_VGA (-2)
+ *     ASK_VGA (-3)
+ * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
+ * of compatibility when extending the table. These are between 0x00 and 0xff.
+ */
+#define VIDEO_FIRST_MENU 0x0000
+
+/* Standard BIOS video modes (BIOS number + 0x0100) */
+#define VIDEO_FIRST_BIOS 0x0100
+
+/* VESA BIOS video modes (VESA number + 0x0200) */
+#define VIDEO_FIRST_VESA 0x0200
+
+/* Video7 special modes (BIOS number + 0x0900) */
+#define VIDEO_FIRST_V7 0x0900
+
+/* Special video modes */
+#define VIDEO_FIRST_SPECIAL 0x0f00
+#define VIDEO_80x25 0x0f00
+#define VIDEO_8POINT 0x0f01
+#define VIDEO_80x43 0x0f02
+#define VIDEO_80x28 0x0f03
+#define VIDEO_CURRENT_MODE 0x0f04
+#define VIDEO_80x30 0x0f05
+#define VIDEO_80x34 0x0f06
+#define VIDEO_80x60 0x0f07
+#define VIDEO_GFX_HACK 0x0f08
+#define VIDEO_LAST_SPECIAL 0x0f09
+
+/* Video modes given by resolution */
+#define VIDEO_FIRST_RESOLUTION 0x1000
+
+/* The "recalculate timings" flag */
+#define VIDEO_RECALC 0x8000
+
+/* Positions of various video parameters passed to the kernel */
+/* (see also include/linux/tty.h) */
+#define PARAM_CURSOR_POS       0x00
+#define PARAM_VIDEO_PAGE       0x04
+#define PARAM_VIDEO_MODE       0x06
+#define PARAM_VIDEO_COLS       0x07
+#define PARAM_VIDEO_EGA_BX     0x0a
+#define PARAM_VIDEO_LINES      0x0e
+#define PARAM_HAVE_VGA         0x0f
+#define PARAM_FONT_POINTS      0x10
+
+#define PARAM_LFB_WIDTH                0x12
+#define PARAM_LFB_HEIGHT       0x14
+#define PARAM_LFB_DEPTH                0x16
+#define PARAM_LFB_BASE         0x18
+#define PARAM_LFB_SIZE         0x1c
+#define PARAM_LFB_LINELENGTH   0x24
+#define PARAM_LFB_COLORS       0x26
+#define PARAM_VESAPM_SEG       0x2e
+#define PARAM_VESAPM_OFF       0x30
+#define PARAM_LFB_PAGES                0x32
+#define PARAM_VESA_ATTRIB      0x34
+
+/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
+#ifdef CONFIG_VIDEO_RETAIN
+#define DO_STORE call store_screen
+#else
+#define DO_STORE
+#endif /* CONFIG_VIDEO_RETAIN */
+
+# This is the main entry point called by setup.S
+# %ds *must* be pointing to the bootsector
+video: pushw   %ds             # We use different segments
+       pushw   %ds             # FS contains original DS
+       popw    %fs
+       pushw   %cs             # DS is equal to CS
+       popw    %ds
+       pushw   %cs             # ES is equal to CS
+       popw    %es
+       xorw    %ax, %ax
+       movw    %ax, %gs        # GS is zero
+       cld
+       call    basic_detect    # Basic adapter type testing (EGA/VGA/MDA/CGA)
+#ifdef CONFIG_VIDEO_SELECT
+       movw    %fs:(0x01fa), %ax               # User selected video mode
+       cmpw    $ASK_VGA, %ax                   # Bring up the menu
+       jz      vid2
+
+       call    mode_set                        # Set the mode
+       jc      vid1
+
+       leaw    badmdt, %si                     # Invalid mode ID
+       call    prtstr
+vid2:  call    mode_menu
+vid1:
+#ifdef CONFIG_VIDEO_RETAIN
+       call    restore_screen                  # Restore screen contents
+#endif /* CONFIG_VIDEO_RETAIN */
+       call    store_edid
+#endif /* CONFIG_VIDEO_SELECT */
+       call    mode_params                     # Store mode parameters
+       popw    %ds                             # Restore original DS
+       ret
+
+# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
+basic_detect:
+       movb    $0, %fs:(PARAM_HAVE_VGA)
+       movb    $0x12, %ah      # Check EGA/VGA
+       movb    $0x10, %bl
+       int     $0x10
+       movw    %bx, %fs:(PARAM_VIDEO_EGA_BX)   # Identifies EGA to the kernel
+       cmpb    $0x10, %bl                      # No, it's a CGA/MDA/HGA card.
+       je      basret
+
+       incb    adapter
+       movw    $0x1a00, %ax                    # Check EGA or VGA?
+       int     $0x10
+       cmpb    $0x1a, %al                      # 1a means VGA...
+       jne     basret                          # anything else is EGA.
+       
+       incb    %fs:(PARAM_HAVE_VGA)            # We've detected a VGA
+       incb    adapter
+basret:        ret
+
+# Store the video mode parameters for later usage by the kernel.
+# This is done by asking the BIOS except for the rows/columns
+# parameters in the default 80x25 mode -- these are set directly,
+# because some very obscure BIOSes supply insane values.
+mode_params:
+#ifdef CONFIG_VIDEO_SELECT
+       cmpb    $0, graphic_mode
+       jnz     mopar_gr
+#endif
+       movb    $0x03, %ah                      # Read cursor position
+       xorb    %bh, %bh
+       int     $0x10
+       movw    %dx, %fs:(PARAM_CURSOR_POS)
+       movb    $0x0f, %ah                      # Read page/mode/width
+       int     $0x10
+       movw    %bx, %fs:(PARAM_VIDEO_PAGE)
+       movw    %ax, %fs:(PARAM_VIDEO_MODE)     # Video mode and screen width
+       cmpb    $0x7, %al                       # MDA/HGA => segment differs
+       jnz     mopar0
+
+       movw    $0xb000, video_segment
+mopar0: movw   %gs:(0x485), %ax                # Font size
+       movw    %ax, %fs:(PARAM_FONT_POINTS)    # (valid only on EGA/VGA)
+       movw    force_size, %ax                 # Forced size?
+       orw     %ax, %ax
+       jz      mopar1
+
+       movb    %ah, %fs:(PARAM_VIDEO_COLS)
+       movb    %al, %fs:(PARAM_VIDEO_LINES)
+       ret
+
+mopar1:        movb    $25, %al
+       cmpb    $0, adapter                     # If we are on CGA/MDA/HGA, the
+       jz      mopar2                          # screen must have 25 lines.
+
+       movb    %gs:(0x484), %al                # On EGA/VGA, use the EGA+ BIOS
+       incb    %al                             # location of max lines.
+mopar2: movb   %al, %fs:(PARAM_VIDEO_LINES)
+       ret
+
+#ifdef CONFIG_VIDEO_SELECT
+# Fetching of VESA frame buffer parameters
+mopar_gr:
+       leaw    modelist+1024, %di
+       movb    $0x23, %fs:(PARAM_HAVE_VGA)
+       movw    16(%di), %ax
+       movw    %ax, %fs:(PARAM_LFB_LINELENGTH)
+       movw    18(%di), %ax
+       movw    %ax, %fs:(PARAM_LFB_WIDTH)
+       movw    20(%di), %ax
+       movw    %ax, %fs:(PARAM_LFB_HEIGHT)
+       movb    25(%di), %al
+       movb    $0, %ah
+       movw    %ax, %fs:(PARAM_LFB_DEPTH)
+       movb    29(%di), %al    
+       movb    $0, %ah
+       movw    %ax, %fs:(PARAM_LFB_PAGES)
+       movl    40(%di), %eax
+       movl    %eax, %fs:(PARAM_LFB_BASE)
+       movl    31(%di), %eax
+       movl    %eax, %fs:(PARAM_LFB_COLORS)
+       movl    35(%di), %eax
+       movl    %eax, %fs:(PARAM_LFB_COLORS+4)
+       movw    0(%di), %ax
+       movw    %ax, %fs:(PARAM_VESA_ATTRIB)
+
+# get video mem size
+       leaw    modelist+1024, %di
+       movw    $0x4f00, %ax
+       int     $0x10
+       xorl    %eax, %eax
+       movw    18(%di), %ax
+       movl    %eax, %fs:(PARAM_LFB_SIZE)
+
+# switching the DAC to 8-bit is for <= 8 bpp only
+       movw    %fs:(PARAM_LFB_DEPTH), %ax
+       cmpw    $8, %ax
+       jg      dac_done
+
+# get DAC switching capability
+       xorl    %eax, %eax
+       movb    10(%di), %al
+       testb   $1, %al
+       jz      dac_set
+
+# attempt to switch DAC to 8-bit
+       movw    $0x4f08, %ax
+       movw    $0x0800, %bx
+       int     $0x10
+       cmpw    $0x004f, %ax
+       jne     dac_set
+       movb    %bh, dac_size           # store actual DAC size
+
+dac_set:
+# set color size to DAC size
+       movb    dac_size, %al
+       movb    %al, %fs:(PARAM_LFB_COLORS+0)
+       movb    %al, %fs:(PARAM_LFB_COLORS+2)
+       movb    %al, %fs:(PARAM_LFB_COLORS+4)
+       movb    %al, %fs:(PARAM_LFB_COLORS+6)
+
+# set color offsets to 0
+       movb    $0, %fs:(PARAM_LFB_COLORS+1)
+       movb    $0, %fs:(PARAM_LFB_COLORS+3)
+       movb    $0, %fs:(PARAM_LFB_COLORS+5)
+       movb    $0, %fs:(PARAM_LFB_COLORS+7)
+
+dac_done:
+# get protected mode interface informations
+       movw    $0x4f0a, %ax
+       xorw    %bx, %bx
+       xorw    %di, %di
+       int     $0x10
+       cmp     $0x004f, %ax
+       jnz     no_pm
+
+       movw    %es, %fs:(PARAM_VESAPM_SEG)
+       movw    %di, %fs:(PARAM_VESAPM_OFF)
+no_pm: ret
+
+# The video mode menu
+mode_menu:
+       leaw    keymsg, %si                     # "Return/Space/Timeout" message
+       call    prtstr
+       call    flush
+nokey: call    getkt
+
+       cmpb    $0x0d, %al                      # ENTER ?
+       je      listm                           # yes - manual mode selection
+
+       cmpb    $0x20, %al                      # SPACE ?
+       je      defmd1                          # no - repeat
+
+       call    beep
+       jmp     nokey
+
+defmd1:        ret                                     # No mode chosen? Default 80x25
+
+listm: call    mode_table                      # List mode table
+listm0:        leaw    name_bann, %si                  # Print adapter name
+       call    prtstr
+       movw    card_name, %si
+       orw     %si, %si
+       jnz     an2
+
+       movb    adapter, %al
+       leaw    old_name, %si
+       orb     %al, %al
+       jz      an1
+
+       leaw    ega_name, %si
+       decb    %al
+       jz      an1
+
+       leaw    vga_name, %si
+       jmp     an1
+
+an2:   call    prtstr
+       leaw    svga_name, %si
+an1:   call    prtstr
+       leaw    listhdr, %si                    # Table header
+       call    prtstr
+       movb    $0x30, %dl                      # DL holds mode number
+       leaw    modelist, %si
+lm1:   cmpw    $ASK_VGA, (%si)                 # End?
+       jz      lm2
+
+       movb    %dl, %al                        # Menu selection number
+       call    prtchr
+       call    prtsp2
+       lodsw
+       call    prthw                           # Mode ID
+       call    prtsp2
+       movb    0x1(%si), %al
+       call    prtdec                          # Rows
+       movb    $0x78, %al                      # the letter 'x'
+       call    prtchr
+       lodsw
+       call    prtdec                          # Columns
+       movb    $0x0d, %al                      # New line
+       call    prtchr
+       movb    $0x0a, %al
+       call    prtchr
+       incb    %dl                             # Next character
+       cmpb    $0x3a, %dl
+       jnz     lm1
+
+       movb    $0x61, %dl
+       jmp     lm1
+
+lm2:   leaw    prompt, %si                     # Mode prompt
+       call    prtstr
+       leaw    edit_buf, %di                   # Editor buffer
+lm3:   call    getkey
+       cmpb    $0x0d, %al                      # Enter?
+       jz      lment
+
+       cmpb    $0x08, %al                      # Backspace?
+       jz      lmbs
+
+       cmpb    $0x20, %al                      # Printable?
+       jc      lm3
+
+       cmpw    $edit_buf+4, %di                # Enough space?
+       jz      lm3
+
+       stosb
+       call    prtchr
+       jmp     lm3
+
+lmbs:  cmpw    $edit_buf, %di                  # Backspace
+       jz      lm3
+
+       decw    %di
+       movb    $0x08, %al
+       call    prtchr
+       call    prtspc
+       movb    $0x08, %al
+       call    prtchr
+       jmp     lm3
+       
+lment: movb    $0, (%di)
+       leaw    crlft, %si
+       call    prtstr
+       leaw    edit_buf, %si
+       cmpb    $0, (%si)                       # Empty string = default mode
+       jz      lmdef
+
+       cmpb    $0, 1(%si)                      # One character = menu selection
+       jz      mnusel
+
+       cmpw    $0x6373, (%si)                  # "scan" => mode scanning
+       jnz     lmhx
+
+       cmpw    $0x6e61, 2(%si)
+       jz      lmscan
+
+lmhx:  xorw    %bx, %bx                        # Else => mode ID in hex
+lmhex: lodsb
+       orb     %al, %al
+       jz      lmuse1
+
+       subb    $0x30, %al
+       jc      lmbad
+
+       cmpb    $10, %al
+       jc      lmhx1
+
+       subb    $7, %al
+       andb    $0xdf, %al
+       cmpb    $10, %al
+       jc      lmbad
+
+       cmpb    $16, %al
+       jnc     lmbad
+
+lmhx1: shlw    $4, %bx
+       orb     %al, %bl
+       jmp     lmhex
+
+lmuse1:        movw    %bx, %ax
+       jmp     lmuse
+
+mnusel:        lodsb                                   # Menu selection
+       xorb    %ah, %ah
+       subb    $0x30, %al
+       jc      lmbad
+
+       cmpb    $10, %al
+       jc      lmuse
+       
+       cmpb    $0x61-0x30, %al
+       jc      lmbad
+       
+       subb    $0x61-0x30-10, %al
+       cmpb    $36, %al
+       jnc     lmbad
+
+lmuse: call    mode_set
+       jc      lmdef
+
+lmbad: leaw    unknt, %si
+       call    prtstr
+       jmp     lm2
+lmscan:        cmpb    $0, adapter                     # Scanning only on EGA/VGA
+       jz      lmbad
+
+       movw    $0, mt_end                      # Scanning of modes is
+       movb    $1, scanning                    # done as new autodetection.
+       call    mode_table
+       jmp     listm0
+lmdef: ret
+
+# Additional parts of mode_set... (relative jumps, you know)
+setv7:                                         # Video7 extended modes
+       DO_STORE
+       subb    $VIDEO_FIRST_V7>>8, %bh
+       movw    $0x6f05, %ax
+       int     $0x10
+       stc
+       ret
+
+_setrec:       jmp     setrec                  # Ugly...
+_set_80x25:    jmp     set_80x25
+
+# Aliases for backward compatibility.
+setalias:
+       movw    $VIDEO_80x25, %ax
+       incw    %bx
+       jz      mode_set
+
+       movb    $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al
+       incw    %bx
+       jnz     setbad                          # Fall-through!
+
+# Setting of user mode (AX=mode ID) => CF=success
+mode_set:
+       movw    %ax, %fs:(0x01fa)               # Store mode for use in acpi_wakeup.S
+       movw    %ax, %bx
+       cmpb    $0xff, %ah
+       jz      setalias
+
+       testb   $VIDEO_RECALC>>8, %ah
+       jnz     _setrec
+
+       cmpb    $VIDEO_FIRST_RESOLUTION>>8, %ah
+       jnc     setres
+       
+       cmpb    $VIDEO_FIRST_SPECIAL>>8, %ah
+       jz      setspc
+       
+       cmpb    $VIDEO_FIRST_V7>>8, %ah
+       jz      setv7
+       
+       cmpb    $VIDEO_FIRST_VESA>>8, %ah
+       jnc     check_vesa
+       
+       orb     %ah, %ah
+       jz      setmenu
+       
+       decb    %ah
+       jz      setbios
+
+setbad:        clc
+       movb    $0, do_restore                  # The screen needn't be restored
+       ret
+
+setvesa:
+       DO_STORE
+       subb    $VIDEO_FIRST_VESA>>8, %bh
+       movw    $0x4f02, %ax                    # VESA BIOS mode set call
+       int     $0x10
+       cmpw    $0x004f, %ax                    # AL=4f if implemented
+       jnz     setbad                          # AH=0 if OK
+
+       stc
+       ret
+
+setbios:
+       DO_STORE
+       int     $0x10                           # Standard BIOS mode set call
+       pushw   %bx
+       movb    $0x0f, %ah                      # Check if really set
+       int     $0x10
+       popw    %bx
+       cmpb    %bl, %al
+       jnz     setbad
+       
+       stc
+       ret
+
+setspc:        xorb    %bh, %bh                        # Set special mode
+       cmpb    $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
+       jnc     setbad
+       
+       addw    %bx, %bx
+       jmp     *spec_inits(%bx)
+
+setmenu:
+       orb     %al, %al                        # 80x25 is an exception
+       jz      _set_80x25
+       
+       pushw   %bx                             # Set mode chosen from menu
+       call    mode_table                      # Build the mode table
+       popw    %ax
+       shlw    $2, %ax
+       addw    %ax, %si
+       cmpw    %di, %si
+       jnc     setbad
+       
+       movw    (%si), %ax                      # Fetch mode ID
+_m_s:  jmp     mode_set
+
+setres:        pushw   %bx                             # Set mode chosen by resolution
+       call    mode_table
+       popw    %bx
+       xchgb   %bl, %bh
+setr1: lodsw
+       cmpw    $ASK_VGA, %ax                   # End of the list?
+       jz      setbad
+       
+       lodsw
+       cmpw    %bx, %ax
+       jnz     setr1
+       
+       movw    -4(%si), %ax                    # Fetch mode ID
+       jmp     _m_s
+
+check_vesa:
+       leaw    modelist+1024, %di
+       subb    $VIDEO_FIRST_VESA>>8, %bh
+       movw    %bx, %cx                        # Get mode information structure
+       movw    $0x4f01, %ax
+       int     $0x10
+       addb    $VIDEO_FIRST_VESA>>8, %bh
+       cmpw    $0x004f, %ax
+       jnz     setbad
+
+       movb    (%di), %al                      # Check capabilities.
+       andb    $0x19, %al
+       cmpb    $0x09, %al
+       jz      setvesa                         # This is a text mode
+
+       movb    (%di), %al                      # Check capabilities.
+       andb    $0x99, %al
+       cmpb    $0x99, %al
+       jnz     _setbad                         # Doh! No linear frame buffer.
+
+       subb    $VIDEO_FIRST_VESA>>8, %bh
+       orw     $0x4000, %bx                    # Use linear frame buffer
+       movw    $0x4f02, %ax                    # VESA BIOS mode set call
+       int     $0x10
+       cmpw    $0x004f, %ax                    # AL=4f if implemented
+       jnz     _setbad                         # AH=0 if OK
+
+       movb    $1, graphic_mode                # flag graphic mode
+       movb    $0, do_restore                  # no screen restore
+       stc
+       ret
+
+_setbad:       jmp     setbad                  # Ugly...
+
+# Recalculate vertical display end registers -- this fixes various
+# inconsistencies of extended modes on many adapters. Called when
+# the VIDEO_RECALC flag is set in the mode ID.
+
+setrec:        subb    $VIDEO_RECALC>>8, %ah           # Set the base mode
+       call    mode_set
+       jnc     rct3
+
+       movw    %gs:(0x485), %ax                # Font size in pixels
+       movb    %gs:(0x484), %bl                # Number of rows
+       incb    %bl
+       mulb    %bl                             # Number of visible
+       decw    %ax                             # scan lines - 1
+       movw    $0x3d4, %dx
+       movw    %ax, %bx
+       movb    $0x12, %al                      # Lower 8 bits
+       movb    %bl, %ah
+       outw    %ax, %dx
+       movb    $0x07, %al              # Bits 8 and 9 in the overflow register
+       call    inidx
+       xchgb   %al, %ah
+       andb    $0xbd, %ah
+       shrb    %bh
+       jnc     rct1
+       orb     $0x02, %ah
+rct1:  shrb    %bh
+       jnc     rct2
+       orb     $0x40, %ah
+rct2:  movb    $0x07, %al
+       outw    %ax, %dx
+       stc
+rct3:  ret
+
+# Table of routines for setting of the special modes.
+spec_inits:
+       .word   set_80x25
+       .word   set_8pixel
+       .word   set_80x43
+       .word   set_80x28
+       .word   set_current
+       .word   set_80x30
+       .word   set_80x34
+       .word   set_80x60
+       .word   set_gfx
+
+# Set the 80x25 mode. If already set, do nothing.
+set_80x25:
+       movw    $0x5019, force_size             # Override possibly broken BIOS
+use_80x25:
+#ifdef CONFIG_VIDEO_400_HACK
+       movw    $0x1202, %ax                    # Force 400 scan lines
+       movb    $0x30, %bl
+       int     $0x10
+#else
+       movb    $0x0f, %ah                      # Get current mode ID
+       int     $0x10
+       cmpw    $0x5007, %ax    # Mode 7 (80x25 mono) is the only one available
+       jz      st80            # on CGA/MDA/HGA and is also available on EGAM
+
+       cmpw    $0x5003, %ax    # Unknown mode, force 80x25 color
+       jnz     force3
+
+st80:  cmpb    $0, adapter     # CGA/MDA/HGA => mode 3/7 is always 80x25
+       jz      set80
+
+       movb    %gs:(0x0484), %al       # This is EGA+ -- beware of 80x50 etc.
+       orb     %al, %al                # Some buggy BIOS'es set 0 rows
+       jz      set80
+       
+       cmpb    $24, %al                # It's hopefully correct
+       jz      set80
+#endif /* CONFIG_VIDEO_400_HACK */
+force3:        DO_STORE
+       movw    $0x0003, %ax                    # Forced set
+       int     $0x10
+set80: stc
+       ret
+
+# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
+set_8pixel:
+       DO_STORE
+       call    use_80x25                       # The base is 80x25
+set_8pt:
+       movw    $0x1112, %ax                    # Use 8x8 font
+       xorb    %bl, %bl
+       int     $0x10
+       movw    $0x1200, %ax                    # Use alternate print screen
+       movb    $0x20, %bl
+       int     $0x10
+       movw    $0x1201, %ax                    # Turn off cursor emulation
+       movb    $0x34, %bl
+       int     $0x10
+       movb    $0x01, %ah                      # Define cursor scan lines 6-7
+       movw    $0x0607, %cx
+       int     $0x10
+set_current:
+       stc
+       ret
+
+# Set the 80x28 mode. This mode works on all VGA's, because it's a standard
+# 80x25 mode with 14-point fonts instead of 16-point.
+set_80x28:
+       DO_STORE
+       call    use_80x25                       # The base is 80x25
+set14: movw    $0x1111, %ax                    # Use 9x14 font
+       xorb    %bl, %bl
+       int     $0x10
+       movb    $0x01, %ah                      # Define cursor scan lines 11-12
+       movw    $0x0b0c, %cx
+       int     $0x10
+       stc
+       ret
+
+# Set the 80x43 mode. This mode is works on all VGA's.
+# It's a 350-scanline mode with 8-pixel font.
+set_80x43:
+       DO_STORE
+       movw    $0x1201, %ax                    # Set 350 scans
+       movb    $0x30, %bl
+       int     $0x10
+       movw    $0x0003, %ax                    # Reset video mode
+       int     $0x10
+       jmp     set_8pt                         # Use 8-pixel font
+
+# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
+set_80x30:
+       call    use_80x25                       # Start with real 80x25
+       DO_STORE
+       movw    $0x3cc, %dx                     # Get CRTC port
+       inb     %dx, %al
+       movb    $0xd4, %dl
+       rorb    %al                             # Mono or color?
+       jc      set48a
+
+       movb    $0xb4, %dl
+set48a:        movw    $0x0c11, %ax            # Vertical sync end (also unlocks CR0-7)
+       call    outidx
+       movw    $0x0b06, %ax                    # Vertical total
+       call    outidx
+       movw    $0x3e07, %ax                    # (Vertical) overflow
+       call    outidx
+       movw    $0xea10, %ax                    # Vertical sync start
+       call    outidx
+       movw    $0xdf12, %ax                    # Vertical display end
+       call    outidx
+       movw    $0xe715, %ax                    # Vertical blank start
+       call    outidx
+       movw    $0x0416, %ax                    # Vertical blank end
+       call    outidx
+       pushw   %dx
+       movb    $0xcc, %dl                      # Misc output register (read)
+       inb     %dx, %al
+       movb    $0xc2, %dl                      # (write)
+       andb    $0x0d, %al      # Preserve clock select bits and color bit
+       orb     $0xe2, %al                      # Set correct sync polarity
+       outb    %al, %dx
+       popw    %dx
+       movw    $0x501e, force_size
+       stc                                     # That's all.
+       ret
+
+# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
+set_80x34:
+       call    set_80x30                       # Set 480 scans
+       call    set14                           # And 14-pt font
+       movw    $0xdb12, %ax                    # VGA vertical display end
+       movw    $0x5022, force_size
+setvde:        call    outidx
+       stc
+       ret
+
+# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
+set_80x60:
+       call    set_80x30                       # Set 480 scans
+       call    set_8pt                         # And 8-pt font
+       movw    $0xdf12, %ax                    # VGA vertical display end
+       movw    $0x503c, force_size
+       jmp     setvde
+
+# Special hack for ThinkPad graphics
+set_gfx:
+#ifdef CONFIG_VIDEO_GFX_HACK
+       movw    $VIDEO_GFX_BIOS_AX, %ax
+       movw    $VIDEO_GFX_BIOS_BX, %bx
+       int     $0x10
+       movw    $VIDEO_GFX_DUMMY_RESOLUTION, force_size
+       stc
+#endif
+       ret
+
+#ifdef CONFIG_VIDEO_RETAIN
+
+# Store screen contents to temporary buffer.
+store_screen:
+       cmpb    $0, do_restore                  # Already stored?
+       jnz     stsr
+
+       testb   $CAN_USE_HEAP, loadflags        # Have we space for storing?
+       jz      stsr
+       
+       pushw   %ax
+       pushw   %bx
+       pushw   force_size                      # Don't force specific size
+       movw    $0, force_size
+       call    mode_params                     # Obtain params of current mode
+       popw    force_size
+       movb    %fs:(PARAM_VIDEO_LINES), %ah
+       movb    %fs:(PARAM_VIDEO_COLS), %al
+       movw    %ax, %bx                        # BX=dimensions
+       mulb    %ah
+       movw    %ax, %cx                        # CX=number of characters
+       addw    %ax, %ax                        # Calculate image size
+       addw    $modelist+1024+4, %ax
+       cmpw    heap_end_ptr, %ax
+       jnc     sts1                            # Unfortunately, out of memory
+
+       movw    %fs:(PARAM_CURSOR_POS), %ax     # Store mode params
+       leaw    modelist+1024, %di
+       stosw
+       movw    %bx, %ax
+       stosw
+       pushw   %ds                             # Store the screen
+       movw    video_segment, %ds
+       xorw    %si, %si
+       rep
+       movsw
+       popw    %ds
+       incb    do_restore                      # Screen will be restored later
+sts1:  popw    %bx
+       popw    %ax
+stsr:  ret
+
+# Restore screen contents from temporary buffer.
+restore_screen:
+       cmpb    $0, do_restore                  # Has the screen been stored?
+       jz      res1
+
+       call    mode_params                     # Get parameters of current mode
+       movb    %fs:(PARAM_VIDEO_LINES), %cl
+       movb    %fs:(PARAM_VIDEO_COLS), %ch
+       leaw    modelist+1024, %si              # Screen buffer
+       lodsw                                   # Set cursor position
+       movw    %ax, %dx
+       cmpb    %cl, %dh
+       jc      res2
+       
+       movb    %cl, %dh
+       decb    %dh
+res2:  cmpb    %ch, %dl
+       jc      res3
+       
+       movb    %ch, %dl
+       decb    %dl
+res3:  movb    $0x02, %ah
+       movb    $0x00, %bh
+       int     $0x10
+       lodsw                                   # Display size
+       movb    %ah, %dl                        # DL=number of lines
+       movb    $0, %ah                         # BX=phys. length of orig. line
+       movw    %ax, %bx
+       cmpb    %cl, %dl                        # Too many?
+       jc      res4
+
+       pushw   %ax
+       movb    %dl, %al
+       subb    %cl, %al
+       mulb    %bl
+       addw    %ax, %si
+       addw    %ax, %si
+       popw    %ax
+       movb    %cl, %dl
+res4:  cmpb    %ch, %al                        # Too wide?
+       jc      res5
+       
+       movb    %ch, %al                        # AX=width of src. line
+res5:  movb    $0, %cl
+       xchgb   %ch, %cl
+       movw    %cx, %bp                        # BP=width of dest. line
+       pushw   %es
+       movw    video_segment, %es
+       xorw    %di, %di                        # Move the data
+       addw    %bx, %bx                        # Convert BX and BP to _bytes_
+       addw    %bp, %bp
+res6:  pushw   %si
+       pushw   %di
+       movw    %ax, %cx
+       rep
+       movsw
+       popw    %di
+       popw    %si
+       addw    %bp, %di
+       addw    %bx, %si
+       decb    %dl
+       jnz     res6
+       
+       popw    %es                             # Done
+res1:  ret
+#endif /* CONFIG_VIDEO_RETAIN */
+
+# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
+outidx:        outb    %al, %dx
+       pushw   %ax
+       movb    %ah, %al
+       incw    %dx
+       outb    %al, %dx
+       decw    %dx
+       popw    %ax
+       ret
+
+# Build the table of video modes (stored after the setup.S code at the
+# `modelist' label. Each video mode record looks like:
+#      .word   MODE-ID         (our special mode ID (see above))
+#      .byte   rows            (number of rows)
+#      .byte   columns         (number of columns)
+# Returns address of the end of the table in DI, the end is marked
+# with a ASK_VGA ID.
+mode_table:
+       movw    mt_end, %di                     # Already filled?
+       orw     %di, %di
+       jnz     mtab1x
+       
+       leaw    modelist, %di                   # Store standard modes:
+       movl    $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL)
+       stosl
+       movb    adapter, %al                    # CGA/MDA/HGA -- no more modes
+       orb     %al, %al
+       jz      mtabe
+       
+       decb    %al
+       jnz     mtabv
+       
+       movl    $VIDEO_8POINT + 0x502b0000, %eax        # The 80x43 EGA mode
+       stosl
+       jmp     mtabe
+
+mtab1x:        jmp     mtab1
+
+mtabv: leaw    vga_modes, %si                  # All modes for std VGA
+       movw    $vga_modes_end-vga_modes, %cx
+       rep     # I'm unable to use movsw as I don't know how to store a half
+       movsb   # of the expression above to cx without using explicit shr.
+
+       cmpb    $0, scanning                    # Mode scan requested?
+       jz      mscan1
+       
+       call    mode_scan
+mscan1:
+
+#ifdef CONFIG_VIDEO_LOCAL
+       call    local_modes
+#endif /* CONFIG_VIDEO_LOCAL */
+
+#ifdef CONFIG_VIDEO_VESA
+       call    vesa_modes                      # Detect VESA VGA modes
+#endif /* CONFIG_VIDEO_VESA */
+
+#ifdef CONFIG_VIDEO_SVGA
+       cmpb    $0, scanning                    # Bypass when scanning
+       jnz     mscan2
+       
+       call    svga_modes                      # Detect SVGA cards & modes
+mscan2:
+#endif /* CONFIG_VIDEO_SVGA */
+
+mtabe:
+
+#ifdef CONFIG_VIDEO_COMPACT
+       leaw    modelist, %si
+       movw    %di, %dx
+       movw    %si, %di
+cmt1:  cmpw    %dx, %si                        # Scan all modes
+       jz      cmt2
+
+       leaw    modelist, %bx                   # Find in previous entries
+       movw    2(%si), %cx
+cmt3:  cmpw    %bx, %si
+       jz      cmt4
+
+       cmpw    2(%bx), %cx                     # Found => don't copy this entry
+       jz      cmt5
+
+       addw    $4, %bx
+       jmp     cmt3
+
+cmt4:  movsl                                   # Copy entry
+       jmp     cmt1
+
+cmt5:  addw    $4, %si                         # Skip entry
+       jmp     cmt1
+
+cmt2:
+#endif /* CONFIG_VIDEO_COMPACT */
+
+       movw    $ASK_VGA, (%di)                 # End marker
+       movw    %di, mt_end
+mtab1: leaw    modelist, %si                   # SI=mode list, DI=list end
+ret0:  ret
+
+# Modes usable on all standard VGAs
+vga_modes:
+       .word   VIDEO_8POINT
+       .word   0x5032                          # 80x50
+       .word   VIDEO_80x43
+       .word   0x502b                          # 80x43
+       .word   VIDEO_80x28
+       .word   0x501c                          # 80x28
+       .word   VIDEO_80x30
+       .word   0x501e                          # 80x30
+       .word   VIDEO_80x34
+       .word   0x5022                          # 80x34
+       .word   VIDEO_80x60
+       .word   0x503c                          # 80x60
+#ifdef CONFIG_VIDEO_GFX_HACK
+       .word   VIDEO_GFX_HACK
+       .word   VIDEO_GFX_DUMMY_RESOLUTION
+#endif
+
+vga_modes_end:
+# Detect VESA modes.
+
+#ifdef CONFIG_VIDEO_VESA
+vesa_modes:
+       cmpb    $2, adapter                     # VGA only
+       jnz     ret0
+
+       movw    %di, %bp                        # BP=original mode table end
+       addw    $0x200, %di                     # Buffer space
+       movw    $0x4f00, %ax                    # VESA Get card info call
+       int     $0x10
+       movw    %bp, %di
+       cmpw    $0x004f, %ax                    # Successful?
+       jnz     ret0
+       
+       cmpw    $0x4556, 0x200(%di)
+       jnz     ret0
+       
+       cmpw    $0x4153, 0x202(%di)
+       jnz     ret0
+       
+       movw    $vesa_name, card_name           # Set name to "VESA VGA"
+       pushw   %gs
+       lgsw    0x20e(%di), %si                 # GS:SI=mode list
+       movw    $128, %cx                       # Iteration limit
+vesa1:
+# gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
+# XXX: lodsw   %gs:(%si), %ax                  # Get next mode in the list
+       gs; lodsw
+       cmpw    $0xffff, %ax                    # End of the table?
+       jz      vesar
+       
+       cmpw    $0x0080, %ax                    # Check validity of mode ID
+       jc      vesa2
+       
+       orb     %ah, %ah                # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
+       jz      vesan                   # Certain BIOSes report 0x80-0xff!
+
+       cmpw    $0x0800, %ax
+       jnc     vesae
+
+vesa2: pushw   %cx
+       movw    %ax, %cx                        # Get mode information structure
+       movw    $0x4f01, %ax
+       int     $0x10
+       movw    %cx, %bx                        # BX=mode number
+       addb    $VIDEO_FIRST_VESA>>8, %bh
+       popw    %cx
+       cmpw    $0x004f, %ax
+       jnz     vesan                   # Don't report errors (buggy BIOSES)
+
+       movb    (%di), %al                      # Check capabilities. We require
+       andb    $0x19, %al                      # a color text mode.
+       cmpb    $0x09, %al
+       jnz     vesan
+       
+       cmpw    $0xb800, 8(%di)         # Standard video memory address required
+       jnz     vesan
+
+       testb   $2, (%di)                       # Mode characteristics supplied?
+       movw    %bx, (%di)                      # Store mode number
+       jz      vesa3
+       
+       xorw    %dx, %dx
+       movw    0x12(%di), %bx                  # Width
+       orb     %bh, %bh
+       jnz     vesan
+       
+       movb    %bl, 0x3(%di)
+       movw    0x14(%di), %ax                  # Height
+       orb     %ah, %ah
+       jnz     vesan
+       
+       movb    %al, 2(%di)
+       mulb    %bl
+       cmpw    $8193, %ax              # Small enough for Linux console driver?
+       jnc     vesan
+
+       jmp     vesaok
+
+vesa3: subw    $0x8108, %bx    # This mode has no detailed info specified,
+       jc      vesan           # so it must be a standard VESA mode.
+
+       cmpw    $5, %bx
+       jnc     vesan
+
+       movw    vesa_text_mode_table(%bx), %ax
+       movw    %ax, 2(%di)
+vesaok:        addw    $4, %di                         # The mode is valid. Store it.
+vesan: loop    vesa1                   # Next mode. Limit exceeded => error
+vesae: leaw    vesaer, %si
+       call    prtstr
+       movw    %bp, %di                        # Discard already found modes.
+vesar: popw    %gs
+       ret
+
+# Dimensions of standard VESA text modes
+vesa_text_mode_table:
+       .byte   60, 80                          # 0108
+       .byte   25, 132                         # 0109
+       .byte   43, 132                         # 010A
+       .byte   50, 132                         # 010B
+       .byte   60, 132                         # 010C
+#endif /* CONFIG_VIDEO_VESA */
+
+# Scan for video modes. A bit dirty, but should work.
+mode_scan:
+       movw    $0x0100, %cx                    # Start with mode 0
+scm1:  movb    $0, %ah                         # Test the mode
+       movb    %cl, %al
+       int     $0x10
+       movb    $0x0f, %ah
+       int     $0x10
+       cmpb    %cl, %al
+       jnz     scm2                            # Mode not set
+
+       movw    $0x3c0, %dx                     # Test if it's a text mode
+       movb    $0x10, %al                      # Mode bits
+       call    inidx
+       andb    $0x03, %al
+       jnz     scm2
+       
+       movb    $0xce, %dl                      # Another set of mode bits
+       movb    $0x06, %al
+       call    inidx
+       shrb    %al
+       jc      scm2
+       
+       movb    $0xd4, %dl                      # Cursor location
+       movb    $0x0f, %al
+       call    inidx
+       orb     %al, %al
+       jnz     scm2
+       
+       movw    %cx, %ax                        # Ok, store the mode
+       stosw
+       movb    %gs:(0x484), %al                # Number of rows
+       incb    %al
+       stosb
+       movw    %gs:(0x44a), %ax                # Number of columns
+       stosb
+scm2:  incb    %cl
+       jns     scm1
+       
+       movw    $0x0003, %ax                    # Return back to mode 3
+       int     $0x10
+       ret
+
+tstidx:        outw    %ax, %dx                        # OUT DX,AX and inidx
+inidx: outb    %al, %dx                        # Read from indexed VGA register
+       incw    %dx                     # AL=index, DX=index reg port -> AL=data
+       inb     %dx, %al
+       decw    %dx
+       ret
+
+# Try to detect type of SVGA card and supply (usually approximate) video
+# mode table for it.
+
+#ifdef CONFIG_VIDEO_SVGA
+svga_modes:
+       leaw    svga_table, %si                 # Test all known SVGA adapters
+dosvga:        lodsw
+       movw    %ax, %bp                        # Default mode table
+       orw     %ax, %ax
+       jz      didsv1
+
+       lodsw                                   # Pointer to test routine
+       pushw   %si
+       pushw   %di
+       pushw   %es
+       movw    $0xc000, %bx
+       movw    %bx, %es
+       call    *%ax                            # Call test routine
+       popw    %es
+       popw    %di
+       popw    %si
+       orw     %bp, %bp
+       jz      dosvga
+       
+       movw    %bp, %si                        # Found, copy the modes
+       movb    svga_prefix, %ah
+cpsvga:        lodsb
+       orb     %al, %al
+       jz      didsv
+       
+       stosw
+       movsw
+       jmp     cpsvga
+
+didsv: movw    %si, card_name                  # Store pointer to card name
+didsv1:        ret
+
+# Table of all known SVGA cards. For each card, we store a pointer to
+# a table of video modes supported by the card and a pointer to a routine
+# used for testing of presence of the card. The video mode table is always
+# followed by the name of the card or the chipset.
+svga_table:
+       .word   ati_md, ati_test
+       .word   oak_md, oak_test
+       .word   paradise_md, paradise_test
+       .word   realtek_md, realtek_test
+       .word   s3_md, s3_test
+       .word   chips_md, chips_test
+       .word   video7_md, video7_test
+       .word   cirrus5_md, cirrus5_test
+       .word   cirrus6_md, cirrus6_test
+       .word   cirrus1_md, cirrus1_test
+       .word   ahead_md, ahead_test
+       .word   everex_md, everex_test
+       .word   genoa_md, genoa_test
+       .word   trident_md, trident_test
+       .word   tseng_md, tseng_test
+       .word   0
+
+# Test routines and mode tables:
+
+# S3 - The test algorithm was taken from the SuperProbe package
+# for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
+s3_test:
+       movw    $0x0f35, %cx    # we store some constants in cl/ch
+       movw    $0x03d4, %dx
+       movb    $0x38, %al
+       call    inidx
+       movb    %al, %bh        # store current CRT-register 0x38
+       movw    $0x0038, %ax
+       call    outidx          # disable writing to special regs
+       movb    %cl, %al        # check whether we can write special reg 0x35
+       call    inidx
+       movb    %al, %bl        # save the current value of CRT reg 0x35
+       andb    $0xf0, %al      # clear bits 0-3
+       movb    %al, %ah
+       movb    %cl, %al        # and write it to CRT reg 0x35
+       call    outidx
+       call    inidx           # now read it back
+       andb    %ch, %al        # clear the upper 4 bits
+       jz      s3_2            # the first test failed. But we have a
+
+       movb    %bl, %ah        # second chance
+       movb    %cl, %al
+       call    outidx
+       jmp     s3_1            # do the other tests
+
+s3_2:  movw    %cx, %ax        # load ah with 0xf and al with 0x35
+       orb     %bl, %ah        # set the upper 4 bits of ah with the orig value
+       call    outidx          # write ...
+       call    inidx           # ... and reread 
+       andb    %cl, %al        # turn off the upper 4 bits
+       pushw   %ax
+       movb    %bl, %ah        # restore old value in register 0x35
+       movb    %cl, %al
+       call    outidx
+       popw    %ax
+       cmpb    %ch, %al        # setting lower 4 bits was successful => bad
+       je      no_s3           # writing is allowed => this is not an S3
+
+s3_1:  movw    $0x4838, %ax    # allow writing to special regs by putting
+       call    outidx          # magic number into CRT-register 0x38
+       movb    %cl, %al        # check whether we can write special reg 0x35
+       call    inidx
+       movb    %al, %bl
+       andb    $0xf0, %al
+       movb    %al, %ah
+       movb    %cl, %al
+       call    outidx
+       call    inidx
+       andb    %ch, %al
+       jnz     no_s3           # no, we can't write => no S3
+
+       movw    %cx, %ax
+       orb     %bl, %ah
+       call    outidx
+       call    inidx
+       andb    %ch, %al
+       pushw   %ax
+       movb    %bl, %ah        # restore old value in register 0x35
+       movb    %cl, %al
+       call    outidx
+       popw    %ax
+       cmpb    %ch, %al
+       jne     no_s31          # writing not possible => no S3
+       movb    $0x30, %al
+       call    inidx           # now get the S3 id ...
+       leaw    idS3, %di
+       movw    $0x10, %cx
+       repne
+       scasb
+       je      no_s31
+
+       movb    %bh, %ah
+       movb    $0x38, %al
+       jmp     s3rest
+
+no_s3: movb    $0x35, %al      # restore CRT register 0x35
+       movb    %bl, %ah
+       call    outidx
+no_s31:        xorw    %bp, %bp        # Detection failed
+s3rest:        movb    %bh, %ah
+       movb    $0x38, %al      # restore old value of CRT register 0x38
+       jmp     outidx
+
+idS3:  .byte   0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
+       .byte   0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
+
+s3_md: .byte   0x54, 0x2b, 0x84
+       .byte   0x55, 0x19, 0x84
+       .byte   0
+       .ascii  "S3"
+       .byte   0
+
+# ATI cards.
+ati_test:
+       leaw    idati, %si
+       movw    $0x31, %di
+       movw    $0x09, %cx
+       repe
+       cmpsb
+       je      atiok
+
+       xorw    %bp, %bp
+atiok: ret
+
+idati: .ascii  "761295520"
+
+ati_md:        .byte   0x23, 0x19, 0x84
+       .byte   0x33, 0x2c, 0x84
+       .byte   0x22, 0x1e, 0x64
+       .byte   0x21, 0x19, 0x64
+       .byte   0x58, 0x21, 0x50
+       .byte   0x5b, 0x1e, 0x50
+       .byte   0
+       .ascii  "ATI"
+       .byte   0
+
+# AHEAD
+ahead_test:
+       movw    $0x200f, %ax
+       movw    $0x3ce, %dx
+       outw    %ax, %dx
+       incw    %dx
+       inb     %dx, %al
+       cmpb    $0x20, %al
+       je      isahed
+
+       cmpb    $0x21, %al
+       je      isahed
+       
+       xorw    %bp, %bp
+isahed:        ret
+
+ahead_md:
+       .byte   0x22, 0x2c, 0x84
+       .byte   0x23, 0x19, 0x84
+       .byte   0x24, 0x1c, 0x84
+       .byte   0x2f, 0x32, 0xa0
+       .byte   0x32, 0x22, 0x50
+       .byte   0x34, 0x42, 0x50
+       .byte   0
+       .ascii  "Ahead"
+       .byte   0
+
+# Chips & Tech.
+chips_test:
+       movw    $0x3c3, %dx
+       inb     %dx, %al
+       orb     $0x10, %al
+       outb    %al, %dx
+       movw    $0x104, %dx
+       inb     %dx, %al
+       movb    %al, %bl
+       movw    $0x3c3, %dx
+       inb     %dx, %al
+       andb    $0xef, %al
+       outb    %al, %dx
+       cmpb    $0xa5, %bl
+       je      cantok
+       
+       xorw    %bp, %bp
+cantok:        ret
+
+chips_md:
+       .byte   0x60, 0x19, 0x84
+       .byte   0x61, 0x32, 0x84
+       .byte   0
+       .ascii  "Chips & Technologies"
+       .byte   0
+
+# Cirrus Logic 5X0
+cirrus1_test:
+       movw    $0x3d4, %dx
+       movb    $0x0c, %al
+       outb    %al, %dx
+       incw    %dx
+       inb     %dx, %al
+       movb    %al, %bl
+       xorb    %al, %al
+       outb    %al, %dx
+       decw    %dx
+       movb    $0x1f, %al
+       outb    %al, %dx
+       incw    %dx
+       inb     %dx, %al
+       movb    %al, %bh
+       xorb    %ah, %ah
+       shlb    $4, %al
+       movw    %ax, %cx
+       movb    %bh, %al
+       shrb    $4, %al
+       addw    %ax, %cx
+       shlw    $8, %cx
+       addw    $6, %cx
+       movw    %cx, %ax
+       movw    $0x3c4, %dx
+       outw    %ax, %dx
+       incw    %dx
+       inb     %dx, %al
+       andb    %al, %al
+       jnz     nocirr
+       
+       movb    %bh, %al
+       outb    %al, %dx
+       inb     %dx, %al
+       cmpb    $0x01, %al
+       je      iscirr
+
+nocirr:        xorw    %bp, %bp
+iscirr: movw   $0x3d4, %dx
+       movb    %bl, %al
+       xorb    %ah, %ah
+       shlw    $8, %ax
+       addw    $0x0c, %ax
+       outw    %ax, %dx
+       ret
+
+cirrus1_md:
+       .byte   0x1f, 0x19, 0x84
+       .byte   0x20, 0x2c, 0x84
+       .byte   0x22, 0x1e, 0x84
+       .byte   0x31, 0x25, 0x64
+       .byte   0
+       .ascii  "Cirrus Logic 5X0"
+       .byte   0
+
+# Cirrus Logic 54XX
+cirrus5_test:
+       movw    $0x3c4, %dx
+       movb    $6, %al
+       call    inidx
+       movb    %al, %bl                        # BL=backup
+       movw    $6, %ax
+       call    tstidx
+       cmpb    $0x0f, %al
+       jne     c5fail
+       
+       movw    $0x1206, %ax
+       call    tstidx
+       cmpb    $0x12, %al
+       jne     c5fail
+       
+       movb    $0x1e, %al
+       call    inidx
+       movb    %al, %bh
+       movb    %bh, %ah
+       andb    $0xc0, %ah
+       movb    $0x1e, %al
+       call    tstidx
+       andb    $0x3f, %al
+       jne     c5xx
+       
+       movb    $0x1e, %al
+       movb    %bh, %ah
+       orb     $0x3f, %ah
+       call    tstidx
+       xorb    $0x3f, %al
+       andb    $0x3f, %al
+c5xx:  pushf
+       movb    $0x1e, %al
+       movb    %bh, %ah
+       outw    %ax, %dx
+       popf
+       je      c5done
+
+c5fail:        xorw    %bp, %bp
+c5done:        movb    $6, %al
+       movb    %bl, %ah
+       outw    %ax, %dx
+       ret
+
+cirrus5_md:
+       .byte   0x14, 0x19, 0x84
+       .byte   0x54, 0x2b, 0x84
+       .byte   0
+       .ascii  "Cirrus Logic 54XX"
+       .byte   0
+
+# Cirrus Logic 64XX -- no known extra modes, but must be identified, because
+# it's misidentified by the Ahead test.
+cirrus6_test:
+       movw    $0x3ce, %dx
+       movb    $0x0a, %al
+       call    inidx
+       movb    %al, %bl        # BL=backup
+       movw    $0xce0a, %ax
+       call    tstidx
+       orb     %al, %al
+       jne     c2fail
+       
+       movw    $0xec0a, %ax
+       call    tstidx
+       cmpb    $0x01, %al
+       jne     c2fail
+       
+       movb    $0xaa, %al
+       call    inidx           # 4X, 5X, 7X and 8X are valid 64XX chip ID's. 
+       shrb    $4, %al
+       subb    $4, %al
+       jz      c6done
+       
+       decb    %al
+       jz      c6done
+       
+       subb    $2, %al
+       jz      c6done
+       
+       decb    %al
+       jz      c6done
+       
+c2fail:        xorw    %bp, %bp
+c6done:        movb    $0x0a, %al
+       movb    %bl, %ah
+       outw    %ax, %dx
+       ret
+
+cirrus6_md:
+       .byte   0
+       .ascii  "Cirrus Logic 64XX"
+       .byte   0
+
+# Everex / Trident
+everex_test:
+       movw    $0x7000, %ax
+       xorw    %bx, %bx
+       int     $0x10
+       cmpb    $0x70, %al
+       jne     noevrx
+       
+       shrw    $4, %dx
+       cmpw    $0x678, %dx
+       je      evtrid
+       
+       cmpw    $0x236, %dx
+       jne     evrxok
+
+evtrid:        leaw    trident_md, %bp
+evrxok:        ret
+
+noevrx:        xorw    %bp, %bp
+       ret
+
+everex_md:
+       .byte   0x03, 0x22, 0x50
+       .byte   0x04, 0x3c, 0x50
+       .byte   0x07, 0x2b, 0x64
+       .byte   0x08, 0x4b, 0x64
+       .byte   0x0a, 0x19, 0x84
+       .byte   0x0b, 0x2c, 0x84
+       .byte   0x16, 0x1e, 0x50
+       .byte   0x18, 0x1b, 0x64
+       .byte   0x21, 0x40, 0xa0
+       .byte   0x40, 0x1e, 0x84
+       .byte   0
+       .ascii  "Everex/Trident"
+       .byte   0
+
+# Genoa.
+genoa_test:
+       leaw    idgenoa, %si                    # Check Genoa 'clues'
+       xorw    %ax, %ax
+       movb    %es:(0x37), %al
+       movw    %ax, %di
+       movw    $0x04, %cx
+       decw    %si
+       decw    %di
+l1:    incw    %si
+       incw    %di
+       movb    (%si), %al
+       testb   %al, %al
+       jz      l2
+
+       cmpb    %es:(%di), %al
+l2:    loope   l1
+       orw     %cx, %cx
+       je      isgen
+       
+       xorw    %bp, %bp
+isgen: ret
+
+idgenoa: .byte 0x77, 0x00, 0x99, 0x66
+
+genoa_md:
+       .byte   0x58, 0x20, 0x50
+       .byte   0x5a, 0x2a, 0x64
+       .byte   0x60, 0x19, 0x84
+       .byte   0x61, 0x1d, 0x84
+       .byte   0x62, 0x20, 0x84
+       .byte   0x63, 0x2c, 0x84
+       .byte   0x64, 0x3c, 0x84
+       .byte   0x6b, 0x4f, 0x64
+       .byte   0x72, 0x3c, 0x50
+       .byte   0x74, 0x42, 0x50
+       .byte   0x78, 0x4b, 0x64
+       .byte   0
+       .ascii  "Genoa"
+       .byte   0
+
+# OAK
+oak_test:
+       leaw    idoakvga, %si
+       movw    $0x08, %di
+       movw    $0x08, %cx
+       repe
+       cmpsb
+       je      isoak
+       
+       xorw    %bp, %bp
+isoak: ret
+
+idoakvga: .ascii  "OAK VGA "
+
+oak_md: .byte  0x4e, 0x3c, 0x50
+       .byte   0x4f, 0x3c, 0x84
+       .byte   0x50, 0x19, 0x84
+       .byte   0x51, 0x2b, 0x84
+       .byte   0
+       .ascii  "OAK"
+       .byte   0
+
+# WD Paradise.
+paradise_test:
+       leaw    idparadise, %si
+       movw    $0x7d, %di
+       movw    $0x04, %cx
+       repe
+       cmpsb
+       je      ispara
+       
+       xorw    %bp, %bp
+ispara:        ret
+
+idparadise:    .ascii  "VGA="
+
+paradise_md:
+       .byte   0x41, 0x22, 0x50
+       .byte   0x47, 0x1c, 0x84
+       .byte   0x55, 0x19, 0x84
+       .byte   0x54, 0x2c, 0x84
+       .byte   0
+       .ascii  "Paradise"
+       .byte   0
+
+# Trident.
+trident_test:
+       movw    $0x3c4, %dx
+       movb    $0x0e, %al
+       outb    %al, %dx
+       incw    %dx
+       inb     %dx, %al
+       xchgb   %al, %ah
+       xorb    %al, %al
+       outb    %al, %dx
+       inb     %dx, %al
+       xchgb   %ah, %al
+       movb    %al, %bl        # Strange thing ... in the book this wasn't
+       andb    $0x02, %bl      # necessary but it worked on my card which
+       jz      setb2           # is a trident. Without it the screen goes
+                               # blurred ...
+       andb    $0xfd, %al
+       jmp     clrb2           
+
+setb2: orb     $0x02, %al      
+clrb2: outb    %al, %dx
+       andb    $0x0f, %ah
+       cmpb    $0x02, %ah
+       je      istrid
+
+       xorw    %bp, %bp
+istrid:        ret
+
+trident_md:
+       .byte   0x50, 0x1e, 0x50
+       .byte   0x51, 0x2b, 0x50
+       .byte   0x52, 0x3c, 0x50
+       .byte   0x57, 0x19, 0x84
+       .byte   0x58, 0x1e, 0x84
+       .byte   0x59, 0x2b, 0x84
+       .byte   0x5a, 0x3c, 0x84
+       .byte   0
+       .ascii  "Trident"
+       .byte   0
+
+# Tseng.
+tseng_test:
+       movw    $0x3cd, %dx
+       inb     %dx, %al        # Could things be this simple ! :-)
+       movb    %al, %bl
+       movb    $0x55, %al
+       outb    %al, %dx
+       inb     %dx, %al
+       movb    %al, %ah
+       movb    %bl, %al
+       outb    %al, %dx
+       cmpb    $0x55, %ah
+       je      istsen
+
+isnot: xorw    %bp, %bp
+istsen:        ret
+
+tseng_md:
+       .byte   0x26, 0x3c, 0x50
+       .byte   0x2a, 0x28, 0x64
+       .byte   0x23, 0x19, 0x84
+       .byte   0x24, 0x1c, 0x84
+       .byte   0x22, 0x2c, 0x84
+       .byte   0x21, 0x3c, 0x84
+       .byte   0
+       .ascii  "Tseng"
+       .byte   0
+
+# Video7.
+video7_test:
+       movw    $0x3cc, %dx
+       inb     %dx, %al
+       movw    $0x3b4, %dx
+       andb    $0x01, %al
+       jz      even7
+
+       movw    $0x3d4, %dx
+even7: movb    $0x0c, %al
+       outb    %al, %dx
+       incw    %dx
+       inb     %dx, %al
+       movb    %al, %bl
+       movb    $0x55, %al
+       outb    %al, %dx
+       inb     %dx, %al
+       decw    %dx
+       movb    $0x1f, %al
+       outb    %al, %dx
+       incw    %dx
+       inb     %dx, %al
+       movb    %al, %bh
+       decw    %dx
+       movb    $0x0c, %al
+       outb    %al, %dx
+       incw    %dx
+       movb    %bl, %al
+       outb    %al, %dx
+       movb    $0x55, %al
+       xorb    $0xea, %al
+       cmpb    %bh, %al
+       jne     isnot
+       
+       movb    $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
+       ret
+
+video7_md:
+       .byte   0x40, 0x2b, 0x50
+       .byte   0x43, 0x3c, 0x50
+       .byte   0x44, 0x3c, 0x64
+       .byte   0x41, 0x19, 0x84
+       .byte   0x42, 0x2c, 0x84
+       .byte   0x45, 0x1c, 0x84
+       .byte   0
+       .ascii  "Video 7"
+       .byte   0
+
+# Realtek VGA
+realtek_test:
+       leaw    idrtvga, %si
+       movw    $0x45, %di
+       movw    $0x0b, %cx
+       repe
+       cmpsb
+       je      isrt
+       
+       xorw    %bp, %bp
+isrt:  ret
+
+idrtvga:       .ascii  "REALTEK VGA"
+
+realtek_md:
+       .byte   0x1a, 0x3c, 0x50
+       .byte   0x1b, 0x19, 0x84
+       .byte   0x1c, 0x1e, 0x84
+       .byte   0x1d, 0x2b, 0x84
+       .byte   0x1e, 0x3c, 0x84
+       .byte   0
+       .ascii  "REALTEK"
+       .byte   0
+
+#endif /* CONFIG_VIDEO_SVGA */
+
+# User-defined local mode table (VGA only)
+#ifdef CONFIG_VIDEO_LOCAL
+local_modes:
+       leaw    local_mode_table, %si
+locm1: lodsw
+       orw     %ax, %ax
+       jz      locm2
+       
+       stosw
+       movsw
+       jmp     locm1
+
+locm2: ret
+
+# This is the table of local video modes which can be supplied manually
+# by the user. Each entry consists of mode ID (word) and dimensions
+# (byte for column count and another byte for row count). These modes
+# are placed before all SVGA and VESA modes and override them if table
+# compacting is enabled. The table must end with a zero word followed
+# by NUL-terminated video adapter name.
+local_mode_table:
+       .word   0x0100                          # Example: 40x25
+       .byte   25,40
+       .word   0
+       .ascii  "Local"
+       .byte   0
+#endif /* CONFIG_VIDEO_LOCAL */
+
+# Read a key and return the ASCII code in al, scan code in ah
+getkey:        xorb    %ah, %ah
+       int     $0x16
+       ret
+
+# Read a key with a timeout of 30 seconds.
+# The hardware clock is used to get the time.
+getkt: call    gettime
+       addb    $30, %al                        # Wait 30 seconds
+       cmpb    $60, %al
+       jl      lminute
+
+       subb    $60, %al
+lminute:
+       movb    %al, %cl
+again: movb    $0x01, %ah
+       int     $0x16
+       jnz     getkey                          # key pressed, so get it
+
+       call    gettime
+       cmpb    %cl, %al
+       jne     again
+
+       movb    $0x20, %al                      # timeout, return `space'
+       ret
+
+# Flush the keyboard buffer
+flush: movb    $0x01, %ah
+       int     $0x16
+       jz      empty
+       
+       xorb    %ah, %ah
+       int     $0x16
+       jmp     flush
+
+empty: ret
+
+# Print hexadecimal number.
+prthw: pushw   %ax
+       movb    %ah, %al
+       call    prthb
+       popw    %ax
+prthb: pushw   %ax
+       shrb    $4, %al
+       call    prthn
+       popw    %ax
+       andb    $0x0f, %al
+prthn: cmpb    $0x0a, %al
+       jc      prth1
+
+       addb    $0x07, %al
+prth1: addb    $0x30, %al
+       jmp     prtchr
+
+# Print decimal number in al
+prtdec:        pushw   %ax
+       pushw   %cx
+       xorb    %ah, %ah
+       movb    $0x0a, %cl
+       idivb   %cl
+       cmpb    $0x09, %al
+       jbe     lt100
+
+       call    prtdec
+       jmp     skip10
+
+lt100: addb    $0x30, %al
+       call    prtchr
+skip10:        movb    %ah, %al
+       addb    $0x30, %al
+       call    prtchr  
+       popw    %cx
+       popw    %ax
+       ret
+
+store_edid:
+       pushw   %es                             # just save all registers 
+       pushw   %ax                             
+       pushw   %bx
+       pushw   %cx
+       pushw   %dx
+       pushw   %di
+
+       pushw   %fs                             
+       popw    %es
+
+       movl    $0x13131313, %eax               # memset block with 0x13
+       movw    $32, %cx
+       movw    $0x140, %di
+       cld
+       rep 
+       stosl  
+
+       movw    $0x4f15, %ax                    # do VBE/DDC 
+       movw    $0x01, %bx
+       movw    $0x00, %cx
+       movw    $0x01, %dx
+       movw    $0x140, %di
+       int     $0x10   
+
+       popw    %di                             # restore all registers        
+       popw    %dx
+       popw    %cx
+       popw    %bx
+       popw    %ax
+       popw    %es     
+       ret
+
+# VIDEO_SELECT-only variables
+mt_end:                .word   0       # End of video mode table if built
+edit_buf:      .space  6       # Line editor buffer
+card_name:     .word   0       # Pointer to adapter name
+scanning:      .byte   0       # Performing mode scan
+do_restore:    .byte   0       # Screen contents altered during mode change
+svga_prefix:   .byte   VIDEO_FIRST_BIOS>>8     # Default prefix for BIOS modes
+graphic_mode:  .byte   0       # Graphic mode with a linear frame buffer
+dac_size:      .byte   6       # DAC bit depth
+
+# Status messages
+keymsg:                .ascii  "Press <RETURN> to see video modes available, "
+               .ascii  "<SPACE> to continue or wait 30 secs"
+               .byte   0x0d, 0x0a, 0
+
+listhdr:       .byte   0x0d, 0x0a
+               .ascii  "Mode:    COLSxROWS:"
+
+crlft:         .byte   0x0d, 0x0a, 0
+
+prompt:                .byte   0x0d, 0x0a
+               .asciz  "Enter mode number or `scan': "
+
+unknt:         .asciz  "Unknown mode ID. Try again."
+
+badmdt:                .ascii  "You passed an undefined mode number."
+               .byte   0x0d, 0x0a, 0
+
+vesaer:                .ascii  "Error: Scanning of VESA modes failed. Please "
+               .ascii  "report to <mj@ucw.cz>."
+               .byte   0x0d, 0x0a, 0
+
+old_name:      .asciz  "CGA/MDA/HGA"
+
+ega_name:      .asciz  "EGA"
+
+svga_name:     .ascii  " "
+
+vga_name:      .asciz  "VGA"
+
+vesa_name:     .asciz  "VESA"
+
+name_bann:     .asciz  "Video adapter: "
+#endif /* CONFIG_VIDEO_SELECT */
+
+# Other variables:
+adapter:       .byte   0       # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
+video_segment: .word   0xb800  # Video memory segment
+force_size:    .word   0       # Use this size instead of the one in BIOS vars
+
+# Setup signature -- must be last
+setup_sig1:    .word   SIG1
+setup_sig2:    .word   SIG2
+
+# After this point, there is some free space which is used by the video mode
+# handling code to store the temporary mode table (not used by the kernel).
+
+modelist:
+
+.text
+endtext:
+.data
+enddata:
+.bss
+endbss:
+
diff --git a/l4/pkg/bootstrap_custom/server/src/ARCH-x86/xen.c b/l4/pkg/bootstrap_custom/server/src/ARCH-x86/xen.c
new file mode 100644 (file)
index 0000000..9aae2a4
--- /dev/null
@@ -0,0 +1,21 @@
+
+#include <h/types.h>
+#include <h/os.h>
+#include <h/hypervisor.h>
+#include <public/xen.h>
+
+asm(".section __xen_guest                                \n"
+    ".ascii \"GUEST_OS=DD-L4\"                           \n"
+    ".ascii \",GUEST_VER=0.1\"                           \n"
+    ".ascii \",XEN_VER=2.0\"                             \n"
+    ".ascii \",VIRT_BASE=0xf0000000\"                    \n"
+    ".ascii \",LOADER=generic\"                          \n"
+    ".ascii \",PT_MODE_WRITABLE\"                        \n"
+    ".previous                                           \n");
+
+int
+putchar(int c)
+{
+  HYPERVISOR_console_io(CONSOLEIO_write, 1, (char *)&c);
+  return c;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/Make.rules b/l4/pkg/bootstrap_custom/server/src/Make.rules
new file mode 100644 (file)
index 0000000..dae9d46
--- /dev/null
@@ -0,0 +1,481 @@
+# vim:set ft=make:
+# 
+# User definable variables for bootstrap:
+# - BOOTSTRAP_CHECK_MD5 set this if you want MD5 checks for modules
+# - BOOTSTRAP_SEARCH_PATH
+# - BOOTSTRAP_ELF_NAME
+# - BOOTSTRAP_MODULES_LIST
+# - BOOTSTRAP_DO_RAW_IMAGE
+# - BOOTSTRAP_DO_UIMAGE
+# - BOOTSTRAP_DO_UEFI if set an image which is bootable by UEFI is built
+# - BOOTSTRAP_NO_STRIP if set no stripping of image
+# - BOOTSTRAP_UIMAGE_COMPRESSION: set to none, gzip, or bzip2
+# - BOOTSTRAP_CMDLINE: compiled-in command line, only used if no cmdline
+#                      given
+# - BOOTSTRAP_OUTPUT_DIR: Optional alternative output directory for all
+#                         images (and generated files), preferable some
+#                         tmpfs directory
+
+INTERNAL_CRT0       := y # the defualt is to use our internal crt0
+DEFAULT_RELOC_arm   := 0x01000000
+DEFAULT_RELOC_x86   := 0x002d0000
+DEFAULT_RELOC_amd64 := 0x002d0000
+DEFAULT_RELOC_ppc32 := 0x002d0000
+DEFAULT_RELOC_sparc := 0x00800000
+RELOC_PHYS          := y
+LDFLAGS              = -nostdlib -static -Bstatic
+EXTRA_GENERAL_D_DEP += .redo-change-tracker $(BID_RAM_BASE_DEP) \
+                      $(wildcard $(L4DIR)/conf/Makeconf.boot $(OBJ_BASE)/conf/Makeconf.boot) \
+                      $(SRC_DIR)/build.pl $(BOOTSTRAP_MODULES_LIST)
+INCLUDE_MAKE_RULES   = $(SRC_DIR)/*/Make.rules
+BOOTSTRAP_LD_dep    := $(SRC_DIR)/ldscript.inc
+
+ifneq ($(BOOTSTRAP_CHECK_MD5),)
+  REQUIRES_LIBS       += libbsd-lite
+  DEFINES             += -DDO_CHECK_MD5
+endif
+
+include $(L4DIR)/mk/Makeconf
+-include $(OBJ_DIR)/Makeconf.local
+-include $(L4DIR)/conf/Makeconf.boot
+-include $(OBJ_BASE)/conf/Makeconf.boot
+
+SRC_CC_IS_CXX11    := y
+
+# Checks added Nov 2010:
+ifneq ($(wildcard $(L4DIR)/conf/Makeconf.bootstrap),)
+$(error $(L4DIR)/conf/Makeconf.bootstrap not used anymore. Please use $(L4DIR)/conf/Makeconf.boot now)
+endif
+ifneq ($(wildcard $(OBJ_BASE)/Makeconf.bootstrap),)
+$(error $(OBJ_BASE)/Makeconf.bootstrap not used anymore. Please use $(OBJ_BASE)/conf/Makeconf.boot now)
+endif
+
+ifeq ($(BOOTSTRAP_DO_UEFI),y)
+  # link to 0x0
+  DEFAULT_RELOC_x86   := 0x0
+  DEFAULT_RELOC_amd64 := 0x0
+
+  BUILD_PIE           := 1
+
+  # lib gnu-efi requirements
+  REQUIRES_LIBS       += gnu-efi
+  EFI_ARCH-amd64      := x86_64
+  EFI_ARCH-x86        := ia32
+  EFI_ARCH            := $(EFI_ARCH-$(ARCH))
+  EFI_BIN_FMT         := efi-app-$(EFI_ARCH)
+  CRTN_dyn_bin        :=
+  CRTEND_dyn_bin      :=
+  INTERNAL_CRT0       := n
+  CRT0                 = $(OBJ_BASE)/lib/$(SYSTEM)/crt0-efi-$(EFI_ARCH).o
+  EXTRA_LIBS           = -L$(OBJ_BASE)/lib/$(SYSTEM) -lefi -lgnuefi
+  CXXFLAGS            += -fshort-wchar
+  CFLAGS              += -fshort-wchar
+endif
+
+BOOTSTRAP_SEARCH_PATH        ?= $(OBJ_DIR)
+BOOTSTRAP_MODULES_LIST       ?= $(SRC_DIR)/modules.list
+BOOTSTRAP_MODULE_PATH_BINLIB ?= $(OBJ_BASE)/bin/$(SYSTEM)/$(BUILD_ABI):$(OBJ_BASE)/lib/$(SYSTEM)/$(BUILD_ABI):$(OBJ_BASE)/lib/$(SYSTEM)
+BOOTSTRAP_ELF_NAME           ?= bootstrap.elf
+MKIMAGE                      ?= mkimage
+BOOTSTRAP_UIMAGE_COMPRESSION ?= none
+
+ifeq ($(BUILD_ARCH),$(filter $(BUILD_ARCH),arm ppc32 sparc))
+  # ARM/PPC/SPARC always uses single image mode
+  # when no entry is given we build the useless auto-build target
+  ifeq ($(E)$(ENTRY),)
+    BOOTSTRAP_ELF_NAME := bootstrap.auto-build-useless.elf
+  endif
+  ENTRY := auto-build-entry
+endif
+
+od := $(if $(BOOTSTRAP_OUTPUT_DIR),$(if $(wildcard $(BOOTSTRAP_OUTPUT_DIR)),,$(shell mkdir $(BOOTSTRAP_OUTPUT_DIR))))
+od := $(if $(BOOTSTRAP_OUTPUT_DIR),$(BOOTSTRAP_OUTPUT_DIR)/)
+
+PRIVATE_INCDIR  = $(SRC_DIR) $(SRC_DIR)/ARCH-$(ARCH)
+
+TARGET         := $(od)$(BOOTSTRAP_ELF_NAME)
+TARGET_BIN      = $(od)$(BOOTSTRAP_ELF_NAME)
+MODE            = lib
+
+include $(SRC_DIR)/Makefile.platform
+
+ifneq ($(DEFAULT_RELOC_arm-$(PLATFORM_TYPE)),)
+DEFAULT_RELOC_arm         := $(DEFAULT_RELOC_arm-$(PLATFORM_TYPE))
+endif
+
+INTERNAL_CRT0 := $(strip $(INTERNAL_CRT0))
+
+CXXFLAGS_amd64 += -mno-sse
+CXXFLAGS_x86   += -mno-sse
+CFLAGS_amd64 += -mno-sse
+CFLAGS_x86   += -mno-sse
+
+SRC_C          += exec.c module.c
+SRC_CC         += region.cc startup.cc init_kip_f.cc \
+                   libc_support+.cc patch.cc koptions.cc \
+                   platform_common.cc memory.cc boot_modules.cc
+
+SRC_CC_x86     += ARCH-x86/reboot.cc
+SRC_CC_amd64   += ARCH-x86/reboot.cc
+SRC_C_x86      += base_critical.c
+SRC_C_amd64    += base_critical.c
+SRC_CC_arm             += ARCH-arm/reboot.cc ARCH-arm/head.cc
+SRC_CC_ppc32    += ARCH-ppc32/init_kip_v2-arch.cc \
+                  ARCH-ppc32/reboot.cc ARCH-ppc32/head.cc
+SRC_CC_sparc   += ARCH-sparc/reboot.cc ARCH-sparc/head.cc
+SRC_CC          += $(SUPPORT_CC_$(ARCH)-$(PLATFORM_TYPE))
+
+SRC_S-$(INTERNAL_CRT0) += ARCH-$(ARCH)/crt0.S
+
+OPTS            = -g -Os $(CARCHFLAGS_$(ARCH)) $(CARCHFLAGS_$(ARCH)_$(CPU)) \
+                  $(GCCNOFPU_$(ARCH))
+DEFINES         += -DRAM_BASE=$(RAM_BASE) -DL4_MINIMAL_LIBC=1
+DEFINES         += -DCMDLINE="\"$(BOOTSTRAP_CMDLINE)\""
+DEFINES         += -DPLATFORM_TYPE=\"$(PLATFORM_TYPE)\"
+DEFINES         += -DPLATFORM_TYPE_$(PLATFORM_TYPE)
+DEFINES         += -DPLATFORM_UART_NR=$(PLATFORM_UART_NR)
+
+MOD_ADDR         = 0x02000000
+
+SRC_S           += $(SRC_S-y)
+CPPFLAGS        += $(CPPFLAGS_$(ARCH)-$(PLATFORM_TYPE))
+CPPFLAGS        += $(BID_PKG_CONFIG_CFLAGS)
+
+ifeq ($(filter clean cleanall,$(MAKECMDGOALS)),)
+ifeq ($(SUPPORT_CC_$(ARCH)-$(PLATFORM_TYPE)),)
+  $(info ERROR: PLATFORM_TYPE=$(PLATFORM_TYPE) has no assigned platform support file)
+  $(info ERROR: A proper PLATFORM_TYPE must be set for a build)
+  $(error .)
+endif
+endif
+
+BOOTSTRAP_L4_LIBS := -lcxx_base -lcxx_io -luc_c_minimal
+DRV_LIBS-ppc32   = -ldrivers_of
+DRV_LIBS         = -ldrivers_uart $(DRV_LIBS-$(ARCH))
+ifeq ($(INTERNAL_CRT0),y)
+CRT0            =
+endif
+LDSCRIPT        = bootstrap.ld
+LDNMAGIC        =
+
+vpath bootstrap.ld.in $(SRC_DIR)/ARCH-$(ARCH)
+
+# can be overwritten by Makeconf.local
+COMPRESS       ?= 0
+REALMODE_LOADING ?= 0
+RML            ?= 0
+BUILD_PIE      ?= 0
+SPARSE_ELF     ?= n
+
+ifeq ($(BUILD_PIE),1)
+DRV_LIBS          := $(patsubst -l%,-l%.p,$(DRV_LIBS))
+BOOTSTRAP_L4_LIBS := $(patsubst -l%,-l%.p,$(BOOTSTRAP_L4_LIBS))
+CFLAGS            += -fpie
+CXXFLAGS          += -fpie
+DEFINES           += -D__PIC__
+LDFLAGS           = -znocombreloc -nostdlib -pie -Bsymbolic
+endif
+
+ifneq ($(REALMODE_LOADING)$(RML),00)
+REALMODE_LOADING := 1
+#$(error Info: Default reloc needs to be 0x00100000)
+# And if you have done so you probably need to relink sigma0 and/or moe
+endif
+
+ifeq ($(ARCH),arm)
+CPPFLAGS         += -DSINGLE_SECTION
+endif
+
+
+
+# convenience
+ifneq ($(E),)
+ENTRY          := $(E)
+endif
+
+ENTRY_FN := $(shell echo "$(ENTRY)" | tr '[ ]' '[_]' )
+
+
+ifneq ($(ENTRY),)
+ ifeq ($(filter clean cleanall,$(MAKECMDGOALS)),)
+  BUILD_MOD_CMD = ( SEARCHPATH="$(BOOTSTRAP_SEARCH_PATH):$(BOOTSTRAP_MODULE_PATH_BINLIB)" \
+                    CC="$(CC)" LD="$(LD)" CROSS_COMPILE=$(CROSS_COMPILE) \
+                    MAKE_INC_FILE=$(PWD)/mod.make.inc \
+                    FLAGS_CC="$(CCXX_FLAGS) -I$(SRC_DIR)" \
+                    OUTPUT_DIR="$(BOOTSTRAP_OUTPUT_DIR)" \
+                    OPT_ARCH=$(ARCH) OPT_COMPRESS=$(COMPRESS) L4DIR=$(L4DIR) \
+                    $(SRC_DIR)/build.pl $(1) $(BOOTSTRAP_MODULES_LIST) "$(ENTRY)" || \
+                    (echo "processing-of-module-list-failed"; exit 1))
+ endif
+endif
+
+
+# we need to re-do if some things change
+.redo-change-tracker: FORCE
+       $(VERBOSE)echo "$(ENTRY) '$(COMPRESS)' '$(BOOTSTRAP_CMDLINE)' '$(BOOTSTRAP_SEARCH_PATH):$(BOOTSTRAP_MODULE_PATH_BINLIB)' '$(RAM_SIZE_MB)' '$(PLATFORM_TYPE)' '$(PLATFORM_UART_NR)' '$(od)' '$(OPT_STRIP)'" > $@.tmp
+       $(if $(BUILD_MOD_CMD),$(VERBOSE)$(call BUILD_MOD_CMD,dump) >> $@.tmp)
+       $(call move_if_changed,$@,$@.tmp)
+
+ifneq ($(ENTRY),)
+
+INSTALL_FILES  = $(BOOTSTRAP_ELF_NAME) bootstrap_$(ENTRY_FN) bootstrap_$(ENTRY_FN).elf
+ifeq ($(ARCH)$(BOOTSTRAP_DO_UEFI),amd64)
+INSTALL_FILES += bootstrap32.elf
+BOOTSTRAP_LINK_SOURCE = bootstrap32.elf
+else
+BOOTSTRAP_LINK_SOURCE = $(BOOTSTRAP_ELF_NAME)
+endif
+
+ifeq ($(BOOTSTRAP_DO_UEFI),y)
+INSTALL_FILES += bootstrap_$(ENTRY_FN).efi bootstrap.efi
+endif
+
+$(od)bootstrap_$(ENTRY_FN): $(od)$(BOOTSTRAP_LINK_SOURCE)
+       $(VERBOSE)$(LN) -f $< $@
+
+$(od)bootstrap_$(ENTRY_FN).elf: $(od)$(BOOTSTRAP_LINK_SOURCE)
+       $(VERBOSE)$(LN) -f $< $@
+
+$(od)bootstrap_$(ENTRY_FN).%: $(od)bootstrap.%
+       $(VERBOSE)$(LN) -f $< $@
+
+ ifeq ($(ARCH),$(filter $(ARCH),arm ppc32))
+   BID_POST_PROG_LINK_MSG_$(od)$(BOOTSTRAP_ELF_NAME) = echo -e "  ==> Post-processing $@"
+   BID_POST_PROG_LINK_$(od)$(BOOTSTRAP_ELF_NAME)     = \
+      $(VERBOSE)LANG=C $(NM) -C $@ | \
+        LANG=C $(GREP) -E ' D __PLATFORMS_(BEGIN|END)$$' | \
+                (read a i; read b i; \
+                 if [ "$$a" = "$$b" ]; then \
+                   echo -e "\nERROR: Missing at least one platform instantiation.\n"; \
+                   $(RM) $@; \
+                   exit 1; \
+                 fi ) || exit 1; \
+      $(if $(BOOTSTRAP_NO_STRIP),,$(STRIP) $@)
+
+   ifneq ($(BOOTSTRAP_DO_RAW_IMAGE)$(BOOTSTRAP_DO_UIMAGE),)
+     BOOTSTRAP_RAW      := $(od)bootstrap.raw
+     INSTALL_FILES      += bootstrap.raw bootstrap_$(ENTRY_FN).raw
+     ifneq ($(BOOTSTRAP_DO_UIMAGE),)
+       ifneq ($(shell command -v $(MKIMAGE)),)
+         BOOTSTRAP_UIMAGE := $(od)bootstrap.uimage
+         INSTALL_FILES    += bootstrap.uimage bootstrap_$(ENTRY_FN).uimage
+       else
+         $(error mkimage($(MKIMAGE)) host tool missing, cannot build bootstrap.uimage)
+       endif
+     endif
+   endif
+ endif
+
+ifneq ($(ENTRY),auto-build-entry)
+all:: $(addprefix $(IMAGES_DIR)/,$(INSTALL_FILES))
+       $(VERBOSE)echo "  Image size(s) in bytes:"
+       $(VERBOSE)for f in $(filter bootstrap_$(ENTRY_FN).elf bootstrap.raw bootstrap.uimage, $(INSTALL_FILES)); do \
+         find $(if $(od),$(od),.) -name $$f -printf " %30f:  %s\n"; \
+       done
+       $(if $(LDFLAGS_bootstrap.elf),$(VERBOSE)echo "  Start address: $(patsubst --defsym=__executable_start=%,%,$(LDFLAGS_bootstrap.elf))")
+       $(VERBOSE)echo "  --> Build-Nr: $$(cat .build_nr)"
+
+# install images into easy to reach directory in build dir
+$(IMAGES_DIR)/%: $(od)%
+       $(VERBOSE)echo "  ==> Installing $< in image directory"
+       $(VERBOSE)(cd $(dir $@) && $(LN) -sf $(if $(od),,$(PWD)/)$<)
+endif # !auto-build-entry
+
+else
+  INSTALL_FILES = bootstrap
+endif # ENTRY
+
+ifneq ($(REALMODE_LOADING),0)
+CPPFLAGS       += -DREALMODE_LOADING -DSINGLE_SECTION
+# don't install bootstrap_$(ENTRY_FN).elf
+INSTALL_FILES   = bootstrap.load
+MOD_ADDR        = 0x00150000
+endif
+
+ifneq ($(COMPRESS),0)
+SRC_C          += uncompress.c gunzip.c
+CFLAGS_gunzip.c := -fno-strict-aliasing
+CPPFLAGS       += -DCOMPRESS
+SPARSE_ELF     := n
+endif
+
+ifeq ($(SPARSE_ELF),y)
+CPPFLAGS       += -DPLACE_MODULES_AT_MODADDR
+endif
+
+ifneq ($(RAM_SIZE_MB),)
+CPPFLAGS       += -DRAM_SIZE_MB=$(RAM_SIZE_MB)
+endif
+
+CXXFLAGS += -fno-rtti -fno-exceptions
+CXXFLAGS += $(call checkcxx,-fno-threadsafe-statics)
+
+ifneq ($(BUILD_MOD_CMD),)
+ ifeq ($(filter clean cleanall,$(MAKECMDGOALS)),)
+
+processing-of-module-list-failed:
+       @echo
+       @echo "  Processing of $(BOOTSTRAP_MODULES_LIST) failed!"
+       @echo
+       @exit 1
+
+mod.make.inc $(od)mbi_modules.bin: $(GENERAL_D_LOC) $(shell $(call BUILD_MOD_CMD,list))
+       @echo Building entry \""$(ENTRY)"\".
+       $(VERBOSE)$(call BUILD_MOD_CMD,build)
+
+  -include mod.make.inc
+  BOOTSTRAP_LD_dep             += mod.make.inc
+  STARTUP_C_dep                := mod.make.inc
+  OBJS_$(od)$(BOOTSTRAP_ELF_NAME)   += $(MODULE_OBJECT_FILES)
+ endif
+
+ CPPFLAGS                     += -DIMAGE_MODE
+endif
+
+CPPFLAGS       += -DMODADDR=$(MOD_ADDR)
+
+LIBS             =
+L4_LIBS          = $(DRV_LIBS) $(BOOTSTRAP_L4_LIBS)
+L4_LIBS         += $(GCCLIB) $(EXTRA_LIBS)
+
+all:: $(BOOTSTRAP_RAW)
+
+# image for use with pxelinux
+bootstrap.load: $(TARGET_BIN) bootsect.o.img setup.o.img
+       @$(GEN_MESSAGE)
+       $(VERBOSE)objcopy -O binary -R .note -R .comment -S $< $<.load.bin
+       $(VERBOSE)cat bootsect.o.img setup.o.img $<.load.bin > $@
+
+bootsect.o.img: ARCH-x86/bootsect.S $(SRC_DIR)/Makefile $(SRC_DIR)/Make.rules
+       @$(GEN_MESSAGE)
+       $(VERBOSE)$(CC) -traditional -nostdinc -nostdlib -c $<
+       $(VERBOSE)$(LD) -m elf_i386 -Ttext 0x0 -o $@ -s --oformat binary \
+         bootsect.o
+       $(VERBOSE)chmod -x $@
+
+setup.o.img: ARCH-x86/setup.S $(SRC_DIR)/Makefile $(SRC_DIR)/Make.rules
+       @$(GEN_MESSAGE)
+       $(VERBOSE)$(CC) -traditional -nostdinc -nostdlib -DARCH_$(ARCH) -c $<
+       $(VERBOSE)$(LD) -m elf_i386 -Ttext 0x0 -o $@ -s --oformat binary \
+         -e begtext setup.o
+       $(VERBOSE)dd if=/dev/zero bs=1 count=$$((3072 - `wc -c < setup.o.img`)) >> setup.o.img 2> /dev/null
+       $(VERBOSE)chmod -x $@
+
+# raw version without ELF, primarily useful for ARM
+$(BOOTSTRAP_RAW): $(TARGET_BIN)
+       @$(GEN_MESSAGE)
+       $(VERBOSE)cp $< $@.tmp
+       $(VERBOSE)$(OBJCOPY) -O binary $@.tmp $@
+       $(VERBOSE)chmod -x $@
+       $(VERBOSE)$(RM) $@.tmp
+
+%.gzip: %
+       gzip -c9 $^ > $@
+
+%.bzip2: %
+       bzip2 -c9 $^ > $@
+
+%.none: %
+       ln -sf $^ $@
+
+MKIMAGE_ARCH = $(if $(filter ppc32,$(ARCH)),ppc,$(ARCH))
+
+# u-boot image, based on raw-version
+$(BOOTSTRAP_UIMAGE): $(BOOTSTRAP_RAW).$(BOOTSTRAP_UIMAGE_COMPRESSION)
+       @$(GEN_MESSAGE)
+       @# mkimage writes the same file which does not play well with hardlinks
+       $(VERBOSE)$(RM) -f $@
+       $(VERBOSE)$(MKIMAGE) -e $(call default_reloc,$(ARCH)) \
+          -a $(call default_reloc,$(ARCH)) -A $(MKIMAGE_ARCH)  \
+          -C $(BOOTSTRAP_UIMAGE_COMPRESSION) \
+          -n "L4 Image #$$(cat .build_nr)" \
+          -d $^ $@
+
+$(TARGET): $(LDSCRIPT) $(OBJS_$(TARGET))
+
+
+increment_build_nr = \
+   $(shell if [ -e .build_nr ]; then            \
+            nr=$$(($$(cat .build_nr) + 1));    \
+          else                                 \
+            nr=1;                              \
+          fi;                                  \
+          echo $$nr > .build_nr; echo $$nr)
+
+
+startup.o: $(STARTUP_C_dep)
+startup.o: CPPFLAGS += -DBUILD_DATE="\"$(shell date)\"" -DBUILD_NR=\"$(call increment_build_nr)\"
+
+$(LDSCRIPT): $(LDSCRIPT).in $(GENERAL_D_LOC) $(BOOTSTRAP_LD_dep)
+       @$(GEN_MESSAGE)
+       $(VERBOSE)$(CROSS_COMPILE)cpp -P $(CPPFLAGS) -DLINKADDR=$(strip $(call default_reloc,$(ARCH))) $< $@;
+
+clean::
+       $(VERBOSE)$(RM) mod.make.inc mod*.bin mbi_modules.bin $(LDSCRIPT)
+       $(VERBOSE)$(RM) setup.o.img bootsect.o.img
+       $(VERBOSE)$(RM) mod*.bin
+       $(VERBOSE)$(RM) $(SRC32_C:.c=.o32) $(SRC32_S:.S=.o32)
+       $(VERBOSE)$(RM) .redo-change-tracker
+
+cleanall::
+       $(VERBOSE)$(RM) $(od)bootstrap_* $(od)bootstrap.*
+
+bootstrap.efi: bootstrap.elf
+       $(OBJCOPY) -S -j .text -j .rodata -j .reloc -j .dynsym -j .dynstr -j .rel.dyn \
+                  -j .data \
+                  -j .data.module_info -j .dynamic -j .rela.dyn -j .rela.plt -j .reloc \
+                  -j .bss -j .module_data \
+                  --target=$(EFI_BIN_FMT) $< $@
+
+ifeq ($(ARCH),amd64)
+
+vpath %.c             $(SRC_DIR)/ARCH-amd64
+vpath %.S             $(SRC_DIR)/ARCH-amd64
+vpath %.c             $(SRC_DIR)/ARCH-amd64/boot32
+vpath %.S             $(SRC_DIR)/ARCH-amd64/boot32
+vpath bootstrap.ld.in $(SRC_DIR)/ARCH-x86
+
+SRC32_C                 = boot_cpu.c boot_kernel.c load_elf.c minilibc_support.c
+SRC32_S                 = boot.S boot_idt.S
+OBJ32           = $(SRC32_S:.S=.o32) $(SRC32_C:.c=.o32)
+CC32            = $(filter-out -m64, $(CC)) -m32
+CFLAGS32        = $(filter-out -m64, $(CFLAGS) $(CFLAGS_$(ARCH))) -m32 $(GCCNOSTACKPROTOPT)
+
+$(OBJ_DIR)/ARCH-amd64/libc32/OBJ-$(ARCH)_$(CPU)/libc32.a: FORCE
+       $(VERBOSE)$(MAKE) O=$(OBJ_BASE) -C $(SRC_DIR)/ARCH-amd64/libc32
+
+bootstrap32.elf: $(OBJ32) bootstrap32.bin $(SRC_DIR)/ARCH-amd64/boot32/bootstrap32.ld $(OBJ_DIR)/ARCH-amd64/libc32/OBJ-$(ARCH)_$(CPU)/libc32.a
+       @$(LINK_MESSAGE)
+       $(VERBOSE)$(CC32) -o $@ -nostdlib -static \
+         -Wl,-T,$(SRC_DIR)/ARCH-amd64/boot32/bootstrap32.ld,--gc-sections $^ -lgcc
+       $(VERBOSE)chmod 755 $@
+
+bootstrap: bootstrap32.elf
+       $(VERBOSE)$(LN) -f $^ $@
+
+bootstrap32.bin: $(BOOTSTRAP_ELF_NAME)
+       @$(GEN_MESSAGE)
+       $(VERBOSE)$(OBJCOPY) -S $< bootstrap64.bin
+       $(VERBOSE)chmod -x bootstrap64.bin
+       $(VERBOSE)$(OBJCOPY) -B i386 -I binary -O elf32-i386 bootstrap64.bin $@
+
+%.o32: %.c $(SRC_DIR)/Makefile $(SRC_DIR)/Make.rules
+       @$(COMP_MESSAGE)
+       $(VERBOSE)$(CC32) -o $@ -c $(DEPEND_FLAG) \
+         $(CPPFLAGS) $(CFLAGS32) $(call absfilename,$<)
+
+%.o32: %.S $(SRC_DIR)/Makefile $(SRC_DIR)/Make.rules
+       @$(COMP_MESSAGE)
+       $(VERBOSE)$(CC32) -o $@ -c $(DEPEND_FLAG) \
+         $(CPPFLAGS) $(CFLAGS32) $(call absfilename,$<)
+
+clean cleanall::
+       $(VERBOSE)PWD=$(call absfilename,$(SRC_DIR)/ARCH-amd64/libc32) \
+         $(MAKE) -C $(SRC_DIR)/ARCH-amd64/libc32 $@
+
+else
+bootstrap: $(BOOTSTRAP_ELF_NAME)
+       $(VERBOSE)$(LN) -f $^ $@
+endif
+
+INSTALL_TARGET := $(if $(od),,$(INSTALL_FILES))
diff --git a/l4/pkg/bootstrap_custom/server/src/Makeconf.local b/l4/pkg/bootstrap_custom/server/src/Makeconf.local
new file mode 100644 (file)
index 0000000..016ee67
--- /dev/null
@@ -0,0 +1,4 @@
+#edited by coon 10 apr
+#REALMODE_LOADING=1
+#JAILHOUSE
+#IMAGE_MODE
\ No newline at end of file
diff --git a/l4/pkg/bootstrap_custom/server/src/Makefile b/l4/pkg/bootstrap_custom/server/src/Makefile
new file mode 100644 (file)
index 0000000..00ad289
--- /dev/null
@@ -0,0 +1,6 @@
+PKGDIR         ?= ../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS                = $(SYSTEMS_PLAIN)
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/bootstrap_custom/server/src/Makefile.platform b/l4/pkg/bootstrap_custom/server/src/Makefile.platform
new file mode 100644 (file)
index 0000000..e1601ec
--- /dev/null
@@ -0,0 +1,46 @@
+
+# ARM platforms
+SUPPORT_CC_arm-sa1000          := platform/sa1000.cc
+SUPPORT_CC_arm-pxa             := platform/pxa.cc
+SUPPORT_CC_arm-integrator      := platform/integrator.cc
+SUPPORT_CC_arm-rv              := platform/rv.cc
+SUPPORT_CC_arm-rv_pbx          := platform/rv.cc
+SUPPORT_CC_arm-rv_vexpress     := platform/rv_vexpress.cc
+SUPPORT_CC_arm-rv_vexpress_a15 := platform/rv_vexpress.cc
+SUPPORT_CC_arm-omap3evm        := platform/omap.cc
+SUPPORT_CC_arm-omap3_am33xx    := platform/omap.cc
+SUPPORT_CC_arm-beagleboard     := platform/omap.cc
+SUPPORT_CC_arm-pandaboard      := platform/omap.cc
+SUPPORT_CC_arm-omap5           := platform/omap.cc
+SUPPORT_CC_arm-tegra2          := platform/tegra2.cc
+SUPPORT_CC_arm-tegra3          := platform/tegra3.cc
+SUPPORT_CC_arm-imx21           := platform/imx.cc
+DEFAULT_RELOC_arm-imx21        := 0x00200000  # because of blob
+SUPPORT_CC_arm-imx35           := platform/imx.cc
+SUPPORT_CC_arm-imx51           := platform/imx.cc
+SUPPORT_CC_arm-imx6            := platform/imx.cc
+SUPPORT_CC_arm-om              := platform/om.cc
+SUPPORT_CC_arm-kirkwood        := platform/kirkwood.cc
+SUPPORT_CC_arm-rpi_a           := platform/rpi.cc
+SUPPORT_CC_arm-rpi_b           := platform/rpi.cc
+SUPPORT_CC_arm-exynos4         := platform/exynos.cc
+SUPPORT_CC_arm-exynos5         := platform/exynos.cc
+SUPPORT_CC_arm-zedboard        := platform/zynq.cc
+SUPPORT_CC_arm-parallella      := platform/zynq.cc
+SUPPORT_CC_arm-cubieboard2     := platform/sunxi.cc
+SUPPORT_CC_arm-armada38x       := platform/armada38x.cc
+
+# PPC
+SUPPORT_CC_ppc32-mpc5200       := platform/mpc5200.cc
+
+# Sparc
+SUPPORT_CC_sparc-leon3         := platform/leon3.cc
+
+# x86
+ifneq ($(BOOTSTRAP_DO_UEFI),y)
+SUPPORT_CC_x86-pc              := platform/x86_pc.cc
+SUPPORT_CC_amd64-pc            := platform/x86_pc.cc
+else
+SUPPORT_CC_x86-pc              := platform/x86_efi_pc.cc
+SUPPORT_CC_amd64-pc            := platform/x86_efi_pc.cc
+endif
diff --git a/l4/pkg/bootstrap_custom/server/src/README b/l4/pkg/bootstrap_custom/server/src/README
new file mode 100644 (file)
index 0000000..afef5a5
--- /dev/null
@@ -0,0 +1,70 @@
+
+bootstrap supports different boot modi.
+
+For x86:
+
+  1)
+     boostrap is started by a multiboot compliant bootloader and modules are
+     attached as multiboot modules. GRUB example:
+
+       kernel bootstrap arg1 args2 ...
+       module kernel
+       module sigma0
+       module roottask
+       module task1
+       ...
+
+   2)
+      bootstrap is started by a multiboot compliant bootloader but includes
+      all modules by itself. GRUB example:
+
+       kernel bootstrap_hello args...
+
+      For module specifications looks into modules.list
+
+   3)
+      bootstrap can boot from real-mode, esp. with pxelinux, i.e. it can be
+      booted via PXE. For that it also needs include all images.
+      This should also work with syslinux (e.g. from CDs/DVDs). (Note, grub
+      can also read is9660 filesystems.)
+
+   4)
+      bootstrap starts from protected mode but isn't started by a multiboot
+      compliant loader. Also needs to include all modules.
+
+For arm:
+
+   Just the single image mode, i.e. all modules packed into bootstrap.
+   Anything else doesn't make any sense (currently).
+
+
+Generating bootstrap in single-image-mode:
+
+ Call make with E=entryname, e.g.
+
+ $ make E=hello
+
+
+Local customization:
+
+ You can put a Makeconf.local file right into this directory
+ (bootstrap/server/src) where you can specify your own search paths etc.
+ Note that it is encouraged to have your local configuration in src/conf
+ rather than in this bootstrap directory.
+
+ Makeconf.local could look like this:
+
+  BOOTSTRAP_SEARCH_PATH_x86 := ../stuff:/home/joe/dev/l4/kernel/fiasco/build-ia32
+
+  KERN_ARM := build-arm
+
+  ifneq ($(PXA),)
+  KERN_ARM     := build-pxa
+  ARM_DRV_TYPE  = pxa
+  endif
+
+  KERN_PATH := /home/joe/dev/l4/kernel/fiasco/$(KERN_ARM)
+  BOOTSTRAP_SEARCH_PATH_arm = ../stuff:$(KERN_PATH):../../../../../bin/arm_sa
+
+  BOOTSTRAP_SEARCH_PATH     = $(BOOTSTRAP_SEARCH_PATH_$(ARCH))
+
diff --git a/l4/pkg/bootstrap_custom/server/src/base_critical.c b/l4/pkg/bootstrap_custom/server/src/base_critical.c
new file mode 100644 (file)
index 0000000..696b2aa
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * (c) 2008-2009 Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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 <l4/util/irq.h>
+#include "base_critical.h"
+
+static l4_umword_t flags;
+static l4_umword_t entry_count;
+
+void
+base_critical_enter(void)
+{
+  if (entry_count == 0)
+    {
+      l4util_flags_save(&flags);
+      l4util_cli();
+    }
+  entry_count++;
+}
+
+void
+base_critical_leave(void)
+{
+  entry_count--;
+  if (entry_count == 0)
+    l4util_flags_restore(&flags);
+}
+
diff --git a/l4/pkg/bootstrap_custom/server/src/base_critical.h b/l4/pkg/bootstrap_custom/server/src/base_critical.h
new file mode 100644 (file)
index 0000000..301c1a4
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef BASE_CRITICAL_H
+#define BASE_CRITICAL_H
+
+#include <l4/sys/compiler.h>
+
+EXTERN_C_BEGIN
+
+void base_critical_enter(void);
+void base_critical_leave(void);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/boot_modules.cc b/l4/pkg/bootstrap_custom/server/src/boot_modules.cc
new file mode 100644 (file)
index 0000000..2446967
--- /dev/null
@@ -0,0 +1,705 @@
+#include "support.h"
+#include "panic.h"
+#include <cassert>
+#include "mod_info.h"
+#ifdef COMPRESS
+#include "uncompress.h"
+#endif
+
+static char const Mod_reg[] = ".Module";
+char const *const Boot_modules::Mod_reg = ::Mod_reg;
+
+// get c if it is printable '.' else
+static char
+get_printable(int c)
+{
+  if (c < 32 || c >= 127)
+    return '.';
+  return c;
+}
+Region
+Boot_modules::mod_region(unsigned index, l4_addr_t start, l4_addr_t size,
+                         Region::Type type)
+{
+  return Region::start_size(start, size, ::Mod_reg,
+                            type, index);
+}
+
+void
+Boot_modules::merge_mod_regions()
+{
+  Region_list *regions = mem_manager->regions;
+  for (Region *r = regions->begin(); r != regions->end(); ++r)
+    {
+      if (r->name() == ::Mod_reg)
+        r->sub_type(0);
+    }
+
+  regions->optimize();
+}
+
+
+/**
+ * \brief move a boot module from src to dest.
+ * \param i The module index
+ * \param dest The destination address
+ * \param src  The source address
+ * \param size The size of the module in bytes
+ * \param overlap_check if true check for overlapping regions at
+ *                      the destination.
+ *
+ * The src and dest buffers may overlap, at the destination set size is
+ * rounded to the next page boundary.
+ */
+void
+Boot_modules::_move_module(unsigned i, void *_dest,
+                           void const *_src, unsigned long size,
+                           bool overlap_check)
+{
+  char *dest = (char *)_dest;
+  char const *src = (char const *)_src;
+
+  if (src == dest)
+    {
+      mem_manager->regions->add(Region::n(dest, dest + size,
+                                          ::Mod_reg, Region::Root, i));
+      return;
+    }
+
+  auto p = Platform_base::platform;
+  char const *vsrc = (char const *)p->to_virt((l4_addr_t)src);
+  char *vdest = (char *)p->to_virt((l4_addr_t)dest);
+
+  if (Verbose_load)
+    {
+      unsigned char c[5];
+      c[0] = get_printable(vsrc[0]);
+      c[1] = get_printable(vsrc[1]);
+      c[2] = get_printable(vsrc[2]);
+      c[3] = get_printable(vsrc[3]);
+      c[4] = 0;
+      printf("  moving module %02d { %lx, %lx } (%s) -> { %lx - %lx } [%ld]\n",
+             i, (unsigned long)src, (unsigned long)src + size - 1, c,
+             (unsigned long)dest, (unsigned long)dest + size - 1, size);
+
+      for (int a = 0; a < 0x100; a += 4)
+        printf("%08x%s", *(unsigned *)(vsrc + a), (a % 32 == 28) ? "\n" : " ");
+      printf("\n");
+    }
+  else
+    printf("  moving module %02d { %lx-%lx } -> { %lx-%lx } [%ld]\n",
+           i, (unsigned long)src, (unsigned long)src + size - 1,
+           (unsigned long)dest, (unsigned long)dest + size - 1, size);
+
+  if (!mem_manager->ram->contains(dest))
+    panic("Panic: Would move outside of RAM");
+
+  if (overlap_check)
+    {
+      Region *overlap = mem_manager->regions->find(dest);
+      if (overlap)
+        {
+          printf("ERROR: module target [%p-%p) overlaps\n",
+                 dest, dest + size - 1);
+          overlap->vprint();
+          mem_manager->regions->dump();
+          panic("cannot move module");
+        }
+    }
+  memmove(vdest, vsrc, size);
+  char *x = vdest + size;
+  memset(x, 0, l4_round_page(x) - x);
+  mem_manager->regions->add(Region::n(dest, dest + size,
+                                      ::Mod_reg, Region::Root, i));
+}
+
+/// sorter data for up to 256 modules (stores module indexes)
+static unsigned short mod_sorter[256];
+/// the first unused entry of the sorter
+static unsigned short const *mod_sorter_end = mod_sorter;
+
+/// add v to the sorter (using insert sort)
+template< typename CMP > void
+mod_insert_sorted(unsigned short v, CMP const &cmp)
+{
+  enum { Max_mods = sizeof(mod_sorter) / sizeof(mod_sorter[0]) };
+
+  if (mod_sorter_end >= mod_sorter + Max_mods)
+    panic("too much modules for module sorter");
+
+  unsigned short *i = mod_sorter;
+  unsigned short const *const e = mod_sorter_end;
+
+  for (; i < e; ++i)
+    {
+      if (cmp(v, *i))
+        {
+          memmove(i + 1, i, (e - i) * sizeof(*i));
+          break;
+        }
+    }
+  *i = v;
+  ++mod_sorter_end;
+}
+
+/// Compare start addresses for two modules
+struct Mbi_mod_cmp
+{
+  Boot_modules *m;
+  Mbi_mod_cmp(Boot_modules *m) : m(m) {}
+  bool operator () (unsigned l, unsigned r) const
+  { return m->module(l, false).start < m->module(r, false).start; }
+};
+
+/// calculate the total size of all modules (rounded to the next p2align)
+static unsigned long
+calc_modules_size(Boot_modules *mbi, unsigned p2align,
+                  unsigned min = 0, unsigned max = ~0U)
+{
+  unsigned long s = 0;
+  unsigned cnt = mbi->num_modules();
+  for (unsigned i = min; i < max && i < cnt; ++i)
+    s += l4_round_size(mbi->module(i).size(), p2align);
+
+  return s;
+}
+
+
+/**
+ * Move modules to another address.
+ *
+ * Source and destination regions may overlap.
+ */
+void
+Boot_modules::move_modules(unsigned long modaddr)
+{
+  unsigned count = num_modules();
+
+  // Remove regions for module contents from region list.
+  // The memory for the boot modules is marked as reserved up to now,
+  // however to not collide with the ELF binaries to be loaded we drop those
+  // regions here and add new reserved regions in move_modules() afterwards.
+  // NOTE: we must be sure that we do not need to allocate any memory from here
+  // to move_modules()
+  for (Region *i = mem_manager->regions->begin();
+      i < mem_manager->regions->end();)
+    if (i->name() == ::Mod_reg)
+      i = mem_manager->regions->remove(i);
+    else
+      ++i;
+
+  printf("  Moving up to %d modules behind %lx\n", count, modaddr);
+  unsigned long req_size = calc_modules_size(this, L4_PAGESHIFT);
+
+  // find a spot to insert the modules
+  mem_manager->ram->sort();
+  char *to = (char *)mem_manager->find_free_ram(req_size, modaddr);
+  if (!to)
+    {
+      printf("fatal: could not find free RAM region for modules\n"
+             "       need %lx bytes above %lx\n", req_size, modaddr);
+      mem_manager->ram->dump();
+      mem_manager->regions->dump();
+      exit (5);
+    }
+
+  // sort the modules according to the start address
+  for (unsigned i = 0; i < count; ++i)
+    mod_insert_sorted(i, Mbi_mod_cmp(this));
+
+  // move modules around ...
+  // The goal is to move all modules in a contiguous region in memory.
+  // The idea is to keep the order of the modules in memory and compact them
+  // into our target region. Therefore we split the modules into two groups.
+  // The first group needs to be moved to higher memory addresses to get to
+  // the target location and the second group needs to be moved backwards.
+
+  // Let's find the first module that needs to be moved backwards and record
+  // target address for this module.
+  unsigned end_fwd; // the index of the first module that needs to move backwards
+  char *cursor = to; // the target address for the first backwards module
+  for (end_fwd = 0; end_fwd < count; ++end_fwd)
+    {
+      Module mod = module(mod_sorter[end_fwd]);
+      if (cursor < mod.start)
+        break;
+
+      cursor += l4_round_page(mod.size());
+    }
+
+  // end_fwd is now the index of the first module that needs to move backwards
+  // cursor cursor is now the target address for the first backwards module
+
+  // move modules forwards, in reverse order so that overlapping is handled
+  // properly
+  char *end_fwd_addr = cursor;
+  for (unsigned i = end_fwd; i > 0; --i)
+    {
+      Module mod = module(mod_sorter[i - 1]);
+      end_fwd_addr -= l4_round_page(mod.size());
+      move_module(mod_sorter[i - 1], end_fwd_addr);
+    }
+
+  // move modules backwards, in normal order so that overlapping is handled
+  // properly
+  for (unsigned i = end_fwd; i < count; ++i)
+    {
+      Module mod = module(mod_sorter[i]);
+      move_module(mod_sorter[i], cursor);
+      cursor += l4_round_page(mod.size());
+    }
+
+  merge_mod_regions();
+}
+
+
+/*
+ * Code for IMAGE_MODE, modules are linked into bootstrap
+ */
+#ifdef IMAGE_MODE
+
+/// array of all module headers
+extern Mod_info _module_info_start[];
+/// the end of the module headers
+extern Mod_info _module_info_end[];
+
+namespace {
+/*
+ * Helper functions for modules
+ */
+
+/// number of linked modules
+static inline unsigned _num_modules()
+{ return _module_info_end - _module_info_start; }
+
+static inline char const *mod_cmdline(Mod_info const *mod)
+{ return (char const *)(l4_addr_t)mod->cmdline; }
+
+static inline char const *mod_name(Mod_info const *mod)
+{ return (char const *)(l4_addr_t)mod->name; }
+
+static inline char const *mod_start(Mod_info const *mod)
+{ return mod->start; }
+
+static inline Region mod_region(Mod_info const *mod, bool round = false,
+                                Region::Type type = Region::Boot)
+{
+  unsigned long sz = mod->size;
+  if (round)
+    sz = l4_round_page(sz);
+  return Region::array(mod_start(mod), sz,
+                       ::Mod_reg,
+                       type, mod - _module_info_start);
+}
+
+#ifdef COMPRESS // only used with compression
+static bool
+drop_mod_region(Mod_info const *mod)
+{
+  // remove the module region for now
+  for (Region *r = mem_manager->regions->begin();
+       r != mem_manager->regions->end();)
+    {
+      if (r->name() == ::Mod_reg
+          && r->sub_type() == mod - _module_info_start)
+        {
+          mem_manager->regions->remove(r);
+          return true;
+        }
+      else
+        ++r;
+    }
+
+  return false;
+}
+#endif
+
+static inline char const *mod_md5compr(Mod_info const *mod)
+{ return (char const *)(l4_addr_t)mod->md5sum_compr; }
+
+static inline char const *mod_md5(Mod_info const *mod)
+{ return (char const *)(l4_addr_t)mod->md5sum_uncompr; }
+
+static inline bool mod_compressed(Mod_info const *mod)
+{ return mod->size != mod->size_uncompressed; }
+
+static inline void
+print_mod(Mod_info const *mod)
+{
+  unsigned index = mod - _module_info_start;
+  printf("  mod%02u: %8p-%8p: %s\n",
+         index, mod_start(mod), mod_start(mod) + mod->size,
+         mod_name(mod));
+}
+
+#ifdef DO_CHECK_MD5
+#include <bsd/md5.h>
+
+static void check_md5(const char *name, u_int8_t *start, unsigned size,
+                      const char *md5sum)
+{
+  MD5_CTX md5ctx;
+  unsigned char digest[MD5_DIGEST_LENGTH];
+  char s[MD5_DIGEST_STRING_LENGTH];
+  static const char hex[] = "0123456789abcdef";
+  int j;
+
+  printf("  Checking checksum of %s ... ", name);
+
+  MD5Init(&md5ctx);
+  MD5Update(&md5ctx, start, size);
+  MD5Final(digest, &md5ctx);
+
+  for (j = 0; j < MD5_DIGEST_LENGTH; j++)
+    {
+      s[j + j] = hex[digest[j] >> 4];
+      s[j + j + 1] = hex[digest[j] & 0x0f];
+    }
+  s[j + j] = '\0';
+
+  if (strcmp(s, md5sum))
+    panic("\nmd5sum mismatch");
+  else
+    printf("Ok.\n");
+}
+#else // DO_CHECK_MD5
+static inline void check_md5(const char *, u_int8_t *, unsigned, const char *)
+{}
+#endif // ! DO_CHECK_MD5
+
+#ifdef COMPRESS
+static void
+decompress_mod(Mod_info *mod, l4_addr_t dest, Region::Type type = Region::Boot)
+{
+  unsigned long dest_size = mod->size_uncompressed;
+  if (!dest)
+    panic("fatal: cannot decompress module: %s (no memory)\n",
+          mod_name(mod));
+
+  if (!mem_manager->ram->contains(Region::n(dest, dest + dest_size)))
+    panic("fatal: module %s does not fit into RAM", mod_name(mod));
+
+  l4_addr_t image =
+    (l4_addr_t)decompress(mod_name(mod), (void*)mod_start(mod),
+                          (void*)dest, mod->size, mod->size_uncompressed);
+  if (image != dest)
+    panic("fatal cannot decompress module: %s (decompression error)\n",
+          mod_name(mod));
+
+  drop_mod_region(mod);
+
+  mod->start = (char *)dest;
+  mod->size = mod->size_uncompressed;
+  mem_manager->regions->add(mod_region(mod, true, type));
+}
+#endif // COMPRESS
+}
+
+
+void
+Boot_modules_image_mode::reserve()
+{
+  for (Mod_info *m = _module_info_start; m != _module_info_end; ++m)
+    {
+      m->start = (char const *)Platform_base::platform->to_phys((l4_addr_t)m->start);
+      mem_manager->regions->add(::mod_region(m));
+    }
+}
+
+
+/// Get module at index (decompress if needed)
+Boot_modules_image_mode::Module
+Boot_modules_image_mode::module(unsigned index, bool uncompress) const
+{
+  // want access to the module, if we have compression we need to decompress
+  // the module first
+  Mod_info *mod = _module_info_start + index;
+#ifdef COMPRESS
+  // we currently assume a module as compressed when the size != size_compressed
+  if (uncompress && mod_compressed(mod))
+    {
+      check_md5(mod_name(mod), (u_int8_t *)mod_start(mod),
+                mod->size, mod_md5compr(mod));
+
+      unsigned long dest_size = l4_round_page(mod->size_uncompressed);
+      decompress_mod(mod, mem_manager->find_free_ram_rev(dest_size));
+
+      check_md5(mod_name(mod), (u_int8_t *)mod_start(mod),
+                mod->size, mod_md5(mod));
+    }
+#else
+  (void)uncompress;
+#endif
+  Module m;
+  m.start   = mod->start;
+  m.end     = mod->start + mod->size;
+  m.cmdline = mod_name(mod);
+  return m;
+}
+
+unsigned
+Boot_modules_image_mode::num_modules() const
+{
+  return _num_modules();
+}
+
+#ifdef COMPRESS
+static void
+decomp_move_mod(Mod_info *mod, char *destbuf)
+{
+  if (mod_compressed(mod))
+    decompress_mod(mod, (l4_addr_t)destbuf, Region::Root);
+  else
+    {
+      memmove(destbuf, mod_start(mod), mod->size_uncompressed);
+#if 0 // cannot simply zero this out, this might overlap with
+      // the next module to decompress
+      l4_addr_t dest_size = l4_round_page( mod->size_uncompressed);
+
+      if (dest_size > mod->size_uncompressed)
+        memset((void *)(destbuf + mod->size_uncompressed), 0,
+            dest_size -  mod->size_uncompressed);
+#endif
+      drop_mod_region(mod);
+      mod->start = destbuf;
+      mem_manager->regions->add(mod_region(mod, true, Region::Root));
+    }
+  print_mod(mod);
+}
+
+void
+Boot_modules_image_mode::decompress_mods(unsigned mod_count, unsigned skip,
+                                         l4_addr_t total_size, l4_addr_t mod_addr)
+{
+  Mod_info *mod_info = _module_info_start;
+  Region_list *regions = mem_manager->regions;
+  assert (mod_count > skip);
+
+  printf("Compressed modules:\n");
+  for (Mod_info const *mod = mod_info; mod != _module_info_end;
+       ++mod)
+    if (mod_compressed(mod))
+      print_mod(mod);
+
+  // sort the modules according to the start address
+  for (unsigned i = skip; i < mod_count; ++i)
+    mod_insert_sorted(i, Mbi_mod_cmp(this));
+
+  // possibly decompress directly behind the end of the first module
+  // We can do this, when we start decompression from the last module
+  // and ensure that no decompressed module overlaps its compressed data
+  Mod_info const *m0 = &mod_info[mod_sorter[0]];
+  char const *rdest = l4_round_page(mod_start(m0) + m0->size);
+  char const *ldest = l4_trunc_page(mod_start(m0) - m0->size_uncompressed);
+
+  // try to find a free spot for decompressing the modules
+  char *destbuf = (char *)mem_manager->find_free_ram(total_size, mod_addr);
+  bool fwd = true;
+
+  if (!destbuf || destbuf > rdest)
+    {
+      // we found free memory behind the compressed modules, we try to find a
+      // spot overlapping with the compressed modules, to safe contiguous
+      // memory
+      char const *rpos = rdest;
+      char const *lpos = ldest;
+      for (unsigned i = 0; i < mod_count - skip; ++i)
+        {
+          Mod_info const *mod = &mod_info[mod_sorter[i]];
+          char const *mstart = mod_start(mod);
+          char const *mend = mod_start(mod) + mod->size;
+          // remove the module region for now
+          for (Region *r = regions->begin(); r != regions->end();)
+            {
+              if (r->name() == ::Mod_reg && r->sub_type() == mod - mod_info)
+                r = regions->remove(r);
+              else
+                ++r;
+            }
+
+          if (rpos < mend)
+            {
+              l4_addr_t delta = l4_round_page(mend) - rpos;
+              rpos += delta;
+              rdest += delta;
+            }
+
+          if (ldest && lpos + mod->size_uncompressed > mstart)
+            {
+              l4_addr_t delta = l4_round_page(lpos + mod->size_uncompressed - mstart);
+              if ((l4_addr_t)ldest > delta)
+                {
+                  lpos -= delta;
+                  ldest -= delta;
+                }
+              else
+                ldest = 0;
+            }
+
+          rpos += l4_round_page(mod->size_uncompressed);
+          lpos += l4_round_page(mod->size_uncompressed);
+        }
+
+      Region dest = Region::array(ldest, total_size);
+      destbuf = const_cast<char *>(ldest);
+      fwd = true;
+      if (!ldest || !mem_manager->ram->contains(dest) || regions->find(dest))
+        {
+          printf("  cannot decompress at %p, try %p\n", ldest, rdest);
+          dest = Region::array(rdest, total_size); // try the move behind version
+          destbuf = const_cast<char *>(rdest);
+          fwd = false;
+
+          if (!mem_manager->ram->contains(dest) || regions->find(dest))
+            {
+              destbuf = (char *)mem_manager->find_free_ram(total_size, (l4_addr_t)rdest);
+              printf("  cannot decompress at %p, use %p\n", rdest, destbuf);
+            }
+        }
+    }
+
+  if (!destbuf)
+    panic("fatal: cannot find memory to  decompress modules");
+
+  printf("Uncompressing modules (modaddr = %p (%s)):\n", destbuf,
+         fwd ? "forwards" : "backwards");
+  if (!fwd)
+    {
+      // advance to last module end
+      destbuf += total_size;
+
+      for (unsigned i = mod_count - skip; i > 0; --i)
+        {
+          Mod_info *mod = _module_info_start + mod_sorter[i - 1];
+          unsigned long dest_size = l4_round_page(mod->size_uncompressed);
+          destbuf -= dest_size;
+          decomp_move_mod(mod, destbuf);
+        }
+    }
+  else
+    {
+      for (unsigned i = 0; i < mod_count - skip; ++i)
+        {
+          Mod_info *mod = _module_info_start + mod_sorter[i];
+          unsigned long dest_size = l4_round_page(mod->size_uncompressed);
+          decomp_move_mod(mod, destbuf);
+          destbuf += dest_size;
+        }
+    }
+
+  // move modules 0-2 out of the way
+  for (unsigned i = 0; i < skip; ++i)
+    {
+      Mod_info *mod = _module_info_start + i;
+      Region mr = ::mod_region(mod);
+      for (Region *r = regions->begin(); r != regions->end(); ++r)
+        {
+          if (r->overlaps(mr) && r->name() != ::Mod_reg)
+            {
+              // overlaps with some non-module, assumingly an ELF region
+              // so move us out of the way
+              char *to = (char *)mem_manager->find_free_ram(mod->size);
+              if (!to)
+                {
+                  printf("fatal: could not find free RAM region for module\n"
+                         "       need %lx bytes\n", (unsigned long)mod->size);
+                  mem_manager->ram->dump();
+                  regions->dump();
+                  panic("\n");
+                }
+              move_module(i, to);
+              break;
+            }
+        }
+    }
+}
+#endif // COMPRESS
+
+/**
+ * Create the basic multi-boot structure in IMAGE_MODE
+ */
+l4util_mb_info_t *
+Boot_modules_image_mode::construct_mbi(unsigned long mod_addr)
+{
+  unsigned long mod_count = _num_modules();
+  unsigned long mbi_size = sizeof(l4util_mb_info_t);
+  mbi_size += sizeof(l4util_mb_mod_t) * mod_count;
+
+  enum { Skip_num_mods = 3 }; // skip fiasco, sigma0, and roottask
+  assert(mod_count >= Skip_num_mods);
+
+  for (Mod_info const *mod = _module_info_start; mod != _module_info_end;
+       ++mod)
+    mbi_size += round_wordsize(strlen(mod_cmdline(mod)) + 1);
+
+  l4util_mb_info_t *mbi = (l4util_mb_info_t *)mem_manager->find_free_ram(mbi_size);
+  if (!mbi)
+    panic("fatal: could not allocate MBI memory: %lu bytes\n", mbi_size);
+
+  Region_list *regions = mem_manager->regions;
+  regions->add(Region::start_size((l4_addr_t)mbi, mbi_size, ".mbi_rt",
+                                  Region::Root));
+  memset(mbi, 0, mbi_size);
+
+  l4util_mb_mod_t *mods = reinterpret_cast<l4util_mb_mod_t *>(mbi + 1);
+  char *mbi_strs = (char *)(mods + mod_count);
+
+  mbi->mods_count  = mod_count;
+  mbi->flags      |= L4UTIL_MB_MODS;
+  mbi->mods_addr   = (l4_addr_t)mods;
+
+
+  Mod_info *const mod_info = _module_info_start;
+  unsigned long total_size = 0;
+  for (Mod_info const *mod = mod_info + Skip_num_mods;
+       mod < _module_info_end;
+       ++mod)
+    {
+      total_size += l4_round_page(mod->size_uncompressed);
+      if (mod_compressed(mod))
+        check_md5(mod_name(mod), (u_int8_t*)mod_start(mod),
+                  mod->size, mod_md5compr(mod));
+    }
+
+#ifdef COMPRESS
+  if (mod_count > Skip_num_mods)
+    decompress_mods(mod_count, Skip_num_mods, total_size, mod_addr);
+  merge_mod_regions();
+#else // COMPRESS
+  move_modules(mod_addr);
+#endif // ! COMPRESS
+
+  for (unsigned i = 0; i < mod_count; ++i)
+    {
+      Mod_info const *mod = &_module_info_start[i];
+      check_md5(mod_name(mod), (u_int8_t*)mod_start(mod),
+                mod->size_uncompressed, mod_md5(mod));
+
+      if (char const *c = mod_cmdline(mod))
+        {
+          unsigned l = strlen(c) + 1;
+          mods[i].cmdline = (l4_addr_t)mbi_strs;
+          memcpy(mbi_strs, c, l);
+          mbi_strs += round_wordsize(l);
+        }
+
+      mods[i].mod_start = (l4_addr_t)mod_start(mod);
+      mods[i].mod_end   = (l4_addr_t)mod_start(mod) + mod->size;
+    }
+
+  return mbi;
+}
+
+
+void
+Boot_modules_image_mode::move_module(unsigned index, void *dest,
+                                     bool overlap_check)
+{
+  Mod_info *mod = &_module_info_start[index];
+  unsigned long size = mod->size;
+  _move_module(index, dest, mod_start(mod), size, overlap_check);
+  mod->start = (char *)dest;
+}
+
+#endif // IMAGE_MODE
+
diff --git a/l4/pkg/bootstrap_custom/server/src/build.pl b/l4/pkg/bootstrap_custom/server/src/build.pl
new file mode 100755 (executable)
index 0000000..3cc854f
--- /dev/null
@@ -0,0 +1,221 @@
+#! /usr/bin/perl -W
+#
+# (c) 2008-2009 Technische Universität Dresden
+# 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.
+#
+# Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+#
+
+use strict;
+
+BEGIN { unshift @INC, $ENV{L4DIR}.'/tool/lib'
+           if $ENV{L4DIR} && -d $ENV{L4DIR}.'/tool/lib/L4';}
+
+use Digest::MD5;
+use L4::ModList;
+
+
+my $cross_compile_prefix = $ENV{CROSS_COMPILE} || '';
+my $arch                 = $ENV{OPT_ARCH}     || "x86";
+
+my $module_path   = $ENV{SEARCHPATH}    || ".";
+my $prog_objcopy  = $ENV{OBJCOPY}       || "${cross_compile_prefix}objcopy";
+my $prog_cc       = $ENV{CC}            || "${cross_compile_prefix}gcc";
+my $prog_ld       = $ENV{LD}            || "${cross_compile_prefix}ld";
+my $prog_cp       = $ENV{PROG_CP}       || "cp";
+my $prog_gzip     = $ENV{PROG_GZIP}     || "gzip";
+my $compress      = $ENV{OPT_COMPRESS}  || 0;
+my $strip         = $ENV{OPT_STRIP}     || 1;
+my $output_dir    = $ENV{OUTPUT_DIR}    || '.';
+my $make_inc_file = $ENV{MAKE_INC_FILE} || "mod.make.inc";
+my $flags_cc      = $ENV{FLAGS_CC}      || '';
+
+my $modulesfile      = $ARGV[1];
+my $entryname        = $ARGV[2];
+
+sub usage()
+{
+  print STDERR "$0 modulefile entry\n";
+}
+
+# Write a string to a file, overwriting it.
+# 1:    filename
+# 2..n: Strings to write to the file
+sub write_to_file
+{
+  my $file = shift;
+
+  open(A, ">$file") || die "Cannot open $file!";
+  while ($_ = shift) {
+    print A;
+  }
+  close A;
+}
+
+sub first_word($)
+{
+  (split /\s+/, shift)[0]
+}
+
+# build object files from the modules
+sub build_obj($$$)
+{
+  my ($cmdline, $modname, $no_strip) = @_;
+  my $_file = first_word($cmdline);
+
+  my $file = L4::ModList::search_file($_file, $module_path)
+    || die "Cannot find file $_file! Used search path: $module_path";
+
+  printf STDERR "Merging image %s to %s [%dkB]\n",
+                $file, $modname, ((-s $file) + 1023) / 1024;
+  # make sure that the file isn't already compressed
+  system("$prog_gzip -dc $file > $modname.ugz 2> /dev/null");
+  $file = "$modname.ugz" if !$?;
+  system("$prog_objcopy -S $file $modname.obj 2> /dev/null")
+    if $strip && !$no_strip;
+  system("$prog_cp         $file $modname.obj")
+    if $? || !$strip || $no_strip;
+  my $uncompressed_size = -s "$modname.obj";
+
+  my $c_unc = Digest::MD5->new;
+  open(M, "$modname.obj") || die "Failed to open $modname.obj: $!";
+  $c_unc->addfile(*M);
+  close M;
+
+  system("$prog_gzip -9f $modname.obj && mv $modname.obj.gz $modname.obj")
+    if $compress;
+
+  my $c_compr = Digest::MD5->new;
+  open(M, "$modname.obj") || die "Failed to open $modname.obj: $!";
+  $c_compr->addfile(*M);
+  close M;
+
+  my $size = -s "$modname.obj";
+  my $md5_compr = $c_compr->hexdigest;
+  my $md5_uncompr = $c_unc->hexdigest;
+
+  my $section_attr = ($arch ne 'sparc' && $arch ne 'arm'
+       ? #'"a", @progbits' # Not Xen
+         '\"awx\", @progbits' # Xen
+       : '#alloc' );
+
+  write_to_file("$modname.extra.c",qq|
+    #include "mod_info.h"
+
+    extern char const _binary_${modname}_start[];
+
+    struct Mod_info const _binary_${modname}_info
+    __attribute__((section(".module_info"), aligned(4))) =
+    {
+      _binary_${modname}_start, $size, $uncompressed_size,
+      "$_file", "$cmdline",
+      "$md5_compr", "$md5_uncompr"
+    };
+
+    asm (".section .module_data, $section_attr           \\n"
+         ".p2align 12                                    \\n"
+         ".global _binary_${modname}_start               \\n"
+         "_binary_${modname}_start:                      \\n"
+         ".incbin \\"$modname.obj\\"                     \\n"
+         "_binary_${modname}_end:                        \\n");
+  |);
+
+  system("$prog_cc $flags_cc -c -o $modname.bin $modname.extra.c");
+  die "Assembling $modname failed" if $?;
+  unlink("$modname.extra.c", "$modname.obj", "$modname.ugz");
+}
+
+sub build_mbi_modules_obj($@)
+{
+  my $cmdline = shift;
+  my @mods = @_;
+  my $asm_string;
+
+  # generate mbi module structures
+  write_to_file("mbi_modules.c", qq|char const _mbi_cmdline[] = "$cmdline";|);
+  system("$prog_cc $flags_cc -c -o mbi_modules.bin mbi_modules.c");
+  die "Compiling mbi_modules.bin failed" if $?;
+  unlink("mbi_modules.c");
+
+}
+
+sub build_objects(@)
+{
+  my %entry = @_;
+  my @mods = @{$entry{mods}};
+  my $objs = "$output_dir/mbi_modules.bin";
+  
+  unlink($make_inc_file);
+
+  # generate module-names
+  for (my $i = 0; $i < @mods; $i++) {
+    $mods[$i]->{modname} = sprintf "mod%02d", $i;
+  }
+
+  build_mbi_modules_obj($entry{bootstrap}{cmdline}, @mods);
+
+  for (my $i = 0; $i < @mods; $i++) {
+    build_obj($mods[$i]->{cmdline}, $mods[$i]->{modname},
+             $mods[$i]->{type} =~ /.+-nostrip$/);
+    $objs .= " $output_dir/$mods[$i]->{modname}.bin";
+  }
+
+  my $make_inc_str = "MODULE_OBJECT_FILES += $objs\n";
+  $make_inc_str   .= "MOD_ADDR            := $entry{modaddr}"
+    if defined $entry{modaddr};
+
+  write_to_file($make_inc_file, $make_inc_str);
+}
+
+
+sub list_files(@)
+{
+  my %entry = @_;
+  print join(' ', map { L4::ModList::search_file_or_die(first_word($_->{cmdline}),
+                                                                   $module_path) }
+                      @{$entry{mods}}), "\n";
+}
+
+sub dump_entry(@)
+{
+  my %entry = @_;
+  print "modaddr=$entry{modaddr}\n" if defined $entry{modaddr};
+  print "$entry{bootstrap}{command}\n";
+  print "$entry{bootstrap}{cmdline}\n";
+  print join("\n", map { $_->{cmdline} } @{$entry{mods}}), "\n";
+  print join(' ', map { $_ } @{$entry{files}}), "\n";
+}
+
+# ------------------------------------------------------------------------
+
+if (!$ARGV[2]) {
+  print STDERR "Error: Invalid usage!\n";
+  usage();
+  exit 1;
+}
+
+if (defined $output_dir)
+  {
+    if (not -d $output_dir)
+      {
+        mkdir $output_dir || die "Cannot create '$output_dir': $!";
+      }
+    chdir $output_dir || die "Cannot change to directory '$output_dir': $!";
+  }
+
+my %entry = L4::ModList::get_module_entry($modulesfile, $entryname);
+
+if ($ARGV[0] eq 'build')
+  {
+    build_objects(%entry);
+  }
+elsif ($ARGV[0] eq 'list')
+  {
+    list_files(%entry);
+  }
+elsif ($ARGV[0] eq 'dump')
+  {
+    dump_entry(%entry);
+  }
diff --git a/l4/pkg/bootstrap_custom/server/src/exec.c b/l4/pkg/bootstrap_custom/server/src/exec.c
new file mode 100644 (file)
index 0000000..2ca7a92
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * \file       bootstrap/server/src/exec.c
+ * \brief      ELF loader
+ * 
+ * \date       2004
+ * \author     Frank Mehnert <fm3@os.inf.tu-dresden.de>,
+ *             Torsten Frenzel <frenzel@os.inf.tu-dresden.de> */
+
+/*
+ * (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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <alloca.h>
+
+#include <l4/util/elf.h>
+
+#include "exec.h"
+
+int
+exec_load_elf(exec_handler_func_t *handler,
+             void *handle, const char **error_msg, l4_addr_t *entry)
+{
+  exec_task_t *t = handle;
+  ElfW(Ehdr) *x = t->mod_start;
+  ElfW(Phdr) *phdr, *ph;
+  int i;
+
+  /* Read the ELF header.  */
+
+  if (!l4util_elf_check_magic(x))
+    return *error_msg="no ELF executable", -1;
+
+  /* Make sure the file is of the right architecture.  */
+  if (!l4util_elf_check_arch(x))
+    return *error_msg="wrong ELF architecture", -1;
+
+  *entry = (l4_addr_t) x->e_entry;
+
+  phdr   = l4util_elf_phdr(x);
+
+  for (i = 0; i < x->e_phnum; i++)
+    {
+      ph = (ElfW(Phdr)*)((l4_addr_t)phdr + i * x->e_phentsize);
+      if (ph->p_type == PT_LOAD)
+       {
+         exec_sectype_t type = EXEC_SECTYPE_ALLOC |
+           EXEC_SECTYPE_LOAD;
+         if (ph->p_flags & PF_R) type |= EXEC_SECTYPE_READ;
+         if (ph->p_flags & PF_W) type |= EXEC_SECTYPE_WRITE;
+         if (ph->p_flags & PF_X) type |= EXEC_SECTYPE_EXECUTE;
+         (*handler)(handle,
+                   ph->p_offset, ph->p_filesz,
+                   ph->p_paddr, ph->p_vaddr, ph->p_memsz, type);
+       }
+    }
+
+  return *error_msg="", 0;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/exec.h b/l4/pkg/bootstrap_custom/server/src/exec.h
new file mode 100644 (file)
index 0000000..5d7bdd0
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *               Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef EXEC_H
+#define EXEC_H
+
+#include "types.h"
+#include <l4/sys/compiler.h>
+#include <l4/util/mb_info.h>
+
+typedef int exec_sectype_t;
+
+#define EXEC_SECTYPE_READ              ((exec_sectype_t)0x000001)
+#define EXEC_SECTYPE_WRITE             ((exec_sectype_t)0x000002)
+#define EXEC_SECTYPE_EXECUTE           ((exec_sectype_t)0x000004)
+#define EXEC_SECTYPE_ALLOC             ((exec_sectype_t)0x000100)
+#define EXEC_SECTYPE_LOAD              ((exec_sectype_t)0x000200)
+
+
+typedef struct
+{
+  void *mod_start;
+  l4util_mb_mod_t *mod;
+  unsigned type;
+  l4_addr_t begin;     /* program begin */
+  l4_addr_t end;       /* program end */
+} exec_task_t;
+
+
+typedef int exec_handler_func_t(void *handle,
+                                 l4_addr_t file_ofs, l4_size_t file_size,
+                                 l4_addr_t mem_addr, l4_addr_t v_addr,
+                                 l4_size_t mem_size,
+                                 exec_sectype_t section_type);
+
+EXTERN_C_BEGIN
+
+int exec_load_elf(exec_handler_func_t *handler_exec,
+                 void *handle, const char **error_msg, l4_addr_t *entry);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/gunzip.c b/l4/pkg/bootstrap_custom/server/src/gunzip.c
new file mode 100644 (file)
index 0000000..9c15df5
--- /dev/null
@@ -0,0 +1,1262 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Most of this file was originally the source file "inflate.c", written
+ * by Mark Adler.  It has been very heavily modified.  In particular, the
+ * original would run through the whole file at once, and this version can
+ * be stopped and restarted on any boundary during the decompression process.
+ *
+ * The license and header comments that file are included here.
+ */
+
+/* inflate.c -- Not copyrighted 1992 by Mark Adler
+   version c10p1, 10 January 1993 */
+
+/* You can do whatever you like with this source file, though I would
+   prefer that if you modify it and redistribute it that you include
+   comments to that effect with your name and the date.  Thank you.
+ */
+
+/*
+   Inflate deflated (PKZIP's method 8 compressed) data.  The compression
+   method searches for as much of the current string of bytes (up to a
+   length of 258) in the previous 32K bytes.  If it doesn't find any
+   matches (of at least length 3), it codes the next byte.  Otherwise, it
+   codes the length of the matched string and its distance backwards from
+   the current position.  There is a single Huffman code that codes both
+   single bytes (called "literals") and match lengths.  A second Huffman
+   code codes the distance information, which follows a length code.  Each
+   length or distance code actually represents a base value and a number
+   of "extra" (sometimes zero) bits to get to add to the base value.  At
+   the end of each deflated block is a special end-of-block (EOB) literal/
+   length code.  The decoding process is basically: get a literal/length
+   code; if EOB then done; if a literal, emit the decoded byte; if a
+   length then get the distance and emit the referred-to bytes from the
+   sliding window of previously emitted data.
+
+   There are (currently) three kinds of inflate blocks: stored, fixed, and
+   dynamic.  The compressor deals with some chunk of data at a time, and
+   decides which method to use on a chunk-by-chunk basis.  A chunk might
+   typically be 32K or 64K.  If the chunk is uncompressible, then the
+   "stored" method is used.  In this case, the bytes are simply stored as
+   is, eight bits per byte, with none of the above coding.  The bytes are
+   preceded by a count, since there is no longer an EOB code.
+
+   If the data is compressible, then either the fixed or dynamic methods
+   are used.  In the dynamic method, the compressed data is preceded by
+   an encoding of the literal/length and distance Huffman codes that are
+   to be used to decode this block.  The representation is itself Huffman
+   coded, and so is preceded by a description of that code.  These code
+   descriptions take up a little space, and so for small blocks, there is
+   a predefined set of codes, called the fixed codes.  The fixed method is
+   used if the block codes up smaller that way (usually for quite small
+   chunks), otherwise the dynamic method is used.  In the latter case, the
+   codes are customized to the probabilities in the current block, and so
+   can code it much better than the pre-determined fixed codes.
+
+   The Huffman codes themselves are decoded using a mutli-level table
+   lookup, in order to maximize the speed of decoding plus the speed of
+   building the decoding tables.  See the comments below that precede the
+   lbits and dbits tuning parameters.
+ */
+
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarly, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+#ifndef NO_DECOMPRESSION
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "gunzip.h"
+
+unsigned int filepos;
+unsigned int filemax;
+unsigned int fsmax;     /* max size of fs/readable media */
+
+grub_error_t errnum;
+
+/* whether to show decompression progress or not */
+enum { do_show_progress = 1 };
+
+/* so we can disable decompression  */
+int no_decompression = 0;
+
+/* used to tell if "read" should be redirected to "gunzip_read" */
+unsigned int compressed_file;
+
+/* internal variables only */
+static unsigned int gzip_data_offset;
+static int gzip_filepos;
+static int gzip_filemax;
+static int gzip_fsmax;
+static int saved_filepos;
+static unsigned long gzip_crc;
+
+/* internal extra variables for use of inflate code */
+static int block_type;
+static unsigned int block_len;
+static int last_block;
+static int code_state;
+
+
+/* Function prototypes */
+static void initialize_tables (void);
+
+static void show_progress(int done, int len)
+{
+  int r = printf("%lld%%", ((unsigned long long)done * 100) / len);
+  while (r-- > 0)
+    putchar('\b');
+  fflush(NULL);
+}
+
+/*
+ *  Linear allocator.
+ */
+
+static unsigned long linalloc_topaddr;
+
+static void *
+linalloc (int size)
+{
+  extern void *lin_alloc_buffer;
+  unsigned long newaddr = (linalloc_topaddr - size) & ~3;
+  if (newaddr < (unsigned long)lin_alloc_buffer)
+    panic("Out of memory while uncompressing");
+  linalloc_topaddr = newaddr;
+  return (void *) linalloc_topaddr;
+}
+
+static void
+reset_linalloc (void)
+{
+  linalloc_topaddr = RAW_ADDR (UPPER_MEM_LINALLOC);
+}
+
+
+/* internal variable swap function */
+static void
+gunzip_swap_values (void)
+{
+  register int itmp;
+
+  /* swap filepos */
+  itmp = filepos;
+  filepos = gzip_filepos;
+  gzip_filepos = itmp;
+
+  /* swap filemax */
+  itmp = filemax;
+  filemax = gzip_filemax;
+  gzip_filemax = itmp;
+
+  /* swap fsmax */
+  itmp = fsmax;
+  fsmax = gzip_fsmax;
+  gzip_fsmax = itmp;
+}
+
+
+/* internal function for eating variable-length header fields */
+static int
+bad_field (int len)
+{
+  unsigned char ch = 1;
+  int not_retval = 1;
+
+  do
+    {
+      if (len >= 0)
+       {
+         if (!(len--))
+           break;
+       }
+      else
+       {
+         if (!ch)
+           break;
+       }
+    }
+  while ((not_retval = grub_read (&ch, 1)) == 1);
+
+  return (!not_retval);
+}
+
+
+/* Little-Endian defines for the 2-byte magic number for gzip files */
+#define GZIP_HDR_LE      0x8B1F
+#define OLD_GZIP_HDR_LE  0x9E1F
+
+/* Compression methods (see algorithm.doc) */
+#define STORED      0
+#define COMPRESSED  1
+#define PACKED      2
+#define LZHED       3
+/* methods 4 to 7 reserved */
+#define DEFLATED    8
+#define MAX_METHODS 9
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01      /* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02      /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04      /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08      /* bit 3 set: original file name present */
+#define COMMENT      0x10      /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20      /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0      /* bit 6,7:   reserved */
+
+#define UNSUPP_FLAGS (CONTINUATION|ENCRYPTED|RESERVED)
+
+/* inflate block codes */
+#define INFLATE_STORED    0
+#define INFLATE_FIXED     1
+#define INFLATE_DYNAMIC   2
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+/*
+ *  Window Size
+ *
+ *  This must be a power of two, and at least 32K for zip's deflate method
+ */
+
+#define WSIZE 0x8000
+
+
+int
+gunzip_test_header (void)
+{
+  unsigned char buf[10] __attribute__((aligned(4)));
+  
+  /* "compressed_file" is already reset to zero by this point */
+
+  /*
+   *  This checks if the file is gzipped.  If a problem occurs here
+   *  (other than a real error with the disk) then we don't think it
+   *  is a compressed file, and simply mark it as such.
+   */
+  if (no_decompression
+      || grub_read (buf, 10) != 10
+      || ((*((unsigned short *) buf) != GZIP_HDR_LE)
+         && (*((unsigned short *) buf) != OLD_GZIP_HDR_LE)))
+    {
+      filepos = 0;
+      return ! errnum;
+    }
+
+  /*
+   *  This does consistency checking on the header data.  If a
+   *  problem occurs from here on, then we have corrupt or otherwise
+   *  bad data, and the error should be reported to the user.
+   */
+  if (buf[2] != DEFLATED
+      || (buf[3] & UNSUPP_FLAGS)
+      || ((buf[3] & EXTRA_FIELD)
+         && (grub_read (buf, 2) != 2
+             || bad_field (*((unsigned short *) buf))))
+      || ((buf[3] & ORIG_NAME) && bad_field (-1))
+      || ((buf[3] & COMMENT) && bad_field (-1)))
+    {
+      if (! errnum)
+       errnum = ERR_BAD_GZIP_HEADER;
+      
+      return 0;
+    }
+
+  gzip_data_offset = filepos;
+  
+  filepos = filemax - 8;
+  
+  if (grub_read (buf, 8) != 8)
+    {
+      if (! errnum)
+       errnum = ERR_BAD_GZIP_HEADER;
+      
+      return 0;
+    }
+
+  gzip_crc = *((unsigned long *) buf);
+  gzip_fsmax = gzip_filemax = *((unsigned long *) (buf + 4));
+
+  initialize_tables ();
+
+  compressed_file = 1;
+  gunzip_swap_values ();
+  /*
+   *  Now "gzip_*" values refer to the compressed data.
+   */
+
+  filepos = 0;
+
+  return 1;
+}
+
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model).
+   Valid extra bits are 0..13.  e == 15 is EOB (end of block), e == 16
+   means that v is a literal, 16 < e < 32 means that v is a pointer to
+   the next table, which codes e - 16 bits, and lastly e == 99 indicates
+   an unused code.  If a code with e == 99 is looked up, this implies an
+   error in the data. */
+struct huft
+{
+  uch e;                       /* number of extra bits or operation */
+  uch b;                       /* number of bits in this code or subcode */
+  union
+    {
+      ush n;                   /* literal, length base, or distance base */
+      struct huft *t;          /* pointer to next level of table */
+    }
+  v;
+};
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+   stream to find repeated byte strings.  This is implemented here as a
+   circular buffer.  The index is updated simply by incrementing and then
+   and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area.  It is assumed
+   to be usable as if it were declared "uch slide[32768];" or as just
+   "uch *slide;" and then malloc'ed in the latter case.  The definition
+   must be in unzip.h, included above. */
+
+
+/* sliding window in uncompressed data */
+static uch slide[WSIZE];
+
+/* current position in slide */
+static unsigned wp;
+
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static unsigned bitorder[] =
+{                              /* Order of the bit length code lengths */
+  16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ush cplens[] __attribute__((aligned(4))) =
+{                              /* Copy lengths for literal codes 257..285 */
+  3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+  35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+       /* note: see note #13 above about the 258 in this list. */
+static ush cplext[] __attribute__((aligned(4))) =
+{                              /* Extra bits for literal codes 257..285 */
+  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+  3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99};      /* 99==invalid */
+static ush cpdist[] __attribute__((aligned(4))) =
+{                              /* Copy offsets for distance codes 0..29 */
+  1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+  257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+  8193, 12289, 16385, 24577};
+static ush cpdext[] __attribute__((aligned(4))) =
+{                              /* Extra bits for distance codes */
+  0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+  7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+  12, 12, 13, 13};
+
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+static int lbits = 9;          /* bits in base literal/length lookup table */
+static int dbits = 6;          /* bits in base distance lookup table */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16                        /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288              /* maximum number of codes in any set */
+
+
+static unsigned hufts;         /* track memory usage */
+
+
+/* Macros for inflate() bit peeking and grabbing.
+   The usage is:
+
+        NEEDBITS(j)
+        x = b & mask_bits[j];
+        DUMPBITS(j)
+
+   where NEEDBITS makes sure that b has at least j bits in it, and
+   DUMPBITS removes the bits from b.  The macros use the variable k
+   for the number of bits in b.  Normally, b and k are register
+   variables for speed, and are initialized at the beginning of a
+   routine that uses these macros from a global bit buffer and count.
+
+   If we assume that EOB will be the longest code, then we will never
+   ask for bits with NEEDBITS that are beyond the end of the stream.
+   So, NEEDBITS should not read any more bytes than are needed to
+   meet the request.  Then no bytes need to be "returned" to the buffer
+   at the end of the last block.
+
+   However, this assumption is not true for fixed blocks--the EOB code
+   is 7 bits, but the other literal/length codes can be 8 or 9 bits.
+   (The EOB code is shorter than other codes because fixed blocks are
+   generally short.  So, while a block always has an EOB, many other
+   literal/length codes have a significantly lower probability of
+   showing up at all.)  However, by making the first table have a
+   lookup of seven bits, the EOB code will be found in that first
+   lookup, and so will not require that too many bits be pulled from
+   the stream.
+ */
+
+static ulg bb;                 /* bit buffer */
+static unsigned bk;            /* bits in bit buffer */
+
+static ush mask_bits[] =
+{
+  0x0000,
+  0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+  0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+#define NEEDBITS(n) do {while(k<(n)){b|=((ulg)get_byte())<<k;k+=8;}} while (0)
+#define DUMPBITS(n) do {b>>=(n);k-=(n);} while (0)
+
+#define INBUFSIZ  0x2000
+
+static unsigned char inbuf[INBUFSIZ];
+static int bufloc;
+
+static int
+get_byte (void)
+{
+  if (filepos == gzip_data_offset || bufloc == INBUFSIZ)
+    {
+      bufloc = 0;
+      grub_read (inbuf, INBUFSIZ);
+    }
+
+  return inbuf[bufloc++];
+}
+
+/* decompression global pointers */
+static struct huft *tl;                /* literal/length code table */
+static struct huft *td;                /* distance code table */
+static int bl;                 /* lookup bits for tl */
+static int bd;                 /* lookup bits for td */
+
+
+/* more function prototypes */
+static int huft_build (unsigned *, unsigned, unsigned, ush *, ush *,
+                      struct huft **, int *);
+static int inflate_codes_in_window (void);
+
+
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return zero on success, one if
+   the given code set is incomplete (the tables are still built in this
+   case), two if the input is invalid (all zero length codes or an
+   oversubscribed set of lengths), and three if not enough memory. */
+
+static int
+huft_build (unsigned *b,       /* code lengths in bits (all assumed <= BMAX) */
+           unsigned n,         /* number of codes (assumed <= N_MAX) */
+           unsigned s,         /* number of simple-valued codes (0..s-1) */
+           ush * d,            /* list of base values for non-simple codes */
+           ush * e,            /* list of extra bits for non-simple codes */
+           struct huft **t,    /* result: starting table */
+           int *m)             /* maximum lookup bits, returns actual */
+{
+  unsigned a;                  /* counter for codes of length k */
+  unsigned c[BMAX + 1];                /* bit length count table */
+  unsigned f;                  /* i repeats in table every f entries */
+  int g;                       /* maximum code length */
+  int h;                       /* table level */
+  register unsigned i;         /* counter, current code */
+  register unsigned j;         /* counter */
+  register int k;              /* number of bits in current code */
+  int l;                       /* bits per table (returned in m) */
+  register unsigned *p;                /* pointer into c[], b[], or v[] */
+  register struct huft *q;     /* points to current table */
+  struct huft r;               /* table entry for structure assignment */
+  struct huft *u[BMAX];                /* table stack */
+  unsigned v[N_MAX];           /* values in order of bit length */
+  register int w;              /* bits before this table == (l * h) */
+  unsigned x[BMAX + 1];                /* bit offsets, then code stack */
+  unsigned *xp;                        /* pointer into x */
+  int y;                       /* number of dummy codes added */
+  unsigned z;                  /* number of entries in current table */
+
+  /* Generate counts for each bit length */
+  memset ((char *) c, 0, sizeof (c));
+  p = b;
+  i = n;
+  do
+    {
+      c[*p]++;                 /* assume all entries <= BMAX */
+      p++;                     /* Can't combine with above line (Solaris bug) */
+    }
+  while (--i);
+  if (c[0] == n)               /* null input--all zero length codes */
+    {
+      *t = (struct huft *) NULL;
+      *m = 0;
+      return 0;
+    }
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                       /* minimum code length */
+  if ((unsigned) l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                       /* maximum code length */
+  if ((unsigned) l > i)
+    l = i;
+  *m = l;
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return 2;                        /* bad input: more codes than bits */
+  if ((y -= c[i]) < 0)
+    return 2;
+  c[i] += y;
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;
+  xp = x + 2;
+  while (--i)
+    {                          /* note that i == g from above */
+      *xp++ = (j += *p++);
+    }
+
+  /* Make a table of values in order of bit lengths */
+  p = b;
+  i = 0;
+  do
+    {
+      if ((j = *p++) != 0)
+       v[x[j]++] = i;
+    }
+  while (++i < n);
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                        /* first Huffman code is zero */
+  p = v;                       /* grab values in bit order */
+  h = -1;                      /* no tables yet--level -1 */
+  w = -l;                      /* bits decoded == (l * h) */
+  u[0] = (struct huft *) NULL; /* just to keep compilers happy */
+  q = (struct huft *) NULL;    /* ditto */
+  z = 0;                       /* ditto */
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+    {
+      a = c[k];
+      while (a--)
+       {
+         /* here i is the Huffman code of length k bits for value *p */
+         /* make tables up to required level */
+         while (k > w + l)
+           {
+             h++;
+             w += l;           /* previous table always l bits */
+
+             /* compute minimum size table less than or equal to l bits */
+             z = (z = g - w) > (unsigned) l ? l : z;   /* upper limit on table size */
+             if ((f = 1 << (j = k - w)) > a + 1)       /* try a k-w bit table */
+               {               /* too few codes for k-w bit table */
+                 f -= a + 1;   /* deduct codes from patterns left */
+                 xp = c + k;
+                 while (++j < z)       /* try smaller tables up to z bits */
+                   {
+                     if ((f <<= 1) <= *++xp)
+                       break;  /* enough codes to use up j bits */
+                     f -= *xp; /* else deduct codes from patterns */
+                   }
+               }
+             z = 1 << j;       /* table entries for j-bit table */
+
+             /* allocate and link in new table */
+             q = (struct huft *) linalloc ((z + 1) * sizeof (struct huft));
+
+             hufts += z + 1;   /* track memory usage */
+             *t = q + 1;       /* link to list for huft_free() */
+             *(t = &(q->v.t)) = (struct huft *) NULL;
+             u[h] = ++q;       /* table starts after link */
+
+             /* connect to last table, if there is one */
+             if (h)
+               {
+                 x[h] = i;     /* save pattern for backing up */
+                 r.b = (uch) l;        /* bits to dump before this table */
+                 r.e = (uch) (16 + j);         /* bits in this table */
+                 r.v.t = q;    /* pointer to this table */
+                 j = i >> (w - l);     /* (get around Turbo C bug) */
+                 u[h - 1][j] = r;      /* connect to last table */
+               }
+           }
+
+         /* set up table entry in r */
+         r.b = (uch) (k - w);
+         if (p >= v + n)
+           r.e = 99;           /* out of values--invalid code */
+         else if (*p < s)
+           {
+             r.e = (uch) (*p < 256 ? 16 : 15);         /* 256 is end-of-block code */
+             r.v.n = (ush) (*p);       /* simple code is just the value */
+             p++;              /* one compiler does not like *p++ */
+           }
+         else
+           {
+             r.e = (uch) e[*p - s];    /* non-simple--look up in lists */
+             r.v.n = d[*p++ - s];
+           }
+
+         /* fill code-like entries with r */
+         f = 1 << (k - w);
+         for (j = i >> w; j < z; j += f)
+           q[j] = r;
+
+         /* backwards increment the k-bit code i */
+         for (j = 1 << (k - 1); i & j; j >>= 1)
+           i ^= j;
+         i ^= j;
+
+         /* backup over finished tables */
+         while ((i & ((1 << w) - 1)) != x[h])
+           {
+             h--;              /* don't need to update q */
+             w -= l;
+           }
+       }
+    }
+
+  /* Return true (1) if we were given an incomplete table */
+  return y != 0 && g != 1;
+}
+
+
+/*
+ *  inflate (decompress) the codes in a deflated (compressed) block.
+ *  Return an error code or zero if it all goes ok.
+ */
+
+static unsigned inflate_n, inflate_d;
+
+static int
+inflate_codes_in_window (void)
+{
+  register unsigned e;         /* table entry flag/number of extra bits */
+  unsigned n, d;               /* length and index for copy */
+  unsigned w;                  /* current window position */
+  struct huft *t;              /* pointer to table entry */
+  unsigned ml, md;             /* masks for bl and bd bits */
+  register ulg b;              /* bit buffer */
+  register unsigned k;         /* number of bits in bit buffer */
+
+  /* make local copies of globals */
+  d = inflate_d;
+  n = inflate_n;
+  b = bb;                      /* initialize bit buffer */
+  k = bk;
+  w = wp;                      /* initialize window position */
+
+  /* inflate the coded data */
+  ml = mask_bits[bl];          /* precompute masks for speed */
+  md = mask_bits[bd];
+  for (;;)                     /* do until end of block */
+    {
+      if (!code_state)
+       {
+         NEEDBITS ((unsigned) bl);
+         if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
+           do
+             {
+               if (e == 99)
+                 {
+                   errnum = ERR_BAD_GZIP_DATA;
+                   return 0;
+                 }
+               DUMPBITS (t->b);
+               e -= 16;
+               NEEDBITS (e);
+             }
+           while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
+         DUMPBITS (t->b);
+
+         if (e == 16)          /* then it's a literal */
+           {
+             slide[w++] = (uch) t->v.n;
+             if (w == WSIZE)
+               break;
+           }
+         else
+           /* it's an EOB or a length */
+           {
+             /* exit if end of block */
+             if (e == 15)
+               {
+                 block_len = 0;
+                 break;
+               }
+
+             /* get length of block to copy */
+             NEEDBITS (e);
+             n = t->v.n + ((unsigned) b & mask_bits[e]);
+             DUMPBITS (e);
+
+             /* decode distance of block to copy */
+             NEEDBITS ((unsigned) bd);
+             if ((e = (t = td + ((unsigned) b & md))->e) > 16)
+               do
+                 {
+                   if (e == 99)
+                     {
+                       errnum = ERR_BAD_GZIP_DATA;
+                       return 0;
+                     }
+                   DUMPBITS (t->b);
+                   e -= 16;
+                   NEEDBITS (e);
+                 }
+               while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e)
+                      > 16);
+             DUMPBITS (t->b);
+             NEEDBITS (e);
+             d = w - t->v.n - ((unsigned) b & mask_bits[e]);
+             DUMPBITS (e);
+             code_state++;
+           }
+       }
+
+      if (code_state)
+       {
+         /* do the copy */
+         do
+           {
+             n -= (e = (e = WSIZE - ((d &= WSIZE - 1) > w ? d : w)) > n ? n
+                   : e);
+             if (w - d >= e)
+               {
+                 memmove (slide + w, slide + d, e);
+                 w += e;
+                 d += e;
+               }
+             else
+               /* purposefully use the overlap for extra copies here!! */
+               {
+                 while (e--)
+                   slide[w++] = slide[d++];
+               }
+             if (w == WSIZE)
+               break;
+           }
+         while (n);
+
+         if (!n)
+           code_state--;
+
+         /* did we break from the loop too soon? */
+         if (w == WSIZE)
+           break;
+       }
+    }
+
+  /* restore the globals from the locals */
+  inflate_d = d;
+  inflate_n = n;
+  wp = w;                      /* restore global window pointer */
+  bb = b;                      /* restore global bit buffer */
+  bk = k;
+
+  return !block_len;
+}
+
+
+/* get header for an inflated type 0 (stored) block. */
+
+static void
+init_stored_block (void)
+{
+  register ulg b;              /* bit buffer */
+  register unsigned k;         /* number of bits in bit buffer */
+
+  /* make local copies of globals */
+  b = bb;                      /* initialize bit buffer */
+  k = bk;
+
+  /* go to byte boundary */
+  DUMPBITS (k & 7);
+
+  /* get the length and its complement */
+  NEEDBITS (16);
+  block_len = ((unsigned) b & 0xffff);
+  DUMPBITS (16);
+  NEEDBITS (16);
+  if (block_len != (unsigned) ((~b) & 0xffff))
+    errnum = ERR_BAD_GZIP_DATA;
+  DUMPBITS (16);
+
+  /* restore global variables */
+  bb = b;
+  bk = k;
+}
+
+
+/* get header for an inflated type 1 (fixed Huffman codes) block.  We should
+   either replace this with a custom decoder, or at least precompute the
+   Huffman tables. */
+
+static void
+init_fixed_block (void)
+{
+  int i;                       /* temporary variable */
+  unsigned l[288];             /* length list for huft_build */
+
+  /* set up literal table */
+  for (i = 0; i < 144; i++)
+    l[i] = 8;
+  for (; i < 256; i++)
+    l[i] = 9;
+  for (; i < 280; i++)
+    l[i] = 7;
+  for (; i < 288; i++)         /* make a complete, but wrong code set */
+    l[i] = 8;
+  bl = 7;
+  if ((i = huft_build (l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
+    {
+      errnum = ERR_BAD_GZIP_DATA;
+      return;
+    }
+
+  /* set up distance table */
+  for (i = 0; i < 30; i++)     /* make an incomplete code set */
+    l[i] = 5;
+  bd = 5;
+  if ((i = huft_build (l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
+    {
+      errnum = ERR_BAD_GZIP_DATA;
+      return;
+    }
+
+  /* indicate we're now working on a block */
+  code_state = 0;
+  block_len++;
+}
+
+
+/* get header for an inflated type 2 (dynamic Huffman codes) block. */
+
+static void
+init_dynamic_block (void)
+{
+  int i;                       /* temporary variables */
+  unsigned j;
+  unsigned l;                  /* last length */
+  unsigned m;                  /* mask for bit lengths table */
+  unsigned n;                  /* number of lengths to get */
+  unsigned nb;                 /* number of bit length codes */
+  unsigned nl;                 /* number of literal/length codes */
+  unsigned nd;                 /* number of distance codes */
+  unsigned ll[286 + 30];       /* literal/length and distance code lengths */
+  register ulg b;              /* bit buffer */
+  register unsigned k;         /* number of bits in bit buffer */
+
+  /* make local bit buffer */
+  b = bb;
+  k = bk;
+
+  /* read in table lengths */
+  NEEDBITS (5);
+  nl = 257 + ((unsigned) b & 0x1f);    /* number of literal/length codes */
+  DUMPBITS (5);
+  NEEDBITS (5);
+  nd = 1 + ((unsigned) b & 0x1f);      /* number of distance codes */
+  DUMPBITS (5);
+  NEEDBITS (4);
+  nb = 4 + ((unsigned) b & 0xf);       /* number of bit length codes */
+  DUMPBITS (4);
+  if (nl > 286 || nd > 30)
+    {
+      errnum = ERR_BAD_GZIP_DATA;
+      return;
+    }
+
+  /* read in bit-length-code lengths */
+  for (j = 0; j < nb; j++)
+    {
+      NEEDBITS (3);
+      ll[bitorder[j]] = (unsigned) b & 7;
+      DUMPBITS (3);
+    }
+  for (; j < 19; j++)
+    ll[bitorder[j]] = 0;
+
+  /* build decoding table for trees--single level, 7 bit lookup */
+  bl = 7;
+  if ((i = huft_build (ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
+    {
+      errnum = ERR_BAD_GZIP_DATA;
+      return;
+    }
+
+  /* read in literal and distance code lengths */
+  n = nl + nd;
+  m = mask_bits[bl];
+  i = l = 0;
+  while ((unsigned) i < n)
+    {
+      NEEDBITS ((unsigned) bl);
+      j = (td = tl + ((unsigned) b & m))->b;
+      DUMPBITS (j);
+      j = td->v.n;
+      if (j < 16)              /* length of code in bits (0..15) */
+       ll[i++] = l = j;        /* save last length in l */
+      else if (j == 16)                /* repeat last length 3 to 6 times */
+       {
+         NEEDBITS (2);
+         j = 3 + ((unsigned) b & 3);
+         DUMPBITS (2);
+         if ((unsigned) i + j > n)
+           {
+             errnum = ERR_BAD_GZIP_DATA;
+             return;
+           }
+         while (j--)
+           ll[i++] = l;
+       }
+      else if (j == 17)                /* 3 to 10 zero length codes */
+       {
+         NEEDBITS (3);
+         j = 3 + ((unsigned) b & 7);
+         DUMPBITS (3);
+         if ((unsigned) i + j > n)
+           {
+             errnum = ERR_BAD_GZIP_DATA;
+             return;
+           }
+         while (j--)
+           ll[i++] = 0;
+         l = 0;
+       }
+      else
+       /* j == 18: 11 to 138 zero length codes */
+       {
+         NEEDBITS (7);
+         j = 11 + ((unsigned) b & 0x7f);
+         DUMPBITS (7);
+         if ((unsigned) i + j > n)
+           {
+             errnum = ERR_BAD_GZIP_DATA;
+             return;
+           }
+         while (j--)
+           ll[i++] = 0;
+         l = 0;
+       }
+    }
+
+  /* free decoding table for trees */
+  reset_linalloc ();
+
+  /* restore the global bit buffer */
+  bb = b;
+  bk = k;
+
+  /* build the decoding tables for literal/length and distance codes */
+  bl = lbits;
+  if ((i = huft_build (ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
+    {
+#if 0
+      if (i == 1)
+       printf ("gunzip: incomplete literal tree\n");
+#endif
+
+      errnum = ERR_BAD_GZIP_DATA;
+      return;
+    }
+  bd = dbits;
+  if ((i = huft_build (ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
+    {
+#if 0
+      if (i == 1)
+       printf ("gunzip: incomplete distance tree\n");
+#endif
+
+      errnum = ERR_BAD_GZIP_DATA;
+      return;
+    }
+
+  /* indicate we're now working on a block */
+  code_state = 0;
+  block_len++;
+}
+
+
+static void
+get_new_block (void)
+{
+  register ulg b;              /* bit buffer */
+  register unsigned k;         /* number of bits in bit buffer */
+
+  hufts = 0;
+
+  /* make local bit buffer */
+  b = bb;
+  k = bk;
+
+  /* read in last block bit */
+  NEEDBITS (1);
+  last_block = (int) b & 1;
+  DUMPBITS (1);
+
+  /* read in block type */
+  NEEDBITS (2);
+  block_type = (unsigned) b & 3;
+  DUMPBITS (2);
+
+  /* restore the global bit buffer */
+  bb = b;
+  bk = k;
+
+  if (block_type == INFLATE_STORED)
+    init_stored_block ();
+  if (block_type == INFLATE_FIXED)
+    init_fixed_block ();
+  if (block_type == INFLATE_DYNAMIC)
+    init_dynamic_block ();
+}
+
+
+static void
+inflate_window (void)
+{
+  /* initialize window */
+  wp = 0;
+
+  /*
+   *  Main decompression loop.
+   */
+
+  while (wp < WSIZE && !errnum)
+    {
+      if (!block_len)
+       {
+         if (last_block)
+           break;
+
+         get_new_block ();
+       }
+
+      if (block_type > INFLATE_DYNAMIC)
+       errnum = ERR_BAD_GZIP_DATA;
+
+      if (errnum)
+       return;
+
+      /*
+       *  Expand stored block here.
+       */
+      if (block_type == INFLATE_STORED)
+       {
+         int w = wp;
+
+         /*
+          *  This is basically a glorified pass-through
+          */
+
+         while (block_len && w < WSIZE && !errnum)
+           {
+             slide[w++] = get_byte ();
+             block_len--;
+           }
+
+         wp = w;
+
+         continue;
+       }
+
+      /*
+       *  Expand other kind of block.
+       */
+
+      if (inflate_codes_in_window ())
+       reset_linalloc ();
+    }
+
+  saved_filepos += WSIZE;
+
+  /* XXX do CRC calculation here! */
+}
+
+
+static void
+initialize_tables (void)
+{
+  saved_filepos = 0;
+  filepos = gzip_data_offset;
+
+  /* initialize window, bit buffer */
+  bk = 0;
+  bb = 0;
+
+  /* reset partial decompression code */
+  last_block = 0;
+  block_len = 0;
+
+  /* reset memory allocation stuff */
+  reset_linalloc ();
+}
+
+
+int
+gunzip_read (unsigned char *buf, int len)
+{
+  int ret = 0;
+  int real_len = len;
+
+  compressed_file = 0;
+  gunzip_swap_values ();
+  /*
+   *  Now "gzip_*" values refer to the uncompressed data.
+   */
+
+  /* do we reset decompression to the beginning of the file? */
+  if (saved_filepos > gzip_filepos + WSIZE)
+    initialize_tables ();
+
+  /*
+   *  This loop operates upon uncompressed data only.  The only
+   *  special thing it does is to make sure the decompression
+   *  window is within the range of data it needs.
+   */
+
+  while (len > 0 && !errnum)
+    {
+      register int size;
+      register char *srcaddr;
+
+      while (gzip_filepos >= saved_filepos)
+       inflate_window ();
+
+      srcaddr = (char *) ((gzip_filepos & (WSIZE - 1)) + slide);
+      size = saved_filepos - gzip_filepos;
+      if (size > len)
+       size = len;
+
+      memmove (buf, srcaddr, size);
+
+      buf += size;
+      len -= size;
+      gzip_filepos += size;
+      ret += size;
+
+      if (do_show_progress)
+        show_progress(ret, real_len);
+    }
+
+  compressed_file = 1;
+  gunzip_swap_values ();
+  /*
+   *  Now "gzip_*" values refer to the compressed data.
+   */
+
+  if (errnum)
+    ret = 0;
+
+  return ret;
+}
+
+#endif /* ! NO_DECOMPRESSION */
diff --git a/l4/pkg/bootstrap_custom/server/src/gunzip.h b/l4/pkg/bootstrap_custom/server/src/gunzip.h
new file mode 100644 (file)
index 0000000..1c3785d
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __BOOTSTRAP__GUNZIP_H__
+#define __BOOTSTRAP__GUNZIP_H__
+
+#include <l4/sys/l4int.h>
+#include "panic.h"
+
+typedef enum
+{
+  ERR_NONE = 0,
+  ERR_BAD_GZIP_DATA,
+  ERR_BAD_GZIP_HEADER,
+
+} grub_error_t;
+
+l4_addr_t gunzip_upper_mem_linalloc(void);
+#define UPPER_MEM_LINALLOC gunzip_upper_mem_linalloc()
+
+#define RAW_ADDR(x) (x)
+#define RAW_SEG(x) (x)
+
+extern unsigned int filepos;
+extern unsigned int filemax;
+extern unsigned int fsmax;     /* max size of fs/readable media */
+extern unsigned int compressed_file;
+extern grub_error_t errnum;
+
+/* Read LEN bytes into BUF from the file that was opened with
+   GRUB_OPEN.  If LEN is -1, read all the remaining data in the file.  */
+int grub_read (unsigned char *buf, int len);
+
+int gunzip_read (unsigned char *buf, int len);
+int gunzip_test_header (void);
+
+void *memmove(void *dest, const void *src, size_t n);
+
+#endif /* ! __BOOTSTRAP__GUNZIP_H__ */
diff --git a/l4/pkg/bootstrap_custom/server/src/init_kip-arch.h b/l4/pkg/bootstrap_custom/server/src/init_kip-arch.h
new file mode 100644 (file)
index 0000000..79bbfcd
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef INIT_KIP_ARCH_H__
+#define INIT_KIP_ARCH_H__
+
+#include <l4/sys/kip.h>
+
+#if defined(ARCH_ppc32)
+void init_kip_v2_arch(l4_kernel_info_t *);
+#endif
+
+#endif
+
diff --git a/l4/pkg/bootstrap_custom/server/src/init_kip.h b/l4/pkg/bootstrap_custom/server/src/init_kip.h
new file mode 100644 (file)
index 0000000..c3c938f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *               Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef INIT_KIP_H__
+#define INIT_KIP_H__
+
+#include <l4/util/mb_info.h>
+#include "startup.h"
+#include "init_kip-arch.h"
+
+#ifdef __cplusplus
+class Region_list;
+
+void init_kip_f(void *_l4i, boot_info_t *bi, l4util_mb_info_t *mbi,
+                Region_list *ram, Region_list *regions);
+#endif
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/init_kip_f.cc b/l4/pkg/bootstrap_custom/server/src/init_kip_f.cc
new file mode 100644 (file)
index 0000000..5f3a80a
--- /dev/null
@@ -0,0 +1,93 @@
+/**
+ * \file
+ */
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Alexander Warg <warg@os.inf.tu-dresden.de>
+ *     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 <stdio.h>
+#include <string.h>
+#include <l4/sys/kip.h>
+#include <l4/util/l4_macros.h>
+#include "panic.h"
+
+#include "macros.h"
+#include "init_kip.h"
+#include "region.h"
+#include "startup.h"
+#include <l4/sys/kip>
+
+using L4::Kip::Mem_desc;
+
+/**
+ * setup Kernel Info Page
+ */
+void
+init_kip_f(void *_l4i, boot_info_t *bi, l4util_mb_info_t *mbi,
+           Region_list *ram, Region_list *regions)
+{
+  l4_kernel_info_t *l4i = (l4_kernel_info_t *)_l4i;
+
+  unsigned char l4_api = l4i->version >> 24;
+
+  if (l4_api != 0x87 /*VERSION_FIASCO*/)
+    panic("cannot load kernels other than Fiasco");
+
+  Mem_desc *md = Mem_desc::first(_l4i);
+  for (Region const* c = ram->begin(); c != ram->end(); ++c)
+    (md++)->set(c->begin(), c->end(), Mem_desc::Conventional);
+
+  for (Region const *c = regions->begin(); c != regions->end(); ++c)
+    {
+      Mem_desc::Mem_type type = Mem_desc::Reserved;
+      unsigned char sub_type = 0;
+      switch (c->type())
+       {
+       case Region::No_mem:
+       case Region::Ram:
+       case Region::Boot:
+         continue;
+       case Region::Kernel:
+         type = Mem_desc::Reserved;
+         break;
+       case Region::Sigma0:
+         type = Mem_desc::Dedicated;
+         break;
+       case Region::Root:
+         type = Mem_desc::Bootloader;
+         break;
+       case Region::Arch:
+         type = Mem_desc::Arch;
+         sub_type = c->sub_type();
+         break;
+        case Region::Info:
+          type = Mem_desc::Info;
+          sub_type = c->sub_type();
+          break;
+        }
+      (md++)->set(c->begin(), c->end() - 1, type, sub_type);
+    }
+
+  l4i->user_ptr = (unsigned long)mbi;
+
+  /* set up sigma0 info */
+  l4i->sigma0_eip = bi->sigma0_start;
+  printf("  Sigma0 config    ip:" l4_addr_fmt " sp:" l4_addr_fmt "\n",
+         l4i->sigma0_eip, l4i->sigma0_esp);
+
+  /* set up roottask info */
+  l4i->root_eip          = bi->roottask_start;
+  printf("  Roottask config  ip:" l4_addr_fmt " sp:" l4_addr_fmt "\n",
+         l4i->root_eip, l4i->root_esp);
+
+  /* Platform info */
+  strncpy(l4i->platform_info.name, PLATFORM_TYPE,
+          sizeof(l4i->platform_info.name));
+  l4i->platform_info.name[sizeof(l4i->platform_info.name) - 1] = 0;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/koptions-def.h b/l4/pkg/bootstrap_custom/server/src/koptions-def.h
new file mode 100644 (file)
index 0000000..d5bb1e0
--- /dev/null
@@ -0,0 +1,83 @@
+#pragma once
+
+#include <l4/sys/types.h>
+
+// To generate the kernel version:
+// perl -p -e 's/l4_uint(\d+)_t/Unsigned$1/;s/^#inc.+/#include "types.h"/' koptions-def.h
+
+namespace L4_kernel_options
+{
+  enum Flags
+  {
+    F_wait              = 1 << 0,
+    F_serial_esc        = 1 << 1,
+    F_noserial          = 1 << 2,
+    F_noscreen          = 1 << 3,
+    F_esc               = 1 << 4,
+    F_nojdb             = 1 << 5,
+    F_nokdb             = 1 << 6,
+    F_nohlt             = 1 << 7,
+    F_apic              = 1 << 8,
+    F_loadcnt           = 1 << 9,
+    F_watchdog          = 1 << 10,
+    F_keymap_de         = 1 << 11,
+    F_irq0              = 1 << 13,
+    F_nosfn             = 1 << 15,
+    F_jdb_never_stop    = 1 << 16,
+
+    F_kmemsize          = 1 << 17,
+    F_tbuf_entries      = 1 << 18,
+    F_out_buf           = 1 << 19,
+    F_uart_baud         = 1 << 20,
+    F_uart_base         = 1 << 21,
+    F_uart_irq          = 1 << 22,
+
+    F_jdb_cmd           = 1 << 23,
+  };
+
+  enum
+  {
+    Magic = 0x4C344B43,
+  };
+
+  enum Uart_type
+  {
+    Uart_type_invalid = 0,
+    Uart_type_ioport  = 1,
+    Uart_type_mmio    = 2,
+  };
+
+  enum
+  {
+    Uart_irq_none = 0xffff,
+  };
+
+  struct Uart
+  {
+    l4_uint32_t  base_baud;    ///< Base baud rate of the UART (if applicable)
+    l4_uint32_t  baud;         ///< Baud rate (this is the baud rate to use)
+    l4_uint16_t  irqno;        ///< (Receive) IRQ
+    l4_uint8_t   reg_shift;    ///< Shift value for register addressing
+    l4_uint8_t   access_type;  ///< Accesstype of UART: unset, MMIO or ports
+    l4_uint64_t  base_address; ///< Start address of UART
+  } __attribute__((packed));
+
+  struct Options
+  {
+    l4_uint32_t  magic;            ///< Magic value
+    l4_uint32_t  version;          ///< Version of this structure
+
+    l4_uint32_t  flags;            ///< Option flags
+
+    l4_uint32_t  kmemsize;         ///< Wanted kernel memory size in KiB
+
+    Uart uart;                     ///< Kernel UART
+
+    char         jdb_cmd[128];
+    l4_uint32_t  tbuf_entries;
+    l4_uint32_t  out_buf;
+
+    l4_uint32_t  opt(Flags flag) const { return flags & flag; }
+
+  } __attribute__((packed));
+};
diff --git a/l4/pkg/bootstrap_custom/server/src/koptions.cc b/l4/pkg/bootstrap_custom/server/src/koptions.cc
new file mode 100644 (file)
index 0000000..ca98cac
--- /dev/null
@@ -0,0 +1,136 @@
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "koptions.h"
+
+static struct {
+  const char *s;
+  unsigned int flag;
+} boolean_opts[] = {
+  { " -wait",              L4_kernel_options::F_wait              },
+  { " -serial_esc",        L4_kernel_options::F_serial_esc        },
+  { " -noserial",          L4_kernel_options::F_noserial          },
+  { " -noscreen",          L4_kernel_options::F_noscreen          },
+  { " -esc",               L4_kernel_options::F_esc               },
+  { " -nojdb",             L4_kernel_options::F_nojdb             },
+  { " -nokdb",             L4_kernel_options::F_nokdb             },
+  { " -nohlt",             L4_kernel_options::F_nohlt             },
+  { " -apic",              L4_kernel_options::F_apic              },
+  { " -loadcnt",           L4_kernel_options::F_loadcnt           },
+  { " -watchdog",          L4_kernel_options::F_watchdog          },
+  { " -irq0",              L4_kernel_options::F_irq0              },
+  { " -nosfn",             L4_kernel_options::F_nosfn             },
+  { " -jdb_never_stop",    L4_kernel_options::F_jdb_never_stop    },
+};
+
+static struct {
+  const char *s;
+  unsigned int flag;
+  unsigned int offset;
+} unsigned_opts[] = {
+  { " -kmemsize",     L4_kernel_options::F_kmemsize,
+                      offsetof(L4_kernel_options::Options, kmemsize) },
+  { " -tbuf_entries", L4_kernel_options::F_tbuf_entries,
+                      offsetof(L4_kernel_options::Options, tbuf_entries) },
+  { " -out_buf",      L4_kernel_options::F_out_buf,
+                      offsetof(L4_kernel_options::Options, out_buf) },
+};
+
+#define MEMBERSIZE(type, member) sizeof(((type *)0)->member)
+
+static struct {
+  const char *s;
+  unsigned int flag;
+  unsigned int size;
+  unsigned int offset;
+} string_opts[] = {
+  { " -jdb_cmd",      L4_kernel_options::F_jdb_cmd,
+                      MEMBERSIZE(L4_kernel_options::Options, jdb_cmd),
+                      offsetof(L4_kernel_options::Options, jdb_cmd) },
+};
+
+static void kcmdline_show(L4_kernel_options::Options *lko)
+{
+  printf("Location: %016lx  Size: %zd Bytes\n",
+         (unsigned long)lko, sizeof(*lko));
+  printf("Flags: %08x\n", lko->flags);
+  for (unsigned i = 0; i < sizeof(boolean_opts) / sizeof(boolean_opts[0]); ++i)
+    {
+      if (lko->flags & boolean_opts[i].flag)
+        printf("  %s\n", boolean_opts[i].s);
+    }
+
+  if (lko->flags & L4_kernel_options::F_kmemsize)
+    printf("Kmemsize: %dKiB\n", lko->kmemsize);
+  if (lko->flags & L4_kernel_options::F_tbuf_entries)
+    printf("Tbuf entries: %d\n", lko->tbuf_entries);
+  if (lko->flags & L4_kernel_options::F_out_buf)
+    printf("Out bufs: %d\n", lko->out_buf);
+
+  if (lko->jdb_cmd[0])
+    printf("JDB command: %s\n", lko->jdb_cmd);
+}
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+void kcmdline_parse(char const *cmdline,
+                    L4_kernel_options::Options *lko)
+{
+  if (0)
+    printf("Kernel command-line: %s\n", cmdline);
+
+  // boolean options
+  for (unsigned i = 0; i < ARRAY_SIZE(boolean_opts); ++i)
+    if (strstr(cmdline, boolean_opts[i].s))
+      lko->flags |= boolean_opts[i].flag;
+
+  // integer options
+  for (unsigned i = 0; i < ARRAY_SIZE(unsigned_opts); ++i)
+    {
+      char *c;
+      unsigned len = strlen(unsigned_opts[i].s);
+      if ((c = strstr(cmdline, unsigned_opts[i].s))
+          && (c[len] == ' ' || c[len] == '='))
+        {
+          lko->flags |= unsigned_opts[i].flag;
+          *(unsigned *)((char *)lko + unsigned_opts[i].offset)
+            = strtol(c + len + 1, 0, 0);
+        }
+    }
+
+  // string options
+  for (unsigned i = 0; i < ARRAY_SIZE(string_opts); ++i)
+    {
+      char *c;
+      unsigned len = strlen(string_opts[i].s);
+      if ((c = strstr(cmdline, string_opts[i].s))
+          && (c[len] == ' ' || c[len] == '='))
+        {
+          char *dst = (char *)lko + string_opts[i].offset;
+          lko->flags |= string_opts[i].flag;
+          c += len + 1;
+          while (*c && *c != ' '
+                 && (dst < (char *)lko + string_opts[i].offset +
+                            string_opts[i].size - 1))
+            *dst++ = *c++;
+          *dst = 0;
+        }
+    }
+
+  // warnings
+  if (strstr(cmdline, "-comport")
+      || strstr(cmdline, "-comspeed")
+      || strstr(cmdline, "-comirq"))
+    printf("WARNING: Command line options -comport, -comspeed and -comirq\n"
+           "         have been moved to bootstrap and are shared beetween\n"
+           "         Fiasco and bootstrap now. Please remove them from\n"
+           "         your Fiasco command line, they do not have an effect\n"
+           "         there.\n");
+
+  if (0)
+    kcmdline_show(lko);
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/koptions.h b/l4/pkg/bootstrap_custom/server/src/koptions.h
new file mode 100644 (file)
index 0000000..f49365a
--- /dev/null
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "koptions-def.h"
+
+void
+kcmdline_parse(char const *cmdline, L4_kernel_options::Options *lko);
diff --git a/l4/pkg/bootstrap_custom/server/src/ldscript.inc b/l4/pkg/bootstrap_custom/server/src/ldscript.inc
new file mode 100644 (file)
index 0000000..40cb6f3
--- /dev/null
@@ -0,0 +1,23 @@
+/* vi:ft=c
+   Common functionality for linker scripts in bootstrap */
+#define CTORS                             \
+    . = ALIGN(8);                         \
+    PROVIDE (__CTORS_BEGIN = .);          \
+    KEEP (*(SORT(.ctors.*)))              \
+    KEEP (*(.ctors))                      \
+    PROVIDE (__CTORS_END = .);            \
+    PROVIDE (__preinit_array_start = .);  \
+    KEEP (*(SORT(.preinit_array.*)))      \
+    KEEP (*(.preinit_array))              \
+    PROVIDE (__preinit_array_end = .);    \
+    PROVIDE (__init_array_start = .);     \
+    KEEP (*(SORT(.init_array.*)))         \
+    KEEP (*(.init_array))                 \
+    PROVIDE (__init_array_end = .);
+
+
+#define PLATFORMS                      \
+    PROVIDE (__PLATFORMS_BEGIN = .);   \
+    KEEP (*(.platformdata))            \
+    PROVIDE (__PLATFORMS_END = .);
+
diff --git a/l4/pkg/bootstrap_custom/server/src/libc_support+.cc b/l4/pkg/bootstrap_custom/server/src/libc_support+.cc
new file mode 100644 (file)
index 0000000..72592fd
--- /dev/null
@@ -0,0 +1,213 @@
+/**
+ * \file       bootstrap/server/src/libc_support.c
+ * \brief      Support for C library
+ *
+ * \date       2004-2008
+ * \author     Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *             Frank Mehnert <fm3@os.inf.tu-dresden.de> */
+
+/*
+ * (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 <unistd.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/types.h>
+#include "panic.h"
+
+#include <l4/cxx/basic_ostream>
+
+#include "support.h"
+
+Platform_base *Platform_base::platform;
+
+static L4::Uart *stdio_uart;
+
+L4::Uart *uart()
+{ return stdio_uart; }
+
+void set_stdio_uart(L4::Uart *uart)
+{ stdio_uart = uart; }
+
+
+inline void *operator new (size_t, void *p) { return p; }
+// IO Stream backend
+namespace {
+
+  class BootstrapIOBackend : public L4::IOBackend
+  {
+  protected:
+    void write(char const *str, unsigned len);
+  };
+
+  void BootstrapIOBackend::write(char const *str, unsigned len)
+  {
+    ::write(STDOUT_FILENO, str, len);
+  }
+
+};
+
+namespace L4 {
+  typedef char Fake_iobackend[sizeof(BootstrapIOBackend)]
+    __attribute__((aligned(__alignof__(BootstrapIOBackend))));
+  typedef char Fake_ostream[sizeof(BasicOStream)]
+    __attribute__((aligned(__alignof__(BasicOStream))));
+
+  Fake_ostream cout;
+  Fake_ostream cerr;
+
+  static Fake_iobackend _iob;
+
+  void iostream_init();
+  void iostream_init()
+  {
+    static int _initialized;
+    if (!_initialized)
+      {
+       _initialized = 1;
+       BootstrapIOBackend *iob = new (&_iob) BootstrapIOBackend();
+       new (&cerr) BasicOStream(iob);
+       new (&cout) BasicOStream(iob);
+      }
+  }
+};
+
+typedef void Ctor();
+
+static void call_ctors(Ctor **start, Ctor **end)
+{
+  for (; start < end; ++start)
+    if (*start)
+      (*start)();
+}
+
+void
+ctor_init()
+{
+  extern Ctor *__CTORS_BEGIN[];
+  extern Ctor *__CTORS_END[];
+  extern Ctor *__init_array_start[];
+  extern Ctor *__init_array_end[];
+  extern Ctor *__preinit_array_start[];
+  extern Ctor *__preinit_array_end[];
+
+  call_ctors(__preinit_array_start, __preinit_array_end);
+  call_ctors(__CTORS_BEGIN, __CTORS_END);
+  call_ctors(__init_array_start, __init_array_end);
+}
+
+
+void exit(int c) throw()
+{
+  _exit(c);
+}
+
+void (*__exit_cleanup) (int) = 0;
+
+extern "C" void __attribute__((noreturn))
+__assert(const char *, const char *, int, register const char *);
+
+extern "C" void __attribute__((noreturn))
+__assert(const char *assertion, const char * filename,
+         int linenumber, register const char * function)
+{
+  printf("%s:%d: %s: Assertion `%s' failed.\n",
+                               filename,
+                               linenumber,
+                               ((function == NULL) ? "?function?" : function),
+                               assertion
+                               );
+  panic("Assertion");
+  while(1)
+    ;
+}
+
+ssize_t
+write(int fd, const void *buf, size_t count)
+{
+  if (!uart())
+    return count;
+
+  if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
+    {
+      char *b = (char *)buf;
+      int i = count;
+      while (i--)
+        {
+          char c = *b++;
+          if (c == '\n')
+            uart()->write("\r", 1);
+          uart()->write(&c, 1);
+        }
+
+      return count;
+    }
+
+  errno = EBADF;
+  return -1;
+}
+
+#undef getchar
+int
+getchar(void)
+{
+  int c;
+  if (!uart())
+    return -1;
+
+  do
+    c = uart()->get_char(0);
+  while (c == -1);
+  return c;
+}
+
+off_t lseek(int /*fd*/, off_t /*offset*/, int /*whence*/)
+{
+  return 0;
+}
+
+void *__dso_handle = &__dso_handle;
+
+extern "C" void reboot(void) __attribute__((noreturn));
+void reboot(void)
+{
+  void reboot_arch() __attribute__((noreturn));
+  reboot_arch();
+}
+
+extern "C" void __attribute__((noreturn))
+_exit(int /*rc*/)
+{
+  printf("\n\033[1mKey press reboots...\033[m\n");
+  getchar();
+  printf("Rebooting.\n\n");
+  reboot();
+}
+
+/** for assert */
+void
+abort(void) throw()
+{
+  _exit(1);
+}
+
+void
+panic(const char *fmt, ...)
+{
+  va_list v;
+  va_start (v, fmt);
+  vprintf(fmt, v);
+  va_end(v);
+  putchar('\n');
+  exit(1);
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/memory.cc b/l4/pkg/bootstrap_custom/server/src/memory.cc
new file mode 100644 (file)
index 0000000..8b07980
--- /dev/null
@@ -0,0 +1,67 @@
+#include "support.h"
+
+unsigned long
+Memory::find_free_ram(unsigned long size,
+                      unsigned long min_addr,
+                      unsigned long max_addr)
+{
+  unsigned long min = min_addr;
+  if (min < sizeof(unsigned long long))
+    min = sizeof(unsigned long long);
+  for (Region *rr = ram->begin(); rr != ram->end(); ++rr)
+    {
+      if (min >= rr->end())
+        continue;
+
+      if (max_addr <= rr->begin())
+        continue;
+
+      if (min < rr->begin())
+        min = rr->begin();
+
+      unsigned long max = max_addr;
+      if (rr->end() < max)
+        max = rr->end();
+
+      Region search_area(min, max, "ram for modules");
+      unsigned long long to = regions->find_free(search_area, size, L4_PAGESHIFT);
+      if (to)
+        return to;
+    }
+  return 0;
+}
+
+unsigned long
+Memory::find_free_ram_rev(unsigned long size,
+                          unsigned long min_addr,
+                          unsigned long max_addr)
+{
+  if (min_addr < sizeof(unsigned long long))
+    min_addr = sizeof(unsigned long long);
+
+  unsigned long max = max_addr;
+  for (Region *rr = ram->end() - 1; rr >= ram->begin(); --rr)
+    {
+      if (min_addr >= rr->end())
+        continue;
+
+      if (max <= rr->begin())
+        continue;
+
+      unsigned long min = min_addr;
+      if (min < rr->begin())
+        min = rr->begin();
+
+      if (rr->end() < max)
+        max = rr->end();
+
+      Region search_area(min, max, "ram for modules");
+      unsigned long long to
+        = regions->find_free_rev(search_area, size, L4_PAGESHIFT);
+      if (to)
+        return to;
+    }
+  return 0;
+}
+
+
diff --git a/l4/pkg/bootstrap_custom/server/src/mod_info.h b/l4/pkg/bootstrap_custom/server/src/mod_info.h
new file mode 100644 (file)
index 0000000..a20d2d0
--- /dev/null
@@ -0,0 +1,13 @@
+#pragma once
+
+/// Info for each module
+struct Mod_info
+{
+  char const *start;
+  unsigned size;
+  unsigned size_uncompressed;
+  char const *name;
+  char const *cmdline;
+  char const *md5sum_compr;
+  char const *md5sum_uncompr;
+} __attribute__((packed));
diff --git a/l4/pkg/bootstrap_custom/server/src/module.c b/l4/pkg/bootstrap_custom/server/src/module.c
new file mode 100644 (file)
index 0000000..2273b27
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * (c) 2008-2009 Frank Mehnert <fm3@os.inf.tu-dresden.de>,
+ *               Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ *     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 <stdio.h>
+#include "module.h"
+
+void
+print_module_name(const char *name, const char *alt_name)
+{
+  const char *c1, *c2;
+
+  if (!name)
+    {
+      printf("%s", alt_name);
+      return;
+    }
+
+  c2 = name;
+  while (*c2 != '\0' && *c2 != ' ')
+    c2++;
+  c1 = c2;
+  if (c1 > name)
+    c1--;
+  while (c1 > name && c2-c1 < 56)
+    c1--;
+
+  printf("%.*s", (unsigned)(c2-c1), c1);
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/module.h b/l4/pkg/bootstrap_custom/server/src/module.h
new file mode 100644 (file)
index 0000000..1252f4a
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *               Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef MODULE_H
+#define MODULE_H
+
+#include <stddef.h>
+#include <l4/util/mb_info.h>
+#include <l4/sys/compiler.h>
+
+EXTERN_C_BEGIN
+
+void print_module_name(const char *name, const char *alt_name);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/panic.h b/l4/pkg/bootstrap_custom/server/src/panic.h
new file mode 100644 (file)
index 0000000..6c2a529
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
+ *     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.
+ */
+#pragma once
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void panic(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+
diff --git a/l4/pkg/bootstrap_custom/server/src/patch.cc b/l4/pkg/bootstrap_custom/server/src/patch.cc
new file mode 100644 (file)
index 0000000..0f13c90
--- /dev/null
@@ -0,0 +1,198 @@
+/**
+ * \file       bootstrap/server/src/patch.c
+ * \brief      Patching of boot modules
+ * 
+ * \date       09/2005
+ * \author     Frank Mehnert <fm3@os.inf.tu-dresden.de> */
+
+/*
+ * (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 <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <l4/sys/consts.h>
+#include <l4/util/mb_info.h>
+#include "panic.h"
+#include "macros.h"
+#include "types.h"
+#include "patch.h"
+#include "startup.h"
+
+
+/* search module in module list */
+static l4util_mb_mod_t*
+search_module(const char *name, size_t name_len, l4util_mb_info_t *mbi,
+              const char **cmdline)
+{
+  unsigned i;
+  const char *c = 0, *ce = 0;
+  l4util_mb_mod_t *mod;
+
+  for (i=0; i<mbi->mods_count; i++)
+    {
+      const char *m, *n;
+
+      mod = (L4_MB_MOD_PTR(mbi->mods_addr)) + i;
+      m = c = L4_CONST_CHAR_PTR(mod->cmdline);
+      ce = strchr(c, ' ');
+      if (!ce)
+       ce = c+strlen(c);
+      for (;;)
+       {
+         if (!(n = strchr(m, name[0])) || n+name_len>ce)
+           break;
+         if (!memcmp(name, n, name_len))
+           {
+             *cmdline = c;
+             return mod;
+           }
+         m = n+1;
+       }
+    }
+
+  return NULL;
+}
+
+/**
+ * Handle -patch=<module_name>,<variable>=blah parameter. Overwrite a specific
+ * module from command line. This allows to change the boot configuration (e.g.
+ * changing parameters of a loader script)
+ */
+void
+patch_module(const char **str, l4util_mb_info_t *mbi)
+{
+  const char *nam_beg, *nam_end;
+  const char *var_beg, *var_end;
+  const char *val_beg, *val_end;
+  char *mod_beg, *mod_end, *mod_ptr, quote = 0;
+  l4_size_t var_size, val_size, max_patch_size;
+  const char *cmdline = 0;
+  l4util_mb_mod_t *mod;
+
+  /* nam_beg ... nam_end */
+  nam_beg = *str+8;
+  nam_end = strchr(nam_beg, ',');
+  if (!nam_end || strpbrk(nam_beg, "\011 =*")-1 < nam_end)
+    panic("-patch: bad module name");
+
+  mod = search_module(nam_beg, nam_end-nam_beg, mbi, &cmdline);
+  if (!mod)
+    panic("-patch: cannot find module \"%.*s\"",
+         (int)(nam_end-nam_beg), nam_beg);
+
+  mod_beg = L4_CHAR_PTR(mod->mod_start);
+  mod_end = L4_CHAR_PTR(mod->mod_end);
+
+  /* How much bytes the module can be enlarged to. The module cannot
+   * be extended beyond page boundaries because the next module starts
+   * there and we don't want to move the following modules. */
+  max_patch_size = l4_round_page((l4_addr_t)mod_end) - (l4_addr_t)mod_end - 1;
+
+  printf("  Patching module \"%s\"\n", cmdline);
+
+  for (var_beg=nam_end; *var_beg==','; var_beg=*str)
+    {
+      var_beg++;
+      /* var_beg ... var_end */
+      var_end = strchr(var_beg, '=');
+      if (!var_end || strpbrk(var_beg, "\011 ,*")-1 < nam_end)
+       panic("-patch: bad variable name");
+      var_size = var_end-var_beg;
+
+      /* val_beg ... val_end, consider quotes */
+      val_beg = val_end = var_end+1;
+      if (*val_end == '"' || *val_end == '\'')
+       {
+         val_beg++;
+         quote = *val_end++;
+       }
+      while (*val_end && ((!quote && !isspace(*val_end) && *val_end!=',') ||
+                         (quote && *val_end!=quote)))
+       val_end++;
+      *str = val_end;
+      if (quote)
+       (*str)++;
+      quote = 0;
+      val_size = val_end-val_beg;
+
+      /* replace all occurences of variable with value */
+      for (mod_ptr=mod_beg;;)
+       {
+         if (!(mod_ptr = (char *)memmem(mod_ptr, mod_end - mod_ptr,
+                                        var_beg, var_end - var_beg)))
+           break;
+         if (var_size < val_size && max_patch_size < val_size-var_size)
+           panic("-patch: not enough space in module");
+         max_patch_size += var_size - val_size;
+         memmove(mod_ptr+val_size, mod_ptr+var_size, mod_end-mod_ptr-var_size);
+         if (val_size < var_size)
+           memset(mod_end-var_size+val_size, 0, var_size-val_size);
+         memcpy(mod_ptr, val_beg, val_size);
+         mod_ptr += val_size;
+         mod_end += val_size - var_size;
+       }
+    }
+
+  mod->mod_end = (l4_addr_t)mod_end;
+}
+
+
+/**
+ * Handle -arg=<module_name>,blah parameter. Replace old command line
+ * parameters of <module_name> by blah. Useful for changing the boot
+ * configuration of a bootstrap image.
+ *
+ * Get a pointer to new argument and return the size.
+ */
+char *
+get_arg_module(char *cmdline, const char *name, unsigned *size)
+{
+  char *val_beg = NULL, *val_end;
+  char *s = cmdline;
+
+  if (!s)
+    return 0;
+
+  while (!val_beg && (s = strstr(s, " -arg=")))
+    {
+      char *a, *name_end;
+
+      s += 6;
+      name_end = strchr(s, ',');
+      if (!name_end)
+       panic("comma missing after modname in -arg=");
+      *name_end = 0;
+
+      for (a = s; *a; a++)
+       if (isspace(*a))
+         panic("Invalid '-arg=modname,text' parameter");
+
+      // we do a fuzzy name-match here
+      if (strstr(name, s))
+       val_beg = name_end+1;
+      *name_end = ',';
+    }
+  if (!val_beg)
+    return 0;
+
+  // consider quotes
+  unsigned char quote = 0;
+  if (*val_beg == '"' || *val_beg == '\'')
+    quote = *val_beg++;
+  val_end = val_beg;
+
+  while (*val_end && ((!quote && !isspace(*val_end)) || *val_end!=quote))
+    val_end++;
+
+  *size = val_end - val_beg;
+  return val_beg;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/patch.h b/l4/pkg/bootstrap_custom/server/src/patch.h
new file mode 100644 (file)
index 0000000..7651ea1
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *               Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef PATCH_H
+#define PATCH_H
+
+#include <l4/sys/compiler.h>
+
+EXTERN_C_BEGIN
+void
+patch_module(const char **str, l4util_mb_info_t *mbi);
+char *
+get_arg_module(char *cmdline, const char *name, unsigned *size);
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/armada38x.cc b/l4/pkg/bootstrap_custom/server/src/platform/armada38x.cc
new file mode 100644 (file)
index 0000000..da271d8
--- /dev/null
@@ -0,0 +1,38 @@
+/*!
+ * \file
+ * \brief  Support for Marvell Armada 38x
+ *
+ * \date   2015
+ * \author Adam Lackorzynski <adam@l4re.org>
+ *
+ */
+/*
+ * (c) 2015 Author(s)
+ *
+ * This file is part of L4Re and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include "support.h"
+#include "mmio_16550.h"
+
+namespace {
+class Platform_arm_armada38x : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+    kuart.base_address = 0xf1012000;
+    kuart.base_baud    = 15625000;
+    kuart.baud         = 115200;
+    kuart.irqno        = 44;
+    kuart.reg_shift    = 2;
+    static L4::Uart_16550 _uart(kuart.base_baud, 0, 0, 0, 0);
+    setup_16550_mmio_uart(&_uart);
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_armada38x);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/exynos.cc b/l4/pkg/bootstrap_custom/server/src/platform/exynos.cc
new file mode 100644 (file)
index 0000000..d10d70d
--- /dev/null
@@ -0,0 +1,58 @@
+/*!
+ * \file
+ * \brief  Support for Exynos platforms
+ *
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2013 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 "support.h"
+#include <l4/drivers/uart_s3c2410.h>
+
+#include <cstdio>
+
+namespace {
+class Platform_arm_exynos : public Platform_single_region_ram
+{
+public:
+  bool probe() { return true; }
+
+  void init()
+  {
+    static L4::Uart_s5pv210 _uart;
+    const unsigned long uart_offset = 0x10000;
+    unsigned long uart_base;
+    unsigned uart_nr = PLATFORM_UART_NR;
+
+#ifdef PLATFORM_TYPE_exynos4
+    uart_base = 0x13800000;
+#else
+    uart_base = 0x12c00000;
+#endif
+
+    static L4::Io_register_block_mmio r(uart_base + uart_nr * uart_offset);
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+  }
+
+  void reboot()
+  {
+#ifdef PLATFORM_TYPE_exynos4
+    *(unsigned *)0x10020400 = 1;
+#else
+    *(unsigned *)0x10040400 = 1;
+#endif
+  }
+
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_exynos);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/imx.cc b/l4/pkg/bootstrap_custom/server/src/platform/imx.cc
new file mode 100644 (file)
index 0000000..5774190
--- /dev/null
@@ -0,0 +1,62 @@
+/*!
+ * \file   support_imx.cc
+ * \brief  Support for the i.MX platform
+ *
+ * \date   2008-02-04
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2008-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 "support.h"
+#include <l4/drivers/uart_imx.h>
+
+namespace {
+class Platform_arm_imx : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+#ifdef PLATFORM_TYPE_imx21
+    static L4::Io_register_block_mmio r(0x1000A000);
+    static L4::Uart_imx21 _uart;
+#elif defined(PLATFORM_TYPE_imx35)
+    static L4::Uart_imx35 _uart;
+    unsigned long uart_base;
+    switch (PLATFORM_UART_NR) {
+      default:
+      case 1: uart_base = 0x43f90000; break;
+      case 2: uart_base = 0x43f94000; break;
+      case 3: uart_base = 0x5000c000; break;
+    }
+    static L4::Io_register_block_mmio r(uart_base);
+#elif defined(PLATFORM_TYPE_imx51)
+    static L4::Io_register_block_mmio r(0x73fbc000);
+    static L4::Uart_imx51 _uart;
+#elif defined(PLATFORM_TYPE_imx6)
+    unsigned long uart_base;
+    switch (PLATFORM_UART_NR) {
+      case 1: uart_base = 0x02020000; break;
+      default:
+      case 2: uart_base = 0x021e8000; break;
+    };
+    static L4::Io_register_block_mmio r(uart_base);
+    static L4::Uart_imx6 _uart;
+#else
+#error Which platform type?
+#endif
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_imx);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/integrator.cc b/l4/pkg/bootstrap_custom/server/src/platform/integrator.cc
new file mode 100644 (file)
index 0000000..0d418e5
--- /dev/null
@@ -0,0 +1,36 @@
+/*!
+ * \file   support_integrator.cc
+ * \brief  Support for the integrator platform
+ *
+ * \date   2008-01-02
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2008-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 "support.h"
+#include <l4/drivers/uart_pl011.h>
+
+namespace {
+class Platform_arm_int : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+    static L4::Io_register_block_mmio r(0x16000000);
+    static L4::Uart_pl011 _uart(24019200);
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_int);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/kirkwood.cc b/l4/pkg/bootstrap_custom/server/src/platform/kirkwood.cc
new file mode 100644 (file)
index 0000000..81fb07f
--- /dev/null
@@ -0,0 +1,46 @@
+/*!
+ * \file   support_kirkwood.cc
+ * \brief  Support for the kirkwood platform
+ *
+ * \date   2010-11
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2010 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 "support.h"
+#include "mmio_16550.h"
+
+namespace {
+class Platform_arm_kirkwood : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+    kuart.base_address = 0xf1012000; /* uart 1: 0xf1012100 */
+    kuart.reg_shift    = 2;
+    kuart.base_baud    = 12500000;
+    kuart.baud         = 115200;
+    kuart.irqno        = 33;         /* uart 1 irq: ??? */
+    static L4::Uart_16550 _uart(kuart.base_baud, 0, 0, 0, 0);
+    setup_16550_mmio_uart(&_uart);
+
+
+    // SPI init, as there's an interrupt pending when coming from u-boot on
+    // the dockstar, so make it go away
+    *(unsigned *)0xf1010600 = 0; // disable
+    *(unsigned *)0xf1010614 = 0; // mask interrupt
+    *(unsigned *)0xf1010610 = 1; // clear interrupt
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_kirkwood);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/leon3.cc b/l4/pkg/bootstrap_custom/server/src/platform/leon3.cc
new file mode 100644 (file)
index 0000000..e9e80f0
--- /dev/null
@@ -0,0 +1,146 @@
+/**
+ * \file   support_sparc_leon3.cc
+ * \brief  Support for the Sparc LEON3 platform
+ *
+ * \date   2010
+ * \author Björn Döbel <doebel@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2010 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 <l4/drivers/uart_leon3.h>
+
+#include "support.h"
+
+namespace {
+class Platform_leon3 :
+  public Platform_base,
+  public Boot_modules_image_mode
+{
+  bool probe() { return true; }
+  Boot_modules *modules() { return this; }
+
+  enum {
+      LEON3_NUM_DEVICE_INFO = 64,
+
+      LEON3_APBUART               = 0x80000100,
+
+      LEON3_VENDOR_GAISLER        = 0x1,
+      LEON3_VENDOR_ESA            = 0x4,
+      LEON3_DEVICEID_MCTRL        = 0xF,
+
+      LEON3_AHB_BAR_MASK_SHIFT    = 4,
+      LEON3_AHB_BAR_MASK_MASK     = 0xFFF,
+      LEON3_AHB_BAR_ADDR_SHIFT    = 20,
+      LEON3_AHB_BAR_ADDR_MASK     = 0xFFF,
+
+      LEON3_MEMCFG2               = 0x80000004,
+      LEON3_MEMCFG2_SDRAMSZ_SHIFT =  23,
+      LEON3_MEMCFG2_SDRAMSZ_MASK  =   7,
+      LEON3_MEMCFG2_RAMSZ_SHIFT   =   9,
+      LEON3_MEMCFG2_SRAM_DISABLEF =  13,
+      LEON3_MEMCFG2_RAMSZ_MASK    = 0xF,
+
+      AHB_MASTER_TABLE      = 0xFFFFF000,
+      AHB_SLAVE_TABLE       = 0xFFFFF800,
+  };
+
+  long _ram_area_start;
+  long _ram_area_size;
+
+  void init()
+  {
+    static L4::Uart_leon3 _uart;
+    static L4::Io_register_block_mmio r(LEON3_APBUART); // XXX hard
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+
+    puts("Scanning AHB masters...");
+    unsigned *idx = (unsigned*)AHB_MASTER_TABLE;
+    while (*idx != 0)
+      {
+        check_device(idx);
+      }
+
+    puts("Scanning AHB slaves...");
+    idx = (unsigned*)AHB_SLAVE_TABLE;
+    while (*idx != 0)
+      {
+        check_device(idx);
+      }
+  }
+
+
+  void check_device(unsigned *&ahb_idx)
+  {
+    short vendor = (*ahb_idx >> 24) & 0xF;
+    short dev    = (*ahb_idx >> 12) & 0xFFF;
+
+    /* Special check: default RAM memory controller -> find out where the RAM area lies and
+     *                how large it is configured to be */
+    if ((vendor == (short)LEON3_VENDOR_ESA) && (dev == (short)LEON3_DEVICEID_MCTRL))
+      {
+        unsigned bar2_addr = (*(ahb_idx+6) >> LEON3_AHB_BAR_ADDR_SHIFT) & LEON3_AHB_BAR_ADDR_MASK;
+        unsigned bar2_mask = (*(ahb_idx+6) >> LEON3_AHB_BAR_MASK_SHIFT) & LEON3_AHB_BAR_MASK_MASK;
+        _ram_area_start = bar2_addr << 20;
+        _ram_area_size  = ~(bar2_mask << 20);
+        printf("RAM AREA: [%08lx - %08lx]\n",
+               _ram_area_start, _ram_area_start + _ram_area_size);
+      }
+    print_device(ahb_idx);
+  }
+
+  void print_device(unsigned *&ahb_idx)
+  {
+    short dev    = (*ahb_idx >> 24) & 0xF;
+    short vendor = (*ahb_idx >> 12) & 0xFFF;
+    printf("dev:vendor %04hx:%04hx\n", dev, vendor);
+    printf("%08x  %08x  %08x  %08x\n", *ahb_idx, *(ahb_idx+1), *(ahb_idx+2), *(ahb_idx+3));
+    ahb_idx += 4;
+    printf("%08x  %08x  %08x  %08x\n", *ahb_idx, *(ahb_idx+1), *(ahb_idx+2), *(ahb_idx+3));
+    ahb_idx += 4;
+    printf("--------------------------------------\n");
+  }
+
+  void setup_memory_map()
+  {
+    /* § 10.8.2
+       SDRAM area is mapped into the upper half of the RAM area defined by BAR2
+       register. When the SDRAM enable bit is set in MCFG2, the controller is
+       enabled and mapped into upper half of the RAM area as long as the SRAM
+       disable bit is not set. If the SRAM disable bit is set, all access to
+       SRAM is disabled and the SDRAM banks are mapped into the lower half of
+       the RAM area.
+     */
+    unsigned mcfg2      = *(unsigned*)LEON3_MEMCFG2;
+    unsigned ram_size   = (mcfg2 >> LEON3_MEMCFG2_RAMSZ_SHIFT) & LEON3_MEMCFG2_RAMSZ_MASK;
+    unsigned sdram_size = (mcfg2 >> LEON3_MEMCFG2_SDRAMSZ_SHIFT) & LEON3_MEMCFG2_SDRAMSZ_MASK;
+
+    sdram_size = 4 << sdram_size;
+
+    long sdram_base = _ram_area_start;
+    if (!(mcfg2 & LEON3_MEMCFG2_SRAM_DISABLEF))
+      sdram_base = _ram_area_start + ((_ram_area_size + 1) >> 1);
+
+#ifdef RAM_SIZE_MB
+    sdram_size = RAM_SIZE_MB;
+    sdram_base = RAM_BASE;
+#endif
+
+    printf("RAM:   %4d kB\n", (8192 << ram_size) / 1024);
+    printf("SDRAM: %4d MB\n", sdram_size);
+
+    mem_manager->ram->add(Region::n(sdram_base, sdram_base + (sdram_size << 20),
+                                    ".sdram", Region::Ram));
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_leon3);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/mmio_16550.h b/l4/pkg/bootstrap_custom/server/src/platform/mmio_16550.h
new file mode 100644 (file)
index 0000000..44337fe
--- /dev/null
@@ -0,0 +1,18 @@
+#include <startup.h>
+#include "support.h"
+#include <l4/drivers/uart_16550.h>
+
+static void setup_16550_mmio_uart(L4::Uart_16550 *uart)
+{
+  kuart.access_type = L4_kernel_options::Uart_type_mmio;
+  static L4::Io_register_block_mmio r(kuart.base_address, kuart.reg_shift);
+  uart->startup(&r);
+  uart->change_mode(3, kuart.baud);
+  set_stdio_uart(uart);
+
+  kuart_flags |=   L4_kernel_options::F_uart_base
+                 | L4_kernel_options::F_uart_baud;
+
+  if (kuart.irqno != L4_kernel_options::Uart_irq_none)
+    kuart_flags |= L4_kernel_options::F_uart_irq;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/mpc5200.cc b/l4/pkg/bootstrap_custom/server/src/platform/mpc5200.cc
new file mode 100644 (file)
index 0000000..732b020
--- /dev/null
@@ -0,0 +1,74 @@
+/**
+ * \file
+ * \brief  Support for the MPC52000
+ *
+ * \date   2009-02-16
+ * \author Sebastian Sumpf <sumpf@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 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 "support.h"
+#include <l4/drivers/uart_of.h>
+#include <l4/drivers/of_if.h>
+#include <l4/drivers/of_dev.h>
+
+namespace {
+class Platform_ppc_mpc52000 :
+  public Platform_base,
+  public Boot_modules_image_mode
+{
+  bool probe() { return true; }
+  Boot_modules *modules() { return this; }
+
+  void boot_kernel(unsigned long entry)
+  {
+    typedef void (*func)(l4util_mb_info_t *, unsigned long);
+    L4_drivers::Of_if of_if;
+    of_if.boot_finish();
+    ((func)entry)(0, of_if.get_prom());
+    exit(-100);
+  }
+
+  void init()
+  {
+    static L4::Uart_of _uart;
+    static L4::Io_register_block_mmio r(0);
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+  }
+
+  void setup_memory_map()
+  {
+    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));
+    mem_manager->ram->add(Region::n(0x0, ram_size, ".ram", Region::Ram));
+
+    // FIXME: move this somewhere else, it has mothing to do with
+    // memory setup
+#if 0
+    /* detect OF devices */
+    unsigned long drives_addr, drives_length;
+
+    if (of_if.detect_devices(&drives_addr, &drives_length))
+      {
+        mbi->flags |= L4UTIL_MB_DRIVE_INFO;
+        mbi->drives_addr   = drives_addr;
+        mbi->drives_length = drives_length;
+      }
+#endif
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_ppc_mpc52000);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/om.cc b/l4/pkg/bootstrap_custom/server/src/platform/om.cc
new file mode 100644 (file)
index 0000000..893616d
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * \file   support_om.cc
+ * \brief  Support for the OpenMoko platform
+ *
+ * \date   2008
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2008-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 "support.h"
+
+#include <l4/drivers/uart_s3c2410.h>
+#include <l4/drivers/uart_dummy.h>
+
+namespace {
+class Platform_arm_om : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+    static L4::Uart_s3c2410 _uart;
+    static L4::Io_register_block_mmio r(0x50000000);
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_om);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/omap.cc b/l4/pkg/bootstrap_custom/server/src/platform/omap.cc
new file mode 100644 (file)
index 0000000..674ccaf
--- /dev/null
@@ -0,0 +1,62 @@
+/*!
+ * \file   support_beagleboard.cc
+ * \brief  Support for the Beagleboard
+ *
+ * \date   2009-08
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 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 "support.h"
+#include <l4/drivers/uart_omap35x.h>
+
+namespace {
+class Platform_arm_omap : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+    static L4::Uart_omap35x _uart;
+#ifdef PLATFORM_TYPE_beagleboard
+    static L4::Io_register_block_mmio r(0x49020000);
+#elif defined(PLATFORM_TYPE_omap3evm)
+    static L4::Io_register_block_mmio r(0x4806a000);
+#elif defined(PLATFORM_TYPE_omap3_am33xx)
+    static L4::Io_register_block_mmio r(0x44e09000);
+#elif defined(PLATFORM_TYPE_pandaboard) || defined(PLATFORM_TYPE_omap5)
+    static L4::Io_register_block_mmio r(0x48020000);
+#else
+#error Unknown platform
+#endif
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+  }
+
+  void arm_switch_to_hyp()
+  {
+    register l4_umword_t f asm("r12") = 0x102;
+    asm volatile("push {fp}                 \n"
+                 "mcr p15, 0, sp, c13, c0, 2\n"
+                 "mov r0, pc                \n"
+                 ".inst 0xe1600071          \n"
+                 "mrc p15, 0, sp, c13, c0, 2\n"
+                 "pop {fp}                  \n"
+                 :
+                 : "r" (f)
+                 : "r0", "r1", "r2", "r3", "r4",
+                   "r5", "r6", "r7", "r8", "r9",
+                   "r10", "memory");
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_omap);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/pxa.cc b/l4/pkg/bootstrap_custom/server/src/platform/pxa.cc
new file mode 100644 (file)
index 0000000..6bfffac
--- /dev/null
@@ -0,0 +1,39 @@
+/*!
+ * \file   support_pxa.cc
+ * \brief  Support for the PXA platform
+ *
+ * \date   2008-01-04
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2008-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 "mmio_16550.h"
+#include "support.h"
+
+namespace {
+class Platform_arm_pxa : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+    kuart.base_address = 0x40100000;
+    kuart.reg_shift    = 2;
+    kuart.base_baud    = L4::Uart_16550::Base_rate_pxa;
+    kuart.baud         = 115200;
+    kuart.irqno        = -1;
+    static L4::Uart_16550 _uart(kuart.base_baud, 0, 1 << 6, 0, 0);
+    setup_16550_mmio_uart(&_uart);
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_pxa);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/rpi.cc b/l4/pkg/bootstrap_custom/server/src/platform/rpi.cc
new file mode 100644 (file)
index 0000000..1af3505
--- /dev/null
@@ -0,0 +1,37 @@
+/*!
+ * \file   rpi.cc
+ * \brief  Support for the Raspberry Pi
+ *
+ * \date   2013
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2013 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 "support.h"
+#include <l4/drivers/uart_pl011.h>
+
+namespace {
+
+class Platform_arm_rpi : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+    static L4::Io_register_block_mmio r(0x20201000);
+    static L4::Uart_pl011 _uart(3000000);
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_rpi);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/rv.cc b/l4/pkg/bootstrap_custom/server/src/platform/rv.cc
new file mode 100644 (file)
index 0000000..5f849bb
--- /dev/null
@@ -0,0 +1,38 @@
+/*!
+ * \file
+ * \brief  Support for the rv platform
+ *
+ * \date   2011
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2008-2011 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 "support.h"
+
+#include <l4/drivers/uart_pl011.h>
+
+namespace {
+
+class Platform_arm_rv : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+  void init()
+  {
+    static L4::Io_register_block_mmio r(0x10009000);
+    static L4::Uart_pl011 _uart(24019200);
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+  }
+};
+
+}
+
+REGISTER_PLATFORM(Platform_arm_rv);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/rv_vexpress.cc b/l4/pkg/bootstrap_custom/server/src/platform/rv_vexpress.cc
new file mode 100644 (file)
index 0000000..7d2a0c0
--- /dev/null
@@ -0,0 +1,45 @@
+/*!
+ * \file
+ * \brief  Support for the rv platform
+ *
+ * \date   2011
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2008-2011 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 "support.h"
+
+#include <l4/drivers/uart_pl011.h>
+
+namespace {
+
+class Platform_arm_rv_vexpress : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+  void init()
+  {
+    unsigned long m;
+    unsigned long uart_base = 0x10009000;
+
+    asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (m));
+    if ((m & 0x00000070) == 0x70)
+      uart_base = 0x1c090000;
+
+    static L4::Io_register_block_mmio r(uart_base);
+    static L4::Uart_pl011 _uart(24019200);
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+  }
+};
+
+}
+
+REGISTER_PLATFORM(Platform_arm_rv_vexpress);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/sa1000.cc b/l4/pkg/bootstrap_custom/server/src/platform/sa1000.cc
new file mode 100644 (file)
index 0000000..b9e65f0
--- /dev/null
@@ -0,0 +1,37 @@
+/*!
+ * \file   support_sa1000.cc
+ * \brief  Support for SA1000 platform
+ *
+ * \date   2008-01-02
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2008-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 "support.h"
+#include <l4/drivers/uart_sa1000.h>
+
+namespace {
+class Platform_arm_sa1000 : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+    static L4::Uart_sa1000 _uart;
+    static L4::Io_register_block_mmio r(0x80010000);
+    //static L4::Io_register_block_mmio r(0x80050000);
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_sa1000);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/sunxi.cc b/l4/pkg/bootstrap_custom/server/src/platform/sunxi.cc
new file mode 100644 (file)
index 0000000..691c4cf
--- /dev/null
@@ -0,0 +1,40 @@
+
+/*!
+ * \file
+ * \brief  Support for sunxi platforms
+ *
+ * \date   2013
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2013 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 "support.h"
+#include "mmio_16550.h"
+
+namespace {
+class Platform_arm_sunxi : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+    kuart.base_address = 0x01c28000;
+    kuart.reg_shift    = 2;
+    kuart.base_baud    = 1500000;
+    kuart.baud         = 115200;
+    kuart.irqno        = 33;
+    static L4::Uart_16550 _uart(kuart.base_baud, 0, 0, 0, 0);
+    setup_16550_mmio_uart(&_uart);
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_sunxi);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/tegra2.cc b/l4/pkg/bootstrap_custom/server/src/platform/tegra2.cc
new file mode 100644 (file)
index 0000000..243db01
--- /dev/null
@@ -0,0 +1,81 @@
+/*!
+ * \file
+ * \brief  Support for Tegra 2 platforms
+ *
+ * \date   2010-05
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2010 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.
+ */
+
+/* Init-code from http://android.git.kernel.org/?p=kernel/tegra.git */
+
+#include "support.h"
+#include "mmio_16550.h"
+
+namespace {
+class Platform_arm_tegra2 : public Platform_single_region_ram
+{
+  void some_delay(int d) const
+    {
+      for (int i = 0; i <  d; i++)
+        asm volatile("":::"memory");
+    }
+
+  bool probe() { return true; }
+
+  void init()
+  {
+    volatile unsigned long *addr;
+
+    addr = (volatile unsigned long *)0x600060a0;
+    *addr = 0x5011b00c;
+
+    /* PLLP_OUTA_0 */
+    addr = (volatile unsigned long *)0x600060a4;
+    *addr = 0x10031c03;
+
+    /* PLLP_OUTB_0 */
+    addr = (volatile unsigned long *)0x600060a8;
+    *addr = 0x06030a03;
+
+    /* PLLP_MISC_0 */
+    addr = (volatile unsigned long *)0x600060ac;
+    *addr = 0x00000800;
+
+    some_delay(1000000);
+
+    /* UARTD clock source is PLLP_OUT0 */
+    addr = (volatile unsigned long *)0x600061c0;
+    *addr = 0;
+
+    /* Enable clock to UARTD */
+    addr = (volatile unsigned long *)0x60006018;
+    *addr |= 2;
+    some_delay(5000);
+
+    /* Deassert reset to UARTD */
+    addr = (volatile unsigned long *)0x6000600c;
+    *addr &= ~2;
+
+    some_delay(5000);
+
+    kuart.base_address = 0x70006300;
+    kuart.reg_shift    = 2;
+    kuart.base_baud    = 13478400;
+    kuart.baud         = 115200;
+    kuart.irqno        = 122;
+    static L4::Uart_16550 _uart(kuart.base_baud, 0, 0, 0, 0);
+    setup_16550_mmio_uart(&_uart);
+ }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_tegra2);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/tegra3.cc b/l4/pkg/bootstrap_custom/server/src/platform/tegra3.cc
new file mode 100644 (file)
index 0000000..4d6b8ed
--- /dev/null
@@ -0,0 +1,50 @@
+/*!
+ * \file
+ * \brief  Support for Tegra 3 platforms
+ *
+ * \date   2013
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2013 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 "support.h"
+#include "mmio_16550.h"
+
+namespace {
+class Platform_arm_tegra3 : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+    switch (PLATFORM_UART_NR)
+      {
+      case 0:
+        kuart.base_address = 0x70006000;
+        kuart.irqno        = 68;
+        break;
+      default:
+      case 2:
+        kuart.base_address = 0x70006200;
+        kuart.irqno        = 78;
+        break;
+      };
+    kuart.reg_shift    = 2;
+    kuart.base_baud    = 25459200;
+    kuart.baud         = 115200;
+
+    static L4::Uart_16550 _uart(kuart.base_baud, 0, 0, 0, 0);
+    setup_16550_mmio_uart(&_uart);
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_tegra3);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/x86_efi_pc.cc b/l4/pkg/bootstrap_custom/server/src/platform/x86_efi_pc.cc
new file mode 100644 (file)
index 0000000..216cc44
--- /dev/null
@@ -0,0 +1,135 @@
+#include "support.h"
+#include "x86_pc-base.h"
+#include <string.h>
+
+#include "startup.h"
+#include "panic.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <efi.h>
+#include <efilib.h>
+#include <l4/util/irq.h> // l4util_cli
+
+namespace {
+
+static inline Region
+new_region(EFI_MEMORY_DESCRIPTOR const *td, char const *name,
+           Region::Type type, char sub = 0)
+{
+  return Region::n(td->PhysicalStart,
+                   td->PhysicalStart + (0x1000 * td->NumberOfPages),
+                   name, type, sub);
+}
+
+class Platform_x86_efi : public Platform_x86,
+  public Boot_modules_image_mode
+{
+public:
+  Boot_modules *modules() { return this; }
+
+  void init_efi(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
+  {
+    efi_image = image;
+    efi_systab = systab;
+
+    InitializeLib(efi_image, efi_systab);
+  }
+
+  void setup_memory_map()
+  {
+    UINTN num_entries;
+    UINTN key;
+    UINTN desc_size;
+    uint32_t desc_ver;
+
+    EFI_MEMORY_DESCRIPTOR *efi_mem_desc
+      = LibMemoryMap(&num_entries, &key, &desc_size, &desc_ver);
+
+    void *table;
+    EFI_GUID Acpi20TableGuid = ACPI_20_TABLE_GUID;
+    EFI_STATUS exit_status
+      = LibGetSystemConfigurationTable(&Acpi20TableGuid, &table);
+
+    if (exit_status != EFI_SUCCESS)
+        exit_status = LibGetSystemConfigurationTable(&AcpiTableGuid, &table);
+
+    if (exit_status != EFI_SUCCESS)
+      printf("No RDSP found in EFI system table\n");
+
+    exit_status = (EFI_STATUS)uefi_call_wrapper((void*)(BS->ExitBootServices), 2, efi_image, key);
+    if (exit_status != EFI_SUCCESS)
+      printf("EFI, ExitBootServices failed: %u\n", (unsigned)exit_status);
+    else
+      printf("Successfully exited EFI boot services.\n");
+
+    // UEFI may have enabled interrupts because of loaded device drivers
+    // Fiasco boot protocol requires interrupts to be disabled
+    l4util_cli();
+
+    enum
+    {
+      Acpi_rdsp = 0,
+      Acpi      = 3,
+      Nvs       = 4,
+    };
+
+
+    Region_list *ram = mem_manager->ram;
+    Region_list *regions = mem_manager->regions;
+
+    void *const map_end = (char *)efi_mem_desc + num_entries * desc_size;
+    for (char *d = (char *)efi_mem_desc; d < map_end; d += desc_size)
+      {
+        EFI_MEMORY_DESCRIPTOR *td = (EFI_MEMORY_DESCRIPTOR *)d;
+
+        switch (td->Type)
+          {
+          case EfiLoaderCode:
+          case EfiLoaderData:
+          case EfiBootServicesCode:
+          case EfiBootServicesData:
+          case EfiConventionalMemory:
+            ram->add(new_region(td, ".ram", Region::Ram));
+            break;
+          case EfiACPIReclaimMemory: // memory holds ACPI tables
+            regions->add(new_region(td, ".ACPI", Region::Arch, Acpi));
+            break;
+          case EfiACPIMemoryNVS: // memory reserved by firmware
+            regions->add(new_region(td, ".ACPI", Region::Arch, Nvs));
+            break;
+          }
+      }
+
+    // add region for ACPI tables
+    regions->add(Region::n(l4_trunc_page((l4_addr_t)table),
+                           l4_trunc_page((l4_addr_t)table) + L4_PAGESIZE,
+                           ".ACPI", Region::Info, Acpi_rdsp), true);
+
+    // merge adjacent regions
+    ram->optimize();
+  }
+
+private:
+  EFI_HANDLE efi_image;
+  EFI_SYSTEM_TABLE *efi_systab;
+};
+
+Platform_x86_efi _x86_pc_platform;
+}
+
+extern "C" EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab);
+EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
+{
+  _x86_pc_platform.init_efi(image, systab);
+  ctor_init();
+  Platform_base::platform = &_x86_pc_platform;
+  _x86_pc_platform.init();
+  _x86_pc_platform.setup_uart(_mbi_cmdline);
+  startup(_mbi_cmdline);
+
+  return EFI_SUCCESS;
+}
+
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/x86_pc-base.h b/l4/pkg/bootstrap_custom/server/src/platform/x86_pc-base.h
new file mode 100644 (file)
index 0000000..2319751
--- /dev/null
@@ -0,0 +1,898 @@
+#include "support.h"
+#include "startup.h"
+
+#include <l4/drivers/uart_16550.h>
+#include <l4/drivers/io_regblock_port.h>
+
+#include <string.h>
+#include "base_critical.h"
+#include "panic.h"
+
+#include <l4/util/cpu.h>
+#include <l4/util/port_io.h>
+#include <l4/cxx/static_container>
+
+#include <cassert>
+#include <cstdio>
+
+/** VGA console output */
+
+static void vga_init()
+{
+  /* Reset any scrolling */
+  l4util_out32(0xc, 0x3d4);
+  l4util_out32(0, 0x3d5);
+  l4util_out32(0xd, 0x3d4);
+  l4util_out32(0, 0x3d5);
+}
+
+static void vga_putchar(unsigned char c)
+{
+  static int ofs = -1, esc, esc_val, attr = 0x07;
+  unsigned char *vidbase = (unsigned char*)0xb8000;
+
+  base_critical_enter();
+
+  if (ofs < 0)
+    {
+      /* Called for the first time - initialize.  */
+      ofs = 80*2*24;
+      vga_putchar('\n');
+    }
+
+  switch (esc)
+    {
+    case 1:
+      if (c == '[')
+       {
+         esc++;
+         goto done;
+       }
+      esc = 0;
+      break;
+
+    case 2:
+      if (c >= '0' && c <= '9')
+       {
+         esc_val = 10*esc_val + c - '0';
+         goto done;
+       }
+      if (c == 'm')
+       {
+         attr = esc_val ? 0x0f : 0x07;
+         goto done;
+       }
+      esc = 0;
+      break;
+    }
+
+  switch (c)
+    {
+    case '\n':
+      memmove(vidbase, vidbase+80*2, 80*2*24);
+      memset(vidbase+80*2*24, 0, 80*2);
+      /* fall through... */
+    case '\r':
+      ofs = 0;
+      break;
+
+    case '\t':
+      ofs = (ofs + 8) & ~7;
+      break;
+
+    case '\033':
+      esc = 1;
+      esc_val = 0;
+      break;
+
+    default:
+      /* Wrap if we reach the end of a line.  */
+      if (ofs >= 80)
+       vga_putchar('\n');
+
+      /* Stuff the character into the video buffer. */
+       {
+         volatile unsigned char *p = vidbase + 80*2*24 + ofs*2;
+         p[0] = c;
+         p[1] = attr;
+         ofs++;
+       }
+      break;
+    }
+
+done:
+  base_critical_leave();
+}
+
+/** Poor man's getchar, only returns raw scan code. We don't need to know
+ * _which_ key was pressed, we only want to know _if_ a key was pressed. */
+static int raw_keyboard_getscancode(void)
+{
+  unsigned status, scan_code;
+
+  base_critical_enter();
+
+  l4util_cpu_pause();
+
+  /* Wait until a scan code is ready and read it. */
+  status = l4util_in8(0x64);
+  if ((status & 0x01) == 0)
+    {
+      base_critical_leave();
+      return -1;
+    }
+  scan_code = l4util_in8(0x60);
+
+  /* Drop mouse events */
+  if ((status & 0x20) != 0)
+    {
+      base_critical_leave();
+      return -1;
+    }
+
+  base_critical_leave();
+  return scan_code;
+}
+
+
+static inline l4_uint32_t
+pci_conf_addr(l4_uint32_t bus, l4_uint32_t dev, l4_uint32_t fn, l4_uint32_t reg)
+{ return 0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3); }
+
+static l4_uint32_t pci_read(unsigned char bus, l4_uint32_t dev,
+                            l4_uint32_t fn, l4_uint32_t reg,
+                            unsigned char width)
+{
+  l4util_out32(pci_conf_addr(bus, dev, fn, reg), 0xcf8);
+
+  switch (width)
+    {
+    case 8:  return l4util_in8(0xcfc + (reg & 3));
+    case 16: return l4util_in16((0xcfc + (reg & 3)) & ~1UL);
+    case 32: return l4util_in32(0xcfc);
+    }
+  return 0;
+}
+
+static void pci_write(unsigned char bus, l4_uint32_t dev,
+                      l4_uint32_t fn, l4_uint32_t reg,
+                      l4_uint32_t val, unsigned char width)
+{
+  l4util_out32(pci_conf_addr(bus, dev, fn, reg), 0xcf8);
+
+  switch (width)
+    {
+    case 8:  l4util_out8(val, 0xcfc + (reg & 3)); break;
+    case 16: l4util_out16(val, (0xcfc + (reg & 3)) & ~1UL); break;
+    case 32: l4util_out32(val, 0xcfc); break;
+    }
+}
+
+
+namespace {
+
+struct Resource
+{
+  enum Type { NO_BAR, IO_BAR, MEM_BAR };
+  Type type;
+  unsigned long base;
+  unsigned long len;
+  Resource() : type(NO_BAR) {}
+};
+
+enum { NUM_BARS = 6 };
+
+struct Serial_board
+{
+  enum Flags
+  {
+    F_bar_per_port = 0x10,
+  };
+
+  unsigned short flags;
+  unsigned short base_bar;
+  unsigned num_ports;
+  unsigned base_baud;
+  unsigned port_offset;
+  unsigned base_offset;
+  unsigned reg_shift;
+
+  Resource bars[NUM_BARS];
+
+  unsigned num_mem_bars() const
+  {
+    unsigned n = 0;
+    for (unsigned i = 0; i < NUM_BARS; ++i)
+      if (bars[i].type == Resource::MEM_BAR)
+        ++n;
+    return n;
+  }
+
+  unsigned num_io_bars() const
+  {
+    unsigned n = 0;
+    for (unsigned i = 0; i < NUM_BARS; ++i)
+      if (bars[i].type == Resource::IO_BAR)
+        ++n;
+    return n;
+  }
+
+  int first_io_bar()
+  {
+    for (unsigned i = 0; i < NUM_BARS; ++i)
+      if (bars[i].type == Resource::IO_BAR)
+        return i;
+    return -1;
+  }
+
+  l4_addr_t get_base(unsigned idx) const
+  {
+    if (idx >= num_ports)
+      idx = 0;
+
+    if (flags & F_bar_per_port)
+      return bars[base_bar + idx].base + base_offset;
+
+    return bars[base_bar].base + base_offset + port_offset * idx;
+  }
+
+  Resource::Type get_type() const
+  { return bars[base_bar].type; }
+};
+
+struct Pci_iterator
+{
+  unsigned bus;
+  unsigned dev;
+  unsigned func;
+
+  l4_uint32_t vd;
+
+  enum { Max_bus = 20 };
+
+  Pci_iterator() : bus(0), dev(0), func(0) {}
+  explicit Pci_iterator(unsigned bus, unsigned dev = 0, unsigned func = 0)
+  : bus(bus), dev(dev), func(func) {}
+
+  static Pci_iterator end() { return Pci_iterator(Max_bus, 0, 0); }
+
+  l4_uint32_t pci_read(l4_uint32_t reg, unsigned char width) const
+  { return ::pci_read(bus, dev, func, reg, width); }
+
+  void pci_write(l4_uint32_t reg, l4_uint32_t val, unsigned char width) const
+  { ::pci_write(bus, dev, func, reg, val, width); }
+
+  void enable_io() const
+  {
+    unsigned cmd = pci_read(4, 16);
+    pci_write(4, cmd | 1, 16);
+  }
+
+  void enable_mmio() const
+  {
+    unsigned cmd = pci_read(4, 16);
+    pci_write(4, cmd | 2, 16);
+  }
+
+  unsigned vendor() const { return vd & 0xffff; }
+  unsigned device() const { return vd >> 16; }
+  unsigned vendor_device() const { return vd; }
+
+  unsigned classcode() const { return pci_read(0x0b, 8); }
+  unsigned subclass()  const { return pci_read(0x0a, 8); }
+  unsigned prog() const { return pci_read(9, 8); }
+
+  bool operator == (Pci_iterator const &o) const
+  { return bus == o.bus && dev == o.dev && func == o.func; }
+
+  bool operator != (Pci_iterator const &o) const
+  { return !operator == (o); }
+
+  Pci_iterator const &operator ++ ()
+  {
+    for (; bus < Max_bus;)
+      {
+        if (func == 0)
+          {
+            unsigned char hdr_type = pci_read(0xe, 8);
+            if (hdr_type & 0x80)
+              ++func;
+            else
+              ++dev;
+          }
+        else if (func < 8)
+          ++func;
+        else
+          {
+            func = 0;
+            ++dev;
+          }
+
+        if (dev >= 32)
+          {
+            ++bus;
+            dev = 0;
+            func = 0;
+          }
+
+        vd = pci_read(0, 32);
+        if (vd == 0xffffffff)
+          continue;
+
+        return *this;
+      }
+
+    dev = 0;
+    func = 0;
+    return *this;
+  }
+
+};
+
+#if 0
+      if (classcode == 0x06 && subclass == 0x04)
+        buses++;
+#endif
+
+
+
+struct Bs_uart : L4::Uart_16550
+{
+  union Regs
+  {
+    cxx::Static_container<L4::Io_register_block_port> io;
+    cxx::Static_container<L4::Io_register_block_mmio> mem;
+  };
+
+  Resource::Type type;
+  bool ok;
+  Regs uart_regs;
+
+  Bs_uart(Serial_board *board, unsigned port, unsigned long baudrate)
+  : L4::Uart_16550(board->base_baud, 0, 0, 0x8 /* out2 */, 0), ok(false)
+  {
+    type = board->get_type();
+    if (type == Resource::IO_BAR)
+      {
+        unsigned base = board->get_base(port);
+        uart_regs.io.construct(base);
+        if (!startup(uart_regs.io))
+          {
+            printf("Could not find or enable UART\n");
+            return;
+          }
+      }
+    if (type == Resource::MEM_BAR)
+      {
+        l4_addr_t base = board->get_base(port);
+        uart_regs.mem.construct(base, board->reg_shift);
+        if (!startup(uart_regs.mem))
+          {
+            printf("Could not find or enable UART\n");
+            return;
+          }
+      }
+
+    if (!change_mode(L4::Uart_16550::MODE_8N1, baudrate))
+      {
+        printf("Could not find or enable UART\n");
+        return;
+      }
+
+    ok = true;
+  }
+
+};
+
+class Dual_uart : public L4::Uart
+{
+private:
+  L4::Uart *_u1, *_u2;
+
+public:
+  Dual_uart(L4::Uart *u1)
+  : _u1(u1), _u2(0)
+  {}
+
+  void set_uart2(L4::Uart *u2)
+  {
+    _u2 = u2;
+  }
+
+  bool startup(L4::Io_register_block const *)
+  {
+    return true;
+  }
+
+  void shutdown()
+  {
+    _u1->shutdown();
+    if (_u2)
+      _u2->shutdown();
+  }
+
+  ~Dual_uart() {}
+#if 0
+  bool enable_rx_irq(bool e)
+  {
+    bool r1 = _u1->enable_rx_irq(e);
+    bool r2 = _u2 ? _u2->enable_rx_irq(e) : false;
+    return r1 && r2;
+  }
+
+  bool enable_tx_irq(bool e)
+  {
+    bool r1 = _u1->enable_tx_irq(e);
+    bool r2 = _u2 ? _u2->enable_tx_irq(e) : false;
+    return r1 && r2;
+  }
+#endif
+
+  bool change_mode(Transfer_mode m, Baud_rate r)
+  {
+    bool r1 = _u1->change_mode(m, r);
+    bool r2 = _u2 ? _u2->change_mode(m, r) : false;
+    return r1 && r2;
+  }
+
+  int char_avail() const
+  {
+    return _u1->char_avail() || (_u2 && _u2->char_avail());
+  }
+
+  int get_char(bool blocking) const
+  {
+    int c;
+    do
+      {
+        c = _u1->get_char(false);
+        if (c == -1 && _u2)
+          c = _u2->get_char(false);
+      }
+    while (blocking && c == -1);
+    return c;
+  }
+
+  int write(char const *s, unsigned long count) const
+  {
+    int r = _u1->write(s, count);
+    if (_u2)
+      _u2->write(s, count);
+    return r;
+  }
+
+};
+
+
+}
+
+struct Pci_com_drv
+{
+  virtual bool setup(Pci_iterator const &i, Serial_board *board) const = 0;
+  virtual ~Pci_com_drv() = 0;
+
+  static void read_bars(Pci_iterator const &i, Serial_board *board);
+
+};
+
+inline Pci_com_drv::~Pci_com_drv() {}
+
+void
+Pci_com_drv::read_bars(Pci_iterator const &dev, Serial_board *board)
+{
+  for (int bar = 0; bar < NUM_BARS; ++bar)
+    {
+      int a = 0x10 + bar * 4;
+
+      unsigned v = dev.pci_read(a, 32);
+      dev.pci_write(a, ~0U, 32);
+      unsigned x = dev.pci_read(a, 32);
+      dev.pci_write(a, v, 32);
+
+      if (!v)
+        continue;
+
+      int s;
+      for (s = 2; s < 32; ++s)
+        if ((x >> s) & 1)
+          break;
+
+      board->bars[bar].base = v & ~3UL;
+      board->bars[bar].len = 1 << s;
+      board->bars[bar].type = (v & 1) ? Resource::IO_BAR : Resource::MEM_BAR;
+
+      if (0)
+        printf("BAR%d: %04x (sz=%d)\n", bar, v & ~3, 1 << s);
+    }
+}
+
+
+struct Pci_com_drv_default : Pci_com_drv
+{
+  bool setup(Pci_iterator const &dev, Serial_board *board) const
+  {
+    read_bars(dev, board);
+    int num_iobars = board->num_io_bars();
+
+    if (num_iobars != 1)
+      return false;
+
+    //int num_membars = board->num_mem_bars();
+    //if (num_membars > 1)
+    //  return false;
+
+    int first_port = board->first_io_bar();
+
+    board->port_offset = 8;
+    board->base_baud = L4::Uart_16550::Base_rate_x86;
+    board->base_bar = first_port;
+    board->num_ports = board->bars[first_port].len / board->port_offset;
+    board->flags = 0;
+    printf("   detected serial IO card: bar=%d ports=%d\n",
+           first_port, board->num_ports);
+    dev.enable_io();
+    return true;
+  }
+};
+
+struct Pci_com_drv_fallback : Pci_com_drv_default
+{
+  bool setup(Pci_iterator const &dev, Serial_board *board) const
+  {
+    // The default drivers only takes 7:80 typed devices
+    if (dev.classcode() != 7)
+      return false;
+
+    if (dev.subclass() != 0x80)
+      return false;
+
+    return Pci_com_drv_default::setup(dev, board);
+  }
+};
+
+
+
+
+struct Pci_com_drv_oxsemi : Pci_com_drv
+{
+  bool setup(Pci_iterator const &dev, Serial_board *board) const
+  {
+    read_bars(dev, board);
+    board->flags = 0;
+    board->num_ports = 0;
+
+    switch (dev.device())
+      {
+      case 0xc158:
+        board->num_ports = 2;
+        board->base_baud = 4000000;
+        board->port_offset = 0x200;
+        board->base_bar = 0;
+        board->base_offset = 0x1000;
+        board->reg_shift = 0;
+        break;
+      default:
+        break;
+      }
+
+    if (!board->num_ports)
+      return false;
+
+    printf("  found oxsemi PCI controller.\n");
+    dev.enable_mmio();
+    return true;
+  }
+};
+
+struct Pci_com_moschip : public Pci_com_drv
+{
+  bool setup(Pci_iterator const &dev, Serial_board *board) const
+  {
+    read_bars(dev, board);
+
+    int first_port = board->first_io_bar();
+
+    board->port_offset = 8;
+    board->base_baud = L4::Uart_16550::Base_rate_x86;
+    board->base_bar = first_port;
+    board->num_ports = board->bars[first_port].len / board->port_offset;
+    board->flags = 0;
+    printf("   detected serial IO card: bar=%d ports=%d\n",
+           first_port, board->num_ports);
+    dev.enable_io();
+    return true;
+  }
+
+};
+
+static Pci_com_drv_fallback _fallback_pci_com;
+static Pci_com_drv_default _default_pci_com;
+static Pci_com_drv_oxsemi _oxsemi_pci_com;
+static Pci_com_moschip _moschip;
+
+#define PCI_DEVICE_ID(vendor, device) \
+  (((unsigned)(device) << 16) | (unsigned)(vendor & 0xffff)), 0xffffffffU
+#define PCI_ANY_DEVICE 0, 0
+
+struct Pci_com_dev
+{
+  unsigned vendor_device;
+  unsigned mask;
+  Pci_com_drv *driver;
+};
+
+Pci_com_dev _devs[] = {
+  { PCI_DEVICE_ID(0x1415, 0xc158), &_oxsemi_pci_com },
+  { PCI_DEVICE_ID(0x9710, 0x9835), &_moschip },
+  { PCI_DEVICE_ID(0x9710, 0x9865), &_moschip },
+  { PCI_DEVICE_ID(0x9710, 0x9922), &_moschip },
+  { PCI_DEVICE_ID(0x8086, 0x8c3d), &_default_pci_com },
+  { PCI_ANY_DEVICE, &_fallback_pci_com },
+};
+
+enum { Num_known_devs = sizeof(_devs) / sizeof(_devs[0]) };
+
+
+static Pci_iterator
+_search_pci_serial_devs(Pci_iterator const &begin, Pci_iterator const &end,
+                        Serial_board *board, bool print)
+{
+  for (Pci_iterator i = begin; i != end; ++i)
+    {
+      if (print)
+        printf("%02x:%02x.%1x Class %02x.%02x Prog %02x: %04x:%04x\n",
+               i.bus, i.dev, i.func, i.classcode(), i.subclass(), i.prog(),
+               i.vendor(), i.device());
+
+      for (unsigned devs = 0; devs < Num_known_devs; ++devs)
+        if (   (i.vendor_device() & _devs[devs].mask) == _devs[devs].vendor_device
+            && _devs[devs].driver->setup(i, board))
+          return i;
+    }
+
+  return end;
+}
+
+static unsigned long
+search_pci_serial_devs(int card_idx, Serial_board *board)
+{
+  Pci_iterator end = Pci_iterator::end();
+  Pci_iterator i;
+  for (int card = 0; i != end; ++i, ++card) {
+    i = _search_pci_serial_devs(i, end, board, false);
+    if (card == card_idx)
+      return 1;
+  }
+
+  return 0;
+}
+
+static void
+scan_pci_uarts(Dual_uart *du, unsigned long baudrate)
+{
+  Serial_board board;
+  Pci_iterator end = Pci_iterator::end();
+  // classes should be 7:0
+  Pci_iterator i;
+  for (int card = 0; i != end; ++i, ++card)
+    {
+      i = _search_pci_serial_devs(i, end, &board, true);
+
+      if (i == end)
+        break;
+
+      for (unsigned p = 0; p < board.num_ports; ++p)
+        {
+          printf("probed PCI UART %02x:%02x.%1x\n",
+                 i.bus, i.dev, i.func);
+          Bs_uart u(&board, p, baudrate);
+          du->set_uart2(&u);
+          printf("probed PCI UART %02x:%02x.%1x\n"
+                 "to use this port set: -comport=pci:%d:%d\n",
+                 i.bus, i.dev, i.func, card, p);
+          du->set_uart2(0);
+        }
+    }
+  printf("done scanning PCI uarts\n");
+}
+
+class Uart_vga : public L4::Uart
+{
+public:
+  Uart_vga()
+  { }
+
+  bool startup(L4::Io_register_block const *)
+  {
+    vga_init();
+    return true;
+  }
+
+  ~Uart_vga() {}
+  void shutdown() {}
+  bool enable_rx_irq(bool) { return false; }
+  bool enable_tx_irq(bool) { return false; }
+  bool change_mode(Transfer_mode, Baud_rate) { return true; }
+  int get_char(bool blocking) const
+  {
+    int c;
+    do
+      c = raw_keyboard_getscancode();
+    while (blocking && c == -1);
+    return c;
+  }
+
+  int char_avail() const
+  {
+    return raw_keyboard_getscancode() != -1;
+  }
+
+  int write(char const *s, unsigned long count) const
+  {
+    unsigned long c = count;
+    while (c)
+      {
+        if (*s == 10)
+          vga_putchar(13);
+        vga_putchar(*s++);
+        --c;
+      }
+    return count;
+  }
+};
+
+
+static void
+legacy_uart(unsigned com_port_or_base, int &com_irq, Serial_board *board)
+{
+  switch (com_port_or_base)
+    {
+    case 1: com_port_or_base = 0x3f8;
+            if (com_irq == -1)
+              com_irq = 4;
+            break;
+    case 2: com_port_or_base = 0x2f8;
+            if (com_irq == -1)
+              com_irq = 3;
+            break;
+    case 3: com_port_or_base = 0x3e8; break;
+    case 4: com_port_or_base = 0x2e8; break;
+    }
+
+  board->num_ports = 1;
+  board->bars[0].type = Resource::IO_BAR;
+  board->bars[0].base = com_port_or_base;
+  board->base_bar = 0;
+  board->flags = 0;
+  board->base_offset = 0;
+  board->port_offset = 8;
+  board->base_baud = L4::Uart_16550::Base_rate_x86;
+  board->reg_shift = 0;
+}
+
+
+class Platform_x86 : public Platform_base
+{
+public:
+#ifdef ARCH_amd64
+  ptab64_mem_info_t const *ptab64_info;
+#endif
+  bool probe() { return true; }
+
+  int init_uart(Serial_board *board, int port, int com_irq, Dual_uart *du)
+  {
+    base_critical_enter();
+    unsigned baudrate = 115200;
+
+    static cxx::Static_container<Bs_uart> uart;
+    uart.construct(board, port, baudrate);
+
+    if (!uart->ok)
+      {
+        base_critical_leave();
+        return 1;
+      }
+
+    if (uart->type == Resource::IO_BAR)
+      {
+        unsigned base = board->get_base(port);
+        kuart.access_type  = L4_kernel_options::Uart_type_ioport;
+        kuart.base_address = base;
+        printf("UART IO: @%x\n", base);
+      }
+    if (uart->type == Resource::MEM_BAR)
+      {
+        l4_addr_t base = board->get_base(port);
+        kuart.access_type  = L4_kernel_options::Uart_type_mmio;
+        kuart.base_address = base;
+        printf("UART MMIO: @%p\n", (void*)base);
+      }
+
+    kuart.base_baud = board->base_baud;
+    kuart.baud = baudrate;
+    kuart.reg_shift = board->reg_shift;
+
+    du->set_uart2(uart);
+
+    kuart.irqno        = com_irq;
+    kuart_flags       |=   L4_kernel_options::F_uart_base
+                         | L4_kernel_options::F_uart_baud;
+    if (com_irq != -1)
+      kuart_flags |= L4_kernel_options::F_uart_irq;
+
+    base_critical_leave();
+    return 0;
+  }
+
+  void init()
+  {};
+
+  void setup_uart(char const *cmdline)
+  {
+    const char *s;
+    int comport = -1;
+    int comirq = -1;
+    int pci = 0;
+    static Uart_vga _vga;
+    static Dual_uart du(&_vga);
+    set_stdio_uart(&du);
+
+    if ((s = check_arg(cmdline, "-comirq")))
+      {
+        s += 8;
+        comirq = strtoul(s, 0, 0);
+      }
+
+    if ((s = check_arg(cmdline, "-comport")))
+      {
+        s += 9;
+        if ((pci = !strncmp(s, "pci:", 4)))
+          s += 4;
+
+        if (pci && !strncmp(s, "probe", 5))
+          {
+            scan_pci_uarts(&du, 115200);
+            reboot();
+          }
+
+        char *ep;
+        comport = strtoul(s, &ep, 0);
+        if (pci && *ep == ':')
+          {
+            pci = comport + 1;
+            comport = strtoul(ep + 1, 0, 0);
+          }
+      }
+
+    if (!check_arg(cmdline, "-noserial"))
+      {
+        Serial_board board;
+        if (pci)
+          {
+            if (!search_pci_serial_devs(pci - 1, &board))
+              {
+                legacy_uart(1, comirq, &board);
+                comport = 0;
+              }
+          }
+        else if (comport == -1)
+          {
+            legacy_uart(1, comirq, &board);
+            comport = 0;
+          }
+        else
+          {
+            legacy_uart(comport, comirq, &board);
+            comport = 0;
+          }
+
+        if (init_uart(&board, comport, comirq, &du))
+          {
+            kuart_flags |= L4_kernel_options::F_noserial;
+            printf("UART init failed\n");
+          }
+      }
+    else
+      kuart_flags |= L4_kernel_options::F_noserial;
+  }
+};
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/x86_pc.cc b/l4/pkg/bootstrap_custom/server/src/platform/x86_pc.cc
new file mode 100644 (file)
index 0000000..85a1c15
--- /dev/null
@@ -0,0 +1,389 @@
+/*!
+ * \file   support_x86.cc
+ * \brief  Support for the x86 platform
+ *
+ * \date   2008-01-02
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2008-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 "support.h"
+#include "x86_pc-base.h"
+
+#include <string.h>
+#include "startup.h"
+#include "panic.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+enum { Verbose_mbi = 1 };
+
+namespace {
+
+#ifdef REALMODE_LOADING
+struct Platform_x86_1 : Platform_x86
+{
+  char const *realmode_pointer;
+
+  void setup_memory_map()
+  {
+    Region_list *ram = mem_manager->ram;
+    Region_list *regions = mem_manager->regions;
+
+    unsigned long m = *(l4_uint32_t*)(realmode_pointer + 0x1e0);
+    printf("Detected memory size: %ldKB\n", m);
+    ram->add(Region::n(0, 0x9fc00, ".ram", Region::Ram));
+    ram->add(Region::n(0x100000, (m + 1024) << 10, ".ram", Region::Ram));
+    regions->add(Region::n(0, 0x1000, ".BIOS", Region::Arch, 0));
+    // Quirks
+
+    // Fix EBDA in conventional memory
+    unsigned long p = *(l4_uint16_t *)0x40e << 4;
+
+    if (p > 0x400)
+      {
+        unsigned long e = p + 1024;
+        Region *r = ram->find(Region(p, e - 1));
+        if (r)
+          {
+            if (e - 1 < r->end())
+              ram->add(Region::n(e, r->end(), ".ram", Region::Ram), true);
+            r->end(p);
+          }
+      }
+  }
+
+  char const *cmdline() const
+  {
+    return 0;
+    l4_uint32_t p = *(l4_uint32_t*)(realmode_pointer + 0x228);
+    if (!p)
+      return 0;
+
+    return (char const *)p;
+  }
+};
+
+#else // REALMODE_LOADING
+
+struct Platform_x86_1 : Platform_x86
+{
+  l4util_mb_info_t *mbi;
+
+  void setup_memory_map()
+  {
+    Region_list *ram = mem_manager->ram;
+    Region_list *regions = mem_manager->regions;
+
+#ifdef ARCH_amd64
+    // add the page-table on which we're running in 64bit mode
+    regions->add(Region::n(ptab64_info->addr, ptab64_info->addr + ptab64_info->size,
+                 ".bootstrap-ptab64", Region::Boot));
+#endif
+   if (!(mbi->flags & L4UTIL_MB_MEM_MAP))
+      {
+        assert(mbi->flags & L4UTIL_MB_MEMORY);
+        ram->add(Region::n(0, (mbi->mem_lower + 1024) << 10, ".ram",
+                           Region::Ram));
+        ram->add(Region::n(0x100000, (mbi->mem_upper + 1024) << 10, ".ram",
+                           Region::Ram));
+      }
+    else
+      {
+        l4util_mb_addr_range_t *mmap;
+        l4util_mb_for_each_mmap_entry(mmap, mbi)
+          {
+            unsigned long long start = (unsigned long long)mmap->addr;
+            unsigned long long end = (unsigned long long)mmap->addr + mmap->size;
+
+            switch (mmap->type)
+              {
+              case 1:
+                ram->add(Region::n(start, end, ".ram", Region::Ram));
+                break;
+              case 2:
+              case 3:
+              case 4:
+                regions->add(Region::n(start, end, ".BIOS", Region::Arch, mmap->type));
+                break;
+              case 5:
+                regions->add(Region::n(start, end, ".BIOS", Region::No_mem));
+                break;
+              default:
+                break;
+              }
+          }
+      }
+
+    regions->add(Region::n(0, 0x1000, ".BIOS", Region::Arch, 0));
+
+
+    // Quirks
+
+    // Fix EBDA in conventional memory
+    unsigned long p = *(l4_uint16_t *)0x40e << 4;
+
+    if (p > 0x400)
+      {
+        unsigned long e = p + 1024;
+        Region *r = ram->find(Region(p, e - 1));
+        if (r)
+          {
+            if (e - 1 < r->end())
+              ram->add(Region::n(e, r->end(), ".ram", Region::Ram), true);
+            r->end(p);
+          }
+      }
+  }
+};
+
+#endif // !REALMODE_LOADING
+
+
+#ifdef IMAGE_MODE
+
+class Platform_x86_loader_mbi :
+  public Platform_x86_1,
+  public Boot_modules_image_mode
+{
+public:
+  Boot_modules *modules() { return this; }
+
+};
+
+Platform_x86_loader_mbi _x86_pc_platform;
+
+#else // IMAGE_MODE
+
+class Platform_x86_multiboot : public Platform_x86_1, public Boot_modules
+{
+public:
+  Boot_modules *modules() { return this; }
+
+  Module module(unsigned index, bool) const
+  {
+    Module m;
+    l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t*)(unsigned long)mbi->mods_addr;
+
+    m.start   = (char const *)(l4_addr_t)mb_mod[index].mod_start;
+    m.end     = (char const *)(l4_addr_t)mb_mod[index].mod_end;
+    m.cmdline = (char const *)(l4_addr_t)mb_mod[index].cmdline;
+    return m;
+  }
+
+  unsigned num_modules() const { return mbi->mods_count; }
+
+  void reserve()
+  {
+    Region_list *regions = mem_manager->regions;
+
+    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((char const *)(l4_addr_t)mbi->cmdline) + 1,
+                             ".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));
+
+    if (mbi->flags & L4UTIL_MB_VIDEO_INFO)
+      {
+        if (mbi->vbe_mode_info)
+          regions->add(Region::start_size(mbi->vbe_mode_info,
+                                          sizeof(l4util_mb_vbe_mode_t),
+                                          ".mbi", Region::Boot));
+        if (mbi->vbe_ctrl_info)
+          regions->add(Region::start_size(mbi->vbe_ctrl_info,
+                                          sizeof(l4util_mb_vbe_ctrl_t),
+                                          ".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((char const *)(l4_addr_t)mb_mod[i].cmdline) + 1,
+                             ".mbi", Region::Boot));
+
+    for (unsigned i = 0; i < mbi->mods_count; ++i)
+      regions->add(mod_region(i, mb_mod[i].mod_start,
+                              mb_mod[i].mod_end - mb_mod[i].mod_start));
+  }
+
+  void move_module(unsigned index, void *dest,
+                   bool overlap_check)
+  {
+    l4util_mb_mod_t *mod = (l4util_mb_mod_t*)(unsigned long)mbi->mods_addr + index;
+    unsigned long size = mod->mod_end - mod->mod_start;
+    _move_module(index, dest, (char const *)(l4_addr_t)mod->mod_start,
+                 size, overlap_check);
+
+    assert ((l4_addr_t)dest < 0xfffffff0);
+    assert ((l4_addr_t)dest < 0xfffffff0 - size);
+    mod->mod_start = (l4_addr_t)dest;
+    mod->mod_end   = (l4_addr_t)dest + size;
+  }
+
+  l4util_mb_info_t *construct_mbi(unsigned long mod_addr)
+  {
+    // calculate the size needed to cover the full MBI, including command lines
+    unsigned long total_size = sizeof(l4util_mb_info_t);
+
+    // consider the global command line
+    if (mbi->flags & L4UTIL_MB_CMDLINE)
+      total_size += round_wordsize(strlen((char const *)(l4_addr_t)mbi->cmdline) + 1);
+
+    // consider VBE info
+    if (mbi->flags & L4UTIL_MB_VIDEO_INFO)
+      {
+        if (mbi->vbe_mode_info)
+          total_size += sizeof(l4util_mb_vbe_mode_t);
+
+        if (mbi->vbe_ctrl_info)
+          total_size += sizeof(l4util_mb_vbe_ctrl_t);
+      }
+
+    // consider modules
+    total_size += sizeof(l4util_mb_mod_t) * mbi->mods_count;
+
+    // scan through all modules and add the command line
+    l4util_mb_mod_t *mods = (l4util_mb_mod_t*)(unsigned long)mbi->mods_addr;
+    for (l4util_mb_mod_t *m = mods; m != mods + mbi->mods_count; ++m)
+      if (m->cmdline)
+        total_size += round_wordsize(strlen((char const *)(l4_addr_t)m->cmdline) + 1);
+
+    if (Verbose_mbi)
+      printf("  need %ld bytes to copy MBI\n", total_size);
+
+    // try to find a free region for the MBI
+    char *_mb = (char *)mem_manager->find_free_ram(total_size);
+    if (!_mb)
+      panic("fatal: could not allocate memory for multi-boot info\n");
+
+    // mark the region as reserved
+    mem_manager->regions->add(Region::start_size((l4_addr_t)_mb, total_size, ".mbi_rt",
+                                                 Region::Root));
+    if (Verbose_mbi)
+      printf("  reserved %ld bytes at %p\n", total_size, _mb);
+
+    // copy the whole MBI
+    l4util_mb_info_t *dst = (l4util_mb_info_t *)_mb;
+    *dst = *mbi;
+
+    l4util_mb_mod_t *dst_mods = (l4util_mb_mod_t *)(dst + 1);
+    dst->mods_addr = (l4_addr_t)dst_mods;
+    _mb = (char *)(dst_mods + mbi->mods_count);
+
+    if (mbi->flags & L4UTIL_MB_VIDEO_INFO)
+      {
+        if (mbi->vbe_mode_info)
+          {
+            l4util_mb_vbe_mode_t *d = (l4util_mb_vbe_mode_t *)_mb;
+            *d = *((l4util_mb_vbe_mode_t *)(l4_addr_t)mbi->vbe_mode_info);
+            dst->vbe_mode_info = (l4_addr_t)d;
+            _mb = (char *)(d + 1);
+          }
+
+        if (mbi->vbe_ctrl_info)
+          {
+            l4util_mb_vbe_ctrl_t *d = (l4util_mb_vbe_ctrl_t *)_mb;
+            *d = *((l4util_mb_vbe_ctrl_t *)(l4_addr_t)mbi->vbe_ctrl_info);
+            dst->vbe_ctrl_info = (l4_addr_t)d;
+            _mb = (char *)(d + 1);
+          }
+      }
+
+    if (mbi->cmdline)
+      {
+        strcpy(_mb, (char const *)(l4_addr_t)mbi->cmdline);
+        dst->cmdline = (l4_addr_t)_mb;
+        _mb += round_wordsize(strlen(_mb) + 1);
+      }
+
+    for (unsigned i = 0; i < mbi->mods_count; ++i)
+      {
+        dst_mods[i] = mods[i];
+        if (char const *c = (char const *)(l4_addr_t)(mods[i].cmdline))
+          {
+            unsigned l = strlen(c) + 1;
+            dst_mods[i].cmdline = (l4_addr_t)_mb;
+            memcpy(_mb, c, l);
+            _mb += round_wordsize(l);
+          }
+      }
+
+    mbi = dst;
+
+    // remove the old MBI from the reserved memory
+    for (Region *r = mem_manager->regions->begin();
+         r != mem_manager->regions->end();)
+      {
+        if (strcmp(r->name(), ".mbi"))
+          ++r;
+        else
+          r = mem_manager->regions->remove(r);
+      }
+
+    move_modules(mod_addr);
+    return mbi;
+  }
+};
+
+Platform_x86_multiboot _x86_pc_platform;
+
+#endif // !IMAGE_MODE
+}
+
+extern "C"
+void __main(l4util_mb_info_t *mbi, unsigned long p2, char const *realmode_si,
+            ptab64_mem_info_t const *ptab64_info);
+
+void __main(l4util_mb_info_t *mbi, unsigned long p2, char const *realmode_si,
+            ptab64_mem_info_t const *ptab64_info)
+{
+  ctor_init();
+  Platform_base::platform = &_x86_pc_platform;
+  _x86_pc_platform.init();
+#ifdef ARCH_amd64
+  // remember this info to reserve the memory in setup_memory_map later
+  _x86_pc_platform.ptab64_info = ptab64_info;
+#else
+  (void)ptab64_info;
+#endif
+  char const *cmdline;
+#if defined(REALMODE_LOADING)
+  /* create synthetic multi boot info, if loaded from realmode */
+  (void)mbi;
+  (void)p2;
+  _x86_pc_platform.realmode_pointer = realmode_si;
+  cmdline = _x86_pc_platform.cmdline();
+  if (!cmdline)
+    cmdline = _mbi_cmdline;
+#else
+  (void)realmode_si;
+  assert(p2 == L4UTIL_MB_VALID); /* we need to be multiboot-booted */
+  _x86_pc_platform.mbi = mbi;
+  cmdline = (char const *)(l4_addr_t)mbi->cmdline;
+#endif
+  _x86_pc_platform.setup_uart(cmdline);
+
+  startup(cmdline);
+}
+
+
diff --git a/l4/pkg/bootstrap_custom/server/src/platform/zynq.cc b/l4/pkg/bootstrap_custom/server/src/platform/zynq.cc
new file mode 100644 (file)
index 0000000..0694536
--- /dev/null
@@ -0,0 +1,49 @@
+/*!
+ * \file
+ * \brief  Support for Zynq platforms
+ *
+ * \date   2013
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2013 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 "support.h"
+#include <l4/drivers/uart_cadence.h>
+
+namespace {
+class Platform_arm_zynq : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+    static L4::Uart_cadence _uart;
+    unsigned long uart_addr;
+    switch (PLATFORM_UART_NR) {
+      case 0: uart_addr = 0xe0000000; // qemu
+      default:
+      case 1: uart_addr = 0xe0001000; // zedboard
+    };
+    static L4::Io_register_block_mmio r(uart_addr);
+    _uart.startup(&r);
+    _uart.change_mode(3, 115200);
+    set_stdio_uart(&_uart);
+  }
+
+  void reboot()
+  {
+    L4::Io_register_block_mmio r(0xf8000200);
+    r.write<unsigned>(1, 0);
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_zynq);
diff --git a/l4/pkg/bootstrap_custom/server/src/platform_common.cc b/l4/pkg/bootstrap_custom/server/src/platform_common.cc
new file mode 100644 (file)
index 0000000..0503802
--- /dev/null
@@ -0,0 +1,74 @@
+#include "support.h"
+#include <l4/cxx/minmax>
+#include <cassert>
+
+#ifdef RAM_SIZE_MB
+
+static unsigned long
+scan_ram_size(unsigned long base_addr, unsigned long max_scan_size_mb)
+{
+  // scan the RAM to find out the RAM size, note that at this point we have
+  // two regions in RAM that we cannot touch, &_start - &_end and the
+  // modules
+
+  // assume that the image is loaded correctly and we need to start
+  // probing for memory wraparounds beyond the end of our image
+  extern char _end[];
+#ifdef IMAGE_MODE
+  extern char _module_data_end[];
+  l4_addr_t lower_bound
+    = l4_round_size((l4_addr_t)cxx::max(_end, _module_data_end), 20);
+#else
+  l4_addr_t lower_bound = l4_round_size((l4_addr_t)_end, 20);
+#endif
+
+  assert(base_addr <= lower_bound);
+  lower_bound -= base_addr;
+
+  // must be a power of 2 and >= (1 << 20)
+  unsigned long increment;
+  unsigned long max_scan_size = max_scan_size_mb << 20;
+
+  // push the initial probe point beyond lower_bound
+  for (increment = 1 << 20;
+       increment < lower_bound && increment < max_scan_size;
+       increment *= 2)
+    {}
+
+  printf("  Scanning up to %ld MB RAM, starting at offset %ldMB\n",
+         max_scan_size_mb, increment >> 20);
+
+  // initialize memory probe points
+  for (unsigned long offset = increment;
+       offset < max_scan_size;
+       offset *= 2)
+    *(unsigned long *)(base_addr + offset) = 0;
+
+  // avoid gcc/clang optimization figuring out that base_addr might
+  // always be 0 and generating a trap here
+  asm("" : "+r" (base_addr));
+  // write something at offset 0, does it appear elsewhere?
+  *(unsigned long *)base_addr = 0x12345678;
+  asm volatile("" : : : "memory");
+  for (unsigned long offset = increment;
+       offset < max_scan_size;
+       offset *= 2)
+    if (*(unsigned long *)(base_addr + offset) == 0x12345678)
+      return offset >> 20;  // detected a wrap around at offset
+
+  return max_scan_size_mb;
+}
+
+void
+Platform_single_region_ram::setup_memory_map()
+{
+  unsigned long ram_size_mb = scan_ram_size(RAM_BASE, RAM_SIZE_MB);
+  printf("  Memory size is %ldMB%s (%08lx - %08lx)\n",
+         ram_size_mb, ram_size_mb != RAM_SIZE_MB ? " (Limited by Scan)" : "",
+         (unsigned long)RAM_BASE, RAM_BASE + (ram_size_mb << 20) - 1);
+  mem_manager->ram->add(
+      Region::n(RAM_BASE,
+                (unsigned long long)RAM_BASE + (ram_size_mb << 20),
+                ".ram", Region::Ram));
+}
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/region.cc b/l4/pkg/bootstrap_custom/server/src/region.cc
new file mode 100644 (file)
index 0000000..6e5e45f
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *               Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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 <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "panic.h"
+#include <l4/util/l4_macros.h>
+
+#include "region.h"
+#include "module.h"
+
+unsigned long long
+Region_list::find_free(Region const &search, unsigned long long _size,
+                       unsigned align) const
+{
+  unsigned long long start = search.begin();
+  unsigned long long end   = search.end();
+  while (1)
+    {
+      start = (start + (1ULL << align) -1) & ~((1ULL << align)-1);
+
+      if (start + _size - 1 > end)
+        return 0;
+
+      if (0)
+        printf("try start %p\n", (void *)start);
+
+      Region *z = find(Region::start_size(start, _size));
+      if (!z)
+        return start;
+
+      start = z->end() + 1;
+    }
+}
+
+unsigned long long
+Region_list::find_free_rev(Region const &search, unsigned long long _size,
+                           unsigned align) const
+{
+  unsigned long long start = search.begin();
+  unsigned long long end   = search.end();
+  while (1)
+    {
+      end -= _size - 1;
+      end &= ~((1ULL << align)-1);
+
+      if (end < start)
+        return 0;
+
+      if (0)
+        printf("try start %p\n", (void *)end);
+
+      Region *z = find(Region::start_size(end, _size));
+      if (!z)
+        return end;
+
+      end = z->begin() - 1;
+    }
+}
+
+void
+Region_list::add_nolimitcheck(Region const &region, bool may_overlap)
+{
+  Region const *r;
+
+  /* Do not add empty regions */
+  if (region.begin() == region.end())
+    return;
+
+  if (_end >= _max)
+    {
+      // try to merge adjacent regions to gain space
+      optimize();
+
+      if (_end >= _max)
+        panic("Bootstrap: %s: Region overflow\n", __func__);
+    }
+
+  if (!may_overlap && (r = find(region)))
+    {
+      printf("  New region for list %s:\t", _name);
+      region.vprint();
+      printf("  overlaps with:         \t");
+      r->vprint();
+
+      dump();
+      panic("region overlap");
+    }
+
+  *_end = region;
+  ++_end;
+  _combined_size += region.size();
+}
+
+void
+Region_list::add(Region const &region, bool may_overlap)
+{
+  Region mem = region;
+
+  if (mem.invalid())
+    {
+      printf("  WARNING: trying to add invalid region to %s list.\n", _name);
+      return;
+    }
+
+  if (mem.begin() > _address_limit)
+    {
+      printf("  Dropping '%s' region ", _name);
+      mem.print();
+      printf(" due to %lld MB address limit\n", _address_limit >> 20);
+      return;
+    }
+
+  if (mem.end() >= _address_limit)
+    {
+      printf("  Limiting '%s' region ", _name);
+      mem.print();
+      mem.end(_address_limit - 1);
+      printf(" to ");
+      mem.print();
+      printf(" due to %lld MB address limit\n", _address_limit >> 20);
+
+    }
+
+  if (_combined_size >= _max_combined_size)
+    {
+      printf("  Dropping '%s' region ", _name);
+      mem.print();
+      printf(" due to %lld MB size limit\n", _max_combined_size >> 20);
+      return;
+    }
+
+  if (_combined_size + mem.size() > _max_combined_size)
+    {
+      printf("  Limiting '%s' region ", _name);
+      mem.print();
+      mem.end(mem.begin() + _max_combined_size - _combined_size - 1);
+      printf(" to ");
+      mem.print();
+      printf(" due to %lld MB size limit\n", _max_combined_size >> 20);
+    }
+
+  add_nolimitcheck(mem, may_overlap);
+}
+
+Region *
+Region_list::find(Region const &o) const
+{
+  for (Region *c = _reg; c < _end; ++c)
+    if (c->overlaps(o))
+      return c;
+
+  return 0;
+}
+
+Region *
+Region_list::contains(Region const &o)
+{
+  for (Region *c = _reg; c < _end; ++c)
+    if (c->contains(o))
+      return c;
+
+  return 0;
+}
+
+void
+Region::print() const
+{
+  printf("  [%9llx, %9llx] {%9llx}", begin(), end(), size());
+}
+
+void
+Region::vprint() const
+{
+  static char const *types[] = {"Gap   ", "Kern  ", "Sigma0",
+                                "Boot  ", "Root  ", "Arch  ", "Ram   ",
+                                "Info  " };
+  printf("  ");
+  print();
+  printf(" %s ", types[type()]);
+  if (name())
+    {
+      if (*name() == '.')
+       printf("%s", name() + 1);
+      else
+       print_module_name(name(), "");
+    }
+  putchar('\n');
+}
+
+void
+Region_list::dump()
+{
+  Region const *i;
+  Region const *j;
+  unsigned long long min, mark = 0;
+
+  printf("Regions of list '%s'\n", _name);
+  for (i = _reg; i < _end; ++i)
+    {
+      min = ~0;
+      Region const *min_idx = 0;
+      for (j = _reg; j < _end; ++j)
+       if (j->begin() < min && j->begin() >= mark)
+         {
+           min     = j->begin();
+           min_idx = j;
+         }
+      if (!min_idx)
+        {
+          i->vprint();
+          continue;
+        }
+      min_idx->vprint();
+      mark = min_idx->begin() + 1;
+    }
+}
+
+void
+Region_list::swap(Region *a, Region *b)
+{
+  Region t = *a; *a = *b; *b = t;
+}
+
+void
+Region_list::sort()
+{
+  if (end() - begin() < 2)
+    return;
+  bool swapped;
+
+  Region *e = end() - 1;
+
+  do
+    {
+      swapped = false;
+      for (Region *c = begin(); c < e; ++c)
+       {
+         Region *n = c; ++n;
+         if (*n < *c)
+           {
+             swap(c,n);
+             swapped = true;
+           }
+       }
+    }
+  while (swapped);
+}
+
+Region *
+Region_list::remove(Region *r)
+{
+  memmove(r, r+1, (end() - r - 1)*sizeof(Region));
+  --_end;
+  return r;
+}
+
+void
+Region_list::optimize()
+{
+  sort();
+  Region *c = begin();
+  while (c < end())
+    {
+      Region *n = c; ++n;
+      if (n == end())
+       return;
+
+      if (n->type() == c->type() && n->sub_type() == c->sub_type()
+         && n->name() == c->name() &&
+         l4_round_page(c->end()) >= l4_trunc_page(n->begin()))
+       {
+         c->end(n->end());
+         remove(n);
+       }
+      else
+       ++c;
+    }
+}
+
+bool
+Region_list::sub(Region const &r)
+{
+  Region *c = contains(r);
+  if (!c)
+    return false;
+
+  if (c->begin() == r.begin() && c->end() == r.end())
+    {
+      remove(c);
+      return true;
+    }
+
+  if (c->begin() == r.begin())
+    {
+      c->begin(r.end() + 1);
+      return true;
+    }
+
+  if (c->end() == r.end())
+    {
+      c->end(r.begin() - 1);
+      return true;
+    }
+
+  Region tail(*c);
+  tail.begin(r.end() + 1);
+  c->end(r.begin() - 1);
+  add(tail);
+  return true;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/region.h b/l4/pkg/bootstrap_custom/server/src/region.h
new file mode 100644 (file)
index 0000000..3a5840a
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *               Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef REGION_H
+#define REGION_H
+
+#include <l4/sys/compiler.h>
+#include <l4/sys/l4int.h>
+
+#include "types.h"
+
+/** Region in memory. */
+class Region
+{
+public:
+  enum Type { No_mem, Kernel, Sigma0, Boot, Root, Arch, Ram, Info };
+
+  /** Basic noop constructor, to be able to have array without ini code */
+  Region() {}
+
+  /** Create an invalid region. */
+  Region(Type) : _begin(0), _end(0) {}
+
+  /** Create a 1byte region at begin, basically for lookups */
+  Region(unsigned long long begin)
+  : _begin(begin), _end(begin), _name(0), _t(No_mem), _s(0)
+  {}
+
+  /** Create a 1byte region for address \a ptr.
+   * @param ptr the start address for the 1byte region.
+   */
+  Region(void const *ptr)
+  : _begin((l4_addr_t)ptr), _end((l4_addr_t)ptr), _name(0), _t(No_mem), _s(0)
+  {}
+
+  /** Create a fully fledged region.
+   * @param begin The start address.
+   * @param end The address of the last byte in the region.
+   * @param name The name for the region (usually the binary name).
+   * @param t The type of the region.
+   * @param sub The subtype of the region.
+   */
+  Region(unsigned long long begin, unsigned long long end,
+         char const *name = 0, Type t = No_mem, short sub = 0)
+  : _begin(begin), _end(end), _name(name), _t(t), _s(sub)
+  {}
+
+  /**
+   * Create a region ...
+   * @param other a region to copy the name, the type, and the sub_type from
+   * @param begin the start address of the new region
+   * @param end the end address (inclusive) of the new region
+   */
+  Region(Region const &other, unsigned long long begin, unsigned long long end)
+  : _begin(begin), _end(end), _name(other._name), _t(other._t), _s(other._s)
+  {}
+
+  /**
+   * Create a region...
+   * @param begin The start address.
+   * @param end The address of the first byte after the region.
+   * @param name The name for the region (usually the binary name).
+   * @param t The type of the region.
+   * @param sub The subtype of the region.
+   */
+  static Region n(unsigned long long begin,
+                  unsigned long long end, char const *name = 0,
+                  Type t = No_mem, short sub = 0)
+  { return Region(begin, end - 1, name, t, sub); }
+
+  /**
+   * Create a region (using start and end pointers)
+   * @param begin start address
+   * @param end the address of the last byte in the region
+   * @param name The name of the region
+   * @param t the type of the region
+   * @param sub the subtype of the region
+   */
+  static Region n(void const *begin,
+                  void const *end, char const *name = 0,
+                  Type t = No_mem, short sub = 0)
+  { return Region((l4_addr_t)begin, (l4_addr_t)end - 1, name, t, sub); }
+
+  /**
+   * Create a region from start and size.
+   * @param begin the start address of the region
+   * @param size the size of the region in bytes
+   * @param name the name of the region
+   * @param t the type of the region
+   * @param sub the subtype of the region
+   */
+  static Region start_size(unsigned long long begin, unsigned long size,
+                           char const *name = 0, Type t = No_mem,
+                           short sub = 0)
+  { return Region(begin, begin + size - 1, name, t, sub); }
+
+  /**
+   * Create a region for the given object.
+   * @param begin a pointer to the object that shall be covered
+   *              (the size of the region will be sizeof(T))
+   * @param name the name of the region
+   * @param t the type of theregion
+   * @param sub the subtype of the region
+   */
+  template< typename T >
+  static Region from_ptr(T const *begin, char const *name = 0,
+                         Type t = No_mem, short sub = 0)
+  { return Region::start_size((l4_addr_t)begin, sizeof(T), name, t, sub); }
+
+  /**
+   * Create a region for an array of objects.
+   * @param begin pointer to the first element of the array
+   * @param size the number of elements in the array (the size of the
+   *             whole region will be size * sizeof(T))
+   * @param name the name of the region
+   * @param t the type of the region
+   * @param sub the subtype of the region
+   */
+  template< typename T >
+  static Region array(T const *begin, unsigned long size, char const *name = 0,
+                      Type t = No_mem, short sub = 0)
+  {
+    return Region::start_size((l4_addr_t)begin, sizeof(T) * size,
+                              name, t, sub);
+  }
+
+  /** Get the start address. */
+  unsigned long long begin() const { return _begin; }
+  /** Get the address of the last byte. */
+  unsigned long long end() const { return _end; }
+  /** Set the start address. */
+  void begin(unsigned long long b) { _begin = b; }
+  /** Set the address of the last byte. */
+  void end(unsigned long long e) { _end = e; }
+  /** Get the name of the region. */
+  char const *name() const { return _name; }
+  /** Get size of the region */
+  unsigned long long size() const { return _end - _begin + 1; }
+  /** Set the name of the region. */
+  void name(char const *name) { _name = name; }
+  /** Get the type of the region. */
+  Type type() const { return (Type)(_t); }
+  /** Get the subtype of the region. */
+  short sub_type() const { return _s; }
+  /** Set the subtype of the region. */
+  void sub_type(short s) { _s = s; }
+
+  /** Print the region [begin; end] */
+  void print() const;
+
+  /** Print the region verbose (with name and type). */
+  void vprint() const;
+
+  /** Compare two regions. */
+  bool operator < (Region const &o) const
+  { return end() < o.begin(); }
+
+  /** Check for an overlap. */
+  bool overlaps(Region const &o) const
+  { return !(*this < o) && !(o < *this); }
+
+  /** Test if o is a sub-region of ourselves. */
+  bool contains(Region const &o) const
+  { return begin() <= o.begin() && end() >= o.end(); }
+
+  /** Calculate the intersection. */
+  Region intersect(Region const &o) const
+  {
+    if (!overlaps(o))
+      return Region(No_mem);
+
+    return Region(begin() > o.begin() ? begin() : o.begin(),
+       end() < o.end() ? end() : o.end(),
+       name(), type(), sub_type());
+  }
+
+  /** Check if the region is invalid */
+  bool invalid() const { return begin()==0 && end()==0; }
+
+private:
+  unsigned long long _begin, _end;
+  char const *_name;
+  short _t, _s;
+};
+
+
+/** List of memory regions, based on an fixed size array. */
+class Region_list
+{
+public:
+  /**
+   * Initialize the region list, using the array of given size
+   * as backing store.
+   */
+  void init(Region *store, unsigned size,
+            const char *name,
+            unsigned long long max_combined_size = ~0ULL,
+            unsigned long long address_limit = ~0ULL)
+  {
+    _reg = _end = store;
+    _max = _reg + size;
+    _name = name;
+    _max_combined_size = max_combined_size;
+    _address_limit = address_limit;
+    _combined_size = 0;
+  }
+
+  /** Helper template for array parameters
+   *
+   * This helper allows to access the type and the size of compile-time
+   * bound arrays. In particular used as parameters.
+   */
+  template< typename T >
+    struct Array_type_helper;
+
+  template< typename T, unsigned SZ >
+    struct Array_type_helper<T[SZ]> {
+      enum { size = SZ };
+      typedef T type;
+    };
+
+  /**
+   * Initialize the region list, using a region array as store
+   *
+   * @param store the array for the regoion backing store.
+   * @param name the name of the region list for output
+   * @param max_combined_size max sum of bytes in this list
+   * @param address_limit maximum allowed address in this list
+   */
+  template<typename STORE>
+  void init(STORE &store,
+            const char *name,
+            unsigned long long max_combined_size = ~0ULL,
+            unsigned long long address_limit = ~0ULL)
+  {
+    init(store, Array_type_helper<STORE>::size, name,
+         max_combined_size, address_limit);
+  }
+
+  /** Search for a region that overlaps o. */
+  Region *find(Region const &o) const;
+
+  /** Search for the region that contains o. */
+  Region *contains(Region const &o);
+
+  /**
+   * Search for a memory region not overlapping any known region,
+   * within search.
+   */
+  unsigned long long find_free(Region const &search,
+                               unsigned long long size, unsigned align) const;
+
+  /**
+   * Search for a memory region not overlapping any know region, starting
+   * from the end of the search region.
+   */
+  unsigned long long find_free_rev(Region const &search, unsigned long long _size,
+                                   unsigned align) const;
+  /**
+   * Add a new region, with a upper limit check and verboseness.
+   */
+  void add(Region const &r, bool may_overlap = false);
+
+  bool sub(Region const &r);
+
+  /** Dump the whole region list. */
+  void dump();
+
+  /** Get the begin() iterator. */
+  Region *begin() const { return _reg; }
+  /** Get the end() iterator. */
+  Region *end() const { return _end; }
+
+  /** Remove the region given by the iterator r. */
+  Region *remove(Region *r);
+
+  /** Sort the region list (does bubble sort). */
+  void sort();
+
+  /** Optimize the region list.
+   * Basically merges all regions with the same type, subtype, and name
+   * that have a begin and end address on the same memory page.
+   */
+  void optimize();
+
+protected:
+  Region *_end;
+  Region *_max;
+  Region *_reg;
+
+  const char *_name;
+  unsigned long long _max_combined_size;
+  unsigned long long _address_limit;
+  unsigned long long _combined_size;
+
+private:
+  void swap(Region *a, Region *b);
+
+  /**
+   * Add a new memory region to the list. The new region must not overlap
+   * any known region.
+   */
+  void add_nolimitcheck(Region const &r, bool may_overlap = false);
+};
+
+#endif
diff --git a/l4/pkg/bootstrap_custom/server/src/startup.cc b/l4/pkg/bootstrap_custom/server/src/startup.cc
new file mode 100644 (file)
index 0000000..d29ac93
--- /dev/null
@@ -0,0 +1,849 @@
+/**
+ * \file       bootstrap/server/src/startup.cc
+ * \brief      Main functions
+ *
+ * \date       09/2004
+ * \author     Torsten Frenzel <frenzel@os.inf.tu-dresden.de>,
+ *             Frank Mehnert <fm3@os.inf.tu-dresden.de>,
+ *             Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *             Alexander Warg <aw11@os.inf.tu-dresden.de>
+ *             Sebastian Sumpf <sumpf@os.inf.tu-dresden.de>
+ */
+
+/*
+ * (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.
+ */
+
+/* LibC stuff */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+/* L4 stuff */
+#include <l4/sys/compiler.h>
+#include <l4/util/mb_info.h>
+#include <l4/util/l4_macros.h>
+#include <l4/util/kip.h>
+#include "panic.h"
+
+/* local stuff */
+#include "exec.h"
+#include "macros.h"
+#include "region.h"
+#include "module.h"
+#include "startup.h"
+#include "support.h"
+#include "init_kip.h"
+#include "patch.h"
+#include "koptions.h"
+
+#undef getchar
+
+/* management of allocated memory regions */
+static Region_list regions;
+static Region __regs[300];
+
+/* management of conventional memory regions */
+static Region_list ram;
+static Region __ram[16];
+
+static Memory _mem_manager = { &ram, &regions };
+Memory *mem_manager = &_mem_manager;
+
+L4_kernel_options::Uart kuart;
+unsigned int kuart_flags;
+
+/*
+ * IMAGE_MODE means that all boot modules are linked together to one
+ * big binary.
+ */
+#ifdef IMAGE_MODE
+static l4_addr_t _mod_addr = RAM_BASE + MODADDR;
+#else
+static l4_addr_t _mod_addr;
+#endif
+
+static const char *builtin_cmdline = CMDLINE;
+
+
+enum {
+  kernel_module,
+  sigma0_module,
+  roottask_module,
+};
+
+/// Info passed through our ELF interpreter code
+struct Elf_info
+{
+  Boot_modules::Module mod;
+  Region::Type type;
+};
+
+static exec_handler_func_t l4_exec_read_exec;
+static exec_handler_func_t l4_exec_add_region;
+
+
+#if 0
+static void
+dump_mbi(l4util_mb_info_t *mbi)
+{
+  printf("%p-%p\n", (void*)(mbi->mem_lower << 10), (void*)(mbi->mem_upper << 10));
+  printf("MBI:     [%p-%p]\n", mbi, mbi + 1);
+  printf("MODINFO: [%p-%p]\n", (char*)mbi->mods_addr,
+      (l4util_mb_mod_t*)(mbi->mods_addr) + mbi->mods_count);
+
+  printf("VBEINFO: [%p-%p]\n", (char*)mbi->vbe_ctrl_info,
+      (l4util_mb_vbe_ctrl_t*)(mbi->vbe_ctrl_info) + 1);
+  printf("VBEMODE: [%p-%p]\n", (char*)mbi->vbe_mode_info,
+      (l4util_mb_vbe_mode_t*)(mbi->vbe_mode_info) + 1);
+
+  l4util_mb_mod_t *m = (l4util_mb_mod_t*)(mbi->mods_addr);
+  l4util_mb_mod_t *me = m + mbi->mods_count;
+  for (; m < me; ++m)
+    {
+      printf("  MOD: [%p-%p]\n", (void*)m->mod_start, (void*)m->mod_end);
+      printf("  CMD: [%p-%p]\n", (char*)m->cmdline,
+         (char*)m->cmdline + strlen((char*)m->cmdline));
+    }
+}
+#endif
+
+
+/**
+ * Scan the memory regions with type == Region::Kernel for a
+ * kernel interface page (KIP).
+ *
+ * After loading the kernel we scan for the magic number at page boundaries.
+ */
+static
+void *find_kip()
+{
+  unsigned char *p, *end;
+  void *k = 0;
+
+  printf("  find kernel info page...\n");
+  for (Region const *m = regions.begin(); m != regions.end(); ++m)
+    {
+      if (m->type() != Region::Kernel)
+       continue;
+
+      if (sizeof(unsigned long) < 8
+          && m->end() >= (1ULL << 32))
+       end = (unsigned char *)(~0UL - 0x1000);
+      else
+       end = (unsigned char *) (unsigned long)m->end();
+
+      for (p = (unsigned char *) (unsigned long)(m->begin() & 0xfffff000);
+          p < end;
+          p += 0x1000)
+       {
+         l4_umword_t magic = L4_KERNEL_INFO_MAGIC;
+         if (memcmp(p, &magic, 4) == 0)
+           {
+             k = p;
+             printf("  found kernel info page at %p\n", p);
+             break;
+           }
+       }
+
+      if (k)
+        break;
+    }
+
+  if (!k)
+    panic("could not find kernel info page, maybe your kernel is too old");
+
+  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");
+
+  unsigned long need_version = 1;
+
+  if (ko->version != need_version)
+    panic("Cannot boot kernel with incompatible options version: %lu, need %lu",
+          (unsigned long)ko->version, need_version);
+
+  return ko;
+}
+
+/**
+ * Get the API version from the KIP.
+ */
+static inline
+unsigned long get_api_version(void *kip)
+{
+  return ((unsigned long *)kip)[1];
+}
+
+
+static char const *
+check_arg_str(char const *cmdline, const char *arg)
+{
+  char const *s = cmdline;
+  while ((s = strstr(s, arg)))
+    {
+      if (s == cmdline
+          || isspace(s[-1]))
+        return s;
+    }
+  return NULL;
+}
+
+static char *
+check_arg_str(char *cmdline, const char *arg)
+{
+  return const_cast<char *>(check_arg_str(const_cast<char const *>(cmdline), arg));
+}
+
+/**
+ * Scan the command line for the given argument.
+ *
+ * The cmdline string may either be including the calling program
+ * (.../bootstrap -arg1 -arg2) or without (-arg1 -arg2) in the realmode
+ * case, there, we do not have a leading space
+ *
+ * return pointer after argument, NULL if not found
+ */
+char const *
+check_arg(char const *cmdline, const char *arg)
+{
+  if (cmdline)
+    return check_arg_str(cmdline, arg);
+
+  return NULL;
+}
+
+
+/**
+ * Calculate the maximum memory limit in MB.
+ *
+ * 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 long
+get_memory_max_address()
+{
+#ifndef __LP64__
+  /* 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 3024ULL << 20;
+#endif
+
+  return ~0ULL;
+}
+
+/*
+ * If available the '-maxmem=xx' command line option is used.
+ */
+static
+unsigned long long
+get_memory_max_size(char const *cmdline)
+{
+  /* maxmem= parameter? */
+  if (char const *c = check_arg(cmdline, "-maxmem="))
+    return strtoul(c + 8, NULL, 10) << 20;
+
+  return ~0ULL;
+}
+
+static int
+parse_memvalue(const char *s, unsigned long *val, char **ep)
+{
+
+  *val = strtoul(s, ep, 0);
+  if (*val == ~0UL)
+    return 1;
+
+  switch (**ep)
+    {
+    case 'G': *val <<= 10;
+    case 'M': *val <<= 10;
+    case 'k': case 'K': *val <<= 10; (*ep)++;
+    };
+
+  return 0;
+}
+
+/*
+ * Parse a memory layout string: size@offset
+ * E.g.: 256M@0x40000000, or 128M@128M
+ */
+static int
+parse_mem_layout(const char *s, unsigned long *sz, unsigned long *offset)
+{
+  char *ep;
+
+  if (parse_memvalue(s, sz, &ep))
+    return 1;
+
+  if (*sz == 0)
+    return 1;
+
+  if (*ep != '@')
+    return 1;
+
+  if (parse_memvalue(ep + 1, offset, &ep))
+    return 1;
+
+  return 0;
+}
+
+static void
+dump_ram_map(bool show_total = false)
+{
+  // print RAM summary
+  unsigned long long sum = 0;
+  for (Region *i = ram.begin(); i < ram.end(); ++i)
+    {
+      printf("  RAM: %016llx - %016llx: %lldkB\n",
+             i->begin(), i->end(), i->size() >> 10);
+      sum += i->size();
+    }
+  if (show_total)
+    printf("  Total RAM: %lldMB\n", sum >> 20);
+}
+
+static void
+setup_memory_map(char const *cmdline)
+{
+  bool parsed_mem_option = false;
+  const char *s = cmdline;
+
+  if (s)
+    {
+      while ((s = check_arg_str((char *)s, "-mem=")))
+        {
+          s += 5;
+          unsigned long sz, offset = 0;
+          if (!parse_mem_layout(s, &sz, &offset))
+            {
+              parsed_mem_option = true;
+              ram.add(Region::n(offset, offset + sz, ".ram", Region::Ram));
+            }
+        }
+    }
+
+  if (!parsed_mem_option)
+    // No -mem option given, use the one given by the platform
+    Platform_base::platform->setup_memory_map();
+
+  dump_ram_map(true);
+}
+
+static void do_the_memset(unsigned long s, unsigned val, unsigned long len)
+{
+  printf("Presetting memory %16lx - %16lx to '%x'\n",
+         s, s + len - 1, val);
+  memset((void *)s, val, len);
+}
+
+static void fill_mem(unsigned fill_value)
+{
+  regions.sort();
+  for (Region const *r = ram.begin(); r != ram.end(); ++r)
+    {
+      unsigned long long b = r->begin();
+      // The regions list must be sorted!
+      for (Region const *reg = regions.begin(); reg != regions.end(); ++reg)
+        {
+          // completely before ram?
+          if (reg->end() < r->begin())
+            continue;
+          // completely after ram?
+          if (reg->begin() > r->end())
+            break;
+
+          if (reg->begin() <= r->begin())
+            b = reg->end() + 1;
+          else if (b > reg->begin()) // some overlapping
+            {
+              if (reg->end() + 1 > b)
+                b = reg->end() + 1;
+            }
+          else
+            {
+              do_the_memset(b, fill_value, reg->begin() - 1 - b + 1);
+              b = reg->end() + 1;
+            }
+        }
+
+      if (b < r->end())
+        do_the_memset(b, fill_value, r->end() - b + 1);
+    }
+}
+
+
+/**
+ * Add the bootstrap binary itself to the allocated memory regions.
+ */
+static void
+init_regions()
+{
+  extern int _start;   /* begin of image -- defined in crt0.S */
+  extern int _end;     /* end   of image -- defined by bootstrap.ld */
+
+  auto *p = Platform_base::platform;
+
+  regions.add(Region::n(p->to_phys((unsigned long)&_start),
+                        p->to_phys((unsigned long)&_end),
+                        ".bootstrap", Region::Boot));
+}
+
+/**
+ * Add all sections of the given ELF binary to the allocated regions.
+ * Actually does not load the ELF binary (see load_elf_module()).
+ */
+static void
+add_elf_regions(Boot_modules::Module const &m, Region::Type type)
+{
+  Elf_info info;
+  l4_addr_t entry;
+  int r;
+  const char *error_msg;
+
+  info.type = type;
+  info.mod = m;
+
+  printf("  Scanning %s\n", m.cmdline);
+
+  r = exec_load_elf(l4_exec_add_region, &info,
+                    &error_msg, &entry);
+
+  if (r)
+    {
+      if (Verbose_load)
+        {
+          printf("\n%p: ", (void*)m.start);
+          for (int i = 0; i < 4; ++i)
+            printf("%08x ", *((unsigned *)m.start + i));
+          printf("  ");
+          for (int i = 0; i < 16; ++i)
+            {
+              unsigned char c = *(unsigned char *)((char *)m.start + i);
+              printf("%c", c < 32 ? '.' : c);
+            }
+        }
+      panic("\n\nThis is an invalid binary, fix it (%s).", error_msg);
+    }
+}
+
+
+/**
+ * Load the given ELF binary into memory and free the source
+ * memory region.
+ */
+static l4_addr_t
+load_elf_module(Boot_modules::Module const &mod)
+{
+  l4_addr_t entry;
+  int r;
+  const char *error_msg;
+
+  r = exec_load_elf(l4_exec_read_exec, const_cast<Boot_modules::Module *>(&mod),
+                    &error_msg, &entry);
+
+#ifndef RELEASE_MODE
+  /* clear the image for debugging and security reasons */
+  memset((void*)mod.start, 0, mod.end - mod.start);
+#endif
+
+  if (r)
+    printf("  => can't load module (%s)\n", error_msg);
+  else
+    {
+      Region m = Region::n(mod.start, l4_round_page(mod.end));
+      if (!regions.sub(m))
+        {
+          Region m = Region::n(mod.start, mod.end);
+          if (!regions.sub(m))
+            {
+              m.vprint();
+              regions.dump();
+              panic ("could not free region for load ELF module");
+            }
+        }
+    }
+
+  return entry;
+}
+
+/**
+ * Simple linear memory allocator.
+ *
+ * Allocate size bytes starting from *ptr and set *ptr to *ptr + size.
+ */
+static inline void*
+lin_alloc(l4_size_t size, char **ptr)
+{
+  void *ret = *ptr;
+  *ptr += (size + 3) & ~3;;
+  return ret;
+}
+
+
+#ifdef ARCH_arm
+static inline l4_umword_t
+running_in_hyp_mode()
+{
+  l4_umword_t cpsr;
+  asm volatile("mrs %0, cpsr" : "=r"(cpsr));
+  return (cpsr & 0x1f) == 0x1a;
+}
+
+static void
+setup_and_check_kernel_config(Platform_base *plat, l4_kernel_info_t *kip)
+{
+  l4_kip_platform_info_arch *ia = &kip->platform_info.arch;
+
+  asm("mrc p15, 0, %0, c0, c0, 0" : "=r" (ia->cpuinfo.MIDR));
+  asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (ia->cpuinfo.CTR));
+  asm("mrc p15, 0, %0, c0, c0, 2" : "=r" (ia->cpuinfo.TCMTR));
+  asm("mrc p15, 0, %0, c0, c0, 3" : "=r" (ia->cpuinfo.TLBTR));
+  asm("mrc p15, 0, %0, c0, c0, 5" : "=r" (ia->cpuinfo.MPIDR));
+  asm("mrc p15, 0, %0, c0, c0, 6" : "=r" (ia->cpuinfo.REVIDR));
+
+  if (((ia->cpuinfo.MIDR >> 16) & 0xf) >= 7)
+    {
+      asm("mrc p15, 0, %0, c0, c1, 0" : "=r" (ia->cpuinfo.ID_PFR[0]));
+      asm("mrc p15, 0, %0, c0, c1, 1" : "=r" (ia->cpuinfo.ID_PFR[1]));
+      asm("mrc p15, 0, %0, c0, c1, 2" : "=r" (ia->cpuinfo.ID_DFR0));
+      asm("mrc p15, 0, %0, c0, c1, 3" : "=r" (ia->cpuinfo.ID_AFR0));
+      asm("mrc p15, 0, %0, c0, c1, 4" : "=r" (ia->cpuinfo.ID_MMFR[0]));
+      asm("mrc p15, 0, %0, c0, c1, 5" : "=r" (ia->cpuinfo.ID_MMFR[1]));
+      asm("mrc p15, 0, %0, c0, c1, 6" : "=r" (ia->cpuinfo.ID_MMFR[2]));
+      asm("mrc p15, 0, %0, c0, c1, 7" : "=r" (ia->cpuinfo.ID_MMFR[3]));
+      asm("mrc p15, 0, %0, c0, c2, 0" : "=r" (ia->cpuinfo.ID_ISAR[0]));
+      asm("mrc p15, 0, %0, c0, c2, 1" : "=r" (ia->cpuinfo.ID_ISAR[1]));
+      asm("mrc p15, 0, %0, c0, c2, 2" : "=r" (ia->cpuinfo.ID_ISAR[2]));
+      asm("mrc p15, 0, %0, c0, c2, 3" : "=r" (ia->cpuinfo.ID_ISAR[3]));
+      asm("mrc p15, 0, %0, c0, c2, 4" : "=r" (ia->cpuinfo.ID_ISAR[4]));
+      asm("mrc p15, 0, %0, c0, c2, 5" : "=r" (ia->cpuinfo.ID_ISAR[5]));
+    }
+
+  const char *s = l4_kip_version_string(kip);
+  if (!s)
+    return;
+
+  bool is_hyp_kernel = false;
+  l4util_kip_for_each_feature(s)
+    if (!strcmp(s, "arm:hyp"))
+      {
+        if (!running_in_hyp_mode())
+          {
+            printf("  Detected HYP kernel, switching to HYP mode\n");
+            plat->arm_switch_to_hyp();
+            if (!running_in_hyp_mode())
+              panic("\nFailed to switch to HYP as required by Fiasco.OC.\n");
+          }
+        is_hyp_kernel = true;
+        break;
+      }
+
+  if (!is_hyp_kernel && running_in_hyp_mode())
+    {
+      printf("  Non-HYP kernel detected but running in HYP mode, switching back.\n");
+      asm volatile("mcr p15, 0, sp, c13, c0, 2    \n"
+                   "msr spsr, %0                  \n"
+                   "adr r0, 1f                    \n"
+                   ".inst 0xe12ef300              \n"  // msr elr_hyp, r0
+                   ".inst 0xe160006e              \n"  // eret
+                   "1: mrc p15, 0, sp, c13, c0, 2 \n"
+                   : : "r" (0x1d3) : "r0", "memory");
+    }
+}
+#endif /* arm */
+
+static unsigned long
+load_elf_module(Boot_modules::Module const &mod, char const *n)
+{
+  printf("  Loading "); print_module_name(mod.cmdline, n); putchar('\n');
+  return load_elf_module(mod);
+}
+
+/**
+ * \brief  Startup, started from crt0.S
+ */
+/* entry point */
+void
+startup(char const *cmdline)
+{
+  if (!cmdline || !*cmdline)
+    cmdline = builtin_cmdline;
+
+  if (check_arg(cmdline, "-noserial"))
+    set_stdio_uart(NULL);
+
+  if (!Platform_base::platform)
+    {
+      // will we ever see this?
+      printf("No platform found, hangup.");
+      while (1)
+        ;
+    }
+
+  Platform_base *plat = Platform_base::platform;
+
+  if (check_arg(cmdline, "-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
+      ", x86-32"
+#endif
+#ifdef ARCH_amd64
+      ", x86-64"
+#endif
+#ifdef __VERSION__
+       ", " __VERSION__
+#endif
+      );
+
+  regions.init(__regs, "regions");
+  ram.init(__ram, "RAM", get_memory_max_size(cmdline), get_memory_max_address());
+
+  setup_memory_map(cmdline);
+
+  /* basically add the bootstrap binary to the allocated regions */
+  init_regions();
+  plat->modules()->reserve();
+
+  /* modules to load by bootstrap */
+  bool sigma0 = true;   /* we need sigma0 */
+  bool roottask = true; /* we need a roottask */
+
+  /* check command line */
+  if (check_arg(cmdline, "-no-sigma0"))
+    sigma0 = 0;
+
+  if (check_arg(cmdline, "-no-roottask"))
+    roottask = 0;
+
+  if (const char *s = check_arg(cmdline, "-modaddr"))
+    _mod_addr = RAM_BASE + strtoul(s + 9, 0, 0);
+
+  _mod_addr = l4_round_page(_mod_addr);
+
+
+  Boot_modules *mods = plat->modules();
+
+  add_elf_regions(mods->module(kernel_module), Region::Kernel);
+
+  if (sigma0)
+    add_elf_regions(mods->module(sigma0_module), Region::Sigma0);
+
+  if (roottask)
+    add_elf_regions(mods->module(roottask_module), Region::Root);
+
+  l4util_mb_info_t *mbi = plat->modules()->construct_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 */
+  assert(mbi->mods_count >= 2);
+  assert(mbi->mods_count <= MODS_MAX);
+
+  if (const char *s = cmdline)
+    {
+      /* patch modules with content given at command line */
+      while ((s = check_arg_str((char *)s, "-patch=")))
+       patch_module(&s, mbi);
+    }
+
+  boot_info_t boot_info;
+  l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t *)(unsigned long)mbi->mods_addr;
+  regions.optimize();
+
+  /* setup kernel PART ONE */
+  boot_info.kernel_start = load_elf_module(mods->module(kernel_module), "[KERNEL]");
+
+  /* setup sigma0 */
+  if (sigma0)
+    boot_info.sigma0_start = load_elf_module(mods->module(sigma0_module), "[SIGMA0]");
+
+  /* setup roottask */
+  if (roottask)
+    boot_info.roottask_start = load_elf_module(mods->module(roottask_module),
+                                               "[ROOTTASK]");
+
+  /* setup kernel PART TWO (special kernel initialization) */
+  void *l4i = find_kip();
+
+  regions.optimize();
+  regions.dump();
+
+  if (char const *c = check_arg(cmdline, "-presetmem="))
+    {
+      unsigned fill_value = strtoul(c + 11, NULL, 0);
+      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);
+  unsigned major = api_version >> 24;
+  printf("  API Version: (%x) %s\n", major, (major & 0x80)?"experimental":"");
+  switch (major)
+    {
+    case 0x87: // Fiasco
+      init_kip_f(l4i, &boot_info, mbi, &ram, &regions);
+      break;
+    case 0x02:
+      panic("cannot boot V.2 API kernels: %lx\n", api_version);
+      break;
+    case 0x03:
+      panic("cannot boot X.0 and X.1 API kernels: %lx\n", api_version);
+      break;
+    case 0x84:
+      panic("cannot boot Fiasco V.4 API kernels: %lx\n", api_version);
+      break;
+    case 0x04:
+      panic("cannot boot V.4 API kernels: %lx\n", api_version);
+    default:
+      panic("cannot boot a kernel with unknown api version %lx\n", api_version);
+      break;
+    }
+
+  printf("  Starting kernel ");
+  print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline),
+                   "[KERNEL]");
+  printf(" at " l4_addr_fmt "\n", boot_info.kernel_start);
+
+#if defined(ARCH_arm)
+  if (major == 0x87)
+    setup_and_check_kernel_config(plat, (l4_kernel_info_t *)l4i);
+#endif
+#if defined(ARCH_ppc32)
+  init_kip_v2_arch((l4_kernel_info_t*)l4i);
+
+  printf("CPU at %lu Khz/Bus at %lu Hz\n",
+         ((l4_kernel_info_t*)l4i)->frequency_cpu,
+         ((l4_kernel_info_t*)l4i)->frequency_bus);
+#endif
+
+  plat->boot_kernel(boot_info.kernel_start);
+  /*NORETURN*/
+}
+
+static int
+l4_exec_read_exec(void * handle,
+                 l4_addr_t file_ofs, l4_size_t file_size,
+                 l4_addr_t mem_addr, l4_addr_t /*v_addr*/,
+                 l4_size_t mem_size,
+                 exec_sectype_t section_type)
+{
+  Boot_modules::Module const *m = (Boot_modules::Module const *)handle;
+  if (!mem_size)
+    return 0;
+
+  if (! (section_type & EXEC_SECTYPE_ALLOC))
+    return 0;
+
+  if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
+    return 0;
+
+  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)))
+    {
+      printf("To be loaded binary region is out of memory region.\n");
+      printf(" Binary region: %lx - %lx\n", mem_addr, mem_addr + mem_size);
+      dump_ram_map();
+      panic("Binary outside memory");
+    }
+
+  memcpy((void *) mem_addr, (char const *)m->start + file_ofs, file_size);
+  if (file_size < mem_size)
+    memset((void *) (mem_addr + file_size), 0, mem_size - file_size);
+
+
+  Region *f = regions.find(mem_addr);
+  if (!f)
+    {
+      printf("could not find %lx\n", mem_addr);
+      regions.dump();
+      panic("Oops: region for module not found\n");
+    }
+
+  f->name(m->cmdline ? m->cmdline :  ".[Unknown]");
+  return 0;
+}
+
+
+static int
+l4_exec_add_region(void *handle,
+                 l4_addr_t /*file_ofs*/, l4_size_t /*file_size*/,
+                 l4_addr_t mem_addr, l4_addr_t v_addr,
+                 l4_size_t mem_size,
+                 exec_sectype_t section_type)
+{
+  Elf_info const *info = (Elf_info const *)handle;
+
+  if (!mem_size)
+    return 0;
+
+  if (! (section_type & EXEC_SECTYPE_ALLOC))
+    return 0;
+
+  if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD)))
+    return 0;
+
+  Region n = Region::n(mem_addr, mem_addr + mem_size,
+                       info->mod.cmdline ? info->mod.cmdline : ".[Unknown]",
+                       info->type, mem_addr == v_addr ? 1 : 0);
+
+  for (Region *r = regions.begin(); r != regions.end(); ++r)
+    if (r->overlaps(n) && r->name() != Boot_modules::Mod_reg)
+      {
+        printf("  New region for list %s:\t", n.name());
+        n.vprint();
+        printf("  overlaps with:         \t");
+        r->vprint();
+        regions.dump();
+        panic("region overlap");
+      }
+
+  regions.add(Region::n(mem_addr, mem_addr + mem_size,
+              info->mod.cmdline ? info->mod.cmdline : ".[Unknown]",
+              info->type, mem_addr == v_addr ? 1 : 0), true);
+  return 0;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/startup.h b/l4/pkg/bootstrap_custom/server/src/startup.h
new file mode 100644 (file)
index 0000000..37a28eb
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *               Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef __STARTUP_H__
+#define __STARTUP_H__
+
+#include <l4/sys/l4int.h>
+#include <l4/util/mb_info.h>
+#include <l4/sys/compiler.h>
+
+#include "types.h"
+
+typedef struct
+{
+  unsigned long kernel_start;
+  unsigned long sigma0_start;
+  unsigned long roottask_start;
+  unsigned long mbi_low, mbi_high;
+} boot_info_t;
+
+//const char * get_cmdline(l4util_mb_info_t *mbi);
+
+#ifdef __cplusplus
+#include "koptions-def.h"
+char const *check_arg(char const *cmdline, const char *arg);
+extern L4_kernel_options::Uart kuart;
+extern unsigned int kuart_flags;
+extern "C" void startup(char const *cmdline);
+#else
+extern void startup(char const *cmdline);
+#endif
+
+#endif /* ! __STARTUP_H__ */
diff --git a/l4/pkg/bootstrap_custom/server/src/support.h b/l4/pkg/bootstrap_custom/server/src/support.h
new file mode 100644 (file)
index 0000000..2247553
--- /dev/null
@@ -0,0 +1,195 @@
+/*!
+ * \file   support.h
+ * \brief  Support header file
+ *
+ * \date   2008-01-02
+ * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2008-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.
+ */
+#ifndef __BOOTSTRAP__SUPPORT_H__
+#define __BOOTSTRAP__SUPPORT_H__
+
+#include <l4/drivers/uart_base.h>
+#include <l4/util/mb_info.h>
+#include <stdio.h>
+#include "region.h"
+#include <cstring>
+#include <cstdlib>
+
+L4::Uart *uart();
+void set_stdio_uart(L4::Uart *uart);
+void ctor_init();
+
+// only available with image builds
+extern char _mbi_cmdline[];
+
+enum { Verbose_load = 0 };
+
+template<typename T>
+inline T *l4_round_page(T *p) { return (T*)l4_round_page((l4_addr_t)p); }
+
+template<typename T>
+inline T *l4_trunc_page(T *p) { return (T*)l4_trunc_page((l4_addr_t)p); }
+
+static inline void __attribute__((always_inline))
+clear_bss()
+{
+  extern char _bss_start[], _bss_end[];
+  extern char crt0_stack_low[], crt0_stack_high[];
+  memset(_bss_start, 0, (char *)&crt0_stack_low - _bss_start);
+  memset(crt0_stack_high, 0, _bss_end - crt0_stack_high);
+}
+
+static inline unsigned long
+round_wordsize(unsigned long s)
+{ return (s + sizeof(unsigned long) - 1) & ~(sizeof(unsigned long) - 1); }
+
+struct Memory
+{
+  Region_list *ram;
+  Region_list *regions;
+  unsigned long find_free_ram(unsigned long size, unsigned long min_addr = 0,
+                              unsigned long max_addr = ~0UL);
+  unsigned long find_free_ram_rev(unsigned long size, unsigned long min_addr = 0,
+                                  unsigned long max_addr = ~0UL);
+};
+
+/**
+ * Interface to boot modules.
+ *
+ * Boot modules can for example be loaded by GRUB, or may be linked
+ * into bootstrap.
+ */
+class Boot_modules
+{
+public:
+
+  /// Main information for each module.
+  struct Module
+  {
+    char const *start;
+    char const *end;
+    char const *cmdline;
+
+    unsigned long size() const { return end -start; }
+  };
+
+  static char const *const Mod_reg;
+
+  virtual ~Boot_modules() = 0;
+  virtual void reserve() = 0;
+  virtual Module module(unsigned index, bool uncompress = true) const = 0;
+  virtual unsigned num_modules() const = 0;
+  virtual l4util_mb_info_t *construct_mbi(unsigned long mod_addr) = 0;
+  virtual void move_module(unsigned index, void *dest,
+                           bool overlap_check = true) = 0;
+  void move_modules(unsigned long modaddr);
+  Region mod_region(unsigned index, l4_addr_t start, l4_addr_t size,
+                    Region::Type type = Region::Boot);
+  void merge_mod_regions();
+
+protected:
+  void _move_module(unsigned index, void *dest, void const *src,
+                    unsigned long size, bool overlap_check);
+};
+
+inline Boot_modules::~Boot_modules() {}
+
+class Platform_base
+{
+public:
+  virtual ~Platform_base() = 0;
+  virtual void init() = 0;
+  virtual void setup_memory_map() = 0;
+  virtual Boot_modules *modules() = 0;
+  virtual bool probe() = 0;
+
+  virtual l4_uint64_t to_phys(l4_addr_t bootstrap_addr)
+  { return bootstrap_addr; }
+
+  virtual l4_addr_t to_virt(l4_uint64_t phys_addr)
+  { return phys_addr; }
+
+  virtual void reboot()
+  {
+    while (1)
+      ;
+  }
+
+  virtual void arm_switch_to_hyp() {}
+
+  virtual void boot_kernel(unsigned long entry)
+  {
+    typedef void (*func)(void);
+    ((func)entry)();
+    exit(-100);
+  }
+
+  // remember the chosen platform
+  static Platform_base *platform;
+
+  // find a platform
+  static void iterate_platforms()
+  {
+    extern Platform_base *__PLATFORMS_BEGIN[];
+    extern Platform_base *__PLATFORMS_END[];
+    for (Platform_base **p = __PLATFORMS_BEGIN; p < __PLATFORMS_END; ++p)
+      if (*p && (*p)->probe())
+        {
+          platform = *p;
+          platform->init();
+          break;
+        }
+  }
+};
+
+inline Platform_base::~Platform_base() {}
+
+#define REGISTER_PLATFORM(type) \
+      static type type##_inst; \
+      static type * const __attribute__((section(".platformdata"),used)) type##_inst_p = &type##_inst
+
+
+#ifdef IMAGE_MODE
+
+/**
+ * For image mode we have this utility that implements
+ * handling of linked in modules.
+ */
+class Boot_modules_image_mode : public Boot_modules
+{
+public:
+  void reserve();
+  Module module(unsigned index, bool uncompress) const;
+  unsigned num_modules() const;
+  void move_module(unsigned index, void *dest,
+                   bool overlap_check = true);
+  l4util_mb_info_t *construct_mbi(unsigned long mod_addr);
+
+private:
+  void decompress_mods(unsigned mod_count, unsigned skip,
+                       l4_addr_t total_size, l4_addr_t mod_addr);
+};
+
+
+class Platform_single_region_ram : public Platform_base,
+  public Boot_modules_image_mode
+{
+public:
+  Boot_modules *modules() { return this; }
+  void setup_memory_map();
+};
+
+#endif
+
+extern Memory *mem_manager;
+
+#endif /* __BOOTSTRAP__SUPPORT_H__ */
diff --git a/l4/pkg/bootstrap_custom/server/src/types.h b/l4/pkg/bootstrap_custom/server/src/types.h
new file mode 100644 (file)
index 0000000..9780be0
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Frank Mehnert <fm3@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+#include <l4/sys/consts.h>
+
+#define MODS_MAX 128
+#define CMDLINE_MAX 1024
+#define MOD_NAME_MAX 1024
+
+typedef char __mb_mod_name_str[MOD_NAME_MAX];
+
+// info where the page table is, for 64bit mode only
+struct ptab64_mem_info_t
+{
+  l4_uint32_t addr;
+  l4_uint32_t size;
+};
+
+#endif /* ! __TYPES_H__ */
diff --git a/l4/pkg/bootstrap_custom/server/src/uncompress.c b/l4/pkg/bootstrap_custom/server/src/uncompress.c
new file mode 100644 (file)
index 0000000..7e13388
--- /dev/null
@@ -0,0 +1,119 @@
+/**
+ * \file       bootstrap/server/src/uncompress.c
+ * \brief      Support for on-the-fly uncompressing of boot modules
+ * 
+ * \date       2004
+ * \author     Adam Lackorzynski <adam@os.inf.tu-dresden.de> */
+
+/*
+ * (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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <l4/sys/l4int.h>
+#include <l4/sys/consts.h>
+
+#include "startup.h"
+#include "gunzip.h"
+#include "uncompress.h"
+
+static void *filestart;
+
+enum { lin_alloc_buffer_size = 12 << 10 };
+unsigned long lin_alloc_buffer[(lin_alloc_buffer_size + sizeof(unsigned long) - 1)/ sizeof(unsigned long)];
+
+/*
+ * Upper address for the allocator for gunzip
+ */
+l4_addr_t
+gunzip_upper_mem_linalloc(void)
+{
+  return (l4_addr_t)lin_alloc_buffer + sizeof(lin_alloc_buffer);
+}
+
+/*
+ * Returns true if file is compressed, false if not
+ */
+static void
+file_open(void *start,  int size)
+{
+  filepos = 0;
+  filestart = start;
+  filemax = size;
+  fsmax = 0xffffffff; /* just big */
+  compressed_file = 0;
+
+  gunzip_test_header();
+}
+
+static int
+module_read(void *buf, int size)
+{
+  memcpy(buf, (const void *)((l4_addr_t)filestart + filepos), size);
+  filepos += size;
+  return size;
+}
+
+int
+grub_read(unsigned char *buf, int len)
+{
+  /* Make sure "filepos" is a sane value */
+  if (/*(filepos < 0) || */(filepos > filemax))
+    filepos = filemax;
+
+  /* Make sure "len" is a sane value */
+  if ((len < 0) || (len > (signed)(filemax - filepos)))
+    len = filemax - filepos;
+
+  /* if target file position is past the end of
+     the supported/configured filesize, then
+     there is an error */
+  if (filepos + len > fsmax)
+    {
+      printf("Filesize error %d + %d > %d\n", filepos, len, fsmax);
+      return 0;
+    }
+
+  if (compressed_file)
+    return gunzip_read (buf, len);
+
+  return module_read(buf, len);
+}
+
+void*
+decompress(const char *name, void *start, void *destbuf,
+           int size, int size_uncompressed)
+{
+  int read_size;
+
+  if (!size_uncompressed)
+    return NULL;
+
+  file_open(start, size);
+
+  // don't move data around if the data isn't compressed
+  if (!compressed_file)
+    return start;
+
+  printf("  Uncompressing %s from %p to %p (%d to %d bytes, %+lld%%).\n",
+        name, start, destbuf, size, size_uncompressed,
+       100*(unsigned long long)size_uncompressed/size - 100);
+
+  // Add 10 to detect too short given size
+  if ((read_size = grub_read(destbuf, size_uncompressed + 10))
+      != size_uncompressed)
+    {
+      printf("Uncorrect decompression: should be %d bytes but got %d bytes. Errnum = %d\n",
+             size_uncompressed, read_size, errnum);
+      return NULL;
+    }
+
+  return destbuf;
+}
diff --git a/l4/pkg/bootstrap_custom/server/src/uncompress.h b/l4/pkg/bootstrap_custom/server/src/uncompress.h
new file mode 100644 (file)
index 0000000..bb64e51
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *     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.
+ */
+#ifndef __BOOTSTRAP__UNCOMPRESS_H__
+#define __BOOTSTRAP__UNCOMPRESS_H__
+
+#include <l4/sys/compiler.h>
+
+EXTERN_C_BEGIN
+
+void *decompress(const char *name, void *start, void *destbuf,
+                 int size, int size_uncompressed);
+
+EXTERN_C_END
+
+#endif /* ! __BOOTSTRAP__UNCOMPRESS_H__ */
diff --git a/l4/pkg/bootstrap_custom/server/src/unpack b/l4/pkg/bootstrap_custom/server/src/unpack
new file mode 100755 (executable)
index 0000000..41c989c
--- /dev/null
@@ -0,0 +1,175 @@
+#! /usr/bin/perl -W
+#
+# by Adam Lackorzynski
+#
+# Simple attack at unpacking a bootstrap-image again. A smarter way would
+# probably be if we'd add some clear marks in the image when generating
+# it...
+#
+# Todo: prettification
+
+use strict;
+
+my @phdrs;
+my $filename = shift;
+die "Need to give filename!" unless defined $filename;
+
+system("arm-linux-objcopy -j .data -O binary $filename unpack.data");
+die "objcopy failed" if $?;
+
+# make it easy, just hold the file parts in memory
+my $unpackdata;
+my $allfile;
+open(A, "unpack.data") || die "Cannot open: $!";
+{
+  local undef $/;
+  $unpackdata = <A>;
+}
+close A;
+
+open(A, $filename) || die "Cannot open: $!";
+{
+  local undef $/;
+  $allfile = <A>;
+}
+close A;
+
+sub find_offset($)
+{
+  my $vaddr = shift;
+  die "find_offset: EINVAL" unless defined $vaddr;
+
+  foreach my $p (@phdrs) {
+    if ($vaddr > @$p{vaddr} && @$p{vaddr} + @$p{memsize} >= $vaddr) {
+      return $vaddr - @$p{vaddr} + @$p{fileoff};
+    }
+  }
+  die "find_phdr unsuccessful";
+}
+
+sub get_string($)
+{
+  unpack("Z*", substr($allfile, find_offset(shift)));
+}
+
+sub get_blob($$)
+{
+  my $vaddr = shift;
+  my $len   = shift;
+  substr($allfile, find_offset($vaddr), $len);
+}
+
+# parse $filename PHDRs
+{
+  my $o = `objdump -p $filename`;
+
+  foreach (split / LOAD /, $o) {
+    if (/off\s+0x([a-fA-F0-9]+)\s+vaddr\s+0x([a-fA-F0-9]+)\s+paddr\s+0x[a-fA-F0-9]+\s+align\s+\d\*\*\d+\s*.\s+filesz\s+0x([a-fA-F0-9]+)\s+memsz\s+0x([a-fA-F0-9]+)/m) {
+      print "PHDR: off=$1 vaddr=$2 fsz=$3 msz=$4\n";
+      push @phdrs, { fileoff => hex($1), vaddr => hex($2), filesize => hex($3), memsize => hex($4) };
+    }
+  }
+}
+
+my $filesize = -s "$filename";
+
+my $offset = 0;
+my %entries;
+my $previous;
+my $delta = 4;
+my $modinfo_size = 24;
+while ($offset < length($unpackdata) - 12 * 4) {
+  my ($start0, $size0, $sizeun0, $name0, $md5comp0, $md5uncomp0,
+      $start1, $size1, $sizeun1, $name1, $md5comp1, $md5uncomp1,
+      $start2, $size2, $sizeun2, $name2, $md5comp2, $md5uncomp2)
+   = unpack("LLLLLLLLLLLLLLLLLL", substr($unpackdata, $offset));
+
+  if ((!defined $previous || $previous + $modinfo_size == $offset)
+      && ($start0 > 0x5000)
+      && ($start1 > 0x5000)
+      && ($start2 > 0x5000)
+      && (($start0 & 0xfff) == 0)
+      && (($start1 & 0xfff) == 0)
+      && (($start2 & 0xfff) == 0)
+      && ($size0 < $filesize)
+      && ($size1 < $filesize)
+      && ($size2 < $filesize)
+      && ($sizeun0 < (80 << 20))
+      && ($sizeun1 < (80 << 20))
+      && ($sizeun2 < (80 << 20))) {
+
+    #printf "%x %x %x\n", $start0, $start1, $start2;
+    printf "Found module info at offset %d/0x%x\n", $offset, $offset;
+
+    $entries{$offset}{addr}                          = $start0;
+    $entries{$offset}{size}                          = $size0;
+    $entries{$offset}{usize}                         = $sizeun0;
+    $entries{$offset}{name}                          = $name0;
+    $entries{$offset}{md5comp}                       = $md5comp0;
+    $entries{$offset}{md5uncomp}                     = $md5uncomp0;
+    $entries{$offset + 1 * $modinfo_size}{addr}      = $start1;
+    $entries{$offset + 1 * $modinfo_size}{size}      = $size1;
+    $entries{$offset + 1 * $modinfo_size}{usize}     = $sizeun1;
+    $entries{$offset + 1 * $modinfo_size}{name}      = $name1;
+    $entries{$offset + 1 * $modinfo_size}{md5comp}   = $md5comp1;
+    $entries{$offset + 1 * $modinfo_size}{md5uncomp} = $md5uncomp1;
+    $entries{$offset + 2 * $modinfo_size}{addr}      = $start2;
+    $entries{$offset + 2 * $modinfo_size}{size}      = $size2;
+    $entries{$offset + 2 * $modinfo_size}{usize}     = $sizeun2;
+    $entries{$offset + 2 * $modinfo_size}{name}      = $name2;
+    $entries{$offset + 2 * $modinfo_size}{md5comp}   = $md5comp2;
+    $entries{$offset + 2 * $modinfo_size}{md5uncomp} = $md5uncomp2;
+
+    $previous = $offset;
+    $delta = $modinfo_size;
+  } else {
+    $delta = 4;
+  }
+  $offset += $delta;
+
+  print "Scanning at offset $offset\n" if $offset % 1000 == 0;
+}
+
+my $dir = "unpack.dir";
+mkdir $dir;
+
+open(MODLIST, ">$dir/modules.list")
+  || die "Cannot open $dir/unpack.modules.list: $!";
+print MODLIST "entry unpacked\n";
+print MODLIST "modaddr 0x01200000\n";
+
+my $nr = 1;
+open(M, ">md5sums") || die "Cannot create checksum file: $!";
+foreach my $e (sort { $a <=> $b } keys %entries)
+{
+  my $name = get_string($entries{$e}{name});
+  my $fname = "$dir/$name";
+  open(A, ">$fname") || die "Cannot create file $fname: $!";
+  print A get_blob($entries{$e}{addr}, $entries{$e}{size});
+  close A;
+
+  print M get_string($entries{$e}{md5uncomp})."  $fname\n";
+
+
+  system("file $fname");
+
+  # missing: cmdlines
+  if ($nr == 1) {
+    print MODLIST "kernel $name\n";
+  } elsif ($nr == 2) {
+    print MODLIST "sigma0 $name\n";
+  } elsif ($nr == 3) {
+    print MODLIST "roottask $name\n";
+  } else {
+    print MODLIST "module $name\n";
+  }
+
+
+  $nr++;
+}
+close M;
+close MODLIST;
+
+unlink "unpack.data";
+
+system("md5sum -c md5sums");