diff --git a/Makefile b/Makefile
index 61340872ad3c05011f34494af51d99943b2b0fa2..c9deb3d3d118b460101bff32a718cfd313ee9f4e 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,10 @@ NAME = Zombeaver
 #
 # set default ARCH
 
-SRCARCH = sparc
+ifndef SRCARCH
+	SRCARCH = sparc
+endif
+ARCH = $(SRCARCH)
 export SRCARCH
 
 # o Do not use make's built-in rules and variables
@@ -614,7 +617,7 @@ leanos-libs	:= $(patsubst %/, %/lib.a, $(libs-y))
 # Externally visible symbols (used by link-leanos.sh)
 export KBUILD_LEANOS_INIT := $(leanos-init)
 export KBUILD_LEANOS_MAIN := $(leanos-core) $(leanos-kernel) $(leanos-libs)
-export KBUILD_LDS          := arch/$(SRCARCH)/kernel/leanos.lds
+export KBUILD_LDS          := arch/$(SRCARCH)/kernel/kernel.lds
 export LDFLAGS_leanos
 
 
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 71857b9b20fb9137489de75438d5e4dc2d8f3838..5ad57eb0c8e1f3aff7d01abfad8ed2d16aedccb5 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -48,6 +48,27 @@ config EXTRA_SPARC_PHYS_BANKS
 	 Set number of additional physical memory banks if the machine has more
 	 than one.
 
+config SPARC_CPU_REG_WINDOWS
+	int "Number of implemented SPARC register windows"
+	default 8
+	range 1 32
+	help
+	 Set the number of register windows implemented in the CPU.
+
+config SPARC_TEXT_START
+	hex "Address of .text section"
+	default 0x40000000
+	help
+	 Set the start address of the .text section. The address of the
+	 built-in SRAM might be a good choice.
+
+config SPARC_FP_START
+	hex "Initial address of the frame pointer"
+	default 0x40100000
+	help
+	 Set the initial frame pointer address. The start of the .text
+	 section plus 1 MiB is usually a safe bet.
+
 menu "Memory Management Settings"
 	depends on MM
 	depends on CHUNK
diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h
new file mode 100644
index 0000000000000000000000000000000000000000..0700b14112a67cdbd69568a50822fb698c99af99
--- /dev/null
+++ b/arch/sparc/include/asm/ttable.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_HEAD_H
+#define _SPARC_HEAD_H
+
+#define SPARC_TRAP_TFLT    0x1          /* Text fault */
+#define SPARC_TRAP_II      0x2          /* Illegal Instruction */
+#define SPARC_TRAP_PI      0x3          /* Privileged Instruction */
+#define SPARC_TRAP_FPD     0x4          /* Floating Point Disabled */
+#define SPARC_TRAP_WOVF    0x5          /* Window Overflow */
+#define SPARC_TRAP_WUNF    0x6          /* Window Underflow */
+#define SPARC_TRAP_MNA     0x7          /* Memory Address Unaligned */
+#define SPARC_TRAP_FPE     0x8          /* Floating Point Exception */
+#define SPARC_TRAP_DFLT    0x9          /* Data Fault */
+#define SPARC_TRAP_TOF     0xa          /* Tag Overflow */
+#define SPARC_TRAP_WPDT    0xb          /* Watchpoint Detected */
+#define SPARC_TRAP_IRQ1    0x11         /* IRQ level 1 */
+#define SPARC_TRAP_IRQ2    0x12         /* IRQ level 2 */
+#define SPARC_TRAP_IRQ3    0x13         /* IRQ level 3 */
+#define SPARC_TRAP_IRQ4    0x14         /* IRQ level 4 */
+#define SPARC_TRAP_IRQ5    0x15         /* IRQ level 5 */
+#define SPARC_TRAP_IRQ6    0x16         /* IRQ level 6 */
+#define SPARC_TRAP_IRQ7    0x17         /* IRQ level 7 */
+#define SPARC_TRAP_IRQ8    0x18         /* IRQ level 8 */
+#define SPARC_TRAP_IRQ9    0x19         /* IRQ level 9 */
+#define SPARC_TRAP_IRQ10   0x1a         /* IRQ level 10 */
+#define SPARC_TRAP_IRQ11   0x1b         /* IRQ level 11 */
+#define SPARC_TRAP_IRQ12   0x1c         /* IRQ level 12 */
+#define SPARC_TRAP_IRQ13   0x1d         /* IRQ level 13 */
+#define SPARC_TRAP_IRQ14   0x1e         /* IRQ level 14 */
+#define SPARC_TRAP_IRQ15   0x1f         /* IRQ level 15 Non-maskable */
+#define SPARC_TRAP_RAC     0x20         /* Register Access Error ??? */
+#define SPARC_TRAP_IAC     0x21         /* Instruction Access Error */
+#define SPARC_TRAP_CPDIS   0x24         /* Co-Processor Disabled */
+#define SPARC_TRAP_BADFL   0x25         /* Unimplemented Flush Instruction */
+#define SPARC_TRAP_CPEX    0x28         /* Co-Processor Exception */
+#define SPARC_TRAP_DACC    0x29         /* Data Access Error */
+#define SPARC_TRAP_DIVZ    0x2a         /* Divide By Zero */
+#define SPARC_TRAP_DSTORE  0x2b         /* Data Store Error (?) */
+#define SPARC_TRAP_DMM     0x2c         /* Data Access MMU Miss (?) */
+#define SPARC_TRAP_IMM     0x3c         /* Instruction Access MMU Miss (?) */
+
+
+#define PSR_PS	0x00000040         /* previous privilege level */
+
+
+#define TTBL_MASK	0xff0	/* trap type mask from tbr */
+#define TTBL_SHIFTLEFT 	    4	/* shift to get a tbr value */
+
+#define TRAP_ENTRY(type, label) rd %psr, %l0; b label; rd %wim, %l3; nop;
+
+#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 1, %l7;
+#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 0, %l7;
+
+
+
+#define WINDOW_OFLOW \
+        rd %psr, %l0; rd %wim, %l3; b __wim_overflow; andcc %l0, PSR_PS, %g0;
+
+#define WINDOW_UFLOW \
+        rd %psr, %l0; rd %wim, %l3; b __wim_underflow; andcc %l0, PSR_PS, %g0;
+
+
+/* either this */
+#define TRAP_EXCEPTION \
+	 rd %tbr, %l3; rd %psr, %l0; ba	__exception_entry; and	%l3, TTBL_MASK,	%l4;
+/* or this one */
+#define TRAP_BAD(num) \
+        rd %psr, %l0; mov num, %l7; b bad_trap_handler; rd %wim, %l3;
+
+
+#define TRAP_INTERRUPT(level) \
+        rd %psr, %l0; mov level, %l7;  b __interrupt_entry; rd %wim, %l3;
+
+/* system calls software trap */
+#define SYSCALL_TRAP \
+        sethi %hi(syscall_tbl), %l7; \
+        or %l7, %lo(syscall_tbl), %l7; \
+        b syscall_trap; \
+        rd %psr, %l0;
+
+
+#endif /* _SPARC_HEAD_H */
diff --git a/arch/sparc/include/mm.h b/arch/sparc/include/mm.h
index ed28bb34851f27791b3de6fde2f5f419dde9c41d..5508c19b1926c25fe6f8fea5063341e825a0be3c 100644
--- a/arch/sparc/include/mm.h
+++ b/arch/sparc/include/mm.h
@@ -32,9 +32,9 @@ extern struct sparc_physical_banks sp_banks[SPARC_PHYS_BANKS + 1];
 
 
 /* linker symbol marking the the start of the program (image) */
-extern char start[];
+extern char _start[];
 /* linker symbol marking the the end of the program */
