mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
[HAL]: Rewrite all V8086-related code in C instead of ASM. Delete v86.s. Makes uses of new macros and developments in NTOS, but should now only end up getting called at shutdown and for bugchecks.
svn path=/trunk/; revision=45272
This commit is contained in:
parent
842d2aa5f9
commit
92df9a6434
4 changed files with 334 additions and 457 deletions
|
@ -41,6 +41,270 @@ PUSHORT HalpSavedIoMap;
|
|||
USHORT HalpSavedIoMapData[32][2];
|
||||
ULONG HalpSavedIoMapEntries;
|
||||
|
||||
/* Where the protected mode stack is */
|
||||
ULONG_PTR HalpSavedEsp;
|
||||
|
||||
/* Where the real mode code ends */
|
||||
extern PVOID HalpRealModeEnd;
|
||||
|
||||
/* REAL MODE CODE AND STACK START HERE ****************************************/
|
||||
|
||||
VOID
|
||||
DECLSPEC_NORETURN
|
||||
HalpRealModeStart(VOID)
|
||||
{
|
||||
/* Do the video BIOS interrupt */
|
||||
HalpCallBiosInterrupt(VIDEO_SERVICES, (SET_VIDEO_MODE << 8) | (GRAPHICS_MODE_12));
|
||||
|
||||
/* Issue the BOP */
|
||||
KiIssueBop();
|
||||
|
||||
/* We want the stack to be inside this function so we can map real mode */
|
||||
HalpRealModeStack(sizeof(ULONG), PAGE_SIZE / 2);
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
/* REAL MODE CODE AND STACK END HERE ******************************************/
|
||||
|
||||
/* V86 OPCODE HANDLERS ********************************************************/
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
HalpOpcodeInvalid(IN PHAL_BIOS_FRAME BiosFrame)
|
||||
{
|
||||
/* Print error message */
|
||||
DPRINT1("HAL: An invalid V86 opcode was encountered at address %x:%x\n",
|
||||
BiosFrame->SegCs, BiosFrame->Eip);
|
||||
|
||||
/* Break */
|
||||
DbgBreakPoint();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
HalpPushInt(IN PHAL_BIOS_FRAME BiosFrame,
|
||||
IN ULONG Interrupt)
|
||||
{
|
||||
PUSHORT Stack;
|
||||
ULONG Eip;
|
||||
|
||||
/* Calculate stack address (SP) */
|
||||
Stack = (PUSHORT)(BiosFrame->SsBase + (BiosFrame->Esp & 0xFFFF));
|
||||
|
||||
/* Push EFlags */
|
||||
Stack--;
|
||||
*Stack = BiosFrame->EFlags & 0xFFFF;
|
||||
|
||||
/* Push CS */
|
||||
Stack--;
|
||||
*Stack = BiosFrame->SegCs & 0xFFFF;
|
||||
|
||||
/* Push IP */
|
||||
Stack--;
|
||||
*Stack = BiosFrame->Eip & 0xFFFF;
|
||||
|
||||
/* Compute new CS:IP from the IVT address for this interrupt entry */
|
||||
Eip = *(PULONG)(Interrupt * 4);
|
||||
BiosFrame->Eip = Eip & 0xFFFF;
|
||||
BiosFrame->SegCs = Eip >> 16;
|
||||
|
||||
/* Update stack address */
|
||||
BiosFrame->Esp = (ULONG_PTR)Stack & 0xFFFF;
|
||||
|
||||
/* Update CS to linear */
|
||||
BiosFrame->CsBase = BiosFrame->SegCs << 4;
|
||||
BiosFrame->CsLimit = 0xFFFF;
|
||||
BiosFrame->CsFlags = 0;
|
||||
|
||||
/* We're done */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
HalpOpcodeINTnn(IN PHAL_BIOS_FRAME BiosFrame)
|
||||
{
|
||||
UCHAR Interrupt;
|
||||
PKTRAP_FRAME TrapFrame;
|
||||
|
||||
/* Convert SS to linear */
|
||||
BiosFrame->SsBase = BiosFrame->SegSs << 4;
|
||||
BiosFrame->SsLimit = 0xFFFF;
|
||||
BiosFrame->SsFlags = 0;
|
||||
|
||||
/* Increase EIP and validate */
|
||||
BiosFrame->Eip++;
|
||||
if (BiosFrame->Eip > BiosFrame->CsLimit) return FALSE;
|
||||
|
||||
/* Read interrupt number */
|
||||
Interrupt = *(PUCHAR)(BiosFrame->CsBase + BiosFrame->Eip);
|
||||
|
||||
/* Increase EIP and push the interrupt */
|
||||
BiosFrame->Eip++;
|
||||
if (HalpPushInt(BiosFrame, Interrupt))
|
||||
{
|
||||
/* Update the trap frame */
|
||||
TrapFrame = BiosFrame->TrapFrame;
|
||||
TrapFrame->HardwareSegSs = BiosFrame->SegSs;
|
||||
TrapFrame->HardwareEsp = BiosFrame->Esp;
|
||||
TrapFrame->SegCs = BiosFrame->SegCs;
|
||||
TrapFrame->EFlags = BiosFrame->EFlags;
|
||||
|
||||
/* Success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Failure */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
HalpDispatchV86Opcode(IN PKTRAP_FRAME TrapFrame)
|
||||
{
|
||||
UCHAR Instruction;
|
||||
HAL_BIOS_FRAME BiosFrame;
|
||||
|
||||
/* Fill out the BIOS frame */
|
||||
BiosFrame.TrapFrame = TrapFrame;
|
||||
BiosFrame.SegSs = TrapFrame->HardwareSegSs;
|
||||
BiosFrame.Esp = TrapFrame->HardwareEsp;
|
||||
BiosFrame.EFlags = TrapFrame->EFlags;
|
||||
BiosFrame.SegCs = TrapFrame->SegCs;
|
||||
BiosFrame.Eip = TrapFrame->Eip;
|
||||
BiosFrame.Prefix = 0;
|
||||
|
||||
/* Convert CS to linear */
|
||||
BiosFrame.CsBase = BiosFrame.SegCs << 4;
|
||||
BiosFrame.CsLimit = 0xFFFF;
|
||||
BiosFrame.CsFlags = 0;
|
||||
|
||||
/* Validate IP */
|
||||
if (BiosFrame.Eip > BiosFrame.CsLimit) return FALSE;
|
||||
|
||||
/* Read IP */
|
||||
Instruction = *(PUCHAR)(BiosFrame.CsBase + BiosFrame.Eip);
|
||||
if (Instruction != 0xCD)
|
||||
{
|
||||
/* We only support INT */
|
||||
HalpOpcodeInvalid(&BiosFrame);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Handle the interrupt */
|
||||
if (HalpOpcodeINTnn(&BiosFrame))
|
||||
{
|
||||
/* Update EIP */
|
||||
TrapFrame->Eip = BiosFrame.Eip;
|
||||
|
||||
/* We're done */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Failure */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* V86 TRAP HANDLERS **********************************************************/
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DECLSPEC_NORETURN
|
||||
HalpTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
|
||||
{
|
||||
/* Enter the trap */
|
||||
KiEnterTrap(TrapFrame);
|
||||
|
||||
/* Check if this is a V86 trap */
|
||||
if (TrapFrame->EFlags & EFLAGS_V86_MASK)
|
||||
{
|
||||
/* Dispatch the opcode and exit the trap */
|
||||
HalpDispatchV86Opcode(TrapFrame);
|
||||
KiEoiHelper(TrapFrame);
|
||||
}
|
||||
|
||||
/* Strange, it isn't! This can happen during NMI */
|
||||
DPRINT1("HAL: Trap0D while not in V86 mode\n");
|
||||
while (TRUE);
|
||||
}
|
||||
|
||||
KiTrap(HalpTrap0D, 0);
|
||||
|
||||
VOID
|
||||
DECLSPEC_NORETURN
|
||||
HalpTrap06(VOID)
|
||||
{
|
||||
PKTRAP_FRAME TrapFrame;
|
||||
|
||||
/* Restore ES/DS to known good values first */
|
||||
Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
|
||||
Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
|
||||
|
||||
/* Read trap frame address */
|
||||
TrapFrame = (PKTRAP_FRAME)HalpSavedEsp;
|
||||
|
||||
/* Restore segments from the trap frame */
|
||||
Ke386SetGs(TrapFrame->SegGs);
|
||||
Ke386SetFs(TrapFrame->SegFs);
|
||||
Ke386SetEs(TrapFrame->SegEs);
|
||||
Ke386SetDs(TrapFrame->SegDs);
|
||||
|
||||
/* Restore EFlags */
|
||||
__writeeflags(TrapFrame->EFlags);
|
||||
|
||||
/* Exit the V86 mode trap frame */
|
||||
KiCallReturn(TrapFrame);
|
||||
}
|
||||
|
||||
/* V8086 ENTER ****************************************************************/
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DECLSPEC_NORETURN
|
||||
HalpBiosCallHandler(IN PKTRAP_FRAME TrapFrame)
|
||||
{
|
||||
/* Must be volatile so it doesn't get optimized away! */
|
||||
volatile KTRAP_FRAME V86TrapFrame;
|
||||
ULONG_PTR StackOffset, CodeOffset;
|
||||
|
||||
/* Fill out the quick-n-dirty trap frame */
|
||||
TrapFrame->EFlags = __readeflags();
|
||||
TrapFrame->SegGs = Ke386GetGs();
|
||||
TrapFrame->SegFs = Ke386GetFs();
|
||||
TrapFrame->SegEs = Ke386GetEs();
|
||||
TrapFrame->SegDs = Ke386GetDs();
|
||||
|
||||
/* Our stack (the frame) */
|
||||
HalpSavedEsp = (ULONG_PTR)TrapFrame;
|
||||
|
||||
/* Kill alignment faults */
|
||||
__writecr0(__readcr0() & ~CR0_AM);
|
||||
|
||||
/* Set new stack address */
|
||||
KeGetPcr()->TSS->Esp0 = HalpSavedEsp - sizeof(FX_SAVE_AREA);
|
||||
|
||||
/* Compute segmented IP and SP offsets */
|
||||
StackOffset = (ULONG_PTR)&HalpRealModeEnd - 4 - (ULONG_PTR)HalpRealModeStart;
|
||||
CodeOffset = (ULONG_PTR)HalpRealModeStart & 0xFFF;
|
||||
|
||||
/* Now build the V86 trap frame */
|
||||
V86TrapFrame.V86Es = 0;
|
||||
V86TrapFrame.V86Ds = 0;
|
||||
V86TrapFrame.V86Gs = 0;
|
||||
V86TrapFrame.V86Fs = 0;
|
||||
V86TrapFrame.HardwareSegSs = 0x2000;
|
||||
V86TrapFrame.HardwareEsp = StackOffset + CodeOffset;
|
||||
V86TrapFrame.EFlags = __readeflags() | EFLAGS_V86_MASK | EFLAGS_IOPL;
|
||||
V86TrapFrame.SegCs = 0x2000;
|
||||
V86TrapFrame.Eip = CodeOffset;
|
||||
|
||||
/* Exit to V86 mode */
|
||||
KiDirectTrapReturn((PKTRAP_FRAME)&V86TrapFrame);
|
||||
}
|
||||
|
||||
KiTrampoline(HalpBiosCall, KI_PUSH_FAKE_ERROR_CODE | KI_NONVOLATILES_ONLY);
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID
|
||||
|
|
|
@ -1,435 +0,0 @@
|
|||
/*
|
||||
* FILE: hal/halx86/generic/bios.S
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PURPOSE: V8086 Real-Mode BIOS Thunking
|
||||
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <asm.h>
|
||||
#include <internal/i386/asmmacro.S>
|
||||
.intel_syntax noprefix
|
||||
|
||||
//
|
||||
// HAL BIOS Frame
|
||||
//
|
||||
#define HALP_BIOS_FRAME_SS 0x00
|
||||
#define HALP_BIOS_FRAME_ESP 0x04
|
||||
#define HALP_BIOS_FRAME_EFLAGS 0x08
|
||||
#define HALP_BIOS_FRAME_CS 0x0C
|
||||
#define HALP_BIOS_FRAME_EIP 0x10
|
||||
#define HALP_BIOS_FRAME_TRAP_FRAME 0x14
|
||||
#define HALP_BIOS_FRAME_CS_LIMIT 0x18
|
||||
#define HALP_BIOS_FRAME_CS_BASE 0x1C
|
||||
#define HALP_BIOS_FRAME_CS_FLAGS 0x20
|
||||
#define HALP_BIOS_FRAME_SS_LIMIT 0x24
|
||||
#define HALP_BIOS_FRAME_SS_BASE 0x28
|
||||
#define HALP_BIOS_FRAME_SS_FLAGS 0x2C
|
||||
#define HALP_BIOS_FRAME_PREFIX 0x30
|
||||
#define HALP_BIOS_FRAME_LENGTH 0x34
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
_HalpSavedEsp:
|
||||
.long 0
|
||||
|
||||
_InvalidMsg:
|
||||
.asciz "HAL: An invalid V86 opcode was encountered at address %x:%x\n"
|
||||
|
||||
_InvalidGpfMsg:
|
||||
.asciz "HAL: Trap0D while not in V86 mode\n"
|
||||
|
||||
_UnhandledMsg:
|
||||
.asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx [%s]!!!\n"
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
.globl _HalpBiosCall@0
|
||||
.func HalpBiosCall@0
|
||||
_HalpBiosCall@0:
|
||||
|
||||
/* Set up stack pointer */
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
/* Build a trap frame */
|
||||
pushfd
|
||||
push edi
|
||||
push esi
|
||||
push ebx
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
push offset _HalpRealModeEnd
|
||||
|
||||
/* Save the stack */
|
||||
mov _HalpSavedEsp, esp
|
||||
|
||||
/* Turn off alignment faults */
|
||||
mov eax, cr0
|
||||
and eax, ~CR0_AM
|
||||
mov cr0, eax
|
||||
|
||||
/* Setup a new stack */
|
||||
mov esi, fs:KPCR_TSS
|
||||
mov eax, esp
|
||||
sub eax, NPX_FRAME_LENGTH
|
||||
mov [esi+KTSS_ESP0], eax
|
||||
|
||||
/* Save V86 registers */
|
||||
push 0
|
||||
push 0
|
||||
push 0
|
||||
push 0
|
||||
push 0x2000
|
||||
|
||||
/* Get linear delta between stack and code */
|
||||
mov eax, offset _HalpRealModeEnd-4
|
||||
sub eax, offset _HalpRealModeStart
|
||||
|
||||
/* Get offset of code */
|
||||
mov edx, offset _HalpRealModeStart
|
||||
and edx, 0xFFF
|
||||
|
||||
/* Add offset to linear address and save the new V86 SP */
|
||||
add eax, edx
|
||||
push eax
|
||||
|
||||
/* Start building interrupt frame. Setup V86 EFLAGS and IOPL 3 */
|
||||
pushfd
|
||||
or dword ptr [esp], EFLAGS_V86_MASK
|
||||
or dword ptr [esp], 0x3000
|
||||
|
||||
/* Push the CS and IP */
|
||||
push 0x2000
|
||||
push edx
|
||||
|
||||
/* Do the interrupt return (jump to V86 mode) */
|
||||
iretd
|
||||
|
||||
.globl _HalpRealModeStart
|
||||
_HalpRealModeStart:
|
||||
|
||||
/* Set mode 13 */
|
||||
mov ax, 0x12
|
||||
.byte 0
|
||||
.byte 0
|
||||
|
||||
/* Do the interrupt */
|
||||
int 0x10
|
||||
|
||||
/* BOP to exit V86 mode */
|
||||
.byte 0xC4
|
||||
.byte 0xC4
|
||||
|
||||
/* The stack lives here */
|
||||
.align 4
|
||||
.space 2048
|
||||
.globl _HalpRealModeEnd
|
||||
_HalpRealModeEnd:
|
||||
|
||||
/* We're back, clean up the trap frame */
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
pop ebx
|
||||
pop esi
|
||||
pop edi
|
||||
popfd
|
||||
|
||||
/* Return to caller */
|
||||
pop ebp
|
||||
ret 0
|
||||
.endfunc
|
||||
|
||||
.globl _HalpOpcodeInvalid@0
|
||||
.func HalpOpcodeInvalid@0
|
||||
_HalpOpcodeInvalid@0:
|
||||
|
||||
/* This should never happen -- is the IOPM damaged? */
|
||||
push [esi+HALP_BIOS_FRAME_EIP]
|
||||
push [esi+HALP_BIOS_FRAME_CS]
|
||||
push offset _InvalidMsg
|
||||
call _DbgPrint
|
||||
add esp, 12
|
||||
|
||||
/* Break */
|
||||
int 3
|
||||
|
||||
/* Nothing to return */
|
||||
xor eax, eax
|
||||
ret 0
|
||||
.endfunc
|
||||
|
||||
.globl _HalpPushInt@0
|
||||
.func HalpPushInt@0
|
||||
_HalpPushInt@0:
|
||||
|
||||
/* Save EBX */
|
||||
push ebx
|
||||
|
||||
/* Get SS offset and base */
|
||||
mov edx, [esi+HALP_BIOS_FRAME_ESP]
|
||||
mov ebx, [esi+HALP_BIOS_FRAME_SS_BASE]
|
||||
|
||||
/* Convert to 16-bits */
|
||||
and edx, 0xFFFF
|
||||
sub dx, 2
|
||||
|
||||
/* Get EFLAGS and write them into the linear address of SP */
|
||||
mov ax, word ptr [esi+HALP_BIOS_FRAME_EFLAGS]
|
||||
mov [ebx+edx], ax
|
||||
sub dx, 2
|
||||
|
||||
/* Get CS segment and write it into SP */
|
||||
mov ax, word ptr [esi+HALP_BIOS_FRAME_CS]
|
||||
mov [ebx+edx], ax
|
||||
sub dx, 2
|
||||
|
||||
/* Get IP and write it into SP */
|
||||
mov ax, word ptr [esi+HALP_BIOS_FRAME_EIP]
|
||||
mov [ebx+edx], ax
|
||||
|
||||
/* Get new IP value (the interrupt ID is in ECX, so this is in the IVT) */
|
||||
mov eax, [ecx*4]
|
||||
push eax
|
||||
|
||||
/* Now save the new IP */
|
||||
movzx eax, ax
|
||||
mov [esi+HALP_BIOS_FRAME_EIP], eax
|
||||
|
||||
/* Save the new CS of this IP */
|
||||
pop eax
|
||||
shr eax, 16
|
||||
mov [esi+HALP_BIOS_FRAME_CS], eax
|
||||
|
||||
/* Update the stack pointer after our manual interrupt frame construction */
|
||||
mov word ptr [esi+HALP_BIOS_FRAME_ESP], dx
|
||||
|
||||
/* Get CS and convert it to linear format */
|
||||
mov eax, [esi+HALP_BIOS_FRAME_CS]
|
||||
shl eax, 4
|
||||
mov [esi+HALP_BIOS_FRAME_CS_BASE], eax
|
||||
mov dword ptr [esi+HALP_BIOS_FRAME_CS_LIMIT], 0xFFFF
|
||||
mov dword ptr [esi+HALP_BIOS_FRAME_CS_FLAGS], 0
|
||||
|
||||
/* Return success and restore EBX */
|
||||
mov eax, 1
|
||||
pop ebx
|
||||
ret 0
|
||||
.endfunc
|
||||
|
||||
.globl _HalpOpcodeINTnn@0
|
||||
.func HalpOpcodeINTnn@0
|
||||
_HalpOpcodeINTnn@0:
|
||||
|
||||
/* Save non-volatiles and stack */
|
||||
push ebp
|
||||
push esi
|
||||
push ebx
|
||||
|
||||
/* Get SS and convert it to linear format */
|
||||
mov eax, [esi+HALP_BIOS_FRAME_SS]
|
||||
shl eax, 4
|
||||
mov [esi+HALP_BIOS_FRAME_SS_BASE], eax
|
||||
mov dword ptr [esi+HALP_BIOS_FRAME_SS_LIMIT], 0xFFFF
|
||||
mov dword ptr [esi+HALP_BIOS_FRAME_SS_FLAGS], 0
|
||||
|
||||
/* Increase IP and check if we're past the CS limit */
|
||||
inc dword ptr [esi+HALP_BIOS_FRAME_EIP]
|
||||
mov edi, [esi+HALP_BIOS_FRAME_EIP]
|
||||
cmp edi, [esi+HALP_BIOS_FRAME_CS_LIMIT]
|
||||
ja EipLimitReached
|
||||
|
||||
/* Convert IP to linear address and read the interrupt number */
|
||||
add edi, [esi+HALP_BIOS_FRAME_CS_BASE]
|
||||
movzx ecx, byte ptr [edi]
|
||||
|
||||
/* Increase EIP and do the interrupt, check for status */
|
||||
inc dword ptr [esi+HALP_BIOS_FRAME_EIP]
|
||||
call _HalpPushInt@0
|
||||
test eax, 0xFFFF
|
||||
jz Done
|
||||
|
||||
/* Update the trap frame */
|
||||
mov ebp, [esi+HALP_BIOS_FRAME_TRAP_FRAME]
|
||||
mov eax, [esi+HALP_BIOS_FRAME_SS]
|
||||
mov [ebp+KTRAP_FRAME_SS], eax
|
||||
mov eax, [esi+HALP_BIOS_FRAME_ESP]
|
||||
mov [ebp+KTRAP_FRAME_ESP], eax
|
||||
mov eax, [esi+HALP_BIOS_FRAME_CS]
|
||||
mov [ebp+KTRAP_FRAME_CS], eax
|
||||
mov eax, [esi+HALP_BIOS_FRAME_EFLAGS]
|
||||
mov [ebp+KTRAP_FRAME_EFLAGS], eax
|
||||
|
||||
/* Set success code */
|
||||
mov eax, 1
|
||||
|
||||
Done:
|
||||
/* Restore volatiles */
|
||||
pop ebx
|
||||
pop edi
|
||||
pop ebp
|
||||
ret 0
|
||||
|
||||
EipLimitReached:
|
||||
/* Set failure code */
|
||||
xor eax, eax
|
||||
jmp Done
|
||||
.endfunc
|
||||
|
||||
.globl _HalpDispatchV86Opcode@0
|
||||
.func HalpDispatchV86Opcode@0
|
||||
_HalpDispatchV86Opcode@0:
|
||||
|
||||
/* Make space for the HAL BIOS Frame on the stack */
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, HALP_BIOS_FRAME_LENGTH
|
||||
|
||||
/* Save non-volatiles */
|
||||
push esi
|
||||
push edi
|
||||
|
||||
/* Save pointer to the trap frame */
|
||||
mov esi, [ebp]
|
||||
mov [ebp-HALP_BIOS_FRAME_LENGTH+HALP_BIOS_FRAME_TRAP_FRAME], esi
|
||||
|
||||
/* Save SS */
|
||||
movzx eax, word ptr [esi+KTRAP_FRAME_SS]
|
||||
mov [ebp-HALP_BIOS_FRAME_LENGTH+HALP_BIOS_FRAME_SS], eax
|
||||
|
||||
/* Save ESP */
|
||||
mov eax, [esi+KTRAP_FRAME_ESP]
|
||||
mov [ebp-HALP_BIOS_FRAME_LENGTH+HALP_BIOS_FRAME_ESP], eax
|
||||
|
||||
/* Save EFLAGS */
|
||||
mov eax, [esi+KTRAP_FRAME_EFLAGS]
|
||||
mov [ebp-HALP_BIOS_FRAME_LENGTH+HALP_BIOS_FRAME_EFLAGS], eax
|
||||
|
||||
/* Save CS */
|
||||
movzx eax, word ptr [esi+KTRAP_FRAME_CS]
|
||||
mov [ebp-HALP_BIOS_FRAME_LENGTH+HALP_BIOS_FRAME_CS], eax
|
||||
|
||||
/* Save EIP */
|
||||
mov eax, [esi+KTRAP_FRAME_EIP]
|
||||
mov [ebp-HALP_BIOS_FRAME_LENGTH+HALP_BIOS_FRAME_EIP], eax
|
||||
|
||||
/* No prefix */
|
||||
xor eax, eax
|
||||
mov [ebp-HALP_BIOS_FRAME_LENGTH+HALP_BIOS_FRAME_PREFIX], eax
|
||||
|
||||
/* Set pointer to HAL BIOS Frame */
|
||||
lea esi, [ebp-HALP_BIOS_FRAME_LENGTH]
|
||||
|
||||
/* Convert CS to linear format */
|
||||
mov eax, [esi+HALP_BIOS_FRAME_CS]
|
||||
shl eax, 4
|
||||
mov [esi+HALP_BIOS_FRAME_CS_BASE], eax
|
||||
mov dword ptr [esi+HALP_BIOS_FRAME_CS_LIMIT], 0xFFFF
|
||||
mov dword ptr [esi+HALP_BIOS_FRAME_CS_FLAGS], 0
|
||||
|
||||
/* Make sure IP is within the CS Limit */
|
||||
mov edi, [esi+HALP_BIOS_FRAME_EIP]
|
||||
cmp edi, [esi+HALP_BIOS_FRAME_CS_LIMIT]
|
||||
ja DispatchError
|
||||
|
||||
/* Convert IP to linear address and read the opcode */
|
||||
add edi, [esi+HALP_BIOS_FRAME_CS_BASE]
|
||||
mov dl, [edi]
|
||||
|
||||
/* We only deal with interrupts */
|
||||
cmp dl, 0xCD
|
||||
je DispatchInt
|
||||
|
||||
/* Anything else is invalid */
|
||||
call _HalpOpcodeInvalid@0
|
||||
jmp DispatchError
|
||||
|
||||
DispatchInt:
|
||||
/* Handle dispatching the interrupt */
|
||||
call _HalpOpcodeINTnn@0
|
||||
test eax, 0xFFFF
|
||||
jz DispatchReturn
|
||||
|
||||
/* Update the trap frame EIP */
|
||||
mov edi, [ebp-0x20]
|
||||
mov eax, [ebp-0x24]
|
||||
mov [edi+KTRAP_FRAME_EIP], eax
|
||||
|
||||
/* Set success code */
|
||||
mov eax, 1
|
||||
|
||||
DispatchReturn:
|
||||
/* Restore registers and return */
|
||||
pop edi
|
||||
pop esi
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret 0
|
||||
|
||||
DispatchError:
|
||||
/* Set failure code and return */
|
||||
xor eax, eax
|
||||
jmp DispatchReturn
|
||||
.endfunc
|
||||
|
||||
.func Ki16BitStackException
|
||||
_Ki16BitStackException:
|
||||
|
||||
/* Save stack */
|
||||
push ss
|
||||
push esp
|
||||
|
||||
/* Go to kernel mode thread stack */
|
||||
mov eax, PCR[KPCR_CURRENT_THREAD]
|
||||
add esp, [eax+KTHREAD_INITIAL_STACK]
|
||||
|
||||
/* Switch to good stack segment */
|
||||
UNHANDLED_PATH "16-Bit Stack"
|
||||
.endfunc
|
||||
|
||||
.globl _HalpTrap0D@0
|
||||
.func HalpTrap0D@0
|
||||
TRAP_FIXUPS htd_a, htd_t, DoFixupV86, DoFixupAbios
|
||||
_HalpTrap0D@0:
|
||||
|
||||
/* Enter trap */
|
||||
TRAP_PROLOG htd_a, htd_t
|
||||
|
||||
/* Check if this is a V86 trap */
|
||||
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
|
||||
jnz DoDispatch
|
||||
|
||||
/* This is weird -- but might happen during an NMI */
|
||||
push offset _InvalidGpfMsg
|
||||
call _DbgPrint
|
||||
add esp, 4
|
||||
|
||||
/* Loop forever */
|
||||
jmp $
|
||||
|
||||
DoDispatch:
|
||||
/* Handle the opcode */
|
||||
call _HalpDispatchV86Opcode@0
|
||||
|
||||
/* Exit the interrupt */
|
||||
jmp _Kei386EoiHelper@0
|
||||
.endfunc
|
||||
|
||||
.globl _HalpTrap06@0
|
||||
.func HalpTrap06@0
|
||||
_HalpTrap06@0:
|
||||
|
||||
/* Restore DS/ES segments */
|
||||
mov eax, KGDT_R3_DATA | RPL_MASK
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
/* Restore ESP and return */
|
||||
mov esp, _HalpSavedEsp
|
||||
ret 0
|
||||
.endfunc
|
|
@ -29,7 +29,6 @@
|
|||
<file>systimer.S</file>
|
||||
<file>timer.c</file>
|
||||
<file>usage.c</file>
|
||||
<file>v86.s</file>
|
||||
</directory>
|
||||
<directory name="include">
|
||||
<pch>hal.h</pch>
|
||||
|
|
|
@ -5,6 +5,23 @@
|
|||
#ifndef __INTERNAL_HAL_HAL_H
|
||||
#define __INTERNAL_HAL_HAL_H
|
||||
|
||||
typedef struct _HAL_BIOS_FRAME
|
||||
{
|
||||
ULONG SegSs;
|
||||
ULONG Esp;
|
||||
ULONG EFlags;
|
||||
ULONG SegCs;
|
||||
ULONG Eip;
|
||||
PKTRAP_FRAME TrapFrame;
|
||||
ULONG CsLimit;
|
||||
ULONG CsBase;
|
||||
ULONG CsFlags;
|
||||
ULONG SsLimit;
|
||||
ULONG SsBase;
|
||||
ULONG SsFlags;
|
||||
ULONG Prefix;
|
||||
} HAL_BIOS_FRAME, *PHAL_BIOS_FRAME;
|
||||
|
||||
#define HAL_APC_REQUEST 0
|
||||
#define HAL_DPC_REQUEST 1
|
||||
|
||||
|
@ -28,6 +45,59 @@
|
|||
#define INT_BCD(int) \
|
||||
(UCHAR)(((int / 10) << 4) + (int % 10))
|
||||
|
||||
//
|
||||
// BIOS Interrupts
|
||||
//
|
||||
#define VIDEO_SERVICES 0x10
|
||||
|
||||
//
|
||||
// Operations for INT 10h (in AH)
|
||||
//
|
||||
#define SET_VIDEO_MODE 0x00
|
||||
|
||||
//
|
||||
// Video Modes for INT10h AH=00 (in AL)
|
||||
//
|
||||
#define GRAPHICS_MODE_12 0x12 /* 80x30 8x16 640x480 16/256K */
|
||||
|
||||
//
|
||||
// Generates a 16-bit (real-mode or Virtual 8086) BIOS interrupt with a given AX */
|
||||
//
|
||||
VOID
|
||||
FORCEINLINE
|
||||
HalpCallBiosInterrupt(IN ULONG Interrupt,
|
||||
IN ULONG Ax)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
".byte 0x66\n"
|
||||
"movl $%c[v], %%eax\n"
|
||||
"int $%c[i]\n"
|
||||
:
|
||||
: [v] "i"(Ax),
|
||||
[i] "i"(Interrupt)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Constructs a stack of the given size and alignment in the real-mode .text region */
|
||||
//
|
||||
VOID
|
||||
FORCEINLINE
|
||||
HalpRealModeStack(IN ULONG Alignment,
|
||||
IN ULONG Size)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
".align %c[v]\n"
|
||||
".space %c[i]\n"
|
||||
".globl _HalpRealModeEnd\n_HalpRealModeEnd:\n"
|
||||
:
|
||||
: [v] "i"(Alignment),
|
||||
[i] "i"(Size)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Commonly stated as being 1.19318MHz
|
||||
//
|
||||
|
@ -557,24 +627,6 @@ HalpBiosDisplayReset(
|
|||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalpBiosCall(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalpTrap0D(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HalpTrap06(
|
||||
VOID
|
||||
);
|
||||
|
||||
//
|
||||
// Processor Halt Routine
|
||||
//
|
||||
|
@ -716,9 +768,6 @@ KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
|
|||
|
||||
extern BOOLEAN HalpNMIInProgress;
|
||||
|
||||
extern PVOID HalpRealModeStart;
|
||||
extern PVOID HalpRealModeEnd;
|
||||
|
||||
extern ADDRESS_USAGE HalpDefaultIoSpace;
|
||||
|
||||
extern KSPIN_LOCK HalpSystemHardwareLock;
|
||||
|
|
Loading…
Reference in a new issue