Imported Upstream version 3.7
[debian/elilo] / x86_64 / rmswitch.S
diff --git a/x86_64/rmswitch.S b/x86_64/rmswitch.S
new file mode 100644 (file)
index 0000000..24fd402
--- /dev/null
@@ -0,0 +1,118 @@
+#
+# 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