-extern char end[];
+extern char _end[];
 
 
 /* The default configuration allows for at most 32 MiB sized blocks
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 5d760a657b2659e0da6fe3361ca29f84b35a9dd9..d1915c93da083f0adf332a0536211b9839bf6e9a 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -1,6 +1,8 @@
-
 CHECKFLAGS     += -D__sparc__
 
+extra-$(CONFIG_ARCH_CUSTOM_BOOT_CODE) += kernel.lds
+obj-$(CONFIG_ARCH_CUSTOM_BOOT_CODE) += ttable.o
+obj-$(CONFIG_ARCH_CUSTOM_BOOT_CODE)  += head.o
 
 obj-y += setup.o
 obj-y += init.o
@@ -18,3 +20,4 @@ obj-y += traps/data_access_exception.o
 obj-y += irq.o
 
 #libs-y                 += lib/
+
diff --git a/arch/sparc/kernel/bootmem.c b/arch/sparc/kernel/bootmem.c
index 14ea331d5e78ab62b482be0a0050cff1fe1f09e9..58d289de1e8f5f631648e163727f6aca8b4b6f62 100644
--- a/arch/sparc/kernel/bootmem.c
+++ b/arch/sparc/kernel/bootmem.c
@@ -145,20 +145,20 @@ void bootmem_init(void)
 	struct page_map_node **pg_node;
 
 
-	pr_info("BOOTMEM: start of program image at %p\n", start);
-	pr_info("BOOTMEM:   end of program image at %p\n", end);
+	pr_info("BOOTMEM: start of program image at %p\n", _start);
+	pr_info("BOOTMEM:   end of program image at %p\n", _end);
 
 
 	/* lowest page frame number coincides with page aligned address
 	 * start symbol in image, which hopefully coincides with the start
 	 * of the RAM we are running from.
 	 */
-	start_img_pfn = PAGE_ALIGN((unsigned long) &start);
+	start_img_pfn = PAGE_ALIGN((unsigned long) &_start);
 
 	/* start allocatable memory with page aligned address of last symbol in
 	 * image, everything before will be reserved
 	 */
-	start_pfn = PAGE_ALIGN((unsigned long) &end);
+	start_pfn = PAGE_ALIGN((unsigned long) &_end);
 
 	/* locate the memory bank we're in
 	 */
diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S
new file mode 100644
index 0000000000000000000000000000000000000000..5cf8eadd5d2c906c098b41e33a9ec93cad8ab1af
--- /dev/null
+++ b/arch/sparc/kernel/head.S
@@ -0,0 +1,80 @@
+
+#ifndef CONFIG_SPARC_CPU_REG_WINDOWS
+#define NWINDOWS 8
+#else
+#define NWINDOWS CONFIG_SPARC_CPU_REG_WINDOWS
+#endif /* CONFIG_SPARC_CPU_REG_WINDOWS */
+
+
+#ifndef CONFIG_SPARC_FP_START
+#define FP_INITIAL	0x40100000
+#else
+#define FP_INITIAL CONFIG_SPARC_FP_START
+#endif /* CONFIG_SPARC_FP_START */
+
+
+
+	.global kernel_entry
+
+kernel_entry:
+
+	/* First, we set the address of our trap table.	The base address is
+	 * stored in bits 31:12 of the trap base register. The remaining fields
+	 * are not affected by a WRTBR. In any case, the trap table must be
+	 * aligned to a 4k boundary, so the bits 11:0 must be zero anyways or
+	 * we are surely boned.
+	 */
+        sethi   %hi(trapbase), %g1
+        or      %g1, %lo(trapbase), %g1
+        mov     %g1, %tbr	! delayed-write instruction
+	/* WRTBR is a delayed-write instruction (0-3 cycles, impl.dependent),
+	 * but we won't access it in the next cycles, so we may continue without
+	 * inserting (3) nops.
+	 */
+
+
+	/* Now we initialise the window invalid mask to detect under/overflows.
+	 * We set the highest-value window to be invalid.
+	 */
+
+        mov     (1 << (NWINDOWS - 1)), %g1
+        mov     %g1, %wim	! delayed-write instruction
+
+
+	/* Initially, we want to start out in the window just below the one
+	 * marked invalid, so we can SAVE up to NWINDOWS - 2 times.
+	 * This is because any subsequent function call (resulting in increasing
+	 * call depth) will require a SAVE instruction, which will in
+	 * turn decrement the current window pointer in the PSR. If the CWP
+	 * reaches the invalid window while increasing the call depth, an
+	 * overflow trap will be generated. If a RESTORE reaches the invalid
+	 * window due to decreasing call depth and incrementing CWP value,
+	 * a underflow trap will occur.
+	 *
+	 * See the SPARCv8 User Manual pp.28 for the other set bits
+	 */
+
+        sethi   %hi(0x00001fc0), %g1
+        or      %g1, %lo(0x00001fc0 | (NWINDOWS - 2)), %g1
+        mov     %g1, %psr	! delayed-write instruction
+
+
+	/* Prepare a C call-stack. Minimum size is 96 bytes, however older
+	 * compilers may reserve 104. We want make sure to support the MPPB's
+	 * GCC 3.x, so we'll go with the slightly larger window size here.
+	 */
+
+        sethi   %hi(FP_INITIAL), %g2
+        or      %g2, %lo(FP_INITIAL), %g2
+        mov     %g2, %fp
+        sub     %fp, 104, %sp	! create a new frame
+
+        /* We have a stack now, so we can start handling traps. */
+	or	%g1, 0x00000020, %g1
+        mov     %g1, %psr ! delayed-write instruction
+
+	call do_basic_setup
+	 nop
+
+	call kernel_main
+	 nop
diff --git a/arch/sparc/kernel/kernel.lds.S b/arch/sparc/kernel/kernel.lds.S
new file mode 100644
index 0000000000000000000000000000000000000000..7fde0a1615b4fcff3b86b66946b54dedf2310a4d
--- /dev/null
+++ b/arch/sparc/kernel/kernel.lds.S
@@ -0,0 +1,111 @@
+/* ld script for sparc32 kernel */
+/* based on macros from linux/include/asm-generic/vmlinux.lds.h */
+
+
+#define INITIAL_ADDRESS 0x00000000 /* rom */
+
+#ifndef CONFIG_SPARC_TEXT_START
+#define TEXTSTART	0x40000000 /* default ram */
+#else
+#define TEXTSTART CONFIG_SPARC_TEXT_START
+#endif /* CONFIG_SPARC_TEXT_START */
+
+
+OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc")
+OUTPUT_ARCH(sparc)
+ENTRY(_start)
+
+SECTIONS
+{
+	. = INITIAL_ADDRESS;
+	.text TEXTSTART :
+	{
+		_text = .;
+		*(.head.text)
+		*.(text .text.*)
+		*(.gnu.warning)
+	} = 0
+	_etext = .;
+
+
+
+	. = ALIGN(16);
+	.rodata : {
+		__start_rodata = .;
+		*(.rodata) *(.rodata.*)
+	}
+
+
+	/* start of data section */
+	_sdata = .;
+	.data : {
+		*(.data .data.*)
+	}
+	/* end of data section */
+	_edata = .;
+
+
+	. = ALIGN(16);
+	__init_begin = .;
+	.init.data : {
+		/* linux-style init calls */
+		__initcall_start = .;
+		KEEP(*(.initcall1.init))
+		KEEP(*(.initcall2.init))
+		KEEP(*(.initcall3.init))
+		KEEP(*(.initcall4.init))
+		KEEP(*(.initcall5.init))
+		KEEP(*(.initcall6.init))
+		KEEP(*(.initcall7.init))
+		__initcall_end = .;
+	}
+	__init_end = .;
+
+
+
+	. = ALIGN(8);
+	__bss_start = .;
+
+	. = ALIGN(8);
+	.bss : {
+		*(.bss .bss.*)
+		*(COMMON)
+	}
+
+	. = ALIGN(8);
+	__bss_stop = .;
+	_end = . ;
+
+	. = ALIGN(16);
+	.eh_frame : {*(.eh_frame)}
+
+	.stab 		0 : { *(.stab) }
+	.stabstr 	0 : { *(.stabstr) }
+	.stab.excl 	0 : { *(.stab.excl) }
+	.stab.exclstr 	0 : { *(.stab.exclstr) }
+	.stab.index 	0 : { *(.stab.index) }
+	.stab.indexstr 	0 : { *(.stab.indexstr) }
+	.comment 	0 : { *(.comment) }
+
+
+	.debug           	0 : { *(.debug) }
+	.line            	0 : { *(.line) }
+	.debug_srcinfo   	0 : { *(.debug_srcinfo) }
+	.debug_sfnames   	0 : { *(.debug_sfnames) }
+	.debug_aranges   	0 : { *(.debug_aranges) }
+	.debug_pubnames  	0 : { *(.debug_pubnames) }
+	.debug_info      	0 : { *(.debug_info .gnu.linkonce.wi.*) }
+	.debug_abbrev    	0 : { *(.debug_abbrev) }
+	.debug_line      	0 : { *(.debug_line) }
+	.debug_frame     	0 : { *(.debug_frame) }
+	.debug_str       	0 : { *(.debug_str) }
+	.debug_loc       	0 : { *(.debug_loc) }
+	.debug_macinfo   	0 : { *(.debug_macinfo) }
+	.debug_pubtypes  	0 : { *(.debug_pubtypes) }
+	.debug_ranges	 	0 : { *(.debug_ranges) }
+	.debug_gnu_pubnames 	0 : { *(.debug_gnu_pubnames) }
+	.debug_gnu_pubtypes 	0 : { *(.debug_gnu_pubtypes) }
+	.debug_types		0 : { *(.debug_types) }
+	.debug_macro		0 : { *(.debug_macro) }
+	.debug_addr		0 : { *(.debug_addr) }
+}
diff --git a/arch/sparc/kernel/ttable.S b/arch/sparc/kernel/ttable.S
new file mode 100644
index 0000000000000000000000000000000000000000..1876278f02983a10ff429f6ad7a803a9a32c2f1b
--- /dev/null
+++ b/arch/sparc/kernel/ttable.S
@@ -0,0 +1,185 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+
+#include <asm/ttable.h>
+
+
+
+.section	".head.text","ax"
+
+        .global  _start
+_start:
+
+	.global _stext
+_stext:
+
+	.global  trapbase
+trapbase:
+
+#ifdef CONFIG_SMP
+trapbase_cpu0:
+#endif /* CONFIG_SMP */
+
+	/* hardware traps (128 total) */
+	! 0x00 reset trap (alternative: b gokernel; nop; nop; nop)
+	b kernel_entry	! branch once on cold start, post setup inserts rd %tbr/%psr (see TRAP_EXCEPTION)
+	 nop			! instructions to raise exception on warm reset
+	ba __exception_entry
+         and    %l3, TTBL_MASK, %l4
+
+	SRMMU_TFAULT
+	TRAP_ENTRY(SPARC_TRAP_II, ill_instruction_trap_handler)
+	TRAP_ENTRY(SPARC_TRAP_PI, priv_instruction_trap_handler)
+	TRAP_ENTRY(SPARC_TRAP_FPD, fpdis_trap_handler)
+	WINDOW_OFLOW
+	WINDOW_UFLOW
+	TRAP_ENTRY(SPARC_TRAP_MNA, mna_trap_handler)
+	TRAP_ENTRY(SPARC_TRAP_FPE, fpe_trap_handler)
+	SRMMU_DFAULT		! Data Fault 
+	TRAP_ENTRY(SPARC_TRAP_TOF, tag_overflow_trap_handler)
+	TRAP_ENTRY(SPARC_TRAP_WPDT, watchpoint_det_trap_handler)
+
+	.rept 5
+	TRAP_EXCEPTION	! bad traps
+	.endr
+
+	TRAP_INTERRUPT(1)
+	TRAP_INTERRUPT(2)
+	TRAP_INTERRUPT(3)
+	TRAP_INTERRUPT(4)
+	TRAP_INTERRUPT(5)
+	TRAP_INTERRUPT(6)
+	TRAP_INTERRUPT(7)
+	TRAP_INTERRUPT(8)
+	TRAP_INTERRUPT(9)
+	TRAP_INTERRUPT(10)
+	TRAP_INTERRUPT(11)
+	TRAP_INTERRUPT(12)
+	TRAP_INTERRUPT(13)
+	TRAP_INTERRUPT(14)
+	TRAP_ENTRY(15, nmi_entry)	! treat NMI interrupt differntly
+
+	TRAP_ENTRY(SPARC_TRAP_RAC, reg_access_trap_handler)
+	TRAP_EXCEPTION		!  Instruction Access Error
+	TRAP_EXCEPTION		!  bad trap
+	TRAP_EXCEPTION		!  bad trap
+	TRAP_ENTRY(SPARC_TRAP_CPDIS, cpdis_trap_handler)
+	TRAP_ENTRY(SPARC_TRAP_BADFL, unimpl_flush_trap_handler)
+	TRAP_EXCEPTION		!  bad trap
+	TRAP_EXCEPTION		!  bad trap
+	TRAP_ENTRY(SPARC_TRAP_CPEX, cpex_trap_handler)
+	SRMMU_DFAULT		!  Data Access Error
+	TRAP_ENTRY(SPARC_TRAP_DIVZ, hw_div0_trap_handler)
+	TRAP_EXCEPTION		!  Data Store Error
+	TRAP_EXCEPTION		!  Data Access MMU Miss
+
+	.rept 15
+	TRAP_EXCEPTION		! bad traps
+	.endr
+
+	TRAP_EXCEPTION		! Instruction Access MMU Miss
+
+	.rept 67
+	TRAP_EXCEPTION		! bad traps
+	.endr
+
+	/* software traps (128 total) */
+	SYSCALL_TRAP		! 0x80 = SunOS syscall()
+	TRAP_EXCEPTION		! 0x81
+	TRAP_EXCEPTION		! 0x82
+	TRAP_EXCEPTION		! 0x83
+	TRAP_EXCEPTION		! 0x84
+	TRAP_EXCEPTION		! 0x85
+
+	.rept 122
+	TRAP_EXCEPTION				! 0x86-0xFF unused
+	.endr
+
+	.globl	end_traptable
+end_traptable:
+
+
+
+
+
+#ifdef CONFIG_SMP
+	.globl	trapbase_cpu1
+trapbase_cpu1:
+
+	/* XXX: stuff */
+
+#endif /* CONFIG_SMP */
+
+
+        .global  leonbare_trapsetup
+leonbare_trapsetup:
+	.global catch_interrupt
+catch_interrupt:
+	.global coldboot_reset
+coldboot_reset:
+	.global __exception_entry
+__exception_entry:
+	.global srmmu_fault
+srmmu_fault:
+	.global ill_instruction_trap_handler
+ill_instruction_trap_handler:
+	.global priv_instruction_trap_handler
+priv_instruction_trap_handler:
+
+
+	.global leonbare_trapreturn
+leonbare_trapreturn:
+	.global fpdis_trap_handler
+fpdis_trap_handler:
+	.global __wim_overflow
+__wim_overflow:
+	.global __wim_underflow
+__wim_underflow:
+	.global mna_trap_handler
+mna_trap_handler:
+	.global fpe_trap_handler
+fpe_trap_handler:
+	.global tag_overflow_trap_handler
+tag_overflow_trap_handler:
+	.global mna_trap_handler
+mna_trap_handler:
+	.global cpdis_trap_handler
+cpdis_trap_handler:
+	.global cpex_trap_handler
+cpex_trap_handler:
+	.global fpe_trap_handler
+fpe_trap_handler:
+	.global hw_div0_trap_handler
+hw_div0_trap_handler:
+	.global __interrupt_entry
+__interrupt_entry:
+	.global __clzsi2
+__clzsi2:
+	.global memset
+memset:
+	.global nmi_entry
+nmi_entry:
+	.global reg_access_trap_handler
+reg_access_trap_handler:
+	.global strchr
+strchr:
+	.global strtol
+strtol:
+	.global syscall_tbl
+syscall_tbl:
+	.global syscall_trap
+syscall_trap:
+	.global tag_overflow_trap_handler
+tag_overflow_trap_handler:
+	.global .udiv
+.udiv:
+	.global .umul
+.umul:
+	.global unimpl_flush_trap_handler
+unimpl_flush_trap_handler:
+	.global vprintf
+vprintf:
+	.global vsnprintf
+vsnprintf:
+	.global watchpoint_det_trap_handler
+watchpoint_det_trap_handler:
diff --git a/include/kernel/kernel.h b/include/kernel/kernel.h
index 7e7fc7e68703b5b8912948337efdb8f072a10453..da84f0c51ad48b4dc3478d8bd380f875f48d8f35 100644
--- a/include/kernel/kernel.h
+++ b/include/kernel/kernel.h
@@ -2,6 +2,7 @@
 #define _KERNEL_H_
 
 #include <compiler.h>
