elilo/ia32/rmswitch.S

119 lines
1.7 KiB
ArmAsm

#
# 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