diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 7898cbc..57bbccd 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -32,7 +32,79 @@
 #define ATAG_CORE 0x54410001
 #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
 
+/*
+ * debug macros, while the MMU is of
+ */
+.macro	pix_ok /* blue */
+#ifdef CONFIG_EFB_DEBUG
+	mov	r12, #0x0014
+	add	r12, r12, #0x00140000
+	str	r12, [r11]
+	add	r11, r11, #4
+	str	r12, [r11]
+	add	r11, r11, #4
+	str	r12, [r11]
+	add	r11, r11, #4
+	str	r12, [r11]
+	add	r11, r11, #4
+	add	r11, r11, #4
+#endif
+.endm
+	
+.macro	pix_ko /* red */
+#ifdef CONFIG_EFB_DEBUG
+	mov	r12, #0xF800
+	add	r12, r12, #0xF8000000
+	str	r12, [r11]
+	add	r11, r11, #4
+	str	r12, [r11]
+	add	r11, r11, #4
+	str	r12, [r11]
+	add	r11, r11, #4
+	str	r12, [r11]
+	add	r11, r11, #4
+	add	r11, r11, #4
+#endif
+.endm
 
+.macro	pix_ctr /* white */
+#ifdef CONFIG_EFB_DEBUG
+	mov	r12, #-1
+	str	r12, [r11]
+	add	r11, r11, #4
+	str	r12, [r11]
+	add	r11, r11, #4
+	str	r12, [r11]
+	add	r11, r11, #4
+	str	r12, [r11]
+	add	r11, r11, #4
+	add	r11, r11, #4
+#endif
+.endm
+	
+/*
+ * a more mmu aware code: the frame buffer is mapped at 0xD0001020,
+ * see arch/arm/mach-omap/debug.c
+ */
+.macro pix_mmu /* black pixel */
+#ifdef CONFIG_EFB_DEBUG
+	mov	r11, #0xD0000000
+	add	r11, r11, #0x1000
+	add	r11, r11, #0x20
+/*	mov     r12, #0x00FF */
+/* 	add     r12, r12, #0x00FF0000 */
+	mov	r12, #0
+	str     r12, [r11]
+	add     r11, r11, #4
+	str     r12, [r11]
+	add     r11, r11, #4
+	str     r12, [r11]
+	add     r11, r11, #4
+	str     r12, [r11]
+	add     r11, r11, #4
+#endif
+.endm
+	
 /*
  * swapper_pg_dir is the virtual address of the initial page table.
  * We place the page tables 16K below KERNEL_RAM_VADDR.  Therefore, we must
@@ -80,15 +152,22 @@
 	.section ".text.head", "ax"
 	.type	stext, %function
 ENTRY(stext)
+	pix_ok
 	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
 						@ and irqs disabled
 	mrc	p15, 0, r9, c0, c0		@ get processor id
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
 	movs	r10, r5				@ invalid processor (r5=0)?
 	beq	__error_p			@ yes, error 'p'
+
+	pix_ok
+
 	bl	__lookup_machine_type		@ r5=machinfo
 	movs	r8, r5				@ invalid machine (r5=0)?
 	beq	__error_a			@ yes, error 'a'
+
+	pix_ok
+
 	bl	__vet_atags
 	bl	__create_page_tables
 
@@ -192,11 +271,17 @@ __enable_mmu:
 	.align	5
 	.type	__turn_mmu_on, %function
 __turn_mmu_on:
+
+	pix_ok
+
 	mov	r0, r0
 	mcr	p15, 0, r0, c1, c0, 0		@ write control reg
 	mrc	p15, 0, r3, c0, c0, 0		@ read id reg
 	mov	r3, r3
 	mov	r3, r3
+
+	pix_mmu
+
 	mov	pc, r13
 
 
@@ -327,6 +412,18 @@ __create_page_tables:
 	str	r3, [r0]
 #endif
 #endif
+
+#ifdef CONFIG_EFB_DEBUG
+	/*
+	 * map frame buffer from 0x10000000 to 0xD0000000
+	 * in order to help debugging
+	 */
+	add	r0, r4, #0xD0000000 >> 18
+	mov	r3, #0x10000000
+	add	r3, r3, r7
+	str	r3, [r0]
+#endif
+
 	mov	pc, lr
 	.ltorg
 
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 4de432e..b2072a8 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -33,6 +33,8 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
+#include <asm/arch/efb.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
@@ -814,6 +816,16 @@ void __init setup_arch(char **cmdline_p)
 	memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
 	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 	parse_cmdline(cmdline_p, from);
+
+#ifdef CONFIG_EFB_DEBUG
+	/*
+	 * paging_init is going to wipe out any section other than the
+	 * kernel code and data allocated in head.S so the framebuffer
+	 * is going not to be available during paging_init.
+	 */
+	efb_disable();
+#endif
+
 	paging_init(&meminfo, mdesc);
 	request_standard_resources(&meminfo, mdesc);
 
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index fc1d2fd..f18404c 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -59,6 +59,12 @@ config MSM_HW3D
 	  Provides access to registers and interrupts needed by
 	  the userspace 3D library.
 
+config EFB_DEBUG
+	bool "Early Frame Buffer debugging routines"
+	depends on MACH_HTCKAISER
+	help
+	  Output in the framebuffer of the HTC phones as early as possible.
+
 config KAISER_LCD
 	tristate "HTC Kaiser VSFB LCD support"
 	depends on MACH_HTCKAISER && LCD_CLASS_DEVICE
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 11d786d..80c6e0c 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -11,5 +11,5 @@ obj-$(CONFIG_MSM_SMD_RPC_ROUTER) += smd_rpcrouter.o
 obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
 obj-$(CONFIG_MSM_HW3D) += hw3d.o
 
+obj-$(CONFIG_EFB_DEBUG) += efb.o efb-font5x5.o
 obj-$(CONFIG_HTCKAISER_LCD) += htckaiser_lcd.o
-
diff --git a/arch/arm/mach-msm/board-htckaiser.c b/arch/arm/mach-msm/board-htckaiser.c
index d384a2d..52c6141 100644
--- a/arch/arm/mach-msm/board-htckaiser.c
+++ b/arch/arm/mach-msm/board-htckaiser.c
@@ -26,6 +26,7 @@
 #include <asm/mach/flash.h>
 
 #include <asm/arch/board.h>
+#include <asm/arch/efb.h>
 
 #include <asm/io.h>
 #include <asm/delay.h>
@@ -125,6 +126,10 @@ static void __init htckaiser_map_io(void)
 	printk("ktckaiser_init_map_io()\n");
 	msm_pmrr_config();
 	iotable_init(msm_io_desc, ARRAY_SIZE(msm_io_desc));
+
+#ifdef CONFIG_EFB_DEBUG
+	efb_enable();
+#endif
 }
 
 MACHINE_START(HTCKAISER, "HTC Kaiser")