+#include <kernel/printk.h>
 
 #define ALIGN_MASK(x, mask)    (((x) + (mask)) & ~(mask))
 #define ALIGN(x, a)            ALIGN_MASK(x, (typeof(x))(a) - 1)
@@ -12,9 +13,8 @@
 #define panic(x) {} while(1);
 
 /* the BUG() macros may be repurposed to log an error and boot to safe mode! */
-#include <stdio.h>
 #define BUG() do { \
-        printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
+        printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
         panic("BUG!"); \
 } while (0)
 
diff --git a/include/kernel/types.h b/include/kernel/types.h
index 94480ce36e3d2754f3edc1600f8285073365feb6..25948df9d4d2adb87ccd1812ba1e88f52c68f139 100644
--- a/include/kernel/types.h
+++ b/include/kernel/types.h
@@ -8,7 +8,7 @@
 #include <compiler.h>
 
 #include <stddef.h>
-
+#include <sys/types.h>
 #include <stdbool.h>
 
 #ifdef __GNUC__
diff --git a/init/Kconfig b/init/Kconfig
index 6b27a0b14dee8ac1d3640565e45d0069eb55128c..ddc0eeb8eadfdd7bfcd11abaaa261f8e77f4e11d 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -36,11 +36,22 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+choice
+	prompt "Boot/Startup code"
+	default TARGET_COMPILER_BOOT_CODE
+
 config TARGET_COMPILER_BOOT_CODE
 	bool "Use target compiler's boot/startup code"
