223 lines
4.3 KiB
ArmAsm
223 lines
4.3 KiB
ArmAsm
/*
|
|
* (C) Copyright 2002
|
|
* Daniel Engstrรถm, Omicron Ceti AB, daniel@omicron.se
|
|
*
|
|
* See file CREDITS for list of people who contributed to this
|
|
* project.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*/
|
|
|
|
|
|
/* 32bit -> 16bit -> 32bit mode switch code */
|
|
|
|
/*
|
|
* Stack frame at 0xe00
|
|
* e00 ebx;
|
|
* e04 ecx;
|
|
* e08 edx;
|
|
* e0c esi;
|
|
* e10 edi;
|
|
* e14 ebp;
|
|
* e18 eax;
|
|
* e1c ds;
|
|
* e20 es;
|
|
* e24 fs;
|
|
* e28 gs;
|
|
* e2c orig_eax;
|
|
* e30 eip;
|
|
* e34 cs;
|
|
* e38 eflags;
|
|
* e3c esp;
|
|
* e40 ss;
|
|
*/
|
|
|
|
#define a32 .byte 0x67; /* address size prefix 32 */
|
|
#define o32 .byte 0x66; /* operand size prefix 32 */
|
|
|
|
.section .realmode, "ax"
|
|
.code16
|
|
/* 16bit protected mode code here */
|
|
.globl realmode_enter
|
|
realmode_enter:
|
|
o32 pusha
|
|
o32 pushf
|
|
cli
|
|
sidt saved_idt
|
|
sgdt saved_gdt
|
|
movl %esp, %eax
|
|
movl %eax, saved_protected_mode_esp
|
|
|
|
movl $0x10, %eax
|
|
movl %eax, %esp
|
|
movw $0x28, %ax
|
|
movw %ax, %ds
|
|
movw %ax, %es
|
|
movw %ax, %fs
|
|
movw %ax, %gs
|
|
|
|
lidt realmode_idt_ptr
|
|
movl %cr0, %eax /* Go back into real mode by */
|
|
andl $0x7ffffffe, %eax /* clearing PE to 0 */
|
|
movl %eax, %cr0
|
|
ljmp $0x0,$do_realmode /* switch to real mode */
|
|
|
|
do_realmode: /* realmode code from here */
|
|
movw %cs,%ax
|
|
movw %ax,%ds
|
|
movw %ax,%es
|
|
movw %ax,%fs
|
|
movw %ax,%gs
|
|
|
|
/* create a temporary stack */
|
|
|
|
movw $0xc0, %ax
|
|
movw %ax, %ss
|
|
movw $0x200, %ax
|
|
movw %ax, %sp
|
|
|
|
popl %ebx
|
|
popl %ecx
|
|
popl %edx
|
|
popl %esi
|
|
popl %edi
|
|
popl %ebp
|
|
popl %eax
|
|
movl %eax, temp_eax
|
|
popl %eax
|
|
movw %ax, %ds
|
|
popl %eax
|
|
movw %ax, %es
|
|
popl %eax
|
|
movw %ax, %fs
|
|
popl %eax
|
|
movw %ax, %gs
|
|
popl %eax /* orig_eax */
|
|
popl %eax
|
|
cs movw %ax, temp_ip
|
|
popl %eax
|
|
cs movw %ax, temp_cs
|
|
o32 popf
|
|
popl %eax
|
|
popw %ss
|
|
movl %eax, %esp
|
|
cs movl temp_eax, %eax
|
|
wbinvd /* self-modifying code,
|
|
* better flush the cache */
|
|
|
|
.byte 0x9a /* lcall */
|
|
temp_ip:
|
|
.word 0 /* new ip */
|
|
temp_cs:
|
|
.word 0 /* new cs */
|
|
realmode_ret:
|
|
/* save eax, esp and ss */
|
|
cs movl %eax, saved_eax
|
|
movl %esp, %eax
|
|
cs movl %eax, saved_esp
|
|
movw %ss, %ax
|
|
cs movw %ax, saved_ss
|
|
|
|
/* restore the stack, note that we set sp to 0x244;
|
|
* pt_regs is 0x44 bytes long and we push the structure
|
|
* backwards on to the stack, bottom first */
|
|
|
|
movw $0xc0, %ax
|
|
movw %ax, %ss
|
|
movw $0x244, %ax
|
|
movw %ax, %sp
|
|
|
|
xorl %eax,%eax
|
|
cs movw saved_ss, %ax
|
|
pushl %eax
|
|
cs movl saved_esp, %eax
|
|
pushl %eax
|
|
o32 pushf
|
|
xorl %eax,%eax
|
|
cs movw temp_cs, %ax
|
|
pushl %eax
|
|
cs movw temp_ip, %ax
|
|
pushl %eax
|
|
pushl $0
|
|
movw %gs, %ax
|
|
pushl %eax
|
|
movw %fs, %ax
|
|
pushl %eax
|
|
movw %es, %ax
|
|
pushl %eax
|
|
movw %ds, %ax
|
|
pushl %eax
|
|
movl saved_eax, %eax
|
|
pushl %eax
|
|
pushl %ebp
|
|
pushl %edi
|
|
pushl %esi
|
|
pushl %edx
|
|
pushl %ecx
|
|
pushl %ebx
|
|
|
|
o32 cs lidt saved_idt
|
|
o32 cs lgdt saved_gdt /* Set GDTR */
|
|
|
|
movl %cr0, %eax /* Go back into protected mode */
|
|
orl $1,%eax /* reset PE to 1 */
|
|
movl %eax, %cr0
|
|
jmp next_line /* flush prefetch queue */
|
|
next_line:
|
|
movw $return_ptr, %ax
|
|
movw %ax,%bp
|
|
o32 cs ljmp *(%bp)
|
|
|
|
.code32
|
|
protected_mode:
|
|
movl $0x18,%eax /* reload GDT[3] */
|
|
movw %ax,%fs /* reset FS */
|
|
movw %ax,%ds /* reset DS */
|
|
movw %ax,%gs /* reset GS */
|
|
movw %ax,%es /* reset ES */
|
|
movw %ax,%ss /* reset SS */
|
|
movl saved_protected_mode_esp, %eax
|
|
movl %eax, %esp
|
|
popf
|
|
popa
|
|
ret
|
|
|
|
temp_eax:
|
|
.long 0
|
|
|
|
saved_ss:
|
|
.word 0
|
|
saved_esp:
|
|
.long 0
|
|
saved_eax:
|
|
.long 0
|
|
|
|
realmode_idt_ptr:
|
|
.word 0x400
|
|
.word 0x0, 0x0
|
|
|
|
saved_gdt:
|
|
.word 0, 0, 0, 0
|
|
saved_idt:
|
|
.word 0, 0, 0, 0
|
|
|
|
saved_protected_mode_esp:
|
|
.long 0
|
|
|
|
return_ptr:
|
|
.long protected_mode
|
|
.word 0x10
|