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