-	default y if CROSS_PLATFORM_TARGET
 	help
-	  Use the compiler-provided boot code (e.g. BCC target)
+	  Use the compiler-provided boot code (e.g. with BCC)
+
+config ARCH_CUSTOM_BOOT_CODE
+	bool "Use architecture's boot/startup code"
+	help
+	  Use the architecture-provided boot code
+
+endchoice # "Boot/Startup code
+
 
 endmenu # "General Setup"
 
diff --git a/init/main.c b/init/main.c
index dd43b1d2836c23e3c10d9b98bbe532c5788018b0..1d3b7f322700f2552bd320bdeb3e003d99f32e7b 100644
--- a/init/main.c
+++ b/init/main.c
@@ -40,7 +40,6 @@
 
 
 
-#ifdef CONFIG_TARGET_COMPILER_BOOT_CODE
 
 /**
  * @brief kernel initialisation routines
@@ -54,20 +53,25 @@ static int kernel_init(void)
 
 	setup_arch();
 
+	/* free_bootmem() */
+	/* run_init_process() */
+
 	return 0;
 }
 arch_initcall(kernel_init);
 
 
+
 /**
  * @brief kernel main function
  */
 
-int main(void)
+int kernel_main(void)
 {
+#if 0
 	void *addr;
 	struct elf_module m;
-
+#endif
 
 	printk(MSG "Loading module image\n");
 
@@ -118,4 +122,30 @@ int main(void)
 	return 0;
 }
 
