Index: kernel/arch/abs32le/src/abs32le.c
===================================================================
--- kernel/arch/abs32le/src/abs32le.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/abs32le/src/abs32le.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -86,5 +86,5 @@
 }
 
-sysarg_t sys_tls_set(sysarg_t addr)
+sysarg_t sys_tls_set(uintptr_t addr)
 {
 	return EOK;
Index: kernel/arch/amd64/Makefile.inc
===================================================================
--- kernel/arch/amd64/Makefile.inc	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/amd64/Makefile.inc	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -72,5 +72,6 @@
 ARCH_SOURCES = \
 	arch/$(KARCH)/src/fpu_context.c \
-	arch/$(KARCH)/src/boot/boot.S \
+	arch/$(KARCH)/src/boot/multiboot.S \
+	arch/$(KARCH)/src/boot/multiboot2.S \
 	arch/$(KARCH)/src/boot/memmap.c \
 	arch/$(KARCH)/src/debug/stacktrace.c \
@@ -79,5 +80,4 @@
 	arch/$(KARCH)/src/context.S \
 	arch/$(KARCH)/src/ddi/ddi.c \
-	arch/$(KARCH)/src/drivers/vesa.c \
 	arch/$(KARCH)/src/drivers/i8254.c \
 	arch/$(KARCH)/src/drivers/i8259.c \
Index: kernel/arch/amd64/include/arch.h
===================================================================
--- kernel/arch/amd64/include/arch.h	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/amd64/include/arch.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -38,5 +38,5 @@
 #include <genarch/multiboot/multiboot.h>
 
-extern void arch_pre_main(uint32_t, const multiboot_info_t *);
+extern void arch_pre_main(uint32_t, void *);
 
 #endif
Index: kernel/arch/amd64/include/boot/boot.h
===================================================================
--- kernel/arch/amd64/include/boot/boot.h	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/amd64/include/boot/boot.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -40,7 +40,4 @@
 #define BOOT_STACK_SIZE  0x000400
 
-#define MULTIBOOT_HEADER_MAGIC  0x1BADB002
-#define MULTIBOOT_HEADER_FLAGS  0x00010003
-
 #ifndef __ASM__
 
Index: kernel/arch/amd64/src/amd64.c
===================================================================
--- kernel/arch/amd64/src/amd64.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/amd64/src/amd64.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -34,38 +34,29 @@
 
 #include <arch.h>
-
 #include <typedefs.h>
-
-#include <config.h>
-
-#include <proc/thread.h>
-#include <genarch/multiboot/multiboot.h>
-#include <genarch/drivers/legacy/ia32/io.h>
-#include <genarch/drivers/ega/ega.h>
-#include <arch/drivers/vesa.h>
-#include <genarch/drivers/i8042/i8042.h>
-#include <genarch/kbrd/kbrd.h>
+#include <errno.h>
+#include <memstr.h>
+#include <interrupt.h>
+#include <console/console.h>
+#include <syscall/syscall.h>
+#include <sysinfo/sysinfo.h>
+#include <arch/bios/bios.h>
+#include <arch/boot/boot.h>
+#include <arch/debugger.h>
 #include <arch/drivers/i8254.h>
 #include <arch/drivers/i8259.h>
-#include <arch/boot/boot.h>
+#include <arch/syscall.h>
+#include <genarch/acpi/acpi.h>
+#include <genarch/drivers/ega/ega.h>
+#include <genarch/drivers/i8042/i8042.h>
+#include <genarch/drivers/legacy/ia32/io.h>
+#include <genarch/fb/bfb.h>
+#include <genarch/kbrd/kbrd.h>
+#include <genarch/multiboot/multiboot.h>
+#include <genarch/multiboot/multiboot2.h>
 
 #ifdef CONFIG_SMP
 #include <arch/smp/apic.h>
 #endif
-
-#include <arch/bios/bios.h>
-#include <arch/cpu.h>
-#include <print.h>
-#include <arch/cpuid.h>
-#include <genarch/acpi/acpi.h>
-#include <panic.h>
-#include <interrupt.h>
-#include <arch/syscall.h>
-#include <arch/debugger.h>
-#include <syscall/syscall.h>
-#include <console/console.h>
-#include <ddi/irq.h>
-#include <sysinfo/sysinfo.h>
-#include <memstr.h>
 
 /** Disable I/O on non-privileged levels
@@ -101,11 +92,13 @@
 /** Perform amd64-specific initialization before main_bsp() is called.
  *
- * @param signature Should contain the multiboot signature.
- * @param mi        Pointer to the multiboot information structure.
- */
-void arch_pre_main(uint32_t signature, const multiboot_info_t *mi)
+ * @param signature Multiboot signature.
+ * @param info      Multiboot information structure.
+ *
+ */
+void arch_pre_main(uint32_t signature, void *info)
 {
 	/* Parse multiboot information obtained from the bootloader. */
-	multiboot_info_parse(signature, mi);
+	multiboot_info_parse(signature, (multiboot_info_t *) info);
+	multiboot2_info_parse(signature, (multiboot2_info_t *) info);
 	
 #ifdef CONFIG_SMP
@@ -153,13 +146,13 @@
 		
 #if (defined(CONFIG_FB) || defined(CONFIG_EGA))
-		bool vesa = false;
+		bool bfb = false;
 #endif
 		
 #ifdef CONFIG_FB
-		vesa = vesa_init();
+		bfb = bfb_init();
 #endif
 		
 #ifdef CONFIG_EGA
-		if (!vesa) {
+		if (!bfb) {
 			outdev_t *egadev = ega_init(EGA_BASE, EGA_VIDEORAM);
 			if (egadev)
@@ -261,10 +254,10 @@
  * we need not to go to CPL0 to read it.
  */
-sysarg_t sys_tls_set(sysarg_t addr)
+sysarg_t sys_tls_set(uintptr_t addr)
 {
 	THREAD->arch.tls = addr;
 	write_msr(AMD_MSR_FS, addr);
 	
-	return 0;
+	return EOK;
 }
 
Index: kernel/arch/amd64/src/boot/boot.S
===================================================================
--- kernel/arch/amd64/src/boot/boot.S	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ 	(revision )
@@ -1,681 +1,0 @@
-/*
- * Copyright (c) 2005 Ondrej Palkovsky
- * Copyright (c) 2006 Martin Decky
- * Copyright (c) 2008 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <arch/boot/boot.h>
-#include <arch/boot/memmap.h>
-#include <arch/mm/page.h>
-#include <arch/mm/ptl.h>
-#include <arch/pm.h>
-#include <arch/cpu.h>
-#include <arch/cpuid.h>
-
-#define START_STACK  (BOOT_OFFSET - BOOT_STACK_SIZE)
-
-.section K_TEXT_START, "ax"
-
-.code32
-
-.macro pm_error msg
-	movl \msg, %esi
-	jmp pm_error_halt
-.endm
-
-.macro pm_status msg
-#ifdef CONFIG_EGA
-	pushl %esi
-	movl \msg, %esi
-	call pm_early_puts
-	popl %esi
-#endif
-.endm
-
-.macro pm2_status msg
-#ifndef CONFIG_FB
-	pm_status \msg
-#endif
-.endm
-
-.align 4
-.global multiboot_image_start
-multiboot_header:
-	.long MULTIBOOT_HEADER_MAGIC
-	.long MULTIBOOT_HEADER_FLAGS
-	.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)  /* checksum */
-	.long multiboot_header
-	.long unmapped_ktext_start
-	.long 0
-	.long 0
-	.long multiboot_image_start
-
-multiboot_image_start:
-	cld
-	
-	/* Initialize stack pointer */
-	movl $START_STACK, %esp
-	
-	/* Initialize Global Descriptor Table register */
-	lgdtl bootstrap_gdtr
-	
-	/* Kernel data + stack */
-	movw $GDT_SELECTOR(KDATA_DES), %cx
-	movw %cx, %es
-	movw %cx, %ds
-	movw %cx, %ss
-	
-	/*
-	 * Simics seems to remove hidden part of GS on entering user mode
-	 * when _visible_ part of GS does not point to user-mode segment.
-	 */
-	movw $GDT_SELECTOR(UDATA_DES), %cx
-	movw %cx, %fs
-	movw %cx, %gs
-	
-	jmpl $GDT_SELECTOR(KTEXT32_DES), $multiboot_meeting_point
-	multiboot_meeting_point:
-	
-	/* Save GRUB arguments */
-	movl %eax, grub_eax
-	movl %ebx, grub_ebx
-	
-	pm_status $status_prot
-	
-	movl $(INTEL_CPUID_EXTENDED), %eax
-	cpuid
-	cmp $(INTEL_CPUID_EXTENDED), %eax
-	ja extended_cpuid_supported
-	
-		pm_error $err_extended_cpuid
-	
-	extended_cpuid_supported:
-	
-	movl $(AMD_CPUID_EXTENDED), %eax
-	cpuid
-	bt $(AMD_EXT_LONG_MODE), %edx
-	jc long_mode_supported
-	
-		pm_error $err_long_mode
-	
-	long_mode_supported:
-	
-	bt $(AMD_EXT_NOEXECUTE), %edx
-	jc noexecute_supported
-	
-		pm_error $err_noexecute
-	
-	noexecute_supported:
-	
-	movl $(INTEL_CPUID_STANDARD), %eax
-	cpuid
-	bt $(INTEL_FXSAVE), %edx
-	jc fx_supported
-	
-		pm_error $err_fx
-	
-	fx_supported:
-	
-	bt $(INTEL_SSE2), %edx
-	jc sse2_supported
-	
-		pm_error $err_sse2
-	
-	sse2_supported:
-	
-#include "vesa_prot.inc"
-	
-	/*
-	 * Protected 32-bit. We want to reuse the code-seg descriptor,
-	 * the Default operand size must not be 1 when entering long mode.
-	 */
-	
-	pm2_status $status_prot2
-	
-	/*
-	 * Enable 64-bit page translation entries - CR4.PAE = 1.
-	 * Paging is not enabled until after long mode is enabled.
-	 */
-	
-	movl %cr4, %eax
-	btsl $5, %eax
-	movl %eax, %cr4
-	
-	/* Set up paging tables */
-	leal ptl_0, %eax
-	movl %eax, %cr3
-	
-	/* Enable long mode */
-	movl $EFER_MSR_NUM, %ecx
-	rdmsr                     /* read EFER */
-	btsl $AMD_LME_FLAG, %eax  /* set LME = 1 */
-	wrmsr
-	
-	/* Enable paging to activate long mode (set CR0.PG = 1) */
-	movl %cr0, %eax
-	btsl $31, %eax
-	movl %eax, %cr0
-	
-	/* At this point we are in compatibility mode */
-	jmpl $GDT_SELECTOR(KTEXT_DES), $start64
-
-/** Print string to EGA display (in light red) and halt.
- *
- * Should be executed from 32 bit protected mode with paging
- * turned off. Stack is not required. This routine is used even
- * if CONFIG_EGA is not enabled. Since we are going to halt the
- * CPU anyway, it is always better to at least try to print
- * some hints.
- *
- * @param %esi Pointer to the NULL-terminated string
- *             to be print.
- *
- */
-pm_error_halt:
-	movl $0xb8000, %edi  /* base of EGA text mode memory */
-	xorl %eax, %eax
-	
-	/* Read bits 8 - 15 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xe, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	inb %dx, %al
-	shl $8, %ax
-	
-	/* Read bits 0 - 7 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xf, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	inb %dx, %al
-	
-	/* Sanity check for the cursor on screen */
-	cmp $2000, %ax
-	jb err_cursor_ok
-	
-		movw $1998, %ax
-	
-	err_cursor_ok:
-	
-	movw %ax, %bx
-	shl $1, %eax
-	addl %eax, %edi
-	
-	err_ploop:
-		lodsb
-		
-		cmp $0, %al
-		je err_ploop_end
-		
-		movb $0x0c, %ah  /* black background, light red foreground */
-		stosw
-		
-		/* Sanity check for the cursor on the last line */
-		inc %bx
-		cmp $2000, %bx
-		jb err_ploop
-		
-		/* Scroll the screen (24 rows) */
-		movl %esi, %edx
-		movl $0xb80a0, %esi
-		movl $0xb8000, %edi
-		movl $960, %ecx
-		rep movsl
-		
-		/* Clear the 24th row */
-		xorl %eax, %eax
-		movl $40, %ecx
-		rep stosl
-		
-		/* Go to row 24 */
-		movl %edx, %esi
-		movl $0xb8f00, %edi
-		movw $1920, %bx
-		
-		jmp err_ploop
-	err_ploop_end:
-	
-	/* Write bits 8 - 15 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xe, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	movb %bh, %al
-	outb %al, %dx
-	
-	/* Write bits 0 - 7 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xf, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	movb %bl, %al
-	outb %al, %dx
-	
-	cli
-	hlt1:
-		hlt
-		jmp hlt1
-
-/** Print string to EGA display (in light green).
- *
- * Should be called from 32 bit protected mode with paging
- * turned off. A stack space of at least 24 bytes is required,
- * but the function does not establish a stack frame.
- *
- * Macros such as pm_status and pm2_status take care that
- * this function is used only when CONFIG_EGA is enabled
- * and CONFIG_FB is disabled.
- *
- * @param %esi Pointer to the NULL-terminated string
- *             to be print.
- *
- */
-pm_early_puts:
-	pushl %eax
-	pushl %ebx
-	pushl %ecx
-	pushl %edx
-	pushl %edi
-	
-	movl $0xb8000, %edi  /* base of EGA text mode memory */
-	xorl %eax, %eax
-	
-	/* Read bits 8 - 15 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xe, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	inb %dx, %al
-	shl $8, %ax
-	
-	/* Read bits 0 - 7 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xf, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	inb %dx, %al
-	
-	/* Sanity check for the cursor on screen */
-	cmp $2000, %ax
-	jb pm_puts_cursor_ok
-	
-		movw $1998, %ax
-	
-	pm_puts_cursor_ok:
-	
-	movw %ax, %bx
-	shl $1, %eax
-	addl %eax, %edi
-	
-	pm_puts_ploop:
-		lodsb
-		
-		cmp $0, %al
-		je pm_puts_ploop_end
-		
-		movb $0x0a, %ah  /* black background, light green foreground */
-		stosw
-		
-		/* Sanity check for the cursor on the last line */
-		inc %bx
-		cmp $2000, %bx
-		jb pm_puts_ploop
-		
-		/* Scroll the screen (24 rows) */
-		movl %esi, %edx
-		movl $0xb80a0, %esi
-		movl $0xb8000, %edi
-		movl $960, %ecx
-		rep movsl
-		
-		/* Clear the 24th row */
-		xorl %eax, %eax
-		movl $40, %ecx
-		rep stosl
-		
-		/* Go to row 24 */
-		movl %edx, %esi
-		movl $0xb8f00, %edi
-		movw $1920, %bx
-		
-		jmp pm_puts_ploop
-	pm_puts_ploop_end:
-	
-	/* Write bits 8 - 15 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xe, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	movb %bh, %al
-	outb %al, %dx
-	
-	/* Write bits 0 - 7 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xf, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	movb %bl, %al
-	outb %al, %dx
-	
-	popl %edi
-	popl %edx
-	popl %ecx
-	popl %ebx
-	popl %eax
-	
-	ret
-
-.code64
-
-.macro long_status msg
-	pushq %rdi
-	movq \msg, %rdi
-	call early_puts
-	popq %rdi
-.endm
-
-start64:
-	
-	/*
-	 * Long mode.
-	 */
-	
-	movq $(PA2KA(START_STACK)), %rsp
-	
-	/* Create the first stack frame */
-	pushq $0
-	movq %rsp, %rbp
-	
-	long_status $status_long
-	
-	/* Call arch_pre_main(grub_eax, grub_ebx) */
-	xorq %rdi, %rdi
-	movl grub_eax, %edi
-	xorq %rsi, %rsi
-	movl grub_ebx, %esi
-	
-	movabsq $arch_pre_main, %rax
-	callq *%rax
-	
-	long_status $status_main
-	
-	/* Call main_bsp() */
-	movabsq $main_bsp, %rax
-	call *%rax
-	
-	/* Not reached */
-	cli
-	hlt0:
-		hlt
-		jmp hlt0
-
-/** Print string to EGA display.
- *
- * Should be called from long mode (with paging enabled
- * and stack established). This function is ABI compliant
- * (without red-zone).
- *
- * If CONFIG_EGA is undefined or CONFIG_FB is defined
- * then this function does nothing.
- *
- * @param %rdi Pointer to the NULL-terminated string
- *             to be printed.
- *
- */
-early_puts:
-	
-#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
-	
-	/* Prologue, save preserved registers */
-	pushq %rbp
-	movq %rsp, %rbp
-	pushq %rbx
-	
-	movq %rdi, %rsi
-	movq $(PA2KA(0xb8000)), %rdi  /* base of EGA text mode memory */
-	xorq %rax, %rax
-	
-	/* Read bits 8 - 15 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xe, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	inb %dx, %al
-	shl $8, %ax
-	
-	/* Read bits 0 - 7 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xf, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	inb %dx, %al
-	
-	/* Sanity check for the cursor on screen */
-	cmp $2000, %ax
-	jb early_puts_cursor_ok
-	
-		movw $1998, %ax
-	
-	early_puts_cursor_ok:
-	
-	movw %ax, %bx
-	shl $1, %rax
-	addq %rax, %rdi
-	
-	early_puts_ploop:
-		lodsb
-		
-		cmp $0, %al
-		je early_puts_ploop_end
-		
-		movb $0x0e, %ah  /* black background, yellow foreground */
-		stosw
-		
-		/* Sanity check for the cursor on the last line */
-		inc %bx
-		cmp $2000, %bx
-		jb early_puts_ploop
-		
-		/* Scroll the screen (24 rows) */
-		movq %rsi, %rdx
-		movq $(PA2KA(0xb80a0)), %rsi
-		movq $(PA2KA(0xb8000)), %rdi
-		movl $480, %ecx
-		rep movsq
-		
-		/* Clear the 24th row */
-		xorl %eax, %eax
-		movl $20, %ecx
-		rep stosq
-		
-		/* Go to row 24 */
-		movq %rdx, %rsi
-		movq $(PA2KA(0xb8f00)), %rdi
-		movw $1920, %bx
-		
-		jmp early_puts_ploop
-	early_puts_ploop_end:
-	
-	/* Write bits 8 - 15 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xe, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	movb %bh, %al
-	outb %al, %dx
-	
-	/* Write bits 0 - 7 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xf, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	movb %bl, %al
-	outb %al, %dx
-	
-	/* Epilogue, restore preserved registers */
-	popq %rbx
-	leave
-	
-#endif
-	
-	ret
-
-#include "vesa_real.inc"
-
-.section K_INI_PTLS, "aw", @progbits
-
-/** Generate initial page table contents.
- *
- * @param cnt Number of entries to generate. Must be multiple of 8.
- * @param g   Number of GB that will be added to the mapping.
- *
- */
-.macro ptl2gen cnt g
-	.if \cnt
-		ptl2gen "\cnt - 8" \g
-		.quad ((\cnt - 8) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
-		.quad ((\cnt - 7) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
-		.quad ((\cnt - 6) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
-		.quad ((\cnt - 5) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
-		.quad ((\cnt - 4) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
-		.quad ((\cnt - 3) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
-		.quad ((\cnt - 2) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
-		.quad ((\cnt - 1) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
-	.endif
-.endm
-
-/* Page table for pages in the 1st gigabyte. */
-.align 4096
-ptl_2_0g:
-	ptl2gen 512 0
-
-/* Page table for pages in the 2nd gigabyte. */
-.align 4096
-ptl_2_1g:
-	ptl2gen 512 1
-
-/* Page table for pages in the 3rd gigabyte. */
-.align 4096
-ptl_2_2g:
-	ptl2gen 512 2
-
-/* Page table for pages in the 4th gigabyte. */
-.align 4096
-ptl_2_3g:
-	ptl2gen 512 3
-
-/* Page table for pages in the 5th gigabyte. */
-.align 4096
-ptl_2_4g:
-	ptl2gen 512 4
-
-/* Page table for pages in the 6th gigabyte. */
-.align 4096
-ptl_2_5g:
-	ptl2gen 512 5
-
-/* Page table for pages in the 7th gigabyte. */
-.align 4096
-ptl_2_6g:
-	ptl2gen 512 6
-
-/* Page table for pages in the 8th gigabyte. */
-.align 4096
-ptl_2_7g:
-	ptl2gen 512 7
-
-.align 4096
-ptl_1:
-	/* Identity mapping for [0; 8G) */
-	.quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
-	.quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT)
-	.quad ptl_2_2g + (PTL_WRITABLE | PTL_PRESENT)
-	.quad ptl_2_3g + (PTL_WRITABLE | PTL_PRESENT)
-	.quad ptl_2_4g + (PTL_WRITABLE | PTL_PRESENT)
-	.quad ptl_2_5g + (PTL_WRITABLE | PTL_PRESENT)
-	.quad ptl_2_6g + (PTL_WRITABLE | PTL_PRESENT)
-	.quad ptl_2_7g + (PTL_WRITABLE | PTL_PRESENT)
-	.fill 504, 8, 0
-
-.align 4096
-.global ptl_0
-ptl_0:
-	.quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
-	.fill 255, 8, 0
-	.quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
-	.fill 255, 8, 0
-
-.section K_DATA_START, "aw", @progbits
-
-bootstrap_gdtr:
-	.word GDT_SELECTOR(GDT_ITEMS)
-	.long KA2PA(gdt)
-
-grub_eax:
-	.long 0
-
-grub_ebx:
-	.long 0
-
-err_extended_cpuid:
-	.asciz "Error: Extended CPUID not supported -- CPU is not 64-bit. System halted."
-err_long_mode:
-	.asciz "Error: 64-bit long mode not supported. System halted."
-err_noexecute:
-	.asciz "Error: No-execute pages not supported. System halted."
-err_fx:
-	.asciz "Error: FXSAVE/FXRESTORE instructions not supported. System halted."
-err_sse2:
-	.asciz "Error: SSE2 instructions not supported. System halted."
-
-status_prot:
-	.asciz "[prot] "
-status_vesa_copy:
-	.asciz "[vesa_copy] "
-status_grub_cmdline:
-	.asciz "[grub_cmdline] "
-status_vesa_real:
-	.asciz "[vesa_real] "
-status_prot2:
-	.asciz "[prot2] "
-status_long:
-	.asciz "[long] "
-status_main:
-	.asciz "[main] "
Index: kernel/arch/amd64/src/boot/memmap.c
===================================================================
--- kernel/arch/amd64/src/boot/memmap.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/amd64/src/boot/memmap.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -35,5 +35,5 @@
 #include <arch/boot/memmap.h>
 
-uint8_t e820counter = 0xffU;
+uint8_t e820counter = 0;
 e820memmap_t e820table[MEMMAP_E820_MAX_RECORDS];
 
Index: kernel/arch/amd64/src/boot/multiboot.S
===================================================================
--- kernel/arch/amd64/src/boot/multiboot.S	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
+++ kernel/arch/amd64/src/boot/multiboot.S	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -0,0 +1,684 @@
+/*
+ * Copyright (c) 2005 Ondrej Palkovsky
+ * Copyright (c) 2006 Martin Decky
+ * Copyright (c) 2008 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch/boot/boot.h>
+#include <arch/mm/page.h>
+#include <arch/mm/ptl.h>
+#include <arch/pm.h>
+#include <genarch/multiboot/multiboot.h>
+#include <arch/cpuid.h>
+#include <arch/cpu.h>
+
+#define START_STACK  (BOOT_OFFSET - BOOT_STACK_SIZE)
+
+.section K_TEXT_START, "ax"
+
+.code32
+
+.macro pm_error msg
+	movl \msg, %esi
+	jmp pm_error_halt
+.endm
+
+.macro pm_status msg
+#ifdef CONFIG_EGA
+	pushl %esi
+	movl \msg, %esi
+	call pm_early_puts
+	popl %esi
+#endif
+.endm
+
+.macro pm2_status msg
+#ifndef CONFIG_FB
+	pm_status \msg
+#endif
+.endm
+
+.align 4
+.global multiboot_image_start
+multiboot_header:
+	.long MULTIBOOT_HEADER_MAGIC
+	.long MULTIBOOT_HEADER_FLAGS
+	.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)  /* checksum */
+	.long multiboot_header
+	.long unmapped_ktext_start
+	.long 0
+	.long 0
+	.long multiboot_image_start
+
+multiboot_image_start:
+	cld
+	
+	/* Initialize stack pointer */
+	movl $START_STACK, %esp
+	
+	/* Initialize Global Descriptor Table register */
+	lgdtl bootstrap_gdtr
+	
+	/* Kernel data + stack */
+	movw $GDT_SELECTOR(KDATA_DES), %cx
+	movw %cx, %es
+	movw %cx, %ds
+	movw %cx, %ss
+	
+	/*
+	 * Simics seems to remove hidden part of GS on entering user mode
+	 * when _visible_ part of GS does not point to user-mode segment.
+	 */
+	movw $GDT_SELECTOR(UDATA_DES), %cx
+	movw %cx, %fs
+	movw %cx, %gs
+	
+	jmpl $GDT_SELECTOR(KTEXT32_DES), $multiboot_meeting_point
+	multiboot_meeting_point:
+	
+	/*
+	 * Protected 32-bit. We want to reuse the code-seg descriptor,
+	 * the Default operand size must not be 1 when entering long mode.
+	 */
+	
+	/* Save multiboot arguments */
+	movl %eax, multiboot_eax
+	movl %ebx, multiboot_ebx
+	
+	pm_status $status_prot
+	
+	movl $(INTEL_CPUID_EXTENDED), %eax
+	cpuid
+	cmp $(INTEL_CPUID_EXTENDED), %eax
+	ja extended_cpuid_supported
+	
+		pm_error $err_extended_cpuid
+	
+	extended_cpuid_supported:
+	
+	movl $(AMD_CPUID_EXTENDED), %eax
+	cpuid
+	bt $(AMD_EXT_LONG_MODE), %edx
+	jc long_mode_supported
+	
+		pm_error $err_long_mode
+	
+	long_mode_supported:
+	
+	bt $(AMD_EXT_NOEXECUTE), %edx
+	jc noexecute_supported
+	
+		pm_error $err_noexecute
+	
+	noexecute_supported:
+	
+	movl $(INTEL_CPUID_STANDARD), %eax
+	cpuid
+	bt $(INTEL_FXSAVE), %edx
+	jc fx_supported
+	
+		pm_error $err_fx
+	
+	fx_supported:
+	
+	bt $(INTEL_SSE2), %edx
+	jc sse2_supported
+	
+		pm_error $err_sse2
+	
+	sse2_supported:
+	
+#include "vesa_prot.inc"
+	
+	pm2_status $status_prot2
+	
+	/*
+	 * Enable 64-bit page translation entries - CR4.PAE = 1.
+	 * Paging is not enabled until after long mode is enabled.
+	 */
+	
+	movl %cr4, %eax
+	btsl $5, %eax
+	movl %eax, %cr4
+	
+	/* Set up paging tables */
+	leal ptl_0, %eax
+	movl %eax, %cr3
+	
+	/* Enable long mode */
+	movl $EFER_MSR_NUM, %ecx
+	rdmsr                     /* read EFER */
+	btsl $AMD_LME_FLAG, %eax  /* set LME = 1 */
+	wrmsr
+	
+	/* Enable paging to activate long mode (set CR0.PG = 1) */
+	movl %cr0, %eax
+	btsl $31, %eax
+	movl %eax, %cr0
+	
+	/* At this point we are in compatibility mode */
+	jmpl $GDT_SELECTOR(KTEXT_DES), $start64
+
+/** Print string to EGA display (in light red) and halt.
+ *
+ * Should be executed from 32 bit protected mode with paging
+ * turned off. Stack is not required. This routine is used even
+ * if CONFIG_EGA is not enabled. Since we are going to halt the
+ * CPU anyway, it is always better to at least try to print
+ * some hints.
+ *
+ * @param %esi Pointer to the NULL-terminated string
+ *             to be print.
+ *
+ */
+pm_error_halt:
+	movl $0xb8000, %edi  /* base of EGA text mode memory */
+	xorl %eax, %eax
+	
+	/* Read bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	shl $8, %ax
+	
+	/* Read bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	
+	/* Sanity check for the cursor on screen */
+	cmp $2000, %ax
+	jb err_cursor_ok
+	
+		movw $1998, %ax
+	
+	err_cursor_ok:
+	
+	movw %ax, %bx
+	shl $1, %eax
+	addl %eax, %edi
+	
+	err_ploop:
+		lodsb
+		
+		cmp $0, %al
+		je err_ploop_end
+		
+		movb $0x0c, %ah  /* black background, light red foreground */
+		stosw
+		
+		/* Sanity check for the cursor on the last line */
+		inc %bx
+		cmp $2000, %bx
+		jb err_ploop
+		
+		/* Scroll the screen (24 rows) */
+		movl %esi, %edx
+		movl $0xb80a0, %esi
+		movl $0xb8000, %edi
+		movl $960, %ecx
+		rep movsl
+		
+		/* Clear the 24th row */
+		xorl %eax, %eax
+		movl $40, %ecx
+		rep stosl
+		
+		/* Go to row 24 */
+		movl %edx, %esi
+		movl $0xb8f00, %edi
+		movw $1920, %bx
+		
+		jmp err_ploop
+	err_ploop_end:
+	
+	/* Write bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bh, %al
+	outb %al, %dx
+	
+	/* Write bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bl, %al
+	outb %al, %dx
+	
+	cli
+	hlt1:
+		hlt
+		jmp hlt1
+
+/** Print string to EGA display (in light green).
+ *
+ * Should be called from 32 bit protected mode with paging
+ * turned off. A stack space of at least 24 bytes is required,
+ * but the function does not establish a stack frame.
+ *
+ * Macros such as pm_status and pm2_status take care that
+ * this function is used only when CONFIG_EGA is enabled
+ * and CONFIG_FB is disabled.
+ *
+ * @param %esi Pointer to the NULL-terminated string
+ *             to be print.
+ *
+ */
+pm_early_puts:
+	pushl %eax
+	pushl %ebx
+	pushl %ecx
+	pushl %edx
+	pushl %edi
+	
+	movl $0xb8000, %edi  /* base of EGA text mode memory */
+	xorl %eax, %eax
+	
+	/* Read bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	shl $8, %ax
+	
+	/* Read bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	
+	/* Sanity check for the cursor on screen */
+	cmp $2000, %ax
+	jb pm_puts_cursor_ok
+	
+		movw $1998, %ax
+	
+	pm_puts_cursor_ok:
+	
+	movw %ax, %bx
+	shl $1, %eax
+	addl %eax, %edi
+	
+	pm_puts_ploop:
+		lodsb
+		
+		cmp $0, %al
+		je pm_puts_ploop_end
+		
+		movb $0x0a, %ah  /* black background, light green foreground */
+		stosw
+		
+		/* Sanity check for the cursor on the last line */
+		inc %bx
+		cmp $2000, %bx
+		jb pm_puts_ploop
+		
+		/* Scroll the screen (24 rows) */
+		movl %esi, %edx
+		movl $0xb80a0, %esi
+		movl $0xb8000, %edi
+		movl $960, %ecx
+		rep movsl
+		
+		/* Clear the 24th row */
+		xorl %eax, %eax
+		movl $40, %ecx
+		rep stosl
+		
+		/* Go to row 24 */
+		movl %edx, %esi
+		movl $0xb8f00, %edi
+		movw $1920, %bx
+		
+		jmp pm_puts_ploop
+	pm_puts_ploop_end:
+	
+	/* Write bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bh, %al
+	outb %al, %dx
+	
+	/* Write bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bl, %al
+	outb %al, %dx
+	
+	popl %edi
+	popl %edx
+	popl %ecx
+	popl %ebx
+	popl %eax
+	
+	ret
+
+.code64
+
+.macro long_status msg
+	pushq %rdi
+	movq \msg, %rdi
+	call early_puts
+	popq %rdi
+.endm
+
+start64:
+	
+	/*
+	 * Long mode.
+	 */
+	
+	movq $(PA2KA(START_STACK)), %rsp
+	
+	/* Create the first stack frame */
+	pushq $0
+	movq %rsp, %rbp
+	
+	long_status $status_long
+	
+	/* Call arch_pre_main(multiboot_eax, multiboot_ebx) */
+	xorq %rdi, %rdi
+	movl multiboot_eax, %edi
+	xorq %rsi, %rsi
+	movl multiboot_ebx, %esi
+	
+	movabsq $arch_pre_main, %rax
+	callq *%rax
+	
+	long_status $status_main
+	
+	/* Call main_bsp() */
+	movabsq $main_bsp, %rax
+	call *%rax
+	
+	/* Not reached */
+	cli
+	hlt0:
+		hlt
+		jmp hlt0
+
+/** Print string to EGA display.
+ *
+ * Should be called from long mode (with paging enabled
+ * and stack established). This function is ABI compliant
+ * (without red-zone).
+ *
+ * If CONFIG_EGA is undefined or CONFIG_FB is defined
+ * then this function does nothing.
+ *
+ * @param %rdi Pointer to the NULL-terminated string
+ *             to be printed.
+ *
+ */
+early_puts:
+	
+#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
+	
+	/* Prologue, save preserved registers */
+	pushq %rbp
+	movq %rsp, %rbp
+	pushq %rbx
+	
+	movq %rdi, %rsi
+	movq $(PA2KA(0xb8000)), %rdi  /* base of EGA text mode memory */
+	xorq %rax, %rax
+	
+	/* Read bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	shl $8, %ax
+	
+	/* Read bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	
+	/* Sanity check for the cursor on screen */
+	cmp $2000, %ax
+	jb early_puts_cursor_ok
+	
+		movw $1998, %ax
+	
+	early_puts_cursor_ok:
+	
+	movw %ax, %bx
+	shl $1, %rax
+	addq %rax, %rdi
+	
+	early_puts_ploop:
+		lodsb
+		
+		cmp $0, %al
+		je early_puts_ploop_end
+		
+		movb $0x0e, %ah  /* black background, yellow foreground */
+		stosw
+		
+		/* Sanity check for the cursor on the last line */
+		inc %bx
+		cmp $2000, %bx
+		jb early_puts_ploop
+		
+		/* Scroll the screen (24 rows) */
+		movq %rsi, %rdx
+		movq $(PA2KA(0xb80a0)), %rsi
+		movq $(PA2KA(0xb8000)), %rdi
+		movl $480, %ecx
+		rep movsq
+		
+		/* Clear the 24th row */
+		xorl %eax, %eax
+		movl $20, %ecx
+		rep stosq
+		
+		/* Go to row 24 */
+		movq %rdx, %rsi
+		movq $(PA2KA(0xb8f00)), %rdi
+		movw $1920, %bx
+		
+		jmp early_puts_ploop
+	early_puts_ploop_end:
+	
+	/* Write bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bh, %al
+	outb %al, %dx
+	
+	/* Write bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bl, %al
+	outb %al, %dx
+	
+	/* Epilogue, restore preserved registers */
+	popq %rbx
+	leave
+	
+#endif
+	
+	ret
+
+#include "vesa_real.inc"
+
+.section K_INI_PTLS, "aw", @progbits
+
+/** Generate initial page table contents.
+ *
+ * @param cnt Number of entries to generate. Must be multiple of 8.
+ * @param g   Number of GB that will be added to the mapping.
+ *
+ */
+.macro ptl2gen cnt g
+	.if \cnt
+		ptl2gen "\cnt - 8" \g
+		.quad ((\cnt - 8) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+		.quad ((\cnt - 7) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+		.quad ((\cnt - 6) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+		.quad ((\cnt - 5) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+		.quad ((\cnt - 4) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+		.quad ((\cnt - 3) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+		.quad ((\cnt - 2) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+		.quad ((\cnt - 1) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.endif
+.endm
+
+/* Page table for pages in the 1st gigabyte. */
+.align 4096
+ptl_2_0g:
+	ptl2gen 512 0
+
+/* Page table for pages in the 2nd gigabyte. */
+.align 4096
+ptl_2_1g:
+	ptl2gen 512 1
+
+/* Page table for pages in the 3rd gigabyte. */
+.align 4096
+ptl_2_2g:
+	ptl2gen 512 2
+
+/* Page table for pages in the 4th gigabyte. */
+.align 4096
+ptl_2_3g:
+	ptl2gen 512 3
+
+/* Page table for pages in the 5th gigabyte. */
+.align 4096
+ptl_2_4g:
+	ptl2gen 512 4
+
+/* Page table for pages in the 6th gigabyte. */
+.align 4096
+ptl_2_5g:
+	ptl2gen 512 5
+
+/* Page table for pages in the 7th gigabyte. */
+.align 4096
+ptl_2_6g:
+	ptl2gen 512 6
+
+/* Page table for pages in the 8th gigabyte. */
+.align 4096
+ptl_2_7g:
+	ptl2gen 512 7
+
+.align 4096
+ptl_1:
+	/* Identity mapping for [0; 8G) */
+	.quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
+	.quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT)
+	.quad ptl_2_2g + (PTL_WRITABLE | PTL_PRESENT)
+	.quad ptl_2_3g + (PTL_WRITABLE | PTL_PRESENT)
+	.quad ptl_2_4g + (PTL_WRITABLE | PTL_PRESENT)
+	.quad ptl_2_5g + (PTL_WRITABLE | PTL_PRESENT)
+	.quad ptl_2_6g + (PTL_WRITABLE | PTL_PRESENT)
+	.quad ptl_2_7g + (PTL_WRITABLE | PTL_PRESENT)
+	.fill 504, 8, 0
+
+.align 4096
+.global ptl_0
+ptl_0:
+	.quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
+	.fill 255, 8, 0
+	.quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
+	.fill 255, 8, 0
+
+.section K_DATA_START, "aw", @progbits
+
+.global bootstrap_gdtr
+bootstrap_gdtr:
+	.word GDT_SELECTOR(GDT_ITEMS)
+	.long KA2PA(gdt)
+
+.global multiboot_eax
+multiboot_eax:
+	.long 0
+
+.global multiboot_ebx
+multiboot_ebx:
+	.long 0
+
+err_extended_cpuid:
+	.asciz "Error: Extended CPUID not supported -- CPU is not 64-bit. System halted."
+err_long_mode:
+	.asciz "Error: 64-bit long mode not supported. System halted."
+err_noexecute:
+	.asciz "Error: No-execute pages not supported. System halted."
+err_fx:
+	.asciz "Error: FXSAVE/FXRESTORE instructions not supported. System halted."
+err_sse2:
+	.asciz "Error: SSE2 instructions not supported. System halted."
+
+status_prot:
+	.asciz "[prot] "
+status_vesa_copy:
+	.asciz "[vesa_copy] "
+status_multiboot_cmdline:
+	.asciz "[multiboot_cmdline] "
+status_vesa_real:
+	.asciz "[vesa_real] "
+status_prot2:
+	.asciz "[prot2] "
+status_long:
+	.asciz "[long] "
+status_main:
+	.asciz "[main] "
Index: kernel/arch/amd64/src/boot/multiboot2.S
===================================================================
--- kernel/arch/amd64/src/boot/multiboot2.S	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
+++ kernel/arch/amd64/src/boot/multiboot2.S	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch/boot/boot.h>
+#include <arch/mm/page.h>
+#include <arch/pm.h>
+#include <arch/cpuid.h>
+#include <arch/cpu.h>
+#include <genarch/multiboot/multiboot2.h>
+
+#define START_STACK  (BOOT_OFFSET - BOOT_STACK_SIZE)
+
+.section K_TEXT_START, "ax"
+
+.code32
+
+.align 8
+.global multiboot2_image_start
+multiboot2_header_start:
+	.long MULTIBOOT2_HEADER_MAGIC
+	.long MULTIBOOT2_HEADER_ARCH_I386
+	.long multiboot2_header_end - multiboot2_header_start
+	.long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT2_HEADER_ARCH_I386 + (multiboot2_header_end - multiboot2_header_start))
+	
+	/* Information request tag */
+	tag_info_req_start:
+		.word MULTIBOOT2_TAG_INFO_REQ
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_info_req_end - tag_info_req_start
+		.long MULTIBOOT2_TAG_MODULE
+		.long MULTIBOOT2_TAG_MEMMAP
+#ifdef CONFIG_FB
+		.long MULTIBOOT2_TAG_FBINFO
+#endif
+	tag_info_req_end:
+	
+	/* Address tag */
+	tag_address_start:
+		.word MULTIBOOT2_TAG_ADDRESS
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_address_end - tag_address_start
+		.long multiboot2_header_start
+		.long unmapped_ktext_start
+		.long 0
+		.long 0
+	tag_address_end:
+	
+	/* Entry address tag */
+	tag_entry_address_start:
+		.word MULTIBOOT2_TAG_ENTRY_ADDRESS
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_entry_address_end - tag_entry_address_start
+		.long multiboot2_image_start
+	tag_entry_address_end:
+	
+	/* Flags tag */
+	tag_flags_start:
+		.word MULTIBOOT2_TAG_FLAGS
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_flags_end - tag_flags_start
+		.long MULTIBOOT2_FLAGS_CONSOLE
+	tag_flags_end:
+	
+#ifdef CONFIG_FB
+	/* Framebuffer tag */
+	tag_framebuffer_start:
+		.word MULTIBOOT2_TAG_FRAMEBUFFER
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_framebuffer_end - tag_framebuffer_start
+		.long CONFIG_BFB_WIDTH
+		.long CONFIG_BFB_HEIGHT
+		.long CONFIG_BFB_BPP
+	tag_framebuffer_end:
+#endif
+	
+	/* Module alignment tag */
+	tag_module_align_start:
+		.word MULTIBOOT2_TAG_MODULE_ALIGN
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_module_align_end - tag_module_align_start
+		.long 0
+	tag_module_align_end:
+	
+	/* Tag terminator */
+	tag_terminator_start:
+		.word MULTIBOOT2_TAG_TERMINATOR
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_terminator_end - tag_terminator_start
+	tag_terminator_end:
+multiboot2_header_end:
+
+multiboot2_image_start:
+	cld
+	
+	/* Initialize stack pointer */
+	movl $START_STACK, %esp
+	
+	/* Initialize Global Descriptor Table register */
+	lgdtl bootstrap_gdtr
+	
+	/* Kernel data + stack */
+	movw $GDT_SELECTOR(KDATA_DES), %cx
+	movw %cx, %es
+	movw %cx, %ds
+	movw %cx, %ss
+	
+	/*
+	 * Simics seems to remove hidden part of GS on entering user mode
+	 * when _visible_ part of GS does not point to user-mode segment.
+	 */
+	movw $GDT_SELECTOR(UDATA_DES), %cx
+	movw %cx, %fs
+	movw %cx, %gs
+	
+	jmpl $GDT_SELECTOR(KTEXT32_DES), $multiboot2_meeting_point
+	multiboot2_meeting_point:
+	
+	/*
+	 * Protected 32-bit. We want to reuse the code-seg descriptor,
+	 * the Default operand size must not be 1 when entering long mode.
+	 */
+	
+	/* Save multiboot arguments */
+	movl %eax, multiboot_eax
+	movl %ebx, multiboot_ebx
+	
+	movl $(INTEL_CPUID_EXTENDED), %eax
+	cpuid
+	cmp $(INTEL_CPUID_EXTENDED), %eax
+	ja extended_cpuid_supported
+	
+		jmp pm_error_halt
+	
+	extended_cpuid_supported:
+	
+	movl $(AMD_CPUID_EXTENDED), %eax
+	cpuid
+	bt $(AMD_EXT_LONG_MODE), %edx
+	jc long_mode_supported
+	
+		jmp pm_error_halt
+	
+	long_mode_supported:
+	
+	bt $(AMD_EXT_NOEXECUTE), %edx
+	jc noexecute_supported
+	
+		jmp pm_error_halt
+	
+	noexecute_supported:
+	
+	movl $(INTEL_CPUID_STANDARD), %eax
+	cpuid
+	bt $(INTEL_FXSAVE), %edx
+	jc fx_supported
+	
+		jmp pm_error_halt
+	
+	fx_supported:
+	
+	bt $(INTEL_SSE2), %edx
+	jc sse2_supported
+	
+		jmp pm_error_halt
+	
+	sse2_supported:
+	
+	/*
+	 * Enable 64-bit page translation entries - CR4.PAE = 1.
+	 * Paging is not enabled until after long mode is enabled.
+	 */
+	
+	movl %cr4, %eax
+	btsl $5, %eax
+	movl %eax, %cr4
+	
+	/* Set up paging tables */
+	leal ptl_0, %eax
+	movl %eax, %cr3
+	
+	/* Enable long mode */
+	movl $EFER_MSR_NUM, %ecx
+	rdmsr                     /* read EFER */
+	btsl $AMD_LME_FLAG, %eax  /* set LME = 1 */
+	wrmsr
+	
+	/* Enable paging to activate long mode (set CR0.PG = 1) */
+	movl %cr0, %eax
+	btsl $31, %eax
+	movl %eax, %cr0
+	
+	/* At this point we are in compatibility mode */
+	jmpl $GDT_SELECTOR(KTEXT_DES), $start64
+
+pm_error_halt:
+	cli
+	hlt1:
+		hlt
+		jmp hlt1
+
+.code64
+
+start64:
+	
+	/*
+	 * Long mode.
+	 */
+	
+	movq $(PA2KA(START_STACK)), %rsp
+	
+	/* Create the first stack frame */
+	pushq $0
+	movq %rsp, %rbp
+	
+	/* Call arch_pre_main(multiboot_eax, multiboot_ebx) */
+	xorq %rdi, %rdi
+	movl multiboot_eax, %edi
+	xorq %rsi, %rsi
+	movl multiboot_ebx, %esi
+	
+	movabsq $arch_pre_main, %rax
+	callq *%rax
+	
+	/* Call main_bsp() */
+	movabsq $main_bsp, %rax
+	call *%rax
+	
+	/* Not reached */
+	cli
+	hlt0:
+		hlt
+		jmp hlt0
Index: kernel/arch/ia32/Makefile.inc
===================================================================
--- kernel/arch/ia32/Makefile.inc	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/ia32/Makefile.inc	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -107,6 +107,6 @@
 	arch/$(KARCH)/src/drivers/i8254.c \
 	arch/$(KARCH)/src/drivers/i8259.c \
-	arch/$(KARCH)/src/drivers/vesa.c \
-	arch/$(KARCH)/src/boot/boot.S \
+	arch/$(KARCH)/src/boot/multiboot.S \
+	arch/$(KARCH)/src/boot/multiboot2.S \
 	arch/$(KARCH)/src/boot/memmap.c \
 	arch/$(KARCH)/src/fpu_context.c \
Index: kernel/arch/ia32/include/arch.h
===================================================================
--- kernel/arch/ia32/include/arch.h	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/ia32/include/arch.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -36,7 +36,7 @@
 #define KERN_ia32_ARCH_H_
 
-#include <genarch/multiboot/multiboot.h>
+#include <typedefs.h>
 
-extern void arch_pre_main(uint32_t, const multiboot_info_t *);
+extern void arch_pre_main(uint32_t, void *);
 
 #endif
Index: kernel/arch/ia32/include/boot/boot.h
===================================================================
--- kernel/arch/ia32/include/boot/boot.h	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/ia32/include/boot/boot.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -40,9 +40,4 @@
 #define BOOT_STACK_SIZE  0x0400
 
-#define MULTIBOOT_HEADER_MAGIC  0x1BADB002
-#define MULTIBOOT_HEADER_FLAGS  0x00010003
-
-#define MULTIBOOT_LOADER_MAGIC  0x2BADB002
-
 #ifndef __ASM__
 
Index: kernel/arch/ia32/include/drivers/vesa.h
===================================================================
--- kernel/arch/ia32/include/drivers/vesa.h	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * Copyright (c) 2006 Jakub Vana
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup ia32
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_ia32_VESA_H_
-#define KERN_ia32_VESA_H_
-
-#include <typedefs.h>
-
-extern bool vesa_init(void);
-
-#endif
-
-/** @}
- */
Index: kernel/arch/ia32/src/boot/boot.S
===================================================================
--- kernel/arch/ia32/src/boot/boot.S	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ 	(revision )
@@ -1,736 +1,0 @@
-/*
- * Copyright (c) 2001 Jakub Jermar
- * Copyright (c) 2005 Martin Decky
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <arch/boot/boot.h>
-#include <arch/boot/memmap.h>
-#include <arch/mm/page.h>
-#include <arch/pm.h>
-#include <arch/cpuid.h>
-
-#define START_STACK  (BOOT_OFFSET - BOOT_STACK_SIZE)
-
-.section K_TEXT_START, "ax"
-
-.code32
-
-.macro pm_error msg
-	movl \msg, %esi
-	jmp pm_error_halt
-.endm
-
-.macro pm_status msg
-#ifdef CONFIG_EGA
-	pushl %esi
-	movl \msg, %esi
-	call pm_early_puts
-	popl %esi
-#endif
-.endm
-
-.macro pm2_status msg
-	pushl \msg
-	call early_puts
-.endm
-
-.align 4
-.global multiboot_image_start
-multiboot_header:
-	.long MULTIBOOT_HEADER_MAGIC
-	.long MULTIBOOT_HEADER_FLAGS
-	.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)  /* checksum */
-	.long multiboot_header
-	.long unmapped_ktext_start
-	.long 0
-	.long 0
-	.long multiboot_image_start
-
-multiboot_image_start:
-	cld
-	
-	/* Initialize stack pointer */
-	movl $START_STACK, %esp
-	
-	/* Initialize Global Descriptor Table register */
-	lgdtl bootstrap_gdtr
-	
-	/* Kernel data + stack */
-	movw $GDT_SELECTOR(KDATA_DES), %cx
-	movw %cx, %es
-	movw %cx, %fs
-	movw %cx, %gs
-	movw %cx, %ds
-	movw %cx, %ss
-	
-	jmpl $GDT_SELECTOR(KTEXT_DES), $multiboot_meeting_point
-	multiboot_meeting_point:
-	
-	/* Save GRUB arguments */
-	movl %eax, grub_eax
-	movl %ebx, grub_ebx
-	
-	pm_status $status_prot
-	
-#include "vesa_prot.inc"
-	
-#ifndef PROCESSOR_i486
-	
-	pm_status $status_prot2
-	
-	movl $(INTEL_CPUID_LEVEL), %eax
-	cpuid
-	cmp $0x0, %eax  /* any function > 0? */
-	jbe pse_unsupported
-	
-	movl $(INTEL_CPUID_STANDARD), %eax
-	cpuid
-	bt $(INTEL_PSE), %edx
-	jnc pse_unsupported
-		
-		/* Map kernel and turn paging on */
-		pm_status $status_pse
-		call map_kernel_pse
-		jmp stack_init
-	
-#endif /* PROCESSOR_i486 */
-	
-	pse_unsupported:
-		
-		/* Map kernel and turn paging on */
-		pm_status $status_non_pse
-		call map_kernel_non_pse
-	
-	stack_init:
-	
-	/* Create the first stack frame */
-	pushl $0
-	movl %esp, %ebp
-	
-	pm2_status $status_prot3
-	
-	/* Call arch_pre_main(grub_eax, grub_ebx) */
-	pushl grub_ebx
-	pushl grub_eax
-	call arch_pre_main
-	
-	pm2_status $status_main
-	
-	/* Call main_bsp() */
-	call main_bsp
-	
-	/* Not reached */
-	cli
-	hlt0:
-		hlt
-		jmp hlt0
-
-/** Setup mapping for the kernel (PSE variant)
- *
- * Setup mapping for both the unmapped and mapped sections
- * of the kernel. For simplicity, we map the entire 4G space.
- *
- */
-.global map_kernel_pse
-map_kernel_pse:
-	/* Paging features */
-	movl %cr4, %ecx
-	orl $(1 << 4), %ecx      /* PSE on */
-	andl $(~(1 << 5)), %ecx  /* PAE off */
-	movl %ecx, %cr4
-	
-	movl $(page_directory + 0), %esi
-	movl $(page_directory + 2048), %edi
-	xorl %ecx, %ecx
-	xorl %ebx, %ebx
-	
-	floop_pse:
-		movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
-		orl %ebx, %eax
-		/* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
-		movl %eax, (%esi, %ecx, 4)
-		/* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
-		movl %eax, (%edi, %ecx, 4)
-		addl $(4 * 1024 * 1024), %ebx
-		
-		incl %ecx
-		cmpl $512, %ecx
-		jl floop_pse
-	
-	movl %esi, %cr3
-	
-	movl %cr0, %ebx
-	orl $(1 << 31), %ebx  /* paging on */
-	movl %ebx, %cr0
-	ret
-
-/** Setup mapping for the kernel (non-PSE variant).
- *
- * Setup mapping for both the unmapped and mapped sections
- * of the kernel. For simplicity, we map the entire 4G space.
- *
- */
-map_kernel_non_pse:
-	/* Paging features */
-	movl %cr4, %ecx
-	andl $(~(1 << 5)), %ecx  /* PAE off */
-	movl %ecx, %cr4
-	
-	call calc_kernel_end
-	call find_mem_for_pt
-	
-	mov kernel_end, %esi
-	mov free_area, %ecx
-	
-	cmpl %esi, %ecx
-	jbe use_kernel_end
-		
-		mov %ecx, %esi
-		
-		/* Align address down to 4k */
-		andl $(~4095), %esi
-		
-	use_kernel_end:
-		
-		/* Align address to 4k */
-		addl $4095, %esi
-		andl $(~4095), %esi
-		
-		/* Allocate space for page tables */
-		movl %esi, pt_loc
-		movl $ballocs, %edi
-		andl $0x7fffffff, %edi
-		
-		movl %esi, (%edi)
-		addl $4, %edi
-		movl $(2 * 1024 * 1024), (%edi)
-		
-		/* Fill page tables */
-		xorl %ecx, %ecx
-		xorl %ebx, %ebx
-		
-		floop_pt:
-			movl $((1 << 1) | (1 << 0)), %eax
-			orl %ebx, %eax
-			movl %eax, (%esi, %ecx, 4)
-			addl $(4 * 1024), %ebx
-			
-			incl %ecx
-			cmpl $(512 * 1024), %ecx
-			
-			jl floop_pt
-		
-		/* Fill page directory */
-		movl $(page_directory + 0), %esi
-		movl $(page_directory + 2048), %edi
-		xorl %ecx, %ecx
-		movl pt_loc, %ebx
-		
-		floop:
-			movl $((1 << 1) | (1 << 0)), %eax
-			orl %ebx, %eax
-			
-			/* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
-			movl %eax, (%esi, %ecx, 4)
-			
-			/* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
-			movl %eax, (%edi, %ecx, 4)
-			addl $(4 * 1024), %ebx
-			
-			incl %ecx
-			cmpl $512, %ecx
-			
-			jl floop
-		
-		movl %esi, %cr3
-		
-		movl %cr0, %ebx
-		orl $(1 << 31), %ebx  /* paging on */
-		movl %ebx, %cr0
-		
-		ret
-
-/** Calculate unmapped address of the end of the kernel. */
-calc_kernel_end:
-	movl $hardcoded_load_address, %edi
-	andl $0x7fffffff, %edi
-	movl (%edi), %esi
-	andl $0x7fffffff, %esi
-	
-	movl $hardcoded_ktext_size, %edi
-	andl $0x7fffffff, %edi
-	addl (%edi), %esi
-	andl $0x7fffffff, %esi
-	
-	movl $hardcoded_kdata_size, %edi
-	andl $0x7fffffff, %edi
-	addl (%edi), %esi
-	andl $0x7fffffff, %esi
-	movl %esi, kernel_end
-	
-	ret
-
-/** Find free 2M (+4k for alignment) region where to store page tables */
-find_mem_for_pt:
-	/* Check if multiboot info is present */
-	cmpl $MULTIBOOT_LOADER_MAGIC, grub_eax
-	je check_multiboot_map
-		
-		ret
-	
-	check_multiboot_map:
-		
-		/* Copy address of the multiboot info to ebx */
-		movl grub_ebx, %ebx
-		
-		/* Check if memory map flag is present */
-		movl (%ebx), %edx
-		andl $(1 << 6), %edx
-		jnz use_multiboot_map
-			
-			ret
-		
-	use_multiboot_map:
-		
-		/* Copy address of the memory map to edx */
-		movl 48(%ebx), %edx
-		movl %edx, %ecx
-		
-		addl 44(%ebx), %ecx
-		
-		/* Find a free region at least 2M in size */
-		check_memmap_loop:
-			
-			/* Is this a free region? */
-			cmp $1, 20(%edx)
-			jnz next_region
-			
-			/* Check size */
-			cmp $0, 16(%edx)
-			jnz next_region
-			
-			cmpl $(2 * 1024 * 1024 + 4 * 1024), 12(%edx)
-			jbe next_region
-			
-			cmp $0, 8(%edx)
-			jz found_region
-		
-		next_region:
-			
-			cmp %ecx, %edx
-			jbe next_region_do
-			
-				ret
-		
-		next_region_do:
-			
-			addl (%edx), %edx
-			addl $4, %edx
-			jmp check_memmap_loop
-			
-		found_region:
-			
-			/* Use end of the found region */
-			mov 4(%edx), %ecx
-			add 12(%edx), %ecx
-			sub $(2 * 1024 * 1024), %ecx
-			mov %ecx, free_area
-			
-			ret
-
-/** Print string to EGA display (in light red) and halt.
- *
- * Should be executed from 32 bit protected mode with paging
- * turned off. Stack is not required. This routine is used even
- * if CONFIG_EGA is not enabled. Since we are going to halt the
- * CPU anyway, it is always better to at least try to print
- * some hints.
- *
- * @param %esi NULL-terminated string to print.
- *
- */
-pm_error_halt:
-	movl $0xb8000, %edi  /* base of EGA text mode memory */
-	xorl %eax, %eax
-	
-	/* Read bits 8 - 15 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xe, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	inb %dx, %al
-	shl $8, %ax
-	
-	/* Read bits 0 - 7 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xf, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	inb %dx, %al
-	
-	/* Sanity check for the cursor on screen */
-	cmp $2000, %ax
-	jb err_cursor_ok
-	
-		movw $1998, %ax
-	
-	err_cursor_ok:
-	
-	movw %ax, %bx
-	shl $1, %eax
-	addl %eax, %edi
-	
-	err_ploop:
-		lodsb
-		
-		cmp $0, %al
-		je err_ploop_end
-		
-		movb $0x0c, %ah  /* black background, light red foreground */
-		stosw
-		
-		/* Sanity check for the cursor on the last line */
-		inc %bx
-		cmp $2000, %bx
-		jb err_ploop
-		
-		/* Scroll the screen (24 rows) */
-		movl %esi, %edx
-		movl $0xb80a0, %esi
-		movl $0xb8000, %edi
-		movl $960, %ecx
-		rep movsl
-		
-		/* Clear the 24th row */
-		xorl %eax, %eax
-		movl $40, %ecx
-		rep stosl
-		
-		/* Go to row 24 */
-		movl %edx, %esi
-		movl $0xb8f00, %edi
-		movw $1920, %bx
-		
-		jmp err_ploop
-	err_ploop_end:
-	
-	/* Write bits 8 - 15 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xe, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	movb %bh, %al
-	outb %al, %dx
-	
-	/* Write bits 0 - 7 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xf, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	movb %bl, %al
-	outb %al, %dx
-	
-	cli
-	hlt1:
-		hlt
-		jmp hlt1
-
-/** Print string to EGA display (in light green).
- *
- * Should be called from 32 bit protected mode with paging
- * turned off. A stack space of at least 24 bytes is required,
- * but the function does not establish a stack frame.
- *
- * Macros such as pm_status take care that this function
- * is used only when CONFIG_EGA is enabled.
- *
- * @param %esi NULL-terminated string to print.
- *
- */
-pm_early_puts:
-	pushl %eax
-	pushl %ebx
-	pushl %ecx
-	pushl %edx
-	pushl %edi
-	
-	movl $0xb8000, %edi  /* base of EGA text mode memory */
-	xorl %eax, %eax
-	
-	/* Read bits 8 - 15 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xe, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	inb %dx, %al
-	shl $8, %ax
-	
-	/* Read bits 0 - 7 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xf, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	inb %dx, %al
-	
-	/* Sanity check for the cursor on screen */
-	cmp $2000, %ax
-	jb pm_puts_cursor_ok
-	
-		movw $1998, %ax
-	
-	pm_puts_cursor_ok:
-	
-	movw %ax, %bx
-	shl $1, %eax
-	addl %eax, %edi
-	
-	pm_puts_ploop:
-		lodsb
-		
-		cmp $0, %al
-		je pm_puts_ploop_end
-		
-		movb $0x0a, %ah  /* black background, light green foreground */
-		stosw
-		
-		/* Sanity check for the cursor on the last line */
-		inc %bx
-		cmp $2000, %bx
-		jb pm_puts_ploop
-		
-		/* Scroll the screen (24 rows) */
-		movl %esi, %edx
-		movl $0xb80a0, %esi
-		movl $0xb8000, %edi
-		movl $960, %ecx
-		rep movsl
-		
-		/* Clear the 24th row */
-		xorl %eax, %eax
-		movl $40, %ecx
-		rep stosl
-		
-		/* Go to row 24 */
-		movl %edx, %esi
-		movl $0xb8f00, %edi
-		movw $1920, %bx
-		
-		jmp pm_puts_ploop
-	pm_puts_ploop_end:
-	
-	/* Write bits 8 - 15 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xe, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	movb %bh, %al
-	outb %al, %dx
-	
-	/* Write bits 0 - 7 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xf, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	movb %bl, %al
-	outb %al, %dx
-	
-	popl %edi
-	popl %edx
-	popl %ecx
-	popl %ebx
-	popl %eax
-	
-	ret
-
-/** Print string to EGA display.
- *
- * Should be called from 32 bit protected mode (with paging
- * enabled and stack established). This function is ABI compliant.
- *
- * If CONFIG_EGA is undefined or CONFIG_FB is defined
- * then this function does nothing.
- *
- * @param %ebp+0x08 NULL-terminated string to print.
- *
- */
-early_puts:
-	
-#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
-	
-	/* Prologue, save preserved registers */
-	pushl %ebp
-	movl %esp, %ebp
-	pushl %ebx
-	pushl %esi
-	pushl %edi
-	
-	movl 0x08(%ebp), %esi
-	movl $(PA2KA(0xb8000)), %edi  /* base of EGA text mode memory */
-	xorl %eax, %eax
-	
-	/* Read bits 8 - 15 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xe, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	inb %dx, %al
-	shl $8, %ax
-	
-	/* Read bits 0 - 7 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xf, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	inb %dx, %al
-	
-	/* Sanity check for the cursor on screen */
-	cmp $2000, %ax
-	jb early_puts_cursor_ok
-	
-		movw $1998, %ax
-	
-	early_puts_cursor_ok:
-	
-	movw %ax, %bx
-	shl $1, %eax
-	addl %eax, %edi
-	
-	early_puts_ploop:
-		lodsb
-		
-		cmp $0, %al
-		je early_puts_ploop_end
-		
-		movb $0x0e, %ah  /* black background, yellow foreground */
-		stosw
-		
-		/* Sanity check for the cursor on the last line */
-		inc %bx
-		cmp $2000, %bx
-		jb early_puts_ploop
-		
-		/* Scroll the screen (24 rows) */
-		movl %esi, %edx
-		movl $(PA2KA(0xb80a0)), %esi
-		movl $(PA2KA(0xb8000)), %edi
-		movl $960, %ecx
-		rep movsl
-		
-		/* Clear the 24th row */
-		xorl %eax, %eax
-		movl $40, %ecx
-		rep stosl
-		
-		/* Go to row 24 */
-		movl %edx, %esi
-		movl $(PA2KA(0xb8f00)), %edi
-		movw $1920, %bx
-		
-		jmp early_puts_ploop
-	early_puts_ploop_end:
-	
-	/* Write bits 8 - 15 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xe, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	movb %bh, %al
-	outb %al, %dx
-	
-	/* Write bits 0 - 7 of the cursor address */
-	movw $0x3d4, %dx
-	movb $0xf, %al
-	outb %al, %dx
-	
-	movw $0x3d5, %dx
-	movb %bl, %al
-	outb %al, %dx
-	
-	/* Epilogue, restore preserved registers */
-	popl %edi
-	popl %esi
-	popl %ebx
-	leave
-	
-#endif
-	
-	ret
-
-#include "vesa_real.inc"
-
-.section K_DATA_START, "aw", @progbits
-
-.align 4096
-page_directory:
-	.space 4096, 0
-
-bootstrap_gdtr:
-	.word GDT_SELECTOR(GDT_ITEMS)
-	.long KA2PA(gdt)
-
-grub_eax:
-	.long 0
-grub_ebx:
-	.long 0
-
-pt_loc:
-	.long 0
-kernel_end:
-	.long 0
-free_area:
-	.long 0
-
-status_prot:
-	.asciz "[prot] "
-status_pse:
-	.asciz "[pse] "
-status_non_pse:
-	.asciz "[non_pse] "
-status_vesa_copy:
-	.asciz "[vesa_copy] "
-status_grub_cmdline:
-	.asciz "[grub_cmdline] "
-status_vesa_real:
-	.asciz "[vesa_real] "
-status_prot2:
-	.asciz "[prot2] "
-status_prot3:
-	.asciz "[prot3] "
-status_main:
-	.asciz "[main] "
Index: kernel/arch/ia32/src/boot/memmap.c
===================================================================
--- kernel/arch/ia32/src/boot/memmap.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/ia32/src/boot/memmap.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -35,5 +35,5 @@
 #include <arch/boot/memmap.h>
 
-uint8_t e820counter = 0xffU;
+uint8_t e820counter = 0;
 e820memmap_t e820table[MEMMAP_E820_MAX_RECORDS];
 
Index: kernel/arch/ia32/src/boot/multiboot.S
===================================================================
--- kernel/arch/ia32/src/boot/multiboot.S	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
+++ kernel/arch/ia32/src/boot/multiboot.S	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -0,0 +1,741 @@
+/*
+ * Copyright (c) 2001 Jakub Jermar
+ * Copyright (c) 2005 Martin Decky
+ * Copyright (c) 2011 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch/boot/boot.h>
+#include <arch/mm/page.h>
+#include <arch/pm.h>
+#include <genarch/multiboot/multiboot.h>
+#include <arch/cpuid.h>
+
+#define START_STACK  (BOOT_OFFSET - BOOT_STACK_SIZE)
+
+.section K_TEXT_START, "ax"
+
+.code32
+
+.macro pm_error msg
+	movl \msg, %esi
+	jmp pm_error_halt
+.endm
+
+.macro pm_status msg
+#ifdef CONFIG_EGA
+	pushl %esi
+	movl \msg, %esi
+	call pm_early_puts
+	popl %esi
+#endif
+.endm
+
+.macro pm2_status msg
+	pushl \msg
+	call early_puts
+.endm
+
+.align 4
+.global multiboot_image_start
+multiboot_header:
+	.long MULTIBOOT_HEADER_MAGIC
+	.long MULTIBOOT_HEADER_FLAGS
+	.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)  /* checksum */
+	.long multiboot_header
+	.long unmapped_ktext_start
+	.long 0
+	.long 0
+	.long multiboot_image_start
+
+multiboot_image_start:
+	cld
+	
+	/* Initialize stack pointer */
+	movl $START_STACK, %esp
+	
+	/* Initialize Global Descriptor Table register */
+	lgdtl bootstrap_gdtr
+	
+	/* Kernel data + stack */
+	movw $GDT_SELECTOR(KDATA_DES), %cx
+	movw %cx, %es
+	movw %cx, %fs
+	movw %cx, %gs
+	movw %cx, %ds
+	movw %cx, %ss
+	
+	jmpl $GDT_SELECTOR(KTEXT_DES), $multiboot_meeting_point
+	multiboot_meeting_point:
+	
+	/* Save multiboot arguments */
+	movl %eax, multiboot_eax
+	movl %ebx, multiboot_ebx
+	
+	pm_status $status_prot
+	
+#include "vesa_prot.inc"
+	
+#ifndef PROCESSOR_i486
+	
+	pm_status $status_prot2
+	
+	movl $(INTEL_CPUID_LEVEL), %eax
+	cpuid
+	cmp $0x0, %eax  /* any function > 0? */
+	jbe pse_unsupported
+	
+	movl $(INTEL_CPUID_STANDARD), %eax
+	cpuid
+	bt $(INTEL_PSE), %edx
+	jnc pse_unsupported
+		
+		/* Map kernel and turn paging on */
+		pm_status $status_pse
+		call map_kernel_pse
+		jmp stack_init
+	
+#endif /* PROCESSOR_i486 */
+	
+	pse_unsupported:
+		
+		/* Map kernel and turn paging on */
+		pm_status $status_non_pse
+		call map_kernel_non_pse
+	
+	stack_init:
+	
+	/* Create the first stack frame */
+	pushl $0
+	movl %esp, %ebp
+	
+	pm2_status $status_prot3
+	
+	/* Call arch_pre_main(multiboot_eax, multiboot_ebx) */
+	pushl multiboot_ebx
+	pushl multiboot_eax
+	call arch_pre_main
+	
+	pm2_status $status_main
+	
+	/* Call main_bsp() */
+	call main_bsp
+	
+	/* Not reached */
+	cli
+	hlt0:
+		hlt
+		jmp hlt0
+
+/** Setup mapping for the kernel (PSE variant)
+ *
+ * Setup mapping for both the unmapped and mapped sections
+ * of the kernel. For simplicity, we map the entire 4G space.
+ *
+ */
+.global map_kernel_pse
+map_kernel_pse:
+	/* Paging features */
+	movl %cr4, %ecx
+	orl $(1 << 4), %ecx      /* PSE on */
+	andl $(~(1 << 5)), %ecx  /* PAE off */
+	movl %ecx, %cr4
+	
+	movl $(page_directory + 0), %esi
+	movl $(page_directory + 2048), %edi
+	xorl %ecx, %ecx
+	xorl %ebx, %ebx
+	
+	floop_pse:
+		movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
+		orl %ebx, %eax
+		/* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
+		movl %eax, (%esi, %ecx, 4)
+		/* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
+		movl %eax, (%edi, %ecx, 4)
+		addl $(4 * 1024 * 1024), %ebx
+		
+		incl %ecx
+		cmpl $512, %ecx
+		jl floop_pse
+	
+	movl %esi, %cr3
+	
+	movl %cr0, %ebx
+	orl $(1 << 31), %ebx  /* paging on */
+	movl %ebx, %cr0
+	ret
+
+/** Setup mapping for the kernel (non-PSE variant).
+ *
+ * Setup mapping for both the unmapped and mapped sections
+ * of the kernel. For simplicity, we map the entire 4G space.
+ *
+ */
+.global map_kernel_non_pse
+map_kernel_non_pse:
+	/* Paging features */
+	movl %cr4, %ecx
+	andl $(~(1 << 5)), %ecx  /* PAE off */
+	movl %ecx, %cr4
+	
+	call calc_kernel_end
+	call find_mem_for_pt
+	
+	mov kernel_end, %esi
+	mov free_area, %ecx
+	
+	cmpl %esi, %ecx
+	jbe use_kernel_end
+		
+		mov %ecx, %esi
+		
+		/* Align address down to 4k */
+		andl $(~4095), %esi
+		
+	use_kernel_end:
+		
+		/* Align address to 4k */
+		addl $4095, %esi
+		andl $(~4095), %esi
+		
+		/* Allocate space for page tables */
+		movl %esi, pt_loc
+		movl $ballocs, %edi
+		andl $0x7fffffff, %edi
+		
+		movl %esi, (%edi)
+		addl $4, %edi
+		movl $(2 * 1024 * 1024), (%edi)
+		
+		/* Fill page tables */
+		xorl %ecx, %ecx
+		xorl %ebx, %ebx
+		
+		floop_pt:
+			movl $((1 << 1) | (1 << 0)), %eax
+			orl %ebx, %eax
+			movl %eax, (%esi, %ecx, 4)
+			addl $(4 * 1024), %ebx
+			
+			incl %ecx
+			cmpl $(512 * 1024), %ecx
+			
+			jl floop_pt
+		
+		/* Fill page directory */
+		movl $(page_directory + 0), %esi
+		movl $(page_directory + 2048), %edi
+		xorl %ecx, %ecx
+		movl pt_loc, %ebx
+		
+		floop:
+			movl $((1 << 1) | (1 << 0)), %eax
+			orl %ebx, %eax
+			
+			/* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
+			movl %eax, (%esi, %ecx, 4)
+			
+			/* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
+			movl %eax, (%edi, %ecx, 4)
+			addl $(4 * 1024), %ebx
+			
+			incl %ecx
+			cmpl $512, %ecx
+			
+			jl floop
+		
+		movl %esi, %cr3
+		
+		movl %cr0, %ebx
+		orl $(1 << 31), %ebx  /* paging on */
+		movl %ebx, %cr0
+		
+		ret
+
+/** Calculate unmapped address of the end of the kernel. */
+calc_kernel_end:
+	movl $hardcoded_load_address, %edi
+	andl $0x7fffffff, %edi
+	movl (%edi), %esi
+	andl $0x7fffffff, %esi
+	
+	movl $hardcoded_ktext_size, %edi
+	andl $0x7fffffff, %edi
+	addl (%edi), %esi
+	andl $0x7fffffff, %esi
+	
+	movl $hardcoded_kdata_size, %edi
+	andl $0x7fffffff, %edi
+	addl (%edi), %esi
+	andl $0x7fffffff, %esi
+	movl %esi, kernel_end
+	
+	ret
+
+/** Find free 2M (+4k for alignment) region where to store page tables */
+find_mem_for_pt:
+	/* Check if multiboot info is present */
+	cmpl $MULTIBOOT_LOADER_MAGIC, multiboot_eax
+	je check_multiboot_map
+		
+		ret
+	
+	check_multiboot_map:
+		
+		/* Copy address of the multiboot info to ebx */
+		movl multiboot_ebx, %ebx
+		
+		/* Check if memory map flag is present */
+		movl (%ebx), %edx
+		andl $(1 << 6), %edx
+		jnz use_multiboot_map
+			
+			ret
+		
+	use_multiboot_map:
+		
+		/* Copy address of the memory map to edx */
+		movl 48(%ebx), %edx
+		movl %edx, %ecx
+		
+		addl 44(%ebx), %ecx
+		
+		/* Find a free region at least 2M in size */
+		check_memmap_loop:
+			
+			/* Is this a free region? */
+			cmp $1, 20(%edx)
+			jnz next_region
+			
+			/* Check size */
+			cmp $0, 16(%edx)
+			jnz next_region
+			
+			cmpl $(2 * 1024 * 1024 + 4 * 1024), 12(%edx)
+			jbe next_region
+			
+			cmp $0, 8(%edx)
+			jz found_region
+		
+		next_region:
+			
+			cmp %ecx, %edx
+			jbe next_region_do
+			
+				ret
+		
+		next_region_do:
+			
+			addl (%edx), %edx
+			addl $4, %edx
+			jmp check_memmap_loop
+			
+		found_region:
+			
+			/* Use end of the found region */
+			mov 4(%edx), %ecx
+			add 12(%edx), %ecx
+			sub $(2 * 1024 * 1024), %ecx
+			mov %ecx, free_area
+			
+			ret
+
+/** Print string to EGA display (in light red) and halt.
+ *
+ * Should be executed from 32 bit protected mode with paging
+ * turned off. Stack is not required. This routine is used even
+ * if CONFIG_EGA is not enabled. Since we are going to halt the
+ * CPU anyway, it is always better to at least try to print
+ * some hints.
+ *
+ * @param %esi NULL-terminated string to print.
+ *
+ */
+pm_error_halt:
+	movl $0xb8000, %edi  /* base of EGA text mode memory */
+	xorl %eax, %eax
+	
+	/* Read bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	shl $8, %ax
+	
+	/* Read bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	
+	/* Sanity check for the cursor on screen */
+	cmp $2000, %ax
+	jb err_cursor_ok
+	
+		movw $1998, %ax
+	
+	err_cursor_ok:
+	
+	movw %ax, %bx
+	shl $1, %eax
+	addl %eax, %edi
+	
+	err_ploop:
+		lodsb
+		
+		cmp $0, %al
+		je err_ploop_end
+		
+		movb $0x0c, %ah  /* black background, light red foreground */
+		stosw
+		
+		/* Sanity check for the cursor on the last line */
+		inc %bx
+		cmp $2000, %bx
+		jb err_ploop
+		
+		/* Scroll the screen (24 rows) */
+		movl %esi, %edx
+		movl $0xb80a0, %esi
+		movl $0xb8000, %edi
+		movl $960, %ecx
+		rep movsl
+		
+		/* Clear the 24th row */
+		xorl %eax, %eax
+		movl $40, %ecx
+		rep stosl
+		
+		/* Go to row 24 */
+		movl %edx, %esi
+		movl $0xb8f00, %edi
+		movw $1920, %bx
+		
+		jmp err_ploop
+	err_ploop_end:
+	
+	/* Write bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bh, %al
+	outb %al, %dx
+	
+	/* Write bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bl, %al
+	outb %al, %dx
+	
+	cli
+	hlt1:
+		hlt
+		jmp hlt1
+
+/** Print string to EGA display (in light green).
+ *
+ * Should be called from 32 bit protected mode with paging
+ * turned off. A stack space of at least 24 bytes is required,
+ * but the function does not establish a stack frame.
+ *
+ * Macros such as pm_status take care that this function
+ * is used only when CONFIG_EGA is enabled.
+ *
+ * @param %esi NULL-terminated string to print.
+ *
+ */
+pm_early_puts:
+	pushl %eax
+	pushl %ebx
+	pushl %ecx
+	pushl %edx
+	pushl %edi
+	
+	movl $0xb8000, %edi  /* base of EGA text mode memory */
+	xorl %eax, %eax
+	
+	/* Read bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	shl $8, %ax
+	
+	/* Read bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	
+	/* Sanity check for the cursor on screen */
+	cmp $2000, %ax
+	jb pm_puts_cursor_ok
+	
+		movw $1998, %ax
+	
+	pm_puts_cursor_ok:
+	
+	movw %ax, %bx
+	shl $1, %eax
+	addl %eax, %edi
+	
+	pm_puts_ploop:
+		lodsb
+		
+		cmp $0, %al
+		je pm_puts_ploop_end
+		
+		movb $0x0a, %ah  /* black background, light green foreground */
+		stosw
+		
+		/* Sanity check for the cursor on the last line */
+		inc %bx
+		cmp $2000, %bx
+		jb pm_puts_ploop
+		
+		/* Scroll the screen (24 rows) */
+		movl %esi, %edx
+		movl $0xb80a0, %esi
+		movl $0xb8000, %edi
+		movl $960, %ecx
+		rep movsl
+		
+		/* Clear the 24th row */
+		xorl %eax, %eax
+		movl $40, %ecx
+		rep stosl
+		
+		/* Go to row 24 */
+		movl %edx, %esi
+		movl $0xb8f00, %edi
+		movw $1920, %bx
+		
+		jmp pm_puts_ploop
+	pm_puts_ploop_end:
+	
+	/* Write bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bh, %al
+	outb %al, %dx
+	
+	/* Write bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bl, %al
+	outb %al, %dx
+	
+	popl %edi
+	popl %edx
+	popl %ecx
+	popl %ebx
+	popl %eax
+	
+	ret
+
+/** Print string to EGA display.
+ *
+ * Should be called from 32 bit protected mode (with paging
+ * enabled and stack established). This function is ABI compliant.
+ *
+ * If CONFIG_EGA is undefined or CONFIG_FB is defined
+ * then this function does nothing.
+ *
+ * @param %ebp+0x08 NULL-terminated string to print.
+ *
+ */
+early_puts:
+	
+#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
+	
+	/* Prologue, save preserved registers */
+	pushl %ebp
+	movl %esp, %ebp
+	pushl %ebx
+	pushl %esi
+	pushl %edi
+	
+	movl 0x08(%ebp), %esi
+	movl $(PA2KA(0xb8000)), %edi  /* base of EGA text mode memory */
+	xorl %eax, %eax
+	
+	/* Read bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	shl $8, %ax
+	
+	/* Read bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	
+	/* Sanity check for the cursor on screen */
+	cmp $2000, %ax
+	jb early_puts_cursor_ok
+	
+		movw $1998, %ax
+	
+	early_puts_cursor_ok:
+	
+	movw %ax, %bx
+	shl $1, %eax
+	addl %eax, %edi
+	
+	early_puts_ploop:
+		lodsb
+		
+		cmp $0, %al
+		je early_puts_ploop_end
+		
+		movb $0x0e, %ah  /* black background, yellow foreground */
+		stosw
+		
+		/* Sanity check for the cursor on the last line */
+		inc %bx
+		cmp $2000, %bx
+		jb early_puts_ploop
+		
+		/* Scroll the screen (24 rows) */
+		movl %esi, %edx
+		movl $(PA2KA(0xb80a0)), %esi
+		movl $(PA2KA(0xb8000)), %edi
+		movl $960, %ecx
+		rep movsl
+		
+		/* Clear the 24th row */
+		xorl %eax, %eax
+		movl $40, %ecx
+		rep stosl
+		
+		/* Go to row 24 */
+		movl %edx, %esi
+		movl $(PA2KA(0xb8f00)), %edi
+		movw $1920, %bx
+		
+		jmp early_puts_ploop
+	early_puts_ploop_end:
+	
+	/* Write bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bh, %al
+	outb %al, %dx
+	
+	/* Write bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bl, %al
+	outb %al, %dx
+	
+	/* Epilogue, restore preserved registers */
+	popl %edi
+	popl %esi
+	popl %ebx
+	leave
+	
+#endif
+	
+	ret
+
+#include "vesa_real.inc"
+
+.section K_DATA_START, "aw", @progbits
+
+.align 4096
+page_directory:
+	.space 4096, 0
+
+.global bootstrap_gdtr
+bootstrap_gdtr:
+	.word GDT_SELECTOR(GDT_ITEMS)
+	.long KA2PA(gdt)
+
+.global multiboot_eax
+multiboot_eax:
+	.long 0
+
+.global multiboot_ebx
+multiboot_ebx:
+	.long 0
+
+pt_loc:
+	.long 0
+kernel_end:
+	.long 0
+free_area:
+	.long 0
+
+status_prot:
+	.asciz "[prot] "
+status_pse:
+	.asciz "[pse] "
+status_non_pse:
+	.asciz "[non_pse] "
+status_vesa_copy:
+	.asciz "[vesa_copy] "
+status_multiboot_cmdline:
+	.asciz "[multiboot_cmdline] "
+status_vesa_real:
+	.asciz "[vesa_real] "
+status_prot2:
+	.asciz "[prot2] "
+status_prot3:
+	.asciz "[prot3] "
+status_main:
+	.asciz "[main] "
Index: kernel/arch/ia32/src/boot/multiboot2.S
===================================================================
--- kernel/arch/ia32/src/boot/multiboot2.S	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
+++ kernel/arch/ia32/src/boot/multiboot2.S	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch/boot/boot.h>
+#include <arch/pm.h>
+#include <arch/cpuid.h>
+#include <genarch/multiboot/multiboot2.h>
+
+#define START_STACK  (BOOT_OFFSET - BOOT_STACK_SIZE)
+
+.section K_TEXT_START, "ax"
+
+.code32
+
+.align 8
+.global multiboot2_image_start
+multiboot2_header_start:
+	.long MULTIBOOT2_HEADER_MAGIC
+	.long MULTIBOOT2_HEADER_ARCH_I386
+	.long multiboot2_header_end - multiboot2_header_start
+	.long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT2_HEADER_ARCH_I386 + (multiboot2_header_end - multiboot2_header_start))
+	
+	/* Information request tag */
+	tag_info_req_start:
+		.word MULTIBOOT2_TAG_INFO_REQ
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_info_req_end - tag_info_req_start
+		.long MULTIBOOT2_TAG_MODULE
+		.long MULTIBOOT2_TAG_MEMMAP
+#ifdef CONFIG_FB
+		.long MULTIBOOT2_TAG_FBINFO
+#endif
+	tag_info_req_end:
+	
+	/* Address tag */
+	tag_address_start:
+		.word MULTIBOOT2_TAG_ADDRESS
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_address_end - tag_address_start
+		.long multiboot2_header_start
+		.long unmapped_ktext_start
+		.long 0
+		.long 0
+	tag_address_end:
+	
+	/* Entry address tag */
+	tag_entry_address_start:
+		.word MULTIBOOT2_TAG_ENTRY_ADDRESS
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_entry_address_end - tag_entry_address_start
+		.long multiboot2_image_start
+	tag_entry_address_end:
+	
+	/* Flags tag */
+	tag_flags_start:
+		.word MULTIBOOT2_TAG_FLAGS
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_flags_end - tag_flags_start
+		.long MULTIBOOT2_FLAGS_CONSOLE
+	tag_flags_end:
+	
+#ifdef CONFIG_FB
+	/* Framebuffer tag */
+	tag_framebuffer_start:
+		.word MULTIBOOT2_TAG_FRAMEBUFFER
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_framebuffer_end - tag_framebuffer_start
+		.long CONFIG_BFB_WIDTH
+		.long CONFIG_BFB_HEIGHT
+		.long CONFIG_BFB_BPP
+	tag_framebuffer_end:
+#endif
+	
+	/* Module alignment tag */
+	tag_module_align_start:
+		.word MULTIBOOT2_TAG_MODULE_ALIGN
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_module_align_end - tag_module_align_start
+		.long 0
+	tag_module_align_end:
+	
+	/* Tag terminator */
+	tag_terminator_start:
+		.word MULTIBOOT2_TAG_TERMINATOR
+		.word MULTIBOOT2_FLAGS_REQUIRED
+		.long tag_terminator_end - tag_terminator_start
+	tag_terminator_end:
+multiboot2_header_end:
+
+multiboot2_image_start:
+	cld
+	
+	/* Initialize stack pointer */
+	movl $START_STACK, %esp
+	
+	/* Initialize Global Descriptor Table register */
+	lgdtl bootstrap_gdtr
+	
+	/* Kernel data + stack */
+	movw $GDT_SELECTOR(KDATA_DES), %cx
+	movw %cx, %es
+	movw %cx, %fs
+	movw %cx, %gs
+	movw %cx, %ds
+	movw %cx, %ss
+	
+	jmpl $GDT_SELECTOR(KTEXT_DES), $multiboot2_meeting_point
+	multiboot2_meeting_point:
+	
+	/* Save multiboot arguments */
+	movl %eax, multiboot_eax
+	movl %ebx, multiboot_ebx
+	
+#ifndef PROCESSOR_i486
+	
+	movl $(INTEL_CPUID_LEVEL), %eax
+	cpuid
+	cmp $0x0, %eax  /* any function > 0? */
+	jbe pse_unsupported
+	
+	movl $(INTEL_CPUID_STANDARD), %eax
+	cpuid
+	bt $(INTEL_PSE), %edx
+	jnc pse_unsupported
+		
+		/* Map kernel and turn paging on */
+		call map_kernel_pse
+		jmp stack_init
+	
+#endif /* PROCESSOR_i486 */
+	
+	pse_unsupported:
+		
+		/* Map kernel and turn paging on */
+		call map_kernel_non_pse
+	
+	stack_init:
+	
+	/* Create the first stack frame */
+	pushl $0
+	movl %esp, %ebp
+	
+	/* Call arch_pre_main(multiboot_eax, multiboot_ebx) */
+	pushl multiboot_ebx
+	pushl multiboot_eax
+	call arch_pre_main
+	
+	/* Call main_bsp() */
+	call main_bsp
+	
+	/* Not reached */
+	cli
+	hlt0:
+		hlt
+		jmp hlt0
Index: kernel/arch/ia32/src/boot/vesa_prot.inc
===================================================================
--- kernel/arch/ia32/src/boot/vesa_prot.inc	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/ia32/src/boot/vesa_prot.inc	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -1,5 +1,4 @@
 #ifdef CONFIG_FB
 
-#define MULTIBOOT_LOADER_MAGIC  0x2BADB002
 #define MBINFO_BIT_CMDLINE      2
 #define MBINFO_OFFSET_CMDLINE   16
@@ -14,13 +13,13 @@
 	rep movsb
 	
-	/* Check for GRUB command line */
+	/* Check for multiboot command line */
 	
-	pm_status $status_grub_cmdline
+	pm_status $status_multiboot_cmdline
 	
-	mov grub_eax, %eax
+	mov multiboot_eax, %eax
 	cmp $MULTIBOOT_LOADER_MAGIC, %eax
 	jne no_cmdline
 	
-	mov grub_ebx, %ebx
+	mov multiboot_ebx, %ebx
 	mov (%ebx), %eax
 	bt $MBINFO_BIT_CMDLINE, %eax
@@ -89,25 +88,33 @@
 		/* Returned back to protected mode */
 		
-		mov %ax, KA2PA(vesa_scanline)
+		movzx %ax, %ecx
+		mov %ecx, KA2PA(bfb_scanline)
+		
 		shr $16, %eax
-		mov %ax, KA2PA(vesa_bpp)
+		mov %ax, KA2PA(bfb_bpp)
 		
-		mov %bx, KA2PA(vesa_height)
+		movzx %bx, %ecx
+		mov %ecx, KA2PA(bfb_height)
+		
 		shr $16, %ebx
-		mov %bx, KA2PA(vesa_width)
+		mov %ebx, KA2PA(bfb_width)
 		
-		mov %dl, KA2PA(vesa_green_pos)
+		mov %dl, KA2PA(bfb_green_pos)
+		
 		shr $8, %edx
-		mov %dl, KA2PA(vesa_green_mask)
+		mov %dl, KA2PA(bfb_green_size)
+		
 		shr $8, %edx
-		mov %dl, KA2PA(vesa_red_pos)
+		mov %dl, KA2PA(bfb_red_pos)
+		
 		shr $8, %edx
-		mov %dl, KA2PA(vesa_red_mask)
+		mov %dl, KA2PA(bfb_red_size)
 		
 		mov %esi, %edx
-		mov %dl, KA2PA(vesa_blue_pos)
+		mov %dl, KA2PA(bfb_blue_pos)
+		
 		shr $8, %edx
-		mov %dl, KA2PA(vesa_blue_mask)
+		mov %dl, KA2PA(bfb_blue_size)
 		
-		mov %edi, KA2PA(vesa_ph_addr)
+		mov %edi, KA2PA(bfb_addr)
 #endif
Index: kernel/arch/ia32/src/boot/vesa_real.inc
===================================================================
--- kernel/arch/ia32/src/boot/vesa_real.inc	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/ia32/src/boot/vesa_real.inc	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -304,5 +304,5 @@
 		/*
 		 * Store mode parameters:
-		 *  eax = bpp[8] scanline[16]
+		 *  eax = bpp[16] scanline[16]
 		 *  ebx = width[16]  height[16]
 		 *  edx = red_mask[8] red_pos[8] green_mask[8] green_pos[8]
@@ -328,4 +328,5 @@
 		shl $8, %edx
 		mov VESA_MODE_RED_POS_OFFSET(%di), %dl
+		
 		shl $8, %edx
 		mov VESA_MODE_GREEN_MASK_OFFSET(%di), %dl
@@ -369,6 +370,10 @@
 		mov $0x0003, %ax
 		int $0x10
-		mov $0xffffffff, %edi
-		xor %ax, %ax
+		
+		xor %eax, %eax
+		xor %ebx, %ebx
+		xor %edx, %edx
+		xor %edi, %edi
+		
 		jz vesa_leave_real  /* force relative jump */
 
@@ -386,7 +391,7 @@
 
 default_mode:
-	.ascii STRING(CONFIG_VESA_MODE)
+	.ascii STRING(CONFIG_BFB_MODE)
 	.ascii "-"
-	.asciz STRING(CONFIG_VESA_BPP)
+	.asciz STRING(CONFIG_BFB_BPP)
 	.fill 24
 
Index: kernel/arch/ia32/src/drivers/vesa.c
===================================================================
--- kernel/arch/ia32/src/drivers/vesa.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ 	(revision )
@@ -1,119 +1,0 @@
-/*
- * Copyright (c) 2006 Jakub Vana
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup ia32
- * @{
- */
-/**
- * @file
- * @brief VESA frame buffer driver.
- */
-
-#ifdef CONFIG_FB
-
-#include <genarch/fb/fb.h>
-#include <arch/drivers/vesa.h>
-#include <console/chardev.h>
-#include <console/console.h>
-#include <putchar.h>
-#include <mm/page.h>
-#include <mm/frame.h>
-#include <mm/as.h>
-#include <arch/mm/page.h>
-#include <synch/spinlock.h>
-#include <arch/asm.h>
-#include <typedefs.h>
-#include <memstr.h>
-#include <bitops.h>
-
-uint32_t vesa_ph_addr;
-uint16_t vesa_width;
-uint16_t vesa_height;
-uint16_t vesa_bpp;
-uint16_t vesa_scanline;
-
-uint8_t vesa_red_mask;
-uint8_t vesa_red_pos;
-
-uint8_t vesa_green_mask;
-uint8_t vesa_green_pos;
-
-uint8_t vesa_blue_mask;
-uint8_t vesa_blue_pos;
-
-bool vesa_init(void)
-{
-	if ((vesa_width == 0xffffU) || (vesa_height == 0xffffU))
-		return false;
-	
-	visual_t visual;
-	
-	switch (vesa_bpp) {
-	case 8:
-		visual = VISUAL_INDIRECT_8;
-		break;
-	case 16:
-		if ((vesa_red_mask == 5) && (vesa_red_pos == 10)
-		    && (vesa_green_mask == 5) && (vesa_green_pos == 5)
-		    && (vesa_blue_mask == 5) && (vesa_blue_pos == 0))
-			visual = VISUAL_RGB_5_5_5_LE;
-		else
-			visual = VISUAL_RGB_5_6_5_LE;
-		break;
-	case 24:
-		visual = VISUAL_BGR_8_8_8;
-		break;
-	case 32:
-		visual = VISUAL_BGR_8_8_8_0;
-		break;
-	default:
-		LOG("Unsupported bits per pixel.");
-		return false;
-	}
-	
-	fb_properties_t vesa_props = {
-		.addr = vesa_ph_addr,
-		.offset = 0,
-		.x = vesa_width,
-		.y = vesa_height,
-		.scan = vesa_scanline,
-		.visual = visual,
-	};
-	
-	outdev_t *fbdev = fb_init(&vesa_props);
-	if (!fbdev)
-		return false;
-	
-	stdout_wire(fbdev);
-	return true;
-}
-
-#endif
-
-/** @}
- */
Index: kernel/arch/ia32/src/ia32.c
===================================================================
--- kernel/arch/ia32/src/ia32.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/ia32/src/ia32.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -36,37 +36,24 @@
 
 #include <arch.h>
-
 #include <typedefs.h>
-
-#include <arch/pm.h>
-
-#include <genarch/multiboot/multiboot.h>
-#include <genarch/drivers/legacy/ia32/io.h>
-#include <genarch/drivers/ega/ega.h>
-#include <arch/drivers/vesa.h>
-#include <genarch/drivers/i8042/i8042.h>
-#include <genarch/kbrd/kbrd.h>
+#include <errno.h>
+#include <memstr.h>
+#include <interrupt.h>
+#include <console/console.h>
+#include <syscall/syscall.h>
+#include <sysinfo/sysinfo.h>
+#include <arch/bios/bios.h>
+#include <arch/boot/boot.h>
+#include <arch/debugger.h>
 #include <arch/drivers/i8254.h>
 #include <arch/drivers/i8259.h>
-
-#include <arch/context.h>
-
-#include <config.h>
-
-#include <arch/interrupt.h>
-#include <arch/asm.h>
 #include <genarch/acpi/acpi.h>
-
-#include <arch/bios/bios.h>
-
-#include <interrupt.h>
-#include <ddi/irq.h>
-#include <arch/debugger.h>
-#include <proc/thread.h>
-#include <syscall/syscall.h>
-#include <console/console.h>
-#include <sysinfo/sysinfo.h>
-#include <arch/boot/boot.h>
-#include <memstr.h>
+#include <genarch/drivers/ega/ega.h>
+#include <genarch/drivers/i8042/i8042.h>
+#include <genarch/drivers/legacy/ia32/io.h>
+#include <genarch/fb/bfb.h>
+#include <genarch/kbrd/kbrd.h>
+#include <genarch/multiboot/multiboot.h>
+#include <genarch/multiboot/multiboot2.h>
 
 #ifdef CONFIG_SMP
@@ -76,11 +63,13 @@
 /** Perform ia32-specific initialization before main_bsp() is called.
  *
- * @param signature Should contain the multiboot signature.
- * @param mi        Pointer to the multiboot information structure.
- */
-void arch_pre_main(uint32_t signature, const multiboot_info_t *mi)
+ * @param signature Multiboot signature.
+ * @param info      Multiboot information structure.
+ *
+ */
+void arch_pre_main(uint32_t signature, void *info)
 {
 	/* Parse multiboot information obtained from the bootloader. */
-	multiboot_info_parse(signature, mi);
+	multiboot_info_parse(signature, (multiboot_info_t *) info);
+	multiboot2_info_parse(signature, (multiboot2_info_t *) info);
 	
 #ifdef CONFIG_SMP
@@ -114,13 +103,13 @@
 		
 #if (defined(CONFIG_FB) || defined(CONFIG_EGA))
-		bool vesa = false;
+		bool bfb = false;
 #endif
 		
 #ifdef CONFIG_FB
-		vesa = vesa_init();
+		bfb = bfb_init();
 #endif
 		
 #ifdef CONFIG_EGA
-		if (!vesa) {
+		if (!bfb) {
 			outdev_t *egadev = ega_init(EGA_BASE, EGA_VIDEORAM);
 			if (egadev)
@@ -216,10 +205,10 @@
  * selector, and the descriptor->base is the correct address.
  */
-sysarg_t sys_tls_set(sysarg_t addr)
+sysarg_t sys_tls_set(uintptr_t addr)
 {
 	THREAD->arch.tls = addr;
 	set_tls_desc(addr);
 	
-	return 0;
+	return EOK;
 }
 
Index: kernel/arch/ia64/include/asm.h
===================================================================
--- kernel/arch/ia64/include/asm.h	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/ia64/include/asm.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -38,5 +38,4 @@
 #include <config.h>
 #include <typedefs.h>
-#include <typedefs.h>
 #include <arch/register.h>
 #include <trace.h>
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/ia64/src/ia64.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -34,38 +34,21 @@
 
 #include <arch.h>
-#include <arch/drivers/ski.h>
-#include <arch/drivers/it.h>
-#include <arch/interrupt.h>
-#include <arch/barrier.h>
-#include <arch/asm.h>
-#include <arch/register.h>
 #include <typedefs.h>
-#include <arch/context.h>
-#include <arch/stack.h>
-#include <arch/mm/page.h>
+#include <errno.h>
 #include <interrupt.h>
-#include <mm/as.h>
-#include <config.h>
 #include <macros.h>
+#include <str.h>
 #include <userspace.h>
 #include <console/console.h>
-#include <abi/proc/uarg.h>
 #include <syscall/syscall.h>
-#include <ddi/irq.h>
-#include <arch/bootinfo.h>
+#include <sysinfo/sysinfo.h>
+#include <arch/drivers/it.h>
+#include <arch/drivers/kbd.h>
+#include <genarch/drivers/ega/ega.h>
+#include <genarch/drivers/i8042/i8042.h>
+#include <genarch/drivers/ns16550/ns16550.h>
 #include <genarch/drivers/legacy/ia32/io.h>
-#include <genarch/drivers/ega/ega.h>
 #include <genarch/kbrd/kbrd.h>
 #include <genarch/srln/srln.h>
-#include <genarch/drivers/i8042/i8042.h>
-#include <genarch/drivers/ns16550/ns16550.h>
-#include <arch/drivers/kbd.h>
-#include <smp/smp.h>
-#include <smp/ipi.h>
-#include <arch/atomic.h>
-#include <panic.h>
-#include <print.h>
-#include <sysinfo/sysinfo.h>
-#include <str.h>
 
 /* NS16550 as a COM 1 */
@@ -262,7 +245,7 @@
  * We use r13 (a.k.a. tp) for this purpose.
  */
-sysarg_t sys_tls_set(sysarg_t addr)
-{
-	return 0;
+sysarg_t sys_tls_set(uintptr_t addr)
+{
+	return EOK;
 }
 
@@ -270,6 +253,5 @@
 {
 	pio_write_8((ioport8_t *)0x64, 0xfe);
-	while (1)
-		;
+	while (1);
 }
 
Index: kernel/arch/ia64/src/start.S
===================================================================
--- kernel/arch/ia64/src/start.S	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/ia64/src/start.S	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -174,5 +174,5 @@
 	mov ar.bspstore = r8
 	loadrs
-
+	
 	#
 	# Initialize memory stack to some sane value and allocate a scratch area
@@ -196,5 +196,5 @@
 	srlz.i
 	srlz.d ;;
-
+	
 	br.call.sptk.many b0 = arch_pre_main
 0:
Index: kernel/arch/mips32/src/mips32.c
===================================================================
--- kernel/arch/mips32/src/mips32.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/mips32/src/mips32.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -34,31 +34,21 @@
 
 #include <arch.h>
-#include <arch/cp0.h>
-#include <arch/exception.h>
-#include <arch/debug.h>
-#include <mm/as.h>
+#include <typedefs.h>
+#include <errno.h>
+#include <interrupt.h>
+#include <macros.h>
+#include <str.h>
+#include <memstr.h>
 #include <userspace.h>
-#include <memstr.h>
-#include <proc/thread.h>
-#include <abi/proc/uarg.h>
-#include <print.h>
 #include <console/console.h>
 #include <syscall/syscall.h>
 #include <sysinfo/sysinfo.h>
-#include <arch/interrupt.h>
-#include <interrupt.h>
-#include <console/chardev.h>
-#include <arch/barrier.h>
+#include <arch/debug.h>
 #include <arch/debugger.h>
+#include <arch/drivers/msim.h>
 #include <genarch/fb/fb.h>
-#include <abi/fb/visuals.h>
 #include <genarch/drivers/dsrln/dsrlnin.h>
 #include <genarch/drivers/dsrln/dsrlnout.h>
 #include <genarch/srln/srln.h>
-#include <macros.h>
-#include <config.h>
-#include <str.h>
-#include <arch/drivers/msim.h>
-#include <arch/asm/regname.h>
 
 /* Size of the code jumping to the exception handler code
@@ -248,7 +238,7 @@
  * possible to have it separately in the future.
  */
-sysarg_t sys_tls_set(sysarg_t addr)
-{
-	return 0;
+sysarg_t sys_tls_set(uintptr_t addr)
+{
+	return EOK;
 }
 
Index: kernel/arch/mips64/src/mips64.c
===================================================================
--- kernel/arch/mips64/src/mips64.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/arch/mips64/src/mips64.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -34,31 +34,21 @@
 
 #include <arch.h>
-#include <arch/cp0.h>
-#include <arch/exception.h>
-#include <arch/debug.h>
-#include <mm/as.h>
+#include <typedefs.h>
+#include <errno.h>
+#include <interrupt.h>
+#include <macros.h>
+#include <str.h>
+#include <memstr.h>
 #include <userspace.h>
-#include <memstr.h>
-#include <proc/thread.h>
-#include <abi/proc/uarg.h>
-#include <print.h>
 #include <console/console.h>
 #include <syscall/syscall.h>
 #include <sysinfo/sysinfo.h>
-#include <arch/interrupt.h>
-#include <interrupt.h>
-#include <console/chardev.h>
-#include <arch/barrier.h>
+#include <arch/debug.h>
 #include <arch/debugger.h>
+#include <arch/drivers/msim.h>
 #include <genarch/fb/fb.h>
-#include <abi/fb/visuals.h>
 #include <genarch/drivers/dsrln/dsrlnin.h>
 #include <genarch/drivers/dsrln/dsrlnout.h>
 #include <genarch/srln/srln.h>
-#include <macros.h>
-#include <config.h>
-#include <str.h>
-#include <arch/drivers/msim.h>
-#include <arch/asm/regname.h>
 
 /* Size of the code jumping to the exception handler code
@@ -226,7 +216,7 @@
  * possible to have it separately in the future.
  */
-sysarg_t sys_tls_set(sysarg_t addr)
-{
-	return 0;
+sysarg_t sys_tls_set(uintptr_t addr)
+{
+	return EOK;
 }
 
Index: kernel/genarch/Makefile.inc
===================================================================
--- kernel/genarch/Makefile.inc	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/genarch/Makefile.inc	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -67,5 +67,6 @@
 		genarch/src/fb/font-8x16.c \
 		genarch/src/fb/logo-196x66.c \
-		genarch/src/fb/fb.c
+		genarch/src/fb/fb.c \
+		genarch/src/fb/bfb.c
 endif
 
@@ -143,5 +144,6 @@
 ifeq ($(CONFIG_MULTIBOOT), y)
 	GENARCH_SOURCES += \
-		genarch/src/multiboot/multiboot.c
+		genarch/src/multiboot/multiboot.c \
+		genarch/src/multiboot/multiboot2.c
 endif
 
Index: kernel/genarch/include/fb/bfb.h
===================================================================
--- kernel/genarch/include/fb/bfb.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
+++ kernel/genarch/include/fb/bfb.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2006 Jakub Vana
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_BFB_H_
+#define KERN_BFB_H_
+
+#include <typedefs.h>
+
+extern uintptr_t bfb_addr;
+extern uint32_t bfb_width;
+extern uint32_t bfb_height;
+extern uint16_t bfb_bpp;
+extern uint32_t bfb_scanline;
+
+extern uint8_t bfb_red_pos;
+extern uint8_t bfb_red_size;
+
+extern uint8_t bfb_green_pos;
+extern uint8_t bfb_green_size;
+
+extern uint8_t bfb_blue_pos;
+extern uint8_t bfb_blue_size;
+
+extern bool bfb_init(void);
+
+#endif
+
+/** @}
+ */
Index: kernel/genarch/include/multiboot/multiboot.h
===================================================================
--- kernel/genarch/include/multiboot/multiboot.h	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/genarch/include/multiboot/multiboot.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -36,11 +36,21 @@
 #define KERN_MULTIBOOT_H_
 
+#define MULTIBOOT_HEADER_MAGIC  0x1badb002
+#define MULTIBOOT_HEADER_FLAGS  0x00010003
+
+#define MULTIBOOT_LOADER_MAGIC  0x2badb002
+
+#ifndef __ASM__
+
 #include <typedefs.h>
 #include <arch/boot/memmap.h>
+
+/** Convert 32-bit multiboot address to a pointer. */
+#define MULTIBOOT_PTR(mba)  ((void *) (uintptr_t) (mba))
 
 /** Multiboot 32-bit address. */
 typedef uint32_t mbaddr_t;
 
-/** Multiboot mod structure */
+/** Multiboot module structure */
 typedef struct {
 	mbaddr_t start;
@@ -48,5 +58,5 @@
 	mbaddr_t string;
 	uint32_t reserved;
-} __attribute__ ((packed)) multiboot_mod_t;
+} __attribute__((packed)) multiboot_module_t;
 
 /** Multiboot mmap structure */
@@ -54,5 +64,5 @@
 	uint32_t size;
 	e820memmap_t mm_info;
-} __attribute__ ((packed)) multiboot_mmap_t;
+} __attribute__((packed)) multiboot_memmap_t;
 
 /** Multiboot information structure */
@@ -74,24 +84,22 @@
 	
 	/* ... */
-} __attribute__ ((packed)) multiboot_info_t;
+} __attribute__((packed)) multiboot_info_t;
 
 enum multiboot_info_flags {
-	MBINFO_FLAGS_MEM     = 0x01,
-	MBINFO_FLAGS_BOOT    = 0x02,
-	MBINFO_FLAGS_CMDLINE = 0x04,
-	MBINFO_FLAGS_MODS    = 0x08,
-	MBINFO_FLAGS_SYMS1   = 0x10,
-	MBINFO_FLAGS_SYMS2   = 0x20,
-	MBINFO_FLAGS_MMAP    = 0x40
+	MULTIBOOT_INFO_FLAGS_MEM     = 0x01,
+	MULTIBOOT_INFO_FLAGS_BOOT    = 0x02,
+	MULTIBOOT_INFO_FLAGS_CMDLINE = 0x04,
+	MULTIBOOT_INFO_FLAGS_MODS    = 0x08,
+	MULTIBOOT_INFO_FLAGS_SYMS1   = 0x10,
+	MULTIBOOT_INFO_FLAGS_SYMS2   = 0x20,
+	MULTIBOOT_INFO_FLAGS_MMAP    = 0x40
 	
 	/* ... */
 };
 
-#define MULTIBOOT_LOADER_MAGIC  0x2BADB002
+extern void multiboot_extract_command(char *, size_t, const char *);
+extern void multiboot_info_parse(uint32_t, const multiboot_info_t *);
 
-/** Convert 32-bit multiboot address to a pointer. */
-#define MULTIBOOT_PTR(mba) ((void *)(uintptr_t) (mba))
-
-extern void multiboot_info_parse(uint32_t, const multiboot_info_t *);
+#endif /* __ASM__ */
 
 #endif
Index: kernel/genarch/include/multiboot/multiboot2.h
===================================================================
--- kernel/genarch/include/multiboot/multiboot2.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
+++ kernel/genarch/include/multiboot/multiboot2.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_MULTIBOOT2_H_
+#define KERN_MULTIBOOT2_H_
+
+#define MULTIBOOT2_HEADER_MAGIC      0xe85250d6
+#define MULTIBOOT2_HEADER_ARCH_I386  0
+
+#define MULTIBOOT2_LOADER_MAGIC  0x36d76289
+
+#define MULTIBOOT2_FLAGS_REQUIRED  0
+#define MULTIBOOT2_FLAGS_CONSOLE   0x03
+
+#define MULTIBOOT2_TAG_TERMINATOR     0
+#define MULTIBOOT2_TAG_INFO_REQ       1
+#define MULTIBOOT2_TAG_ADDRESS        2
+#define MULTIBOOT2_TAG_ENTRY_ADDRESS  3
+#define MULTIBOOT2_TAG_FLAGS          4
+#define MULTIBOOT2_TAG_FRAMEBUFFER    5
+#define MULTIBOOT2_TAG_MODULE_ALIGN   6
+
+#define MULTIBOOT2_TAG_MODULE  3
+#define MULTIBOOT2_TAG_MEMMAP  6
+#define MULTIBOOT2_TAG_FBINFO  8
+
+#define MULTIBOOT2_VISUAL_INDEXED  0
+#define MULTIBOOT2_VISUAL_RGB      1
+#define MULTIBOOT2_VISUAL_EGA      2
+
+#ifndef __ASM__
+
+#include <typedefs.h>
+#include <arch/boot/memmap.h>
+
+/** Multiboot2 32-bit address. */
+typedef uint32_t mb2addr_t;
+
+/** Multiboot2 information structure */
+typedef struct {
+	uint32_t size;
+	uint32_t reserved;
+} __attribute__((packed)) multiboot2_info_t;
+
+/** Multiboot2 modules structure */
+typedef struct {
+	mb2addr_t start;
+	mb2addr_t end;
+	char string[];
+} __attribute__((packed)) multiboot2_module_t;
+
+/** Multiboot2 memmap structure */
+typedef struct {
+	uint32_t entry_size;
+	uint32_t entry_version;
+} __attribute__ ((packed)) multiboot2_memmap_t;
+
+/** Multiboot2 memmap entry structure */
+typedef struct {
+	uint64_t base_address;
+	uint64_t size;
+	uint32_t type;
+	uint32_t reserved;
+} __attribute__((packed)) multiboot2_memmap_entry_t;
+
+/** Multiboot2 palette structure */
+typedef struct {
+	uint8_t red;
+	uint8_t green;
+	uint8_t blue;
+} __attribute__((packed)) multiboot2_colorinfo_palette_t;
+
+/** Multiboot2 indexed color information structure */
+typedef struct {
+	uint32_t colors;
+	multiboot2_colorinfo_palette_t palette[];
+} __attribute__((packed)) multiboot2_colorinfo_indexed_t;
+
+/** Multiboot2 RGB color information structure */
+typedef struct {
+	uint8_t red_pos;
+	uint8_t red_size;
+	uint8_t green_pos;
+	uint8_t green_size;
+	uint8_t blue_pos;
+	uint8_t blue_size;
+} __attribute__((packed)) multiboot2_colorinfo_rgb_t;
+
+/** Multiboot2 framebuffer information structure */
+typedef struct {
+	uint64_t addr;
+	uint32_t scanline;
+	uint32_t width;
+	uint32_t height;
+	uint8_t bpp;
+	uint8_t visual;
+	uint8_t reserved;
+	union {
+		multiboot2_colorinfo_indexed_t indexed;
+		multiboot2_colorinfo_rgb_t rgb;
+	};
+} __attribute__((packed)) multiboot2_fbinfo_t;
+
+/** Generic multiboot2 tag */
+typedef struct {
+	uint32_t type;
+	uint32_t size;
+	union {
+		multiboot2_module_t module;
+		multiboot2_memmap_t memmap;
+		multiboot2_fbinfo_t fbinfo;
+	};
+} __attribute__((packed)) multiboot2_tag_t;
+
+extern void multiboot2_info_parse(uint32_t, const multiboot2_info_t *);
+
+#endif /* __ASM__ */
+
+#endif
+
+/** @}
+ */
Index: kernel/genarch/src/drivers/i8042/i8042.c
===================================================================
--- kernel/genarch/src/drivers/i8042/i8042.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/genarch/src/drivers/i8042/i8042.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -44,4 +44,5 @@
 #include <mm/slab.h>
 #include <ddi/device.h>
+#include <time/delay.h>
 
 #define i8042_SET_COMMAND  0x60
@@ -51,4 +52,6 @@
 #define i8042_BUFFER_FULL_MASK  0x01
 #define i8042_WAIT_MASK         0x02
+
+#define i8042_TIMEOUT  65536
 
 static irq_ownership_t i8042_claim(irq_t *irq)
@@ -77,6 +80,24 @@
 static void i8042_clear_buffer(i8042_t *dev)
 {
-	while (pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK)
+	for (uint32_t i = 0; i < i8042_TIMEOUT; i++) {
+		if ((pio_read_8(&dev->status) & i8042_BUFFER_FULL_MASK) == 0)
+			break;
+		
 		(void) pio_read_8(&dev->data);
+		delay(50);  /* 50 us think time */
+	}
+}
+
+static void i8042_send_command(i8042_t *dev, uint8_t cmd)
+{
+	for (uint32_t i = 0; i < i8042_TIMEOUT; i++) {
+		if ((pio_read_8(&dev->status) & i8042_WAIT_MASK) == 0)
+			break;
+		
+		delay(50);  /* 50 us think time */
+	}
+	
+	pio_write_8(&dev->status, cmd);
+	delay(10000);  /* 10 ms think time */
 }
 
@@ -84,6 +105,6 @@
 i8042_instance_t *i8042_init(i8042_t *dev, inr_t inr)
 {
-	i8042_instance_t *instance
-	    = malloc(sizeof(i8042_instance_t), FRAME_ATOMIC);
+	i8042_instance_t *instance =
+	    malloc(sizeof(i8042_instance_t), FRAME_ATOMIC);
 	if (instance) {
 		instance->i8042 = dev;
@@ -96,5 +117,4 @@
 		instance->irq.handler = i8042_irq_handler;
 		instance->irq.instance = instance;
-		
 	}
 	
@@ -107,7 +127,8 @@
 	ASSERT(kbrdin);
 	
+	i8042_clear_buffer(instance->i8042);
+	
 	instance->kbrdin = kbrdin;
 	irq_register(&instance->irq);
-	i8042_clear_buffer(instance->i8042);
 }
 
@@ -116,9 +137,6 @@
 {
 	interrupts_disable();
-	
 	i8042_clear_buffer(dev);
-	
-	/* Reset CPU */
-	pio_write_8(&dev->status, i8042_CPU_RESET);
+	i8042_send_command(dev, i8042_CPU_RESET);
 }
 
Index: kernel/genarch/src/fb/bfb.c
===================================================================
--- kernel/genarch/src/fb/bfb.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
+++ kernel/genarch/src/fb/bfb.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2006 Jakub Vana
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/**
+ * @file
+ * @brief Boot framebuffer driver.
+ */
+
+#include <typedefs.h>
+#include <genarch/fb/fb.h>
+#include <genarch/fb/bfb.h>
+#include <console/console.h>
+
+uintptr_t bfb_addr = 0;
+uint32_t bfb_width = 0;
+uint32_t bfb_height = 0;
+uint16_t bfb_bpp = 0;
+uint32_t bfb_scanline = 0;
+
+uint8_t bfb_red_pos = 0;
+uint8_t bfb_red_size = 0;
+
+uint8_t bfb_green_pos = 0;
+uint8_t bfb_green_size = 0;
+
+uint8_t bfb_blue_pos = 0;
+uint8_t bfb_blue_size = 0;
+
+bool bfb_init(void)
+{
+	if ((bfb_addr == 0) || (bfb_width == 0) || (bfb_height == 0) ||
+	    (bfb_bpp == 0) || (bfb_scanline == 0))
+		return false;
+	
+	fb_properties_t bfb_props = {
+		.addr = bfb_addr,
+		.offset = 0,
+		.x = bfb_width,
+		.y = bfb_height,
+		.scan = bfb_scanline
+	};
+	
+	switch (bfb_bpp) {
+	case 8:
+		bfb_props.visual = VISUAL_INDIRECT_8;
+		break;
+	case 16:
+		if ((bfb_red_pos == 10) && (bfb_red_size == 5) &&
+		    (bfb_green_pos == 5) && (bfb_green_size == 5) &&
+		    (bfb_blue_pos == 0) && (bfb_blue_size == 5))
+			bfb_props.visual = VISUAL_RGB_5_5_5_LE;
+		else
+			bfb_props.visual = VISUAL_RGB_5_6_5_LE;
+		break;
+	case 24:
+		bfb_props.visual = VISUAL_BGR_8_8_8;
+		break;
+	case 32:
+		bfb_props.visual = VISUAL_BGR_8_8_8_0;
+		break;
+	default:
+		LOG("Unsupported bits per pixel.");
+		return false;
+	}
+	
+	outdev_t *fbdev = fb_init(&bfb_props);
+	if (!fbdev)
+		return false;
+	
+	stdout_wire(fbdev);
+	return true;
+}
+
+/** @}
+ */
Index: kernel/genarch/src/multiboot/multiboot.c
===================================================================
--- kernel/genarch/src/multiboot/multiboot.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/genarch/src/multiboot/multiboot.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -33,18 +33,17 @@
  */
 
+#include <typedefs.h>
 #include <genarch/multiboot/multiboot.h>
-#include <typedefs.h>
 #include <config.h>
 #include <str.h>
-#include <macros.h>
 
 /** Extract command name from the multiboot module command line.
  *
- * @param buf      Destination buffer (will always NULL-terminate).
- * @param sz       Size of destination buffer (in bytes).
+ * @param buf      Destination buffer (will be always NULL-terminated).
+ * @param size     Size of destination buffer (in bytes).
  * @param cmd_line Input string (the command line).
  *
  */
-static void extract_command(char *buf, size_t sz, const char *cmd_line)
+void multiboot_extract_command(char *buf, size_t size, const char *cmd_line)
 {
 	/* Find the first space. */
@@ -69,5 +68,41 @@
 	
 	/* Copy the command. */
-	str_ncpy(buf, sz, start, (size_t) (end - start));
+	str_ncpy(buf, size, start, (size_t) (end - start));
+}
+
+static void multiboot_modules(uint32_t count, multiboot_module_t *mods)
+{
+	for (uint32_t i = 0; i < count; i++) {
+		if (init.cnt >= CONFIG_INIT_TASKS)
+			break;
+		
+		init.tasks[init.cnt].addr = PA2KA(mods[i].start);
+		init.tasks[init.cnt].size = mods[i].end - mods[i].start;
+		
+		/* Copy command line, if available. */
+		if (mods[i].string) {
+			multiboot_extract_command(init.tasks[init.cnt].name,
+			    CONFIG_TASK_NAME_BUFLEN, MULTIBOOT_PTR(mods[i].string));
+		} else
+			init.tasks[init.cnt].name[0] = 0;
+		
+		init.cnt++;
+	}
+}
+
+static void multiboot_memmap(uint32_t length, multiboot_memmap_t *memmap)
+{
+	uint32_t pos = 0;
+	
+	while ((pos < length) && (e820counter < MEMMAP_E820_MAX_RECORDS)) {
+		e820table[e820counter] = memmap->mm_info;
+		
+		/* Compute address of next structure. */
+		uint32_t size = sizeof(memmap->size) + memmap->size;
+		memmap = (multiboot_memmap_t *) ((uintptr_t) memmap + size);
+		pos += size;
+		
+		e820counter++;
+	}
 }
 
@@ -78,59 +113,21 @@
  *
  * @param signature Should contain the multiboot signature.
- * @param mi        Pointer to the multiboot information structure.
+ * @param info      Multiboot information structure.
+ *
  */
-void multiboot_info_parse(uint32_t signature, const multiboot_info_t *mi)
+void multiboot_info_parse(uint32_t signature, const multiboot_info_t *info)
 {
-	uint32_t flags;
+	if (signature != MULTIBOOT_LOADER_MAGIC)
+		return;
 	
-	if (signature == MULTIBOOT_LOADER_MAGIC)
-		flags = mi->flags;
-	else {
-		/* No multiboot info available. */
-		flags = 0;
-	}
-	
-	/* Copy module information. */
-	uint32_t i;
-	if ((flags & MBINFO_FLAGS_MODS) != 0) {
-		init.cnt = min(mi->mods_count, CONFIG_INIT_TASKS);
-		multiboot_mod_t *mods
-		    = (multiboot_mod_t *) MULTIBOOT_PTR(mi->mods_addr);
-		
-		for (i = 0; i < init.cnt; i++) {
-			init.tasks[i].addr = PA2KA(mods[i].start);
-			init.tasks[i].size = mods[i].end - mods[i].start;
-			
-			/* Copy command line, if available. */
-			if (mods[i].string) {
-				extract_command(init.tasks[i].name,
-				    CONFIG_TASK_NAME_BUFLEN,
-				    MULTIBOOT_PTR(mods[i].string));
-			} else
-				init.tasks[i].name[0] = 0;
-		}
-	} else
-		init.cnt = 0;
+	/* Copy modules information. */
+	if ((info->flags & MULTIBOOT_INFO_FLAGS_MODS) != 0)
+		multiboot_modules(info->mods_count,
+		    (multiboot_module_t *) MULTIBOOT_PTR(info->mods_addr));
 	
 	/* Copy memory map. */
-	
-	if ((flags & MBINFO_FLAGS_MMAP) != 0) {
-		int32_t mmap_length = mi->mmap_length;
-		multiboot_mmap_t *mme = MULTIBOOT_PTR(mi->mmap_addr);
-		e820counter = 0;
-		
-		i = 0;
-		while ((mmap_length > 0) && (i < MEMMAP_E820_MAX_RECORDS)) {
-			e820table[i++] = mme->mm_info;
-			
-			/* Compute address of next structure. */
-			uint32_t size = sizeof(mme->size) + mme->size;
-			mme = ((void *) mme) + size;
-			mmap_length -= size;
-		}
-		
-		e820counter = i;
-	} else
-		e820counter = 0;
+	if ((info->flags & MULTIBOOT_INFO_FLAGS_MMAP) != 0)
+		multiboot_memmap(info->mmap_length,
+		    (multiboot_memmap_t *) MULTIBOOT_PTR(info->mmap_addr));
 }
 
Index: kernel/genarch/src/multiboot/multiboot2.c
===================================================================
--- kernel/genarch/src/multiboot/multiboot2.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
+++ kernel/genarch/src/multiboot/multiboot2.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/** @file
+ */
+
+#include <typedefs.h>
+#include <genarch/multiboot/multiboot.h>
+#include <genarch/multiboot/multiboot2.h>
+#include <genarch/fb/bfb.h>
+#include <config.h>
+#include <align.h>
+
+#define MULTIBOOT2_TAG_ALIGN  8
+
+static void multiboot2_module(const multiboot2_module_t *module)
+{
+	if (init.cnt < CONFIG_INIT_TASKS) {
+		init.tasks[init.cnt].addr = PA2KA(module->start);
+		init.tasks[init.cnt].size = module->end - module->start;
+		multiboot_extract_command(init.tasks[init.cnt].name,
+		    CONFIG_TASK_NAME_BUFLEN, module->string);
+		
+		init.cnt++;
+	}
+}
+
+static void multiboot2_memmap(uint32_t length, const multiboot2_memmap_t *memmap)
+{
+	multiboot2_memmap_entry_t *entry = (multiboot2_memmap_entry_t *)
+	    ((uintptr_t) memmap + sizeof(*memmap));
+	uint32_t pos = sizeof(*memmap);
+	
+	while ((pos < length) && (e820counter < MEMMAP_E820_MAX_RECORDS)) {
+		e820table[e820counter].base_address = entry->base_address;
+		e820table[e820counter].size = entry->size;
+		e820table[e820counter].type = entry->type;
+		
+		/* Compute address of next entry. */
+		entry = (multiboot2_memmap_entry_t *)
+		    ((uintptr_t) entry + memmap->entry_size);
+		pos += memmap->entry_size;
+		
+		e820counter++;
+	}
+}
+
+static void multiboot2_fbinfo(const multiboot2_fbinfo_t *fbinfo)
+{
+#ifdef CONFIG_FB
+	if (fbinfo->visual == MULTIBOOT2_VISUAL_RGB) {
+		bfb_addr = fbinfo->addr;
+		bfb_width = fbinfo->width;
+		bfb_height = fbinfo->height;
+		bfb_bpp = fbinfo->bpp;
+		bfb_scanline = fbinfo->scanline;
+		
+		bfb_red_pos = fbinfo->rgb.red_pos;
+		bfb_red_size = fbinfo->rgb.red_size;
+		
+		bfb_green_pos = fbinfo->rgb.green_pos;
+		bfb_green_size = fbinfo->rgb.green_size;
+		
+		bfb_blue_pos = fbinfo->rgb.blue_pos;
+		bfb_blue_size = fbinfo->rgb.blue_size;
+	}
+#endif
+}
+
+/** Parse multiboot2 information structure.
+ *
+ * If @a signature does not contain a valid multiboot2 signature,
+ * assumes no multiboot2 information is available.
+ *
+ * @param signature Should contain the multiboot2 signature.
+ * @param info      Multiboot2 information structure.
+ *
+ */
+void multiboot2_info_parse(uint32_t signature, const multiboot2_info_t *info)
+{
+	if (signature != MULTIBOOT2_LOADER_MAGIC)
+		return;
+	
+	const multiboot2_tag_t *tag = (const multiboot2_tag_t *)
+	    ALIGN_UP((uintptr_t) info + sizeof(*info), MULTIBOOT2_TAG_ALIGN);
+	
+	while (tag->type != MULTIBOOT2_TAG_TERMINATOR) {
+		switch (tag->type) {
+		case MULTIBOOT2_TAG_MODULE:
+			multiboot2_module(&tag->module);
+			break;
+		case MULTIBOOT2_TAG_MEMMAP:
+			multiboot2_memmap(tag->size, &tag->memmap);
+			break;
+		case MULTIBOOT2_TAG_FBINFO:
+			multiboot2_fbinfo(&tag->fbinfo);
+			break;
+		}
+		
+		tag = (const multiboot2_tag_t *)
+		    ALIGN_UP((uintptr_t) tag + tag->size, MULTIBOOT2_TAG_ALIGN);
+	}
+}
+
+/** @}
+ */
Index: kernel/generic/include/ddi/ddi.h
===================================================================
--- kernel/generic/include/ddi/ddi.h	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/include/ddi/ddi.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -55,5 +55,10 @@
 extern void ddi_parea_register(parea_t *);
 
-extern sysarg_t sys_physmem_map(sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+extern sysarg_t sys_physmem_map(uintptr_t, uintptr_t, size_t, unsigned int);
+
+extern sysarg_t sys_dmamem_map(uintptr_t, size_t, unsigned int, unsigned int,
+    void *);
+extern sysarg_t sys_dmamem_unmap(uintptr_t, size_t, unsigned int);
+
 extern sysarg_t sys_iospace_enable(ddi_ioarg_t *);
 
Index: kernel/generic/include/lib/rd.h
===================================================================
--- kernel/generic/include/lib/rd.h	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/include/lib/rd.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -38,44 +38,5 @@
 #include <typedefs.h>
 
-/**
- * RAM disk version
- */
-#define RD_VERSION	1
-
-/**
- * RAM disk magic number
- */
-#define RD_MAGIC_SIZE	4
-#define RD_MAG0			'H'
-#define RD_MAG1			'O'
-#define RD_MAG2			'R'
-#define RD_MAG3			'D'
-
-/**
- * RAM disk data encoding types
- */
-#define RD_DATA_NONE	0
-#define RD_DATA_LSB		1		/* Least significant byte first (little endian) */
-#define RD_DATA_MSB		2		/* Most signigicant byte first (big endian) */
-
-/**
- * RAM disk error return codes
- */
-#define RE_OK			0	/* No error */
-#define RE_INVALID		1	/* Invalid RAM disk image */
-#define RE_UNSUPPORTED		2	/* Non-supported image (e.g. wrong version) */
-
-/** RAM disk header */
-struct rd_header {
-	uint8_t magic[RD_MAGIC_SIZE];
-	uint8_t version;
-	uint8_t data_type;
-	uint32_t header_size;
-	uint64_t data_size;
-} __attribute__ ((packed));
-
-typedef struct rd_header rd_header_t;
-
-extern int init_rd(rd_header_t *addr, size_t size);
+extern void init_rd(void *, size_t);
 
 #endif
Index: kernel/generic/include/mm/page.h
===================================================================
--- kernel/generic/include/mm/page.h	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/include/mm/page.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -66,5 +66,6 @@
 extern uintptr_t hw_map(uintptr_t, size_t);
 
-extern sysarg_t sys_page_find_mapping(uintptr_t, uintptr_t *);
+extern int page_find_mapping(uintptr_t, void **);
+extern sysarg_t sys_page_find_mapping(uintptr_t, void *);
 
 #endif
Index: kernel/generic/include/synch/smc.h
===================================================================
--- kernel/generic/include/synch/smc.h	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/include/synch/smc.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -36,5 +36,5 @@
 #define KERN_SMC_H_
 
-extern sysarg_t sys_smc_coherence(uintptr_t va, size_t size);
+extern sysarg_t sys_smc_coherence(uintptr_t, size_t);
 
 #endif
Index: kernel/generic/include/syscall/syscall.h
===================================================================
--- kernel/generic/include/syscall/syscall.h	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/include/syscall/syscall.h	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -45,5 +45,5 @@
 extern sysarg_t syscall_handler(sysarg_t, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t, sysarg_t);
-extern sysarg_t sys_tls_set(sysarg_t);
+extern sysarg_t sys_tls_set(uintptr_t);
 
 #endif
Index: kernel/generic/src/ddi/ddi.c
===================================================================
--- kernel/generic/src/ddi/ddi.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/src/ddi/ddi.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -45,4 +45,5 @@
 #include <mm/frame.h>
 #include <mm/as.h>
+#include <mm/page.h>
 #include <synch/mutex.h>
 #include <syscall/copy.h>
@@ -52,4 +53,5 @@
 #include <errno.h>
 #include <trace.h>
+#include <bitops.h>
 
 /** This lock protects the parea_btree. */
@@ -87,25 +89,26 @@
 /** Map piece of physical memory into virtual address space of current task.
  *
- * @param pf    Physical address of the starting frame.
- * @param vp    Virtual address of the starting page.
+ * @param phys  Physical address of the starting frame.
+ * @param virt  Virtual address of the starting page.
  * @param pages Number of pages to map.
  * @param flags Address space area flags for the mapping.
  *
- * @return 0 on success, EPERM if the caller lacks capabilities to use this
- *         syscall, EBADMEM if pf or vf is not page aligned, ENOENT if there
- *         is no task matching the specified ID or the physical address space
- *         is not enabled for mapping and ENOMEM if there was a problem in
- *         creating address space area.
- *
- */
-NO_TRACE static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, size_t pages,
+ * @return EOK on success.
+ * @return EPERM if the caller lacks capabilities to use this syscall.
+ * @return EBADMEM if phys or virt is not page aligned.
+ * @return ENOENT if there is no task matching the specified ID or
+ *         the physical address space is not enabled for mapping.
+ * @return ENOMEM if there was a problem in creating address space area.
+ *
+ */
+NO_TRACE static int ddi_physmem_map(uintptr_t phys, uintptr_t virt, size_t pages,
     unsigned int flags)
 {
 	ASSERT(TASK);
 	
-	if ((pf % FRAME_SIZE) != 0)
+	if ((phys % FRAME_SIZE) != 0)
 		return EBADMEM;
 	
-	if ((vp % PAGE_SIZE) != 0)
+	if ((virt % PAGE_SIZE) != 0)
 		return EBADMEM;
 	
@@ -118,5 +121,5 @@
 	
 	mem_backend_data_t backend_data;
-	backend_data.base = pf;
+	backend_data.base = phys;
 	backend_data.frames = pages;
 	
@@ -129,5 +132,5 @@
 	btree_node_t *nodep;
 	parea_t *parea = (parea_t *) btree_search(&parea_btree,
-	    (btree_key_t) pf, &nodep);
+	    (btree_key_t) phys, &nodep);
 	
 	if ((parea != NULL) && (parea->frames >= pages)) {
@@ -149,5 +152,5 @@
 	
 	irq_spinlock_lock(&zones.lock, true);
-	size_t znum = find_zone(ADDR2PFN(pf), pages, 0);
+	size_t znum = find_zone(ADDR2PFN(phys), pages, 0);
 	
 	if (znum == (size_t) -1) {
@@ -182,5 +185,5 @@
 	
 map:
-	if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp,
+	if (!as_area_create(TASK->as, flags, FRAMES2SIZE(pages), virt,
 	    AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) {
 		/*
@@ -253,6 +256,6 @@
 /** Wrapper for SYS_PHYSMEM_MAP syscall.
  *
- * @param phys_base Physical base address to map
- * @param virt_base Destination virtual address
+ * @param phys  Physical base address to map
+ * @param virt  Destination virtual address
  * @param pages Number of pages
  * @param flags Flags of newly mapped pages
@@ -261,10 +264,10 @@
  *
  */
-sysarg_t sys_physmem_map(sysarg_t phys_base, sysarg_t virt_base,
-    sysarg_t pages, sysarg_t flags)
-{
-	return (sysarg_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base,
-	    FRAME_SIZE), ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE),
-	    (size_t) pages, (int) flags);
+sysarg_t sys_physmem_map(uintptr_t phys, uintptr_t virt,
+    size_t pages, unsigned int flags)
+{
+	return (sysarg_t)
+	    ddi_physmem_map(ALIGN_DOWN(phys, FRAME_SIZE),
+	    ALIGN_DOWN(virt, PAGE_SIZE), pages, flags);
 }
 
@@ -287,4 +290,74 @@
 }
 
+NO_TRACE static int dmamem_map(uintptr_t virt, size_t size,
+    unsigned int map_flags, unsigned int flags, void **phys)
+{
+	ASSERT(TASK);
+	
+	if ((flags & DMAMEM_FLAGS_ANONYMOUS) == 0) {
+		// TODO: implement locking of non-anonymous mapping
+		return page_find_mapping(virt, phys);
+	} else {
+		// TODO: implement locking
+		
+		if ((virt % PAGE_SIZE) != 0)
+			return EBADMEM;
+		
+		size_t pages = SIZE2FRAMES(size);
+		uint8_t order;
+		
+		/* We need the 2^order >= pages */
+		if (pages == 1)
+			order = 0;
+		else
+			order = fnzb(pages - 1) + 1;
+		
+		*phys = frame_alloc_noreserve(order, 0);
+		if (*phys == NULL)
+			return ENOMEM;
+		
+		mem_backend_data_t backend_data;
+		backend_data.base = (uintptr_t) *phys;
+		backend_data.frames = pages;
+		
+		if (!as_area_create(TASK->as, map_flags, size, virt,
+		    AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) {
+			frame_free_noreserve((uintptr_t) *phys);
+			return ENOMEM;
+		}
+		
+		return EOK;
+	}
+}
+
+NO_TRACE static int dmamem_unmap(uintptr_t virt, size_t size,
+    unsigned int flags)
+{
+	// TODO: implement unlocking & unmap
+	return EOK;
+}
+
+sysarg_t sys_dmamem_map(uintptr_t virt, size_t size, unsigned int map_flags,
+    unsigned int flags, void *phys_ptr)
+{
+	void *phys;
+	int rc = dmamem_map(virt, size, map_flags, flags, &phys);
+	if (rc != EOK)
+		return rc;
+	
+	rc = copy_to_uspace(phys_ptr, &phys, sizeof(phys));
+	if (rc != EOK) {
+		dmamem_unmap(virt, size, flags);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+sysarg_t sys_dmamem_unmap(uintptr_t virt, size_t size, unsigned int flags)
+{
+	return dmamem_unmap(virt, size, flags);
+}
+
 /** @}
  */
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/src/ipc/irq.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -365,26 +365,15 @@
 		return IRQ_DECLINE;
 	
-#define CMD_MEM_READ(target) \
-do { \
-	void *va = code->cmds[i].addr; \
-	if (AS != irq->driver_as) \
-		as_switch(AS, irq->driver_as); \
-	memcpy_from_uspace(&target, va, (sizeof(target))); \
-	if (dstarg) \
-		scratch[dstarg] = target; \
-} while(0)
-
-#define CMD_MEM_WRITE(val) \
-do { \
-	void *va = code->cmds[i].addr; \
-	if (AS != irq->driver_as) \
-		as_switch(AS, irq->driver_as); \
-	memcpy_to_uspace(va, &val, sizeof(val)); \
-} while (0)
-
 	as_t *current_as = AS;
-	size_t i;
-	for (i = 0; i < code->cmdcount; i++) {
+	if (current_as != irq->driver_as)
+		as_switch(AS, irq->driver_as);
+	
+	for (size_t i = 0; i < code->cmdcount; i++) {
 		uint32_t dstval;
+		void *va;
+		uint8_t val8;
+		uint16_t val16;
+		uint32_t val32;
+		
 		uintptr_t srcarg = code->cmds[i].srcarg;
 		uintptr_t dstarg = code->cmds[i].dstarg;
@@ -442,50 +431,56 @@
 			}
 			break;
-		case CMD_MEM_READ_8: {
-			uint8_t val;
-			CMD_MEM_READ(val);
-			break;
-			}
-		case CMD_MEM_READ_16: {
-			uint16_t val;
-			CMD_MEM_READ(val);
-			break;
-			}
-		case CMD_MEM_READ_32: {
-			uint32_t val;
-			CMD_MEM_READ(val);
-			break;
-			}
-		case CMD_MEM_WRITE_8: {
-			uint8_t val = code->cmds[i].value;
-			CMD_MEM_WRITE(val);
-			break;
-			}
-		case CMD_MEM_WRITE_16: {
-			uint16_t val = code->cmds[i].value;
-			CMD_MEM_WRITE(val);
-			break;
-			}
-		case CMD_MEM_WRITE_32: {
-			uint32_t val = code->cmds[i].value;
-			CMD_MEM_WRITE(val);
-			break;
-			}
+		case CMD_MEM_READ_8:
+			va = code->cmds[i].addr;
+			memcpy_from_uspace(&val8, va, sizeof(val8));
+			if (dstarg)
+				scratch[dstarg] = val8;
+			break;
+		case CMD_MEM_READ_16:
+			va = code->cmds[i].addr;
+			memcpy_from_uspace(&val16, va, sizeof(val16));
+			if (dstarg)
+				scratch[dstarg] = val16;
+			break;
+		case CMD_MEM_READ_32:
+			va = code->cmds[i].addr;
+			memcpy_from_uspace(&val32, va, sizeof(val32));
+			if (dstarg)
+				scratch[dstarg] = val32;
+			break;
+		case CMD_MEM_WRITE_8:
+			val8 = code->cmds[i].value;
+			va = code->cmds[i].addr;
+			memcpy_to_uspace(va, &val8, sizeof(val8));
+			break;
+		case CMD_MEM_WRITE_16:
+			val16 = code->cmds[i].value;
+			va = code->cmds[i].addr;
+			memcpy_to_uspace(va, &val16, sizeof(val16));
+			break;
+		case CMD_MEM_WRITE_32:
+			val32 = code->cmds[i].value;
+			va = code->cmds[i].addr;
+			memcpy_to_uspace(va, &val32, sizeof(val32));
+			break;
 		case CMD_MEM_WRITE_A_8:
 			if (srcarg) {
-				uint8_t val = scratch[srcarg];
-				CMD_MEM_WRITE(val);
+				val8 = scratch[srcarg];
+				va = code->cmds[i].addr;
+				memcpy_to_uspace(va, &val8, sizeof(val8));
 			}
 			break;
 		case CMD_MEM_WRITE_A_16:
 			if (srcarg) {
-				uint16_t val = scratch[srcarg];
-				CMD_MEM_WRITE(val);
+				val16 = scratch[srcarg];
+				va = code->cmds[i].addr;
+				memcpy_to_uspace(va, &val16, sizeof(val16));
 			}
 			break;
 		case CMD_MEM_WRITE_A_32:
 			if (srcarg) {
-				uint32_t val = scratch[srcarg];
-				CMD_MEM_WRITE(val);
+				val32 = scratch[srcarg];
+				va = code->cmds[i].addr;
+				memcpy_to_uspace(va, &val32, sizeof(val32));
 			}
 			break;
@@ -513,4 +508,5 @@
 		}
 	}
+	
 	if (AS != current_as)
 		as_switch(AS, current_as);
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/src/ipc/sysipc.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -278,5 +278,5 @@
 		}
 	} else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_IN) {
-		if (!IPC_GET_RETVAL(answer->data)) { 
+		if (!IPC_GET_RETVAL(answer->data)) {
 			irq_spinlock_lock(&answer->sender->lock, true);
 			as_t *as = answer->sender->as;
Index: kernel/generic/src/lib/rd.c
===================================================================
--- kernel/generic/src/lib/rd.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/src/lib/rd.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -33,5 +33,5 @@
 /**
  * @file
- * @brief	RAM disk support.
+ * @brief RAM disk support.
  *
  * Support for RAM disk images.
@@ -39,66 +39,31 @@
 
 #include <lib/rd.h>
-#include <byteorder.h>
 #include <mm/frame.h>
 #include <sysinfo/sysinfo.h>
 #include <ddi/ddi.h>
-#include <align.h>
 
-static parea_t rd_parea;		/**< Physical memory area for rd. */
+/** Physical memory area for RAM disk. */
+static parea_t rd_parea;
 
-/**
- * RAM disk initialization routine. At this point, the RAM disk memory is shared
- * and information about the share is provided as sysinfo values to the
- * userspace tasks.
- */  
-int init_rd(rd_header_t *header, size_t size)
+/** RAM disk initialization routine
+ *
+ * The information about the RAM disk is provided as sysinfo
+ * values to the uspace tasks.
+ *
+ */
+void init_rd(void *data, size_t size)
 {
-	/* Identify RAM disk */
-	if ((header->magic[0] != RD_MAG0) || (header->magic[1] != RD_MAG1) ||
-	    (header->magic[2] != RD_MAG2) || (header->magic[3] != RD_MAG3))
-		return RE_INVALID;
+	uintptr_t base = KA2PA((uintptr_t) data);
+	ASSERT((base % FRAME_SIZE) == 0);
 	
-	/* Identify version */	
-	if (header->version != RD_VERSION)
-		return RE_UNSUPPORTED;
-	
-	uint32_t hsize;
-	uint64_t dsize;
-	switch (header->data_type) {
-	case RD_DATA_LSB:
-		hsize = uint32_t_le2host(header->header_size);
-		dsize = uint64_t_le2host(header->data_size);
-		break;
-	case RD_DATA_MSB:
-		hsize = uint32_t_be2host(header->header_size);
-		dsize = uint64_t_be2host(header->data_size);
-		break;
-	default:
-		return RE_UNSUPPORTED;
-	}
-	
-	if ((hsize % FRAME_SIZE) || (dsize % FRAME_SIZE))
-		return RE_UNSUPPORTED;
-		
-	if (hsize > size)
-		return RE_INVALID;
-	
-	if ((uint64_t) hsize + dsize > size)
-		dsize = size - hsize;
-	
-	rd_parea.pbase = ALIGN_DOWN((uintptr_t) KA2PA((void *) header + hsize),
-	    FRAME_SIZE);
-	rd_parea.frames = SIZE2FRAMES(dsize);
+	rd_parea.pbase = base;
+	rd_parea.frames = SIZE2FRAMES(size);
 	rd_parea.unpriv = false;
 	rd_parea.mapped = false;
 	ddi_parea_register(&rd_parea);
-
+	
 	sysinfo_set_item_val("rd", NULL, true);
-	sysinfo_set_item_val("rd.header_size", NULL, hsize);	
-	sysinfo_set_item_val("rd.size", NULL, dsize);
-	sysinfo_set_item_val("rd.address.physical", NULL,
-	    (sysarg_t) KA2PA((void *) header + hsize));
-
-	return RE_OK;
+	sysinfo_set_item_val("rd.size", NULL, size);
+	sysinfo_set_item_val("rd.address.physical", NULL, (sysarg_t) base);
 }
 
Index: kernel/generic/src/main/kinit.c
===================================================================
--- kernel/generic/src/main/kinit.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/src/main/kinit.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -179,5 +179,5 @@
 	for (i = 0; i < init.cnt; i++) {
 		if (init.tasks[i].addr % FRAME_SIZE) {
-			printf("init[%zu].addr is not frame aligned\n", i);
+			printf("init[%zu]: Address is not frame aligned\n", i);
 			programs[i].task = NULL;
 			continue;
@@ -203,22 +203,28 @@
 		    namebuf, &programs[i]);
 		
-		if ((rc == 0) && (programs[i].task != NULL)) {
+		if (rc == 0) {
+			if (programs[i].task != NULL) {
+				/*
+				 * Set capabilities to init userspace tasks.
+				 */
+				cap_set(programs[i].task, CAP_CAP | CAP_MEM_MANAGER |
+				    CAP_IO_MANAGER | CAP_IRQ_REG);
+				
+				if (!ipc_phone_0)
+					ipc_phone_0 = &programs[i].task->answerbox;
+			}
+			
 			/*
-			 * Set capabilities to init userspace tasks.
+			 * If programs[i].task == NULL then it is
+			 * the program loader and it was registered
+			 * successfully.
 			 */
-			cap_set(programs[i].task, CAP_CAP | CAP_MEM_MANAGER |
-			    CAP_IO_MANAGER | CAP_IRQ_REG);
-			
-			if (!ipc_phone_0)
-				ipc_phone_0 = &programs[i].task->answerbox;
-		} else if (rc == 0) {
-			/* It was the program loader and was registered */
-		} else {
-			/* RAM disk image */
-			int rd = init_rd((rd_header_t *) init.tasks[i].addr, init.tasks[i].size);
-			
-			if (rd != RE_OK)
-				printf("Init binary %zu not used (error %d)\n", i, rd);
-		}
+		} else if (i == init.cnt - 1) {
+			/*
+			 * Assume the last task is the RAM disk.
+			 */
+			init_rd((void *) init.tasks[i].addr, init.tasks[i].size);
+		} else
+			printf("init[%zu]: Init binary load failed (error %d)\n", i, rc);
 	}
 	
Index: kernel/generic/src/main/main.c
===================================================================
--- kernel/generic/src/main/main.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/src/main/main.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -268,6 +268,6 @@
 	 * Create the first thread.
 	 */
-	thread_t *kinit_thread
-		= thread_create(kinit, NULL, kernel, 0, "kinit", true);
+	thread_t *kinit_thread =
+	    thread_create(kinit, NULL, kernel, 0, "kinit", true);
 	if (!kinit_thread)
 		panic("Cannot create kinit thread.");
Index: kernel/generic/src/mm/page.c
===================================================================
--- kernel/generic/src/mm/page.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/src/mm/page.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -53,5 +53,5 @@
  * We assume that the other processors are either not using the mapping yet
  * (i.e. during the bootstrap) or are executing the TLB shootdown code.  While
- * we don't care much about the former case, the processors in the latter case 
+ * we don't care much about the former case, the processors in the latter case
  * will do an implicit serialization by virtue of running the TLB shootdown
  * interrupt handler.
@@ -198,34 +198,37 @@
 }
 
+int page_find_mapping(uintptr_t virt, void **phys)
+{
+	mutex_lock(&AS->lock);
+	
+	pte_t *pte = page_mapping_find(AS, virt, false);
+	if ((!PTE_VALID(pte)) || (!PTE_PRESENT(pte))) {
+		mutex_unlock(&AS->lock);
+		return ENOENT;
+	}
+	
+	*phys = (void *) PTE_GET_FRAME(pte) +
+	    (virt - ALIGN_DOWN(virt, PAGE_SIZE));
+	
+	mutex_unlock(&AS->lock);
+	
+	return EOK;
+}
 
 /** Syscall wrapper for getting mapping of a virtual page.
- * 
- * @retval EOK Everything went find, @p uspace_frame and @p uspace_node
- *             contains correct values.
- * @retval ENOENT Virtual address has no mapping.
- */
-sysarg_t sys_page_find_mapping(uintptr_t virt_address,
-    uintptr_t *uspace_frame)
-{
-	mutex_lock(&AS->lock);
-	
-	pte_t *pte = page_mapping_find(AS, virt_address, false);
-	if (!PTE_VALID(pte) || !PTE_PRESENT(pte)) {
-		mutex_unlock(&AS->lock);
-		
-		return (sysarg_t) ENOENT;
-	}
-	
-	uintptr_t phys_address = PTE_GET_FRAME(pte);
-	
-	mutex_unlock(&AS->lock);
-	
-	int rc = copy_to_uspace(uspace_frame,
-	    &phys_address, sizeof(phys_address));
-	if (rc != EOK) {
-		return (sysarg_t) rc;
-	}
-	
-	return EOK;
+ *
+ * @return EOK on success.
+ * @return ENOENT if no virtual address mapping found.
+ *
+ */
+sysarg_t sys_page_find_mapping(uintptr_t virt, void *phys_ptr)
+{
+	void *phys;
+	int rc = page_find_mapping(virt, &phys);
+	if (rc != EOK)
+		return rc;
+	
+	rc = copy_to_uspace(phys_ptr, &phys, sizeof(phys));
+	return (sysarg_t) rc;
 }
 
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision 3b71e84dce17092725ada79fab0ccaf7ded86420)
+++ kernel/generic/src/syscall/syscall.c	(revision 7aaed09d88be49fac8360d3017e3328ed9b0635c)
@@ -176,4 +176,6 @@
 	(syshandler_t) sys_device_assign_devno,
 	(syshandler_t) sys_physmem_map,
+	(syshandler_t) sys_dmamem_map,
+	(syshandler_t) sys_dmamem_unmap,
 	(syshandler_t) sys_iospace_enable,
 	(syshandler_t) sys_register_irq,
