--- /dev/null
+#
+# Switch from protected mode to real mode and jump to setup.S
+# image located at %cx:0.
+#
+# This module must be placed into physical memory at 0:7C00h.
+# EFI has some real mode thunking code at 2000:0h.
+#
+# Processor and non-maskable interrupts should be disabled
+# before control is passed to this module.
+#
+
+.global _start
+
+.code32
+.text
+_start:
+ #
+ # Load identity mapped GDT & real mode IDT.
+ # Add 7C00h to the addresses since this is linked to start
+ # at 0h and it is being placed at 7C00h.
+ #
+
+ lgdt %cs:gdt_48 + 0x7C00
+ lidt %cs:idt_48 + 0x7C00
+
+ #
+ # Turn off PG bit in CR0 and set CR3 to zero.
+ #
+
+ movl %cr0, %eax
+ andl $0x7FFFFFFF, %eax
+ movl %eax, %cr0
+
+ xorl %eax, %eax
+ movl %eax, %cr3
+
+ #
+ # Reload CS.
+ # Now we add 7B00h because we need to force the segment
+ # address and selector to be the same.
+ #
+
+ .byte 0xEA
+ .long pm_reload + 0x7B00
+ .word 0x10
+
+pm_reload:
+
+.code16
+
+ #
+ # Reload DS, ES, FS, GS & SS.
+ #
+
+ movw $0x18, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ #
+ # Switch to real mode. Clear PE bit in CR0.
+ #
+
+ movl %cr0, %eax
+ andl $0xFFFFFFFE, %eax
+ movl %eax, %cr0
+
+ #
+ # Reload CS.
+ #
+
+ .byte 0xEA
+ .word rm_reload + 0x7C00
+ .word 0
+
+rm_reload:
+
+ #
+ # Reload SS & SP.
+ #
+
+ xorw %ax, %ax
+ movw %ax, %ss
+ movw $0x7BFE, %sp
+
+ #
+ # Start running setup.S
+ #
+
+ .byte 0xEA
+ .word 0
+ .word 0x9020
+
+ #
+ # GDT & IDT stuff for switching into real mode.
+ #
+
+gdt: .word 0, 0, 0, 0 # unused (00h)
+ .word 0, 0, 0, 0 # dummy (08h)
+ .word 0xFFFF, 0x100 # code (10h)
+ .word 0x9A00, 0
+ .word 0xFFFF, 0x180 # data (18h)
+ .word 0x9200, 0
+
+gdt_48: .word 0x08 * 0x400
+ .long gdt + 0x7C00
+
+idt_48: .word 0x400
+ .long 0
+
+ #
+ # Be careful not to exceed 1F0h or the the bootsect.S
+ # parameters will be lost!
+ #
+
+.end