-#endif /* CONFIG_TARGET_COMPILER_BOOT_CODE */
+#ifdef CONFIG_ARCH_CUSTOM_BOOT_CODE
+
+extern initcall_t __initcall_start;
+extern initcall_t __initcall_end;
+
+static void do_initcalls(void)
+{
+    initcall_t *p = &__initcall_start;
+
+    while(p < &__initcall_end) {
+        if (*p)
+            (*p)();
+	p++;
+    }
+
+}
+
+void do_basic_setup(void)
+{
+	do_initcalls();
+}
+
+
+#endif /* CONFIG_ARCH_CUSTOM_BOOT_CODE */
+
+
+
diff --git a/scripts/link-leanos.sh b/scripts/link-leanos.sh
index 807131caf9a612432ab07ab25b6dbf86259637a1..db0f57a1cb85898593977e34b47939a1766e1e76 100755
--- a/scripts/link-leanos.sh
+++ b/scripts/link-leanos.sh
@@ -80,26 +80,20 @@ modpost_link()
 leanos_link()
 {
 	local lds="${objtree}/${KBUILD_LDS}"
-	local objects
 
 
-	# since we link against the BCC libc at this time, we'll just
+	# if we link against the (BCC) libc, we'll just
 	# call $CC instead of LD
-	${CC} ${LDFLAGS} ${LDFLAGS_leanos} ${3} -o ${2}		\
-		${KBUILD_LEANOS_INIT} ${KBUILD_LEANOS_MAIN} ${1}
-
-#	if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then
-#		objects="--whole-archive built-in.o ${1}"
-#	else
-#		objects="${KBUILD_LEANOS_INIT}			\
-#			--start-group				\
-#			${KBUILD_LEANOS_MAIN}			\
-#			--end-group				\
-#			${1}"
-#	fi
-#
-#	${LD} ${LDFLAGS} ${LDFLAGS_leanos} -o ${2}		\
-#		-T ${lds} ${objects}
+	if [ -n "${CONFIG_TARGET_COMPILER_BOOT_CODE}" ]; then
+		${CC} ${LDFLAGS} ${LDFLAGS_leanos} ${3} -o ${2}		\
+			${KBUILD_LEANOS_INIT} ${KBUILD_LEANOS_MAIN} ${1}
+	fi
+
+	if [ -n "${CONFIG_ARCH_CUSTOM_BOOT_CODE}" ]; then
+		${LD} ${LDFLAGS} ${LDFLAGS_leanos} ${3} -o ${2}		\
+			-T ${lds} ${KBUILD_LEANOS_INIT} ${KBUILD_LEANOS_MAIN} \
+			${1}
+	fi
 
 }
 
@@ -303,7 +297,15 @@ if [ "$1" = "embed" ]; then
 #		exit
 #	fi
 
-	embedflags="-Wl,--format=binary -Wl,modules.image -Wl,--format=default"
+	if [ -n "${CONFIG_TARGET_COMPILER_BOOT_CODE}" ]; then
+		embedflags="-Wl,--format=binary -Wl,modules.image -Wl,--format=default"
+	fi
+
+	if [ -n "${CONFIG_ARCH_CUSTOM_BOOT_CODE}" ]; then
+		embedflags="--format=binary modules.image --format=default"
+	fi
+
+
 	rm -f modules.image
 	${AR} rcs ${srctree}/modules.image \
 		$(tr '\n' ' ' < ${srctree}/modules.order) \