summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MdePkg/Library/BaseLib/Ia32/Thunk16.S205
1 files changed, 184 insertions, 21 deletions
diff --git a/MdePkg/Library/BaseLib/Ia32/Thunk16.S b/MdePkg/Library/BaseLib/Ia32/Thunk16.S
index b3ac412efe..97b49f5a38 100644
--- a/MdePkg/Library/BaseLib/Ia32/Thunk16.S
+++ b/MdePkg/Library/BaseLib/Ia32/Thunk16.S
@@ -11,7 +11,7 @@
#
# Module Name:
#
-# Thunk.asm
+# Thunk16.S
#
# Abstract:
#
@@ -19,26 +19,189 @@
#
#------------------------------------------------------------------------------
-.global _m16Start, _m16Size, _mThunk16Attr, _m16GdtBase, _m16Gdt, _m16GdtrBase, _mTransition
- ##########
- # FIXME! #
- ##########
-# The following data are INVALID!!
-# They just follow GAS syntax.
-_m16Start: .byte 0x00
-_m16Size: .word 0x00
-_mThunk16Attr: .word 0x00
-_m16Gdt: .word 0x00
-_m16GdtrBase: .word 0x00
-_mTransition: .word 0x00
-
+.global _m16Start, _m16Size, _mThunk16Attr, _m16GdtrBase, _m16Gdt, _m16GdtrBase, _mTransition
.global _InternalAsmThunk16
+
+#THUNK_ATTRIBUTE_BIG_REAL_MODE EQU 1
+#THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 EQU 2
+#THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL EQU 4
+
+ .code:
+
+_m16Start:
+
+SavedGdt: .space 6
+
+_BackFromUserCode:
+ push %ss
+ push %cs
+ .byte 0x66
+ call @Base1 # push eip
+@Base1:
+ pushfw # pushfd actually
+ cli # disable interrupts
+ push %gs
+ push %fs
+ push %es
+ push %ds
+ pushaw # pushad actually
+ .byte 0x66,0xba # mov edx, imm32
+_ThunkAttr: .space 4
+ testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl
+ jz @1
+ movl $0x15cd2401, %eax # mov ax, 2401h & int 15h
+ cli # disable interrupts
+ jnc @2
+@1:
+ testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl
+ jz @2
+ inb $0x92, %al
+ orb $2, %al
+ outb %al, $0x92 # deactivate A20M#
+@2:
+ movl %ss, %eax
+ .byte 0x67, 0x66, 0x8d, 0x6c, 0x24, 0x34, 0x66
+ mov %ebp,0xffffffd8(%esi)
+ mov 0xfffffff8(%esi),%ebx
+ shlw $4, %ax # shl eax, 4
+ addw %ax, %bp # add ebp, eax
+ .byte 0x66,0xb8 # mov eax, imm32
+SavedCr4: .space 4
+ movl %eax, %cr4
+ lgdtw %cs:0xfffffff2(%edi)
+ .byte 0x66,0xb8 # mov eax, imm32
+SavedCr0: .space 4
+ movl %eax, %cr0
+ .byte 0xb8 # mov ax, imm16
+SavedSs: .space 2
+ movl %eax, %ss
+ .byte 0x66,0xbc # mov esp, imm32
+SavedEsp: .space 4
+ .byte 0x66
+ lret # return to protected mode
+
+_EntryPoint: .long _ToUserCode - _m16Start
+ .word 0x8
+_16Idtr: .word 0x3ff
+ .long 0
+_16Gdtr: .word GdtEnd - _NullSegDesc - 1
+_16GdtrBase: .long _NullSegDesc
+
+_ToUserCode:
+ movl %ss, %edx
+ movl %ecx, %ss # set new segment selectors
+ movl %ecx, %ds
+ movl %ecx, %es
+ movl %ecx, %fs
+ movl %ecx, %gs
+ movl %eax, %cr0
+ movl %ebp, %cr4 # real mode starts at next instruction
+ movl %esi, %ss # set up 16-bit stack segment
+ xchgw %bx, %sp # set up 16-bit stack pointer
+ .byte 0x66
+ call @Base # push eip
+@Base:
+ popw %bp # ebp <- offset @Base
+ addr16 pushl 36(%si)
+ .byte 0x36
+ lea 0xc(%esi),%eax
+ pushl %eax
+ lret
+
+@RealMode:
+ mov %edx,%cs:0xffffffc5(%esi)
+ mov %bx,%cs:0xffffffcb(%esi)
+ lidtw %cs:0xffffffd7(%esi)
+ popaw # popad actually
+ popl %ds
+ popl %es
+ popl %fs
+ popl %gs
+ popfw # popfd
+ lretw # transfer control to user code
+
+_NullSegDesc: .quad 0
+_16CsDesc:
+ .word -1
+ .word 0
+ .byte 0
+ .byte 0x9b
+ .byte 0x8f # 16-bit segment, 4GB limit
+ .byte 0
+_16DsDesc:
+ .word -1
+ .word 0
+ .byte 0
+ .byte 0x93
+ .byte 0x8f # 16-bit segment, 4GB limit
+ .byte 0
+GdtEnd:
+
+#
+# @param RegSet Pointer to a IA32_DWORD_REGS structure
+# @param Transition Pointer to the transition code
+# @return The address of the 16-bit stack after returning from user code
+#
_InternalAsmThunk16:
+ push %ebp
+ push %ebx
+ push %esi
+ push %edi
+ push %ds
+ push %es
+ push %fs
+ push %gs
+ movl 36(%esp), %esi # esi <- RegSet
+ movzwl 0x32(%esi),%edx
+ mov 0xc(%esi),%edi
+ add $0xffffffc8,%edi
+ movl %edi, %ebx # ebx <- stack offset
+ imul $0x10,%edx,%eax
+ push $0xd
+ addl %eax, %edi # edi <- linear address of 16-bit stack
+ popl %ecx
+ rep
+ movsl # copy RegSet
+ movl 40(%esp), %eax # eax <- address of transition code
+ movl %edx, %esi # esi <- 16-bit stack segment
+ lea 0x5e(%eax),%edx
+ movl %eax, %ecx
+ andl $0xf, %ecx
+ shll $12, %eax
+ lea 0x6(%ecx),%ecx
+ movw %cx, %ax
+ stosl # [edi] <- return address of user code
+ sgdtl 0xffffffa2(%edx)
+ sidtl 0x24(%esp)
+ movl %cr0, %eax
+ movl %eax, (%edx) # save CR0 in SavedCr0
+ andl $0x7ffffffe, %eax # clear PE, PG bits
+ movl %cr4, %ebp
+ mov %ebp,0xfffffff1(%edx)
+ andl $0x300, %ebp # clear all but PCE and OSFXSR bits
+ pushl $0x10
+ popl %ecx # ecx <- selector for data segments
+ lgdtl 0x20(%edx)
+ pushfl
+ lcall *0x14(%edx)
+ popfl
+ lidtl 0x24(%esp)
+ lea 0xffffffcc(%ebp),%eax
+ pop %gs
+ pop %fs
+ pop %es
+ pop %ds
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %ebp
+ ret
+
+ .const:
+
+_m16Size: .word _InternalAsmThunk16 - _m16Start
+_mThunk16Attr: .word _ThunkAttr - _m16Start
+_m16Gdt: .word _NullSegDesc - _m16Start
+_m16GdtrBase: .word _16GdtrBase - _m16Start
+_mTransition: .word _EntryPoint - _m16Start
- ##########
- # FIXME! #
- ##########
- # This function won't work for now.
- # it will directly enter dead loop.
- jmp .
- \ No newline at end of file