Beispiel #1
0
VOID
NTAPI
Fast486SetSegment(PFAST486_STATE State,
                  FAST486_SEG_REGS Segment,
                  USHORT Selector)
{
    /* Call the internal function */
    Fast486LoadSegment(State, Segment, Selector);
}
Beispiel #2
0
VOID
NTAPI
Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset)
{
    /* Load the new CS */
    if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment))
    {
        /* An exception occurred, let the handler execute instead */
        return;
    }

    /* Set the new IP */
    State->InstPtr.Long = Offset;
}
Beispiel #3
0
VOID
NTAPI
Fast486SetStack(PFAST486_STATE State, USHORT Segment, ULONG Offset)
{
    /* Load the new SS */
    if (!Fast486LoadSegment(State, FAST486_REG_SS, Segment))
    {
        /* An exception occurred, let the handler execute instead */
        return;
    }

    /* Set the new SP */
    State->GeneralRegs[FAST486_REG_ESP].Long = Offset;
}
Beispiel #4
0
BOOLEAN
Fast486InterruptInternal(PFAST486_STATE State,
                         USHORT SegmentSelector,
                         ULONG Offset,
                         ULONG GateType)
{
    BOOLEAN GateSize = (GateType == FAST486_IDT_INT_GATE_32)
                       || (GateType == FAST486_IDT_TRAP_GATE_32);

    /* Check for protected mode */
    if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
    {
        FAST486_TSS Tss;
        USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector;
        ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long;
        
        if (GateSize != (State->SegmentRegs[FAST486_REG_CS].Size))
        {
            /*
             * The gate size doesn't match the current operand size, so toggle
             * the OPSIZE flag.
             */
            State->PrefixFlags ^= FAST486_PREFIX_OPSIZE;
        }

        /* Check if the interrupt handler is more privileged */
        if (Fast486GetCurrentPrivLevel(State) > GET_SEGMENT_RPL(SegmentSelector))
        {
            /* Read the TSS */
            if (!Fast486ReadLinearMemory(State,
                                         State->TaskReg.Base,
                                         &Tss,
                                         sizeof(Tss)))
            {
                /* Exception occurred */
                return FALSE;
            }

            /* Check the new (higher) privilege level */
            switch (GET_SEGMENT_RPL(SegmentSelector))
            {
                case 0:
                {
                    if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss0))
                    {
                        /* Exception occurred */
                        return FALSE;
                    }
                    State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp0;

                    break;
                }

                case 1:
                {
                    if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss1))
                    {
                        /* Exception occurred */
                        return FALSE;
                    }
                    State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp1;

                    break;
                }

                case 2:
                {
                    if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss2))
                    {
                        /* Exception occurred */
                        return FALSE;
                    }
                    State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp2;

                    break;
                }

                default:
                {
                    /* Should never reach here! */
                    ASSERT(FALSE);
                }
            }

            /* Push SS selector */
            if (!Fast486StackPush(State, OldSs)) return FALSE;

            /* Push stack pointer */
            if (!Fast486StackPush(State, OldEsp)) return FALSE;
        }
    }
    else
    {
        if (State->SegmentRegs[FAST486_REG_CS].Size)
        {
            /* Set OPSIZE, because INT always pushes 16-bit values in real mode */
            State->PrefixFlags |= FAST486_PREFIX_OPSIZE;
        }
    }

    /* Push EFLAGS */
    if (!Fast486StackPush(State, State->Flags.Long)) return FALSE;

    /* Push CS selector */
    if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector)) return FALSE;

    /* Push the instruction pointer */
    if (!Fast486StackPush(State, State->InstPtr.Long)) return FALSE;

    if ((GateType == FAST486_IDT_INT_GATE) || (GateType == FAST486_IDT_INT_GATE_32))
    {
        /* Disable interrupts after a jump to an interrupt gate handler */
        State->Flags.If = FALSE;
    }

    /* Load new CS */
    if (!Fast486LoadSegment(State, FAST486_REG_CS, SegmentSelector))
    {
        /* An exception occurred during the jump */
        return FALSE;
    }

    if (GateSize)
    {
        /* 32-bit code segment, use EIP */
        State->InstPtr.Long = Offset;
    }
    else
    {
        /* 16-bit code segment, use IP */
        State->InstPtr.LowWord = LOWORD(Offset);
    }

    return TRUE;
}