Index: kernel/arch/amd64/Makefile.inc
===================================================================
--- kernel/arch/amd64/Makefile.inc	(revision fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/arch/amd64/Makefile.inc	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/arch/amd64/include/arch.h	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/arch/amd64/include/boot/boot.h	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/arch/amd64/src/amd64.c	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -41,7 +41,8 @@
 #include <proc/thread.h>
 #include <genarch/multiboot/multiboot.h>
+#include <genarch/multiboot/multiboot2.h>
 #include <genarch/drivers/legacy/ia32/io.h>
 #include <genarch/drivers/ega/ega.h>
-#include <arch/drivers/vesa.h>
+#include <genarch/fb/bfb.h>
 #include <genarch/drivers/i8042/i8042.h>
 #include <genarch/kbrd/kbrd.h>
@@ -101,11 +102,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 +156,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)
Index: kernel/arch/amd64/src/boot/boot.S
===================================================================
--- kernel/arch/amd64/src/boot/boot.S	(revision fb48a0e907656015204723ad5eead3719f29242e)
+++ 	(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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/arch/amd64/src/boot/memmap.c	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
+++ kernel/arch/amd64/src/boot/multiboot.S	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
+++ kernel/arch/amd64/src/boot/multiboot2.S	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -0,0 +1,253 @@
+/*
+ * 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
+		.long MULTIBOOT2_TAG_FBINFO
+	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:
+	
+	/* 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:
+	
+	/* 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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/arch/ia32/Makefile.inc	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -106,6 +106,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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/arch/ia32/include/arch.h	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/arch/ia32/include/boot/boot.h	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 fb48a0e907656015204723ad5eead3719f29242e)
+++ 	(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 fb48a0e907656015204723ad5eead3719f29242e)
+++ 	(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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/arch/ia32/src/boot/memmap.c	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
+++ kernel/arch/ia32/src/boot/multiboot.S	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
+++ kernel/arch/ia32/src/boot/multiboot2.S	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -0,0 +1,176 @@
+/*
+ * 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
+		.long MULTIBOOT2_TAG_FBINFO
+	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:
+	
+	/* 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:
+	
+	/* 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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/arch/ia32/src/boot/vesa_prot.inc	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/arch/ia32/src/boot/vesa_real.inc	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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
+		
+		xor %eax, %eax
+		xor %ebx, %ebx
+		xor %edx, %edx
 		mov $0xffffffff, %edi
-		xor %ax, %ax
+		
 		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 fb48a0e907656015204723ad5eead3719f29242e)
+++ 	(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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/arch/ia32/src/ia32.c	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -42,7 +42,8 @@
 
 #include <genarch/multiboot/multiboot.h>
+#include <genarch/multiboot/multiboot2.h>
 #include <genarch/drivers/legacy/ia32/io.h>
 #include <genarch/drivers/ega/ega.h>
-#include <arch/drivers/vesa.h>
+#include <genarch/fb/bfb.h>
 #include <genarch/drivers/i8042/i8042.h>
 #include <genarch/kbrd/kbrd.h>
@@ -76,11 +77,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 +117,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)
Index: kernel/genarch/Makefile.inc
===================================================================
--- kernel/genarch/Makefile.inc	(revision fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/genarch/Makefile.inc	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
+++ kernel/genarch/include/fb/bfb.h	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/genarch/include/multiboot/multiboot.h	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
+++ kernel/genarch/include/multiboot/multiboot2.h	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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/fb/bfb.c
===================================================================
--- kernel/genarch/src/fb/bfb.c	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
+++ kernel/genarch/src/fb/bfb.c	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -0,0 +1,102 @@
+/*
+ * 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 = (uintptr_t) -1;
+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_width == 0) || (bfb_height == 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 fb48a0e907656015204723ad5eead3719f29242e)
+++ kernel/genarch/src/multiboot/multiboot.c	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -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 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
+++ kernel/genarch/src/multiboot/multiboot2.c	(revision 8d2cd8ba26540466897f4a3bc31c276fd9cd3cd4)
@@ -0,0 +1,132 @@
+/*
+ * 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)
+{
+	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;
+	}
+}
+
+/** 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);
+	}
+}
+
+/** @}
+